views:

2058

answers:

5

I'm wondering if there's a way to count lines inside a div for example. Say we have a div like so:

<div id="content">hello how are you?</div>

Depending on many factors, the div can have one, or two, or even four lines of text. Is there any way for the script to know?

In other words, are automatic breaks represented in DOM at all?

+3  A: 

If the div's size is dependent on the content (which I assume to be the case from your description) then you can retrieve the div's height using:

var divHeight = document.getElementById('content').offsetHeight;

And divide by the font line height:

document.getElementById('content').style.lineHeight;

Or to get the line height if it hasn't been explicitly set:

var element = document.getElementById('content');
document.defaultView.getComputedStyle(element, null).getPropertyValue("lineHeight");

You will also need to take into account padding and any inter-line spacing.

EDIT

Full self contained test, explicitly setting line-height:

<html>
<script>
function countLines() {
    var divHeight = document.getElementById('content').offsetHeight;
    var lineHeight = parseInt(document.getElementById('content').style.lineHeight);
    var lines = divHeight / lineHeight;
    alert("Lines: " + lines);
}
</script>
<body onload="countLines();">
<div id="content" style="width: 80px; line-height: 20px;">
hello how are you? hello how are you? hello how are you? hello how are you?
</div>
</body>
</html>
Pool
It's a good start except that the line-height may not always have been set. You should get that from computed style of the element.
Chetan Sastry
Ta, updated to include computed style
Pool
On second thoughts, the line-height need not always be numeric (or in pixels). So if your code relies on it and your CSS convention permits it, you should probably set a line height in pixels.
Chetan Sastry
Yes, none of it will work if the div doesn't resize according to the content - depends on OP's exact requirement.
Pool
@Chetan - setting text dimensions in pixels is generally considered a bad thing. http://www.astahost.com/Sizes-Webdesign-Em-Vs-Px-t8926.html
annakata
This may only work in simplest case (like my example). If there are spans inside, inline-block elements and so on, straightforward division by (parent) font-size is worthless.Still, it is better than nothing, thanks.
buti-oxa
A: 

No, not reliably. There are simply too many unknown variables

  1. What OS (different DPIs, font variations, etc...)?
  2. Do they have their font-size scaled up because they are practically blind?
  3. Heck, in webkit browsers, you can actually resize textboxes to your heart's desire.

The list goes on. Someday I hope there will be such a method of reliably accomplishing this with JavaScript, but until that day comes, your out of luck.

I hate these kinds of answers and I hope someone can prove me wrong.

KyleFarris
+1  A: 

You should be able to split('\n').length and get the line breaks.

update: this works on FF/Chrome but not IE.

<html>
<head>
<script src="jquery-1.3.2.min.js"></script>
<script>
    $(document).ready(function() {
        var arr = $("div").text().split('\n');
        for (var i = 0; i < arr.length; i++)
            $("div").after(i + '=' + arr[i] + '<br/>');
    });
</script>
</head>
<body>
<div>One
Two
Three</div>
</body>
</html>
Chad Grant
Try it and let us know how that goes. I'm dead serious, not being sarcastic. You can use this code in FireBug's console on this very page. var the_text = $('.welovestackoverflow p').text(); var numlines = the_text.split("\n").length; alert(numlines);
KyleFarris
Thanks for this surprize, I did not know it is possible, but this is not what I want. Jquery seems to count hard line breaks in the source, and I am interested in automatic line breaks in the result. In the case of your "One Two Three" div, the result should be 1, because browser put all text into one line.
buti-oxa
Then I misunderstood your question. You want to find the computed line-height then.
Chad Grant
A: 

I am convinced that it is impossible now. It was, though.

IE7’s implementation of getClientRects did exactly what I want. Open this page in IE8, try refreshing it varying window width, and see how number of lines in the first element changes accordingly. Here’s the key lines of the javascript from that page:

var rects = elementList[i].getClientRects();
var p = document.createElement('p');
p.appendChild(document.createTextNode('\'' + elementList[i].tagName + '\' element has ' + rects.length + ' line(s).'));

Unfortunately for me, Firefox always returns one client rectangle per element, and IE8 does the same now. (Martin Honnen’s page works today because IE renders it in IE compat view; press F12 in IE8 to play with different modes.)

This is sad. It looks like once again Firefox’s literal but worthless implementation of the spec won over Microsoft’s useful one. Or do I miss a situation where new getClientRects may help a developer?

buti-oxa
+1  A: 

One solution is to enclose every word in a span tag using script. Then if the Y dimension of a given span tag is less than that of it's immediate predecessor then a line break has occurred.

Bob Brunius
Clever! How do you do that? I guess you assume text only paragraph (as I have in the example). I did not have this limitation in mind, but it may be OK, provided the script does not crash when there is something else inside the paragraph.
buti-oxa
On second thought, this method fails if there are vertically aligned spans in the line. So, even text only paragraph may be counted wrongly.
buti-oxa