【问题标题】:detecting line-breaks with jQuery?用jQuery检测换行符?
【发布时间】:2011-01-12 17:12:33
【问题描述】:

是否可以让 jQuery/javascript 检测字符串在哪里被破坏(以适应 CSS 宽度限制)以便在新行的开头插入 DOM 元素?

【问题讨论】:

  • 您是在寻找单词的换行位置,还是在寻找<br>
  • 输入的是什么字符串?
  • 你在每行开头之前插入的内容是什么?
  • @Marnix 正在寻找包装。 @amosrivera 只是一个句子,它是一个标题。 @Jacob 不确定你的意思?在动态内容之前有一个

    和一个

标签: javascript jquery line-breaks


【解决方案1】:

我想出了一个方法,但对于您的目的来说它可能有点矫枉过正,所以请考虑到这一点。

您需要创建元素的克隆,清空原始元素,然后将每个单词移回原始元素。如果高度在任何时候发生变化,则在该单词之前会有一个换行符。使用$(el).text() 会相当简单,但如果里面可以有其他标签,而不仅仅是文本,它会变得更加复杂。我尝试在此答案框中解释如何按节点分解它,但发现在 jsFiddle 中创建一个 jQuery 插件更容易。链接在这里:http://jsfiddle.net/nathan/qkmse/ (Gist)。

它不能很好地处理浮动元素,并且在其他一些情况下它会摔倒。如果您需要更多选项,或者它不能完全满足您的目的,或者您不确定如何应用它,请告诉我,我会尽力提供帮助。

【讨论】:

  • 开箱即用 - 暴力取胜!
  • 这个comment 解决了类似的问题,它将每一行文本包装在一个跨度中(具有唯一的类!)。它使用this plugin
【解决方案2】:

这是一种方法。注意:如果不使用等宽字体,我看不到理想的解决方案。与字符的等号使这项任务变得更加容易。

  1. 等宽字符
  2. 计算一个字符的大小
  3. 计算容器的大小
  4. 每行查找字符
  5. 查找行将中断的位置(即空格、破折号等)
  6. 获取所有中断索引。

查看相关 html 的 jsfiddle。我还没有完成这个功能。计算断裂指数时需要进行更多检查。现在它正在使用 lastIndexOf(' '),但这忽略了下一个索引可能是空格或当前索引。我也没有考虑其他换行符。然而,这应该是一个很好的起点。

var text = $('#text').text(),                   // "lorem ipsum ... "
    len = text.length,                          // total chars
    width = $('#text').width(),                 // container width
    span = $('<span />').append('a').appendTo('#sandbox'),
    charWidth = span.width(),                  // add single character to span and test width
    charsPerRow = Math.floor(width/charWidth); // total characters that can fit in one row

var breakingIndexes = [], // will contain indexes of all soft-breaks
    gRowStart = 0,        // global row start index
    gRowEnd = charsPerRow;// global row end index

while(gRowEnd < len){
    var rowEnd = text.substring(gRowStart, gRowEnd).lastIndexOf(' '); // add more checks for break conditions here
    breakingIndexes.push(gRowStart + rowEnd); // add breaking index to array
    gRowStart = gRowStart + rowEnd + 1; // next start is the next char
    gRowEnd = gRowStart + charsPerRow;  // global end inxex is start + charsperrow
}

var text2 = $('#text2').text();           // "lorem ipsum ... " now not width bound
var start = 0, newText = '';
for(var i=0; i < breakingIndexes.length; i++){
    newText += text2.substring(start, breakingIndexes[i]) + '<br />'; // add hard breaks
    start = breakingIndexes[i]; // update start
}

$('#text2').html(newText); // output with breaks

http://jsfiddle.net/Y5Ftn/1/

【讨论】:

  • 问题确实是很多字符有不同的空间。您可以做的一件事是将1ex 视为charWidth。或者也许(这更难)创建charWidth 的估计值。但这取决于语言,通过哪种字符更有可能出现在您的文本中。或者,如果自动换行不是您要找的,最好使用max-char,比如 W,这是一个巨大的字符。或者也许将其视为具有差异的Gaussian 函数?
  • @marnix - 我看不出这些是非常准确的计算,因为非等宽字体具有不同的字符宽度。您当然可以计算所有常见字符的宽度,并根据各个字符的宽度实际计算每一行。然而,这似乎非常低效。
  • 我刚刚在 IE 7 中进行了测试(此处为企业标准 :( ),它的格式不正确,但在 Chrome 8 中看起来很棒!只是想你可能想知道,也许可以完成...
  • 正如我所说,它不应该在每一行都计算。尽管它在多项式时间内是可行的,但这是您不想要的。为您正在使用的语言创建一个估计值。大多数自然过程都是高斯的,所以这将是一件好事,或者您可以将其设为离散的 E[X],因为字符数是离散的。 'W' 看起来像max-char 一样的好字符,因为它几乎是所有字体中最大的字符。所以是的,创建一个估计值比在SPAN 中取一个“a”更好。
【解决方案3】:

这是我的脚本,它接受文本,然后使每一行成为一个跨度

CSS:

    margin: 0;
        padding: 0;
    }

    .title{
        width: 300px;
        background-color: rgba(233,233,233,0.5);
        line-height: 20px;
    }

    span{
        color: white;
        background-color: red;
        display: inline-block;
        font-size: 30px;
    }

    a{
        text-decoration: none;
        color: black;
    }

html

<div class="title">
        <a href="">SOME TEXT LONG TEXT ANDTHISISLONG AND THIS OTHER TEXT</a>
    </div>

JS

$(function(){

        $(".title").find("a").each(function(){

            var $this = $(this);
            var originalText = $this.text();
            $this.empty();

            var sections = [];

            $.each( originalText.split(" "), function(){
                var $span = $("<span>" + this + "</span>");
                $this.append($span);

                var index = $span.position().top;

                if( sections[index] === undefined ){
                    sections[index] = "";
                }

                sections[index] += $span.text() + " ";
            });

            $this.empty();

            for(var i = 0; i< sections.length; i++){
                if( sections[i] !== undefined ){
                    var spanText = $.trim(sections[i]);                     
                    $this.append("<span>" + spanText + "</span>");
                }
            }

        });

    });

您必须包含 jQuery。

【讨论】:

  • 这很好,谢谢!尽管有一些边缘情况,例如浏览器可能会在空格以外的地方中断(制表符、换行符、U+2028,可能是连字符)。
【解决方案4】:

我不知道有任何内置的 jQuery 的 javascript 函数可以做到这一点。然而,你可以自己做,但如果你有很多文本,它可能会很慢。

理论上,您可以确保将高度设置为自动,删除文本,然后逐字重新插入。在高度发生变化时,您删除最后一个单词,并插入您的 dom 元素。同样,如果有很多文本,这会很慢,更好的方法是不更改原始元素,而是在另一个可能隐藏的元素中进行,然后在完成时替换原始元素。这样,您的用户就不会看到内容消失然后逐字返回。

另一种方法是使用类似的原理,从一个大小相同且高度为 auto 的空元素开始,然后插入一个新字符和一个空格,直到得到一个新行。从那里,您可以将其用作上述技术的近似值,或者您可以盲目地将每个字符串的长度相加,直到找到新行,同时考虑到您的 dom 元素的宽度。不过,这种技术在等宽字体上效果更好,这就是仅将其用作近似值的地方。

也就是说,有一种方法可以使用画布测量文本,但这可能是极端的。理论上是这样,创建一个画布元素,获取上下文,设置所有字体属性,然后使用context.measureText() 方法。可以在here找到它的使用示例。

【讨论】:

    【解决方案5】:

    不确定您的用例到底是什么,但http://code.google.com/p/hyphenator/ 可能是您的问题的解决方案,或者如果您深入研究 hyphenator.js 源代码,您或许能够找到您正在寻找的代码。

    【讨论】:

      【解决方案6】:

      我认为使用正则表达式检测会更容易——在保持效率的同时代码更少。

      这对我有用:

      if ((/(\r\n|\n|\r)/.test($(this).val()))) {
          alert('there are line breaks here')
      }
      

      我不确定这是否适用于您损坏的字符串,但它适用于使用 jQuery 检测换行符。

      【讨论】:

      • 此代码是否会因 DOM 中的正常文本换行而导致中断?
      • 我只对此进行了初步测试,但我相信是的。我知道它肯定适用于 textareas,这是我过去使用过的地方。
      • 它在 textareas 中工作,因为编辑元素会改变 DOM。这不是其他元素的情况。
      【解决方案7】:

      或者,您可以将文本块的宽度与其父级的宽度进行比较。如果块至少是其父级宽度的 98%,则可以肯定它会中断

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-02-16
        • 2021-07-23
        • 2015-01-25
        • 2012-03-04
        • 2013-07-22
        • 1970-01-01
        相关资源
        最近更新 更多