wake-up-neo.com

Zeilenumbrüche finden

Angenommen, ich habe einen zufälligen Textblock in einer einzelnen Zeile. So

Lorem ipsum dolor sit amet, consectetur adipiscing elit.

Aber aus welchem ​​Grund auch immer (Breiteneinstellungen für das enthaltende Element, Verwendung von Text-Zoom usw.), wird auf dem Bildschirm des Betrachters als zwei oder mehr Zeilen angezeigt.

Lorem ipsum dolor sit amet,

consectetur adipiscing elit.

oder 

Lorem ipsum dolor sit

amet, consectetur

adipiscing elit.

Gibt es eine Möglichkeit, über Javascript herauszufinden, wo diese Zeilenumbrüche auftreten?

$('p').text() und $('p').html() geben Lorem ipsum dolor sit amet, consectetur adipiscing elit. zurück, unabhängig davon, wie der Text angezeigt wird.

39
Inaimathi

Hier ist, was ich am Ende verwendet habe (fühle mich frei zu kritisieren und für deine eigenen schändlichen Zwecke zu kopieren).

Zunächst einmal, wenn die Bearbeitung vom Benutzer eingeht, wird sie mit $(editableElement).lineText(userInput) getrennt.

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(" "));
};

Die Ersetzung der Zeilenumbrüche geschieht, weil das Bearbeitungstextfeld mit $(editableElement).text() gefüllt ist, wodurch <br/>-Tags ignoriert werden, die Höhe der folgenden Zeile in der Anzeige jedoch weiterhin geändert wird. Dies war nicht Teil des ursprünglichen Ziels, sondern nur ziemlich tief hängende Früchte.

Wenn ich formatierten Text herausziehen muss, rufe ich $(editableElement).getLines() an, wo

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;
};

Das Endergebnis ist eine Liste von Hashwerten, die jeweils den Inhalt und den vertikalen Versatz einer einzelnen Textzeile enthalten.

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

Wenn ich nur unformatierten Text haben möchte, wird $(editableElement).text() immer noch angezeigt

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

Wenn Sie etwas wollen, das lächerlich einfach und wahrscheinlich zu nutzlos für Sie ist (wenn Sie irgendeine Art von HTML im Absatz haben, müssen Sie das ändern), dann schauen Sie sich das an: 

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]);
        }
    }
});

Es ist so lächerlich einfach, dass es funktionieren könnte. Dies bedeutet, den Text durch Leerzeichen aufzulösen und dann die Wörter Wort für Wort anzufügen, wobei auf eine Erhöhung der Höhe des Elements zu achten ist, die einen Zeilenumbruch anzeigen würde. 

Schau es dir hier an: http://www.jsfiddle.net/xRPYN/2/

26
Yi Jiang

Für einen Anwendungsfall wie die PDF-Generierung.

Sie können sich auf Zeichen pro Zeile beschränken, wenn eine Aufteilung im mittleren Wort auftritt, passen Sie sie entsprechend an.

Um genauere Zeichen pro Zeile zu erhalten, können Sie Monospaced-Schriftarten verwenden und dann die Breite pro Zeichen für jede zulässige Schriftart festlegen. Teilen Sie dann die Zeichenbreite durch die Größe der zulässigen Textzeilenbreite, und Sie haben die zulässigen Zeichen pro Zeile für diese Schriftart.

Sie können nicht in einem Abstand stehende Schriftarten verwenden, müssen dann aber die Breite jedes Buchstabens messen - ugh. Sie können die Breite der Schätzung automatisieren, indem Sie einen Bereich ohne Rand oder Abstand angeben. Fügen Sie jedes Zeichen für jede Schriftart (und Größe) hinzu, messen Sie dann die Breite des Bereichs und verwenden Sie diesen.

Ich habe den Code aufgearbeitet:

/**
 * 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'
        });
    }

});
11
balupton

Die oben genannten Lösungen funktionieren nicht, wenn Sie eine komplexere Struktur wie einen Link in einem Absatz haben (z. B. können Sie <b><i><a href></a> in einem <p> haben).

Also habe ich eine Javascript-Bibliothek erstellt, um herauszufinden, wo Zeilen umbrochen werden, die in diesen Fällen funktionieren: http://github.com/xdamman/js-line-wrap-detector

Ich hoffe das hilft.

7
xdamman

Ich habe eine Situation, in der ich jede Zeile in einer Spanne umschließen muss. Ich mache das, damit ich einem Textblock einen aufgefüllten Hervorhebungseffekt hinzufügen kann. Wenn Sie den Hintergrund zu einem Span-Tag hinzufügen, das den Text umgibt, werden nur der Anfang und das Ende des Textblocks aufgefüllt. Jede Zeile muss einzeln umbrochen werden.

Dies ist, was ich auf der Grundlage der obigen Vorschläge kam:

$.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();
0
user3761817

Eine konzeptionell einfache Methode, die auch bei internen Markups und beliebigen Schriftarten und Stilen funktioniert, besteht darin, einen ersten Durchlauf durchzuführen, bei dem jedes Wort einfach in sein eigenes Element eingefügt wird (möglicherweise 'SPAN' oder ein benutzerdefinierter Name wie 'w').

Dann können Sie mit getBoundingClientRect () iterieren, um herauszufinden, wo sich die Eigenschaft 'top' ändert:

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;
    }
}

Es hört sich langsam an, aber wenn die Dokumente nicht wirklich groß sind, werden Sie es nicht bemerken.

0
TextGeek