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

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

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

例如…!

I have some text that wraps onto three lines in this container

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

 
I have some text that wraps onto three lines in this container

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

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

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

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

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

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

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

解决方案1:getClientRects()

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

优点

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

缺点

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

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

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

使用split()方法将文本拆分为数组,并将字边界或空白作为参数传递。 将数组重新连接到每个元素之间带有的字符串,并用包装整个事物,并将原始文本节点替换为包含元素中的结果HTML。 现在,遍历每个span元素,检查容器内的y位置。 当y位置增加时,您知道已到达新行,并且之前的元素可以合并为单个跨度。

优点

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

缺点

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

结论

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

我把Andy E(上图)的解决方案#2放在一起。 即拆分,加入,循环,合并

这是算法:

 var spanInserted = $('#someText').html().split(" ").join(" "); var wrapped = ("").concat(spanInserted, ""); $('#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; }); 

请享用…

 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[x]+"" } $('#quote').html(output) 

这将为您提供文本节点,但我不确定它有用

 $("#quote") .contents() .filter(function() { return this.nodeType == 3; })