How to capture one line of text in a div

I looked around for similar SO posts related to this, but no one is dealing with what I'm looking for. Say I have text, I drop it into a div and add some arbitrary (possibly even dynamic) width to this div. Is there a way that I can then capture and manipulate individual lines of text in a programmaticaly div (say, for example, grab and then wrap each line of text in my own span tag or something like that that allows me to manipulate individual lines)?

I was able to accomplish this using a monospace font and basically first creating one spacing per line and simply assigning the same number of characters for each range (with a little extra code, so the words are not cropped, of course) but I would like to be able to do this with non-monospace fonts , which will cause a problem, of course, because the horizontal distance of characters varies for fonts that do not have a monopoly.

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 result of this largely depends on what you expect. Live here here . What I'm trying to find out:

  • Are newline characters that I can access automatically inserted when a line break?

  • Are there any other mechanisms or properties in the DOM that I can crack to manipulate a single line in a div?

  • Is there any other approach, which, however, I could not keep the appearance of the natural flow of non-monospaced text, being able to access the line by line? As I said above, I did this with a monospaced text, but my approach depended on the uniform horizontal distance of the monospaced text.

+7
source share
4 answers

The suggestions from the other answers made me curious, so I put them to the test, and here 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 a lot of comments, but feel free to ask if something is clear.

To see the code in action (including some fancy colors ;-)) take a look at my script: 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 the Chrome Inspector shows that there is a big difference in performance. The @orbs solution takes 754 ms and 17 MB, while my solution takes 136 ms and 14 MB.

Some tips, try limiting your DOM operations (I marked them in the fiddle). They slow down your code because the browser needs to display your page again. I do only 2 , and you are 3 + 2x number of words + 1x number of lines . This probably explains the big difference in speed. And the longer the text, the greater the difference.

Don't try to break @orb's solution, just trying to help and explain the differences ...

+5
source

I thought it would be a good idea to post a solution that I came up with for my own question, because it looks pretty elegant. I didn't have to wrap every word in the gap - I just used visibility: a hidden test range to see if the next word in the line would make the line run through the width of the container before actually adding the next word to the line. When I collected each row, I added them to the array. Then I just added each row to the container, iterating over the array. This is living here (at least for a while).

 /*global console, $, OO*/ /*jslint browser: true*/ (function (undefined) { "use strict"; $(window).on('load', function (event) { 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>').width('200px').text(str).appendTo('body'); wrapLines($container); }); function wrapLines($container) { var text = $container.text(), words = text.split(' '), lines = [], line = $('<span>'), tmp = $('<span>').css('visibility', 'hidden').appendTo('body'); $container.text(""); $.each(words, function (index, word) { if (tmp.text(line.text() + " " + word).width() < $container.width()) { line.text(line.text() + " " + word); } else { lines.push(line); line.remove(); line = $('<span>'); tmp.text(""); } }); tmp.remove(); for (var kittens = 0 ; kittens < lines.length; kittens++) { lines[kittens].appendTo($container); console.log(lines[kittens].width()); } } }()); 
+2
source

Not sure if I fully understand your question, but ... Can you get div height right? Divide this by the (height) CSS-height and you should have the number of lines of text.

You can then check the position of any given character / word by making an invisible div containing a portion of the source text and performing the above trick to find its line. Does it help?

0
source

Bob Monteverde provided a very nice piece of code for calculating the line width here . You can use this and start comparing the line width with the actual width of your div to find individual lines.

0
source

All Articles