如何使用jQuery将标签中的上一个,当前和下一个单词包装起来?

不确定标题是否选好……

我正在尝试模拟HTML / JS / CSS中的文本选择,以便在真正选择文本时摆脱移动设备上的动作气泡。

更具体地说,我试图避免这种情况: 在此处输入图像描述

视觉:

在此处输入图像描述

我构建它的方式可能会因为无关紧要而改变,因为所选文本被包装在span.selection并且在该标记内部,还有两个插入符号用作处理程序:

 Lorem ipsum dolor      sit amet, consectetur      adipiscing elit.  

理想情况下,使用拖放选项来选择更多或更少的文本会很有趣,但我相信这样做很难做到,在这种情况下,也许可以点击插入符选择前一个或后一个单词并将其包装在.selection并不会那么糟糕。

这是jsfiddle: http : //jsfiddle.net/m6Qx4/

周围的文本也可能包含HTML标签,例如:

    /

  • 可能存在,使解析更难。

    有什么想法可以做到这一点?

    状态更新:

    我实际上设法使它与.click(); 事件监听器使用我的自定义jQuery方法。

    最后,我将用jQuery UI draggable替换click事件,以便选择周围的单词,只要它可用于移动设备。

    我目前的错误包括红色插入符号的重新定位。 我试图摧毁它们并在它们之前添加/追加它们仍然无法正常工作。 可能是Firefox的一个错误,在对文本节点进行更改后无法正确重新加载DOM?

    参考: jsFiddle

    要检查jsFiddle.net由于最近停机的运行情况,请访问他们的推文

    一些想法:

    我无法看到如何将中的所有内容包装起来是一个可行的解决方案。 当你有这样的事情时会发生什么?

     

    The important terms will be bolded in this text

    当您选择The important ,您会遇到一些标记混乱,其中标记的正文要与标记的正文重叠。

    我认为更好的解决方案是使用相同的类具有多个选择标记。 每次遇到HTML标记时,都会跳过标记并创建新的选择 。 然后,当您重新定位您的插入符号时,您只需执行以下操作:

     $(".selection:first").prepend(startCaret); $(".selection:last").append(endCaret); 

    我玩这个想法,它对我来说很好。 如果你想得到真正的想象,你可以尝试合并选择 s,当你遇到它的相应的开始标记后找到一个结束标记,但这将是很多工作。


    您的插入符号移动不正确,因为您指定了绝对定位样式。 将其更改为亲属,并为每个插入符号提供一个  。 您将不得不使用其他一些定位CSS设置来使其看起来恰到好处,但它会随着您对这些更改的预期而移动(例如此处 )。


    当我正在为此做一些想法时,我尝试在插入符号上进行绝对定位,这样就不必在选择移动它们。 那是个错误。 我遇到了没有任何标记溢出到新行的段落的问题。 坚持你的选择中的插入符号。


    最后,一些思考问题:

    • 你打算限制范围吗? (即,如果您开始在

      标签内选择,请不要让选择在该标签之外溢出到下一个

      或其他任何内容)

    • 某些标签是否无法选择? (即

      等)

    我认为这个想法很酷,但它可能是一个非常庞大的项目。 我会发布一些我试过的原型,当我让它们更加精致时。

    要涵盖Rusty的问题:

    首先拆分标签:

     var textBlock = textContainer.html(), taglessArray = textBlock.split(/<[^>]*>/), arrayOfTags = textBlock.match(/<[^>]*>/g), tagsFirst = (textBlock[0] === '<') ? true : false, //parens for legibility only //tagsFirst is a switch that tells us which to start splicing back in later 

    现在让我们将所有非空格包装在我们可以使用的span标签中

     var i = taglessArray.length; while(i--){ taglessArray[i].replace(/([^\s]*)/g,'$1'); } //not 100% sure I got that right - haven't tested - but the idea is , wrap all non //whitespace/word boundary blocks in 'selectableWord' classed span tags 

    现在把它们重新组合在一起。 原始文本格式标签应保留位置。 显然,'selectableWord'分类跨度应避免布局/格式化影响

     var addToArray, adderArray; if(tagsFirst){ addToArray = arrayOfTags; adderArray = taglessArray; } else { addToArray = taglessArray; adderArray = arrayOfTags; } var oLen, //used to retain 'original length' i2 = oLen = (tagsFirst.length + arrayOfTags.length), rejoinArray = []; while(i2--){ //not 100% sure I got this right - hope you get the general idea var currentKey = oLen - 1 - i2; //if first or alternating from first 0,2,4,etc... if(currentKey === 0 || ( currentKey % 2 === 0) { rejoinArray[currentKey] = addToArray.shift(); //remove first element and return } //should be keys 1,3,5,etc... else { rejoinArray[currentKey] = adderArray.shift(); } } 

    当然所有这些都是非常未经测试的,可能是错误/错误,但我认为基本的想法非常酷。 撕掉标签。 在您可以使用的跨度中包裹未标记的单词数组。 然后将所有愚蠢的标签拼接回去。它们仍应包裹所有相同的单词。 这假定基本的HTML完整性。 您的文本块仅包含内嵌显示标记,这些标记可以包含单词或单词集。 除非存在不正确的嵌套跨度,否则不正确的嵌套可能不是问题。