Подтвердить что ты не робот

Поиск строк

Предположим, что у меня есть случайный блок текста в одной строке. Таким образом

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() return Lorem ipsum dolor sit amet, consectetur adipiscing elit. независимо от того, как отображается текст.

4b9b3361

Ответ 1

Вот что я в итоге использовал (не стесняйтесь критиковать и копировать свои собственные гнусные цели).

Во-первых, когда редактирование приходит от пользователя, оно разбивается на $(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."

Ответ 2

Хорошо, если вам нужно что-то, что смехотворно просто и, вероятно, слишком бесполезно для вас (это потребует серьезной модификации, если в абзаце есть какой-то 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/

Ответ 3

Для использования, например, для генерации 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\ words, or to show disinterest in a diatribe, rant, instructions, unsolicited advice, parenting, etc. Also used when recalling and retelling another\ 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'
        });
    }

});

Ответ 4

Вышеупомянутые решения не работают, если у вас более сложная структура, такая как ссылка в абзаце (например, вы можете иметь <b><i><a href></a> внутри <p>).

Итак, я создал javascript-библиотеку, чтобы определить, где в этом случае работает перенос строк: http://github.com/xdamman/js-line-wrap-detector

Надеюсь, это поможет.

Ответ 5

У меня есть ситуация, когда мне нужно обернуть каждую строку в промежутке. Я делаю это так, чтобы добавить текстовый блок добавленного эффекта выделения. Добавление фона в тег 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();