Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to capture one line of text in a div

I've looked around at similar SO posts related to this, but none deal with exactly what I am looking for. Say I have some text, I throw it in a div, and add some arbitrary (possibly even dynamic) width to that div. Is there any way that I can then capture and manipulate individual lines of text in the div programmaticaly (say, for example, capture and then wrap every line of text in its own span tag or something like this that will enable me to manipulate individual lines)?

I have been able to accomplish this using a monospace font and basically first creating one span per line and just assigning the same number of characters per span (with a little extra code so words don't get cut off of course), but I would like to be able to do this with non-monospaced fonts, which will cause an issue of course because horizontal spacing of characters varies for non-monopsaced fonts.

var str = "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.",
    container = $('<div>');
    container.width('100px').html(str).appendTo('body');

The output of this is pretty much what you expect. It is live here. What I seek to figure out:

  1. Are newline characters that I can access automatically inserted when the line breaks?

  2. Are there any other mechanisms or properties in the DOM I can hack into to manipulate one line in a div?

  3. Is there another approach I haven't though of to be able to retain the appearance of natural flow of non-monospaced text while being able to access text line-by-line? As I said above, I have accomplished this with monospaced text, but my approach was dependent on the uniform horizontal spacing of monospaced text.

like image 296
orb Avatar asked Apr 25 '13 19:04

orb


1 Answers

The suggestions from the other answers made me curious so i put them to the test, and this is what i came up with:

function wrapLines($container) {
    // get the text from the conatiner
    var text = $container.text();

    // split the text into words
    var words = text.split(' ');

   // wrap each word in a span and add it to a tmp
   var tmp = '';
   tmp += '<span>' + words.join('</span><span>') + '</span> ';

   // remove the text from the container, and replace it with the wrapped words
   $container.html($(tmp));

    // prepare the offset variable and tmp
    var tmp = '';
    var top = null;
    $container.find('span').each(function(index, word) {
        $word = $(word);
        // if this is the first iteration
        if (top == null) {
            // set the top
            top = $word.position().top;
            // open the first line
            tmp = '<span class="line">';
        }

        // if this is a new line (top is bigger then the previous word)
        if (top < $word.position().top) {
            // close the previous line and start a new one
            tmp += '</span><span class="line">';
            // change the top
            top = $word.position().top;            
        }

        // add the content of the word node + a space
        tmp += $word.text() + ' ';
    });
    // close the last line
    tmp += '</span>';

    // remove the content of the conatiner, and replace it with the wrapped lines
    $container.html($(tmp));    
}

I added plenty of comments, but feel free to ask if something isn't clear.

To see the code in action (including some fancy colors ;-) ), have a look at my fiddle: http://jsfiddle.net/yZnp8/1/

edit:
I put the code from @orb next to my solution here: http://jsfiddle.net/yZnp8/5/.

A quick comparison with Chrome Inspector shows that there is a big performance diiference. @orbs solution takes 754ms and 17MB while my solution takes 136ms and 14MB.

A little word of advice, try to limit your DOM operations (I marked them in the fiddle). They slow your code down, as the browser needs to render your page all over again. I do only 2, while you do 3 + 2x number of words + 1x number of lines. This is probably what explains the big difference in speed. And the longer the text, the bigger the difference will become.

Not trying to break @orb solution down, just trying to be helpful and explain the differences...

like image 187
Pevara Avatar answered Sep 21 '22 15:09

Pevara