寻找换行符

IT技术 javascript jquery html dom text
2021-02-06 15:04:42

假设我在一行中有一些随机的文本块。像这样

Lorem ipsum dolor sit amet, consectetur adipiscing elit.

但无论出于何种原因(包含元素的宽度设置、文本缩放的使用等),它在查看器的屏幕上显示为两行或更多行。

Lorem ipsum dolor sit amet,

consectetur adipiscing elit.

或者

Lorem ipsum dolor sit

amet, consectetur

adipiscing elit.

有没有办法通过javascript找出这些换行发生的地方?

$('p').text()$('p').html()返回Lorem ipsum dolor sit amet, consectetur adipiscing elit.不管是如何显示的文本。

6个回答

好吧,如果你想要一些非常简单并且可能对你来说太无用的东西(如果你在段落中有任何类型的 HTML,它需要进行重大修改),然后看看这个:

var para = $('p');

para.each(function(){
    var current = $(this);
    var text = current.text();
    var words = text.split(' ');

    current.text(words[0]);
    var height = current.height();

    for(var i = 1; i < words.length; i++){
        current.text(current.text() + ' ' + words[i]);

        if(current.height() > height){
            height = current.height();
            // (i-1) is the index of the word before the text wraps
            console.log(words[i-1]);
        }
    }
});

它是如此简单可笑,它可能只是工作。这样做是将文本按空格分开,然后将单词逐字追加,观察元素高度的任何增加,这将表明换行。

在这里看看:http : //www.jsfiddle.net/xRPYN/2/

jsfiddle 设置似乎停在第一行。我的下意识反应是我不能使用它,因为用户实际上可以控制容器的宽度/高度,但经过反思,我可以在屏幕外某处创建一个具有相同宽度的临时 p,没有高度规范(此时我可以在每行之后清除电流以获得“在换行处分隔的行列表”的所需输出)。我试试看。
2021-03-12 15:04:42
优秀的!我把它改成了一个函数,比如:function isTextWrapped(div) { var wraps=0; var words = div.text().split(' '); div.text(words[0]); var 高度 = div.height(); for(var i = 1; i < words.length; i++){ div.text(div.text() + ' ' + words[i]); if(div.height() > height){ height = div.height(); 包裹++;返回包装;}
2021-03-17 15:04:42
很棒的工作......如果有人需要(仅在chrome中测试)jsfiddle.net/tV29m,那么没有jQuery也是一样
2021-03-21 15:04:42
我还确认它在从右到左文本(阿拉伯语)时没有弄乱文本。虽然如果你担心你可以让它存储原始文本并在最后替换它
2021-03-23 15:04:42

对于像 pdf 生成这样的用例。

您可以限制每行字符,如果中间单词出现拆分,请适当调整。

要获得每行更准确的字符,您可以使用等宽字体,然后确定允许的每种字体的每个字符的宽度。然后将字符宽度除以允许的文本行宽的大小,您将拥有该字体的每行允许的字符。

您可以使用非等宽字体,但是您必须测量每个字母的宽度 - 呃。您可以自动进行宽度猜测的一种方法是使用没有边距或填充的跨度,为每种字体(和大小)添加每个字符,然后测量跨度的宽度并使用它。

我已经完成了代码:

/**
 * jQuery getFontSizeCharObject
 * @version 1.0.0
 * @date September 18, 2010
 * @since 1.0.0, September 18, 2010
 * @package jquery-sparkle {@link http://www.balupton/projects/jquery-sparkle}
 * @author Benjamin "balupton" Lupton {@link http://www.balupton.com}
 * @copyright (c) 2010 Benjamin Arthur Lupton {@link http://www.balupton.com}
 * @license Attribution-ShareAlike 2.5 Generic {@link http://creativecommons.org/licenses/by-sa/2.5/
 */
$.getFontSizeCharObject = function(fonts,sizes,chars){
    var fonts = fonts||['Arial','Times'],
        sizes = sizes||['12px','14px'],
        chars = chars||['a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','y','x','z',
                        'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','Y','X','Z',
                        '0','1','2','3','4','5','6','7','8','9','-','=',
                        '!','@','#','$','%','^','&','*','(',')','_','+',
                        '[',']','{','}','\\','|',
                        ';',"'",':','"',
                        ',','.','/','<','>','?',' '],
        font_size_char = {},
        $body = $('body'),
        $span = $('<span style="padding:0;margin:0;letter-spacing:0:word-spacing:0"/>').appendTo($body);

    $.each(fonts, function(i,font){
        $span.css('font-family', font);
        font_size_char[font] = font_size_char[font]||{};
        $.each(sizes, function(i,size){
            $span.css('font-size',size);
            font_size_char[font][size] = font_size_char[font][size]||{};
            $.each(chars,function(i,char){
                if ( char === ' ' ) {
                    $span.html('&nbsp;');
                }
                else {
                    $span.text(char);
                }
                var width = $span.width()||0;
                font_size_char[font][size][char] = width;
            });
        });
    });

    $span.remove();

    return font_size_char;
};

/**
 * jQuery adjustedText Element Function
 * @version 1.0.0
 * @date September 18, 2010
 * @since 1.0.0, September 18, 2010
 * @package jquery-sparkle {@link http://www.balupton/projects/jquery-sparkle}
 * @author Benjamin "balupton" Lupton {@link http://www.balupton.com}
 * @copyright (c) 2010 Benjamin Arthur Lupton {@link http://www.balupton.com}
 * @license Attribution-ShareAlike 2.5 Generic {@link http://creativecommons.org/licenses/by-sa/2.5/
 */
$.fn.adjustedText = function(text,maxLineWidth){
    var $this = $(this),
        font_size_char = $.getFontSizeCharObject(),
        char_width = font_size_char['Times']['14px'],
        maxLineWidth = parseInt(maxLineWidth,10),
        newlinesAt = [],
        lineWidth = 0,
        lastSpace = null;

    text = text.replace(/\s+/g, ' ');

    $.each(text,function(i,char){
        var width = char_width[char]||0;
        lineWidth += width;
        if ( /^[\-\s]$/.test(char) ) {
            lastSpace = i;
        }
        //console.log(i,char,lineWidth,width);
        if ( lineWidth >= maxLineWidth ) {
            newlinesAt.push(lastSpace||i);
            lineWidth = width;
            lastSpace = null;
        }
    });

    $.each(newlinesAt,function(i,at){
        text = text.substring(0,at+i)+"\n"+text.substring(at+i);
    });

    text = text.replace(/\ ?\n\ ?/g, "\n");

    console.log(text,newlinesAt);

    $this.text(text);

    return $this;
};

$(function(){
    var $body = $('body'),
        $textarea = $('#mytext'),
        $btn = $('#mybtn'),
        $div = $('#mydiv');

    if ( $textarea.length === 0 && $div.length === 0 ) {
        $body.empty();

        $textarea = $('<textarea id="mytext"/>').val('(When spoken repeatedly, often three times in succession: blah blah blah!) Imitative of idle, meaningless talk; used sometimes in a slightly derogatory manner to mock or downplay another\'s words, or to show disinterest in a diatribe, rant, instructions, unsolicited advice, parenting, etc. Also used when recalling and retelling another\'s words, as a substitute for the portions of the speech deemed irrelevant.').appendTo($body);
        $div = $('<div id="mydiv"/>').appendTo($body);
        $btn = $('<button id="mybtn">Update Div</button>').click(function(){
            $div.adjustedText($textarea.val(),'300px');
        }).appendTo($body);

        $div.add($textarea).css({
            'width':'300px',
            'font-family': 'Times',
            'font-size': '14px'
        });
        $div.css({
            'width':'auto',
            'white-space':'pre',
            'text-align':'left'
        });
    }

});
这比我预期的任何人投入的工作都要多。+1。我认为就我的目的而言,可能有一种更简单的方法(因为我真的只需要在它们环绕的点处分隔的行列表,而且只要我得到UI 来做同样的事情)。我会玩一会儿并发布我的代码。谢谢你把我指向这个方向。
2021-03-26 15:04:42
与功能完全无关;你需要把 .com 放在你的@package
2021-03-31 15:04:42

这是我最终使用的内容(为了您自己的邪恶目的,请随意批评和复制)。

首先,当编辑来自用户时,它被分解为$(editableElement).lineText(userInput).

jQuery.fn.lineText = function (userInput) {
   var a = userInput.replace(/\n/g, " \n<br/> ").split(" ");
   $.each(a, function(i, val) { 
      if(!val.match(/\n/) && val!="") a[i] = '<span class="word-measure">' + val + '</span>';
   });
   $(this).html(a.join(" "));
};

发生换行替换是因为编辑文本框填充了$(editableElement).text(),这会忽略<br/>标签,但出于排版目的,它们仍会更改显示中下一行的高度。这不是最初目标的一部分,只是悬而未决的成果。

当我需要拉出格式化文本时,我调用$(editableElement).getLines(), where

jQuery.fn.getLines = function (){
   var count = $(this).children(".word-measure").length;
   var lineAcc = [$(this).children(".word-measure:eq(0)").text()];
   var textAcc = [];
   for(var i=1; i<count; i++){
      var prevY = $(this).children(".word-measure:eq("+(i-1)+")").offset().top;
      if($(this).children(".word-measure:eq("+i+")").offset().top==prevY){
         lineAcc.push($(this).children(".word-measure:eq("+i+")").text());
   } else {
     textAcc.push({text: lineAcc.join(" "), top: prevY});
     lineAcc = [$(this).children(".word-measure:eq("+i+")").text()];
   }
   }
   textAcc.push({text: lineAcc.join(" "), top: $(this).children(".word-measure:last").offset().top});
   return textAcc;
};

最终结果是一个哈希列表,每个哈希都包含一行文本的内容和垂直偏移。

[{"text":"Some dummy set to","top":363},
 {"text":"demonstrate...","top":382},
 {"text":"The output of this","top":420},
 {"text":"wrap-detector.","top":439}]

如果我只想要无格式文本,$(editableElement).text()仍然返回

"Some dummy set to demonstrate... The output of this wrap-detector."

一旦您拥有更复杂的结构,例如段落中的链接(例如,您可以<b><i><a href></a><p>.

所以我做了一个 javascript 库来检测在这些情况下行的换行位置:http : //github.com/xdamman/js-line-wrap-detector

我希望这有帮助。

我有一种情况,我需要将每一行都包裹在一个跨度中。我这样做是为了向文本块添加填充突出显示效果。将背景添加到环绕文本的 span 标签只会填充文本块的开头和结尾,每行必须单独包装。

这是我根据上面的建议提出的:

$.fn.highlghtWrap = function () {
    this.each( function () {
      var current = $( this );
      var text = current.text();
      var words = text.split( ' ' );
      var line = '';
      var lines = [];

      current.text( words[ 0 ] );
      var height = current.height();
      line = words[ 0 ];
      for ( var i = 1; i < words.length; i++ ) {
        current.text( current.text() + ' ' + words[ i ] );

        if ( current.height() > height ) {
          lines.push( line );
          line = words[ i ];
          height = current.height();
        } else {
          line = line + ' ' + words[ i ];
        }
      }
      lines.push( line );
      current.html( '' );
      $.each( lines, function ( v, a ) {
        current.html( current.html() + '<span>' + a +
          ' </span>' );
      } );
    } );
  }

  $( '.home-top_wrapper h2' ).highlghtWrap();
  $( '.home-top_wrapper p' ).highlghtWrap();