我可以在跨度中包装每行多行文本吗?

Bel*_*dio 14 javascript jquery text

我一直试图弄清楚如何做到这一点(如果它甚至可能)并且已经画了一个空白......

我有一些文本将包装到多行.我想检测每条线,并将其包裹在一个范围内.最后,我想从一个循环数组为每个span分配一个类.

例如...!

<div id="quote">
    I have some text that
    wraps onto three lines
    in this container
</div>
Run Code Online (Sandbox Code Playgroud)

我想让我的jquery解析这些行,检测它包裹的位置,并将其转换为:

<div id="quote">
    <span class="red-bg">I have some text that</span>
    <span class="orange-bg">wraps onto three lines</span>
    <span class="yellow-bg">in this container</span>
</div>
Run Code Online (Sandbox Code Playgroud)

我想动态执行此操作的原因是我在响应式模板中执行此操作,因此有时相同的文本将仅包装在两行中,或者在iPhone中可能包含四行.

这可行吗?我发现了这个 - > http://vidasp.net/tinydemos/numberOfLines.html它计算了一个文本块中使用的行数,但这并没有真正扩展到我需要的地方.

如果任何jquery忍者可以帮助我会非常感激!

And*_*y E 10

看起来你问的是如何将文本分割成浏览器自然包装的文本.不幸的是,这根本不是直截了当的.它也不健壮 - 考虑以下情况:

  • 用户浏览到您的页面,渲染div并触发onload事件,
  • 从文本节点创建3个span元素,每个包装的文本行创建1个,
  • 用户调整浏览器的大小并更改div的大小.

结果是跨度不再与线的开始和结束位置相关联.当然,使用固定宽度的元素可以避免这种情况,或者您可以在浏览器调整大小时重新调整整个内容,但这只是它如何破坏的一个示例.

不过,这并不容易.之前出现了一个类似的问题(虽然目标不同),并且出现了两个解决方案,这两个方面都有帮助:

解决方案1:getClientRects()

实际上不要将文本换成跨距,而是使用每行文本的位置和尺寸getClientRects().然后,创建所需的跨距数,并在每行文本后面定位/调整它们的大小.

优点

  • 快速; getClientRects返回每一行的位置
  • 简单; 代码比解决方案2更优雅

缺点

  • 包含的文本必须包含在内联元素中.
  • 没有样式实际应用于文本(如font-weight或font-color).仅适用于背景颜色或边框等内容.

随答案提供的演示显示了如何突出显示当前鼠标下方的文本行.

解决方案2:拆分,连接,循环,合并

使用split()方法将文本拆分为数组,并将字边界或空白作为参数传递.重新加入所述阵列成一个字符串与</span><span>每个元素之间,敷整个事情与<span></span>,并与在含元件生成的HTML替换原始文本节点.现在,遍历每个span元素,检查容器内的y位置.当y位置增加时,您知道已到达新行,并且之前的元素可以合并为单个跨度.

优点

  • 每行都可以使用任何CSS属性进行样式设置,例如font-weight或text-decoration.
  • 每一行都有自己的事件处理程序.

缺点

  • 由于众多的DOM和字符串操作,缓慢而笨拙

结论

可能还有其他方法可以实现您的目标,但我不确定自己. TextNode.splitText(n)传递要分割的字符的数字索引时,可以在twain(!)中拆分TextNode.上述两种解决方案都不是完美的,并且一旦包含元素调整大小就会中断.


小智 6

我放在一起小提琴安迪E(以上)实施的解决方案#2.即分裂,加入,循环,合并

这是算法:

var spanInserted = $('#someText').html().split(" ").join(" </span><span>");
var wrapped = ("<span>").concat(spanInserted, "</span>");
$('#someText').html(wrapped);
var refPos = $('#someText span:first-child').position().top;
var newPos;
$('#someText span').each(function(index) {
    newPos = $(this).position().top   
    if (index == 0){
       return;
    }
    if (newPos == refPos){
        $(this).prepend($(this).prev().text() + " ");
        $(this).prev().remove();
    } 
    refPos = newPos;
});
Run Code Online (Sandbox Code Playgroud)

请享用...


Dio*_*ane 1

var classes = ",red-bg,orange-bg,yellow-bg".split(",")
var txt = $('#quote').html().split("\n")
//this gives you FIVE items because of the leading and trailing CRs
//so we skip the first and last item in the loop
var output = ""
for(var x=1;x<txt.length-1;x++) {
    output = output + "<span class='"+classes[x]+"'>"+txt[x]+"</span>"
}
$('#quote').html(output)
Run Code Online (Sandbox Code Playgroud)