Andrew Tibbetts
Andrew Tibbetts

Reputation: 3072

Get width of last line in a paragraph of text

Is it possible to somehow measure the length of the last line of text in a paragraph that has multiple breaks / returns?

          Morbi leo risus, porta ac consectetur ac, vestibulum at eros.
          Donec id elit non mi porta gravida at eget metus. Nulla vitae
          elit libero, a pharetra augue. Nullam id dolor id nibh
          ultricies vehicula ut id elit. Vivamus sagittis lacus vel
[here] ->|augue laoreet rutrum faucibus dolor auctor.|<- [to here]

Note: There are no manual breaks in the text. It is a single line of text wrapped inside, let's say, a <p></p> tag.

Upvotes: 15

Views: 3868

Answers (3)

user1467267
user1467267

Reputation:

Try this http://jsfiddle.net/Qb9WX/3/

HTML

<div id="demo">
    Morbi leo risus, porta ac consectetur ac, vestibulum at eros.
    Donec id elit non mi porta gravida at eget metus. Nulla vitae
    elit libero, a pharetra augue. Nullam id dolor id nibh
    ultricies vehicula ut id elit. Vivamus sagittis lacus vel
    augue laoreet rutrum faucibus dolor auctor.
</div>

JS

$(document).ready(function() {
    var content = $('#demo').html();
    content = content.replace(/(\w|\s)/g, '<span>$1</span>');
    $('#demo').html(content);

    // Check each <span> for its offsetTop
    var highest_top = 0;
    var tmp_top = 0;
    $('#demo span').each(function() {
        tmp_top = $(this)[0].offsetTop;
        if (tmp_top > highest_top) {
            highest_top = tmp_top;
        }
    });

    // Collect total width
    var total_width = 0;
    $('#demo span').each(function() {
        check_top = $(this)[0].offsetTop;
        if (check_top == highest_top) {
            total_width += $(this).width();
        }
    });

    console.log(total_width);
});

You can tweak it to your own needs.

For me it gives 88px in the fiddle:

enter image description here

You can buffer back the original (span-less) string into the element too after doing the calculations. This way you don't need to keep the cluttered elements.

A final note; if you use foreign characters (like the German ß or Russian/Japanese/etc.) the regex might fail to match on \w. You need to expand your knowledge on character-set matching then. But that goes beyond the scope of this question.

Small (delayed) update

You might want to change:

/(\w|\s)/g

to something like:

/([^\n\t])/g

This way you will match anything except tabs and newlines. I noticed the pixel count might be a bit off if you match only letters and spaces. It might miss important comma's and other read-signs.

Upvotes: 3

Nelson Menezes
Nelson Menezes

Reputation: 2094

It should be sufficient to append a zero-width element at the very end of the string and measure its left offset.

HTML

<p id="text">…text…</p>

JS

// NOTE: This assumes LTR text!
// Using JQuery for simpler code

var $el = $("#text");
var originalText = $el.html();

$el.html(originalText + "<span id='cursor'></span>");
alert($("#cursor").offset().left + "px");
$el.html(originalText);

JSFiddle: http://jsfiddle.net/Ca4fF/1/

Upvotes: 22

erik258
erik258

Reputation: 16302

Edit: this was written before the clarification that there are no line breaks in the paragraph. Sorry, not applicable.

If you trim whitespace at beginning and ending of the string (ie the paragraph), and then split around newlines and take the last element of the result, you should be close to getting what you want.

<div class='input'>
Morbi leo risus, porta ac consectetur ac, vestibulum at eros.
Donec id elit non mi porta gravida at eget metus. Nulla vitae
elit libero, a pharetra augue. Nullam id dolor id nibh
ultricies vehicula ut id elit. Vivamus sagittis lacus vel
augue laoreet rutrum faucibus dolor auctor.
</div>
<div class='result'>
</div>

and

$('div.result').html( "" )
$('div.input').each( function(){
    var lines = $(this).html(
       ).replace(/^\s+/, ''
       ).replace(/\s+$/,''
       ).split("\n")
    $('div.result').append("<p><kbd>" + 
       lines[lines.length-1].length + 
       "</kbd>: <i>"+lines[lines.length-1]+"</p>" 
    )       
})

http://jsfiddle.net/xbFAx/

Upvotes: 0

Related Questions