代码之家  ›  专栏  ›  技术社区  ›  Inaimathi

查找换行符

  •  39
  • Inaimathi  · 技术社区  · 14 年前

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

    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() 返回 洛雷姆·伊普索姆·多洛·西特·阿美,神圣的爱的精英。 无论文本如何显示。

    6 回复  |  直到 14 年前
        1
  •  26
  •   Yi Jiang G-Man    14 年前

    好吧,如果你想要一些非常简单的东西,可能对你来说太没用了(如果你在段落中有任何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/

        2
  •  12
  •   balupton    14 年前

    用于生成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'
            });
        }
    
    });
    
        3
  •  11
  •   Inaimathi    9 年前

    以下是我最后使用的东西(为了你自己的邪恶目的,请随意批评和复制)。

    首先,当编辑来自用户时,它与 $(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() ,在哪里

    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."
    
        4
  •  7
  •   xdamman    11 年前

    一旦你有了更复杂的结构(比如段落中的链接),上面的解决方案就不起作用了。 <b><i><a href></a> <p> )

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

    我希望这有帮助。

        5
  •  0
  •   user3761817    7 年前

    在这种情况下,我需要把每一行都用一个跨距来包装。我这样做是为了向文本块添加加垫突出显示效果。将背景添加到包装文本的跨度标记将只填充文本块的开头和结尾,每行必须单独包装。

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

    $.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();
    
        6
  •  0
  •   TextGeek    6 年前

    当存在内部标记和任意字体和样式时,概念上简单的方法也可以工作,就是进行第一次传递,将每个单词简单地放入自己的元素(可能是“span”,或者像“w”这样的自定义名称)。

    然后,可以使用getboundingclientrect()迭代以查找“top”属性的更改位置:

    function findBreaks() {
        var words = document.getElementsByTagName('w');
        var lastTop = 0;
        for (var i=0; i<words.length; i++) {
            var newTop = words[i].getBoundingClientRect().top;
            if (newTop == lastTop) continue;
            console.log("new line " + words[i].textContent + " at: " + newTop);
            lastTop = newTop;
        }
    }
    

    这听起来很慢,但除非文件很大,否则你不会注意到。