14

I need to calculate the width and the height of the selected/highlighted text using JavaScript.

I am using the following code written by Tim Down, as the starting point,

function getSelectionCoords() {
    var sel = document.selection, range;
    var x = 0, y = 0;
    if (sel) {
        if (sel.type != "Control") {
            range = sel.createRange();
            range.collapse(true);
            x = range.boundingLeft;
            y = range.boundingTop;
        }
    } else if (window.getSelection) {
        sel = window.getSelection();
        if (sel.rangeCount) {
            range = sel.getRangeAt(0).cloneRange();
            if (range.getClientRects) {
                range.collapse(true);
                var rect = range.getClientRects()[0];
                x = rect.left;
                y = rect.top;
            }
        }
    }
    return { x: x, y: y };
}

The left & the top co-ordinates are being displayed correctly. To calculate the width & the height, I need the right & the bottom positions as well.

So I added few lines of code to find the bottom & the right positions (Code available here - http://jsfiddle.net/pankajparashar/kv2Bp/). But to my surprise, the code displays the left & the right co-ordinates always the same, even though there is visible difference between them (tested only in firefox).

There is no problem with the top & the bottom positions, as they are working perfectly, which will help me calculate the height. But to calculate the width, I would still need the correct right co-ordinate.

Can anybody point any flaws with the code? or any alternate approach, using which I can calculate the width & the height of the selected text?

2 Answers 2

18

Here's some code to get the dimensions of the selection's bounding rectangle. It's pretty similar to the original code.

Demo: http://jsfiddle.net/UFkjy/

function getSelectionDimensions() {
    var sel = document.selection, range;
    var width = 0, height = 0;
    if (sel) {
        if (sel.type != "Control") {
            range = sel.createRange();
            width = range.boundingWidth;
            height = range.boundingHeight;
        }
    } else if (window.getSelection) {
        sel = window.getSelection();
        if (sel.rangeCount) {
            range = sel.getRangeAt(0).cloneRange();
            if (range.getBoundingClientRect) {
                var rect = range.getBoundingClientRect();
                width = rect.right - rect.left;
                height = rect.bottom - rect.top;
            }
        }
    }
    return { width: width , height: height };
}
Sign up to request clarification or add additional context in comments.

7 Comments

Excellent! Exactly, what i was looking for! Also works in Internet Explorer as well.
I realize this is an older thread - but looking at the Fiddle, the height number is inaccurate when crossing <p> elements. If all the text is within a single <p> element it's accurate, but not when crossing <p> elements.
@Wes: You're right, in Chrome, at least. Firefox is OK, Safari 7.1 is OK. I suspect a browser bug in Chrome.
@TimDown it looks like you're correct. I've submitted a bug to the Google Chrome team. Hopefully they'll fix it, though probably not likely any time soon.
While not a beautiful solution and not supported everywhere, I've found that this can be addressed by checking navigator.userAgent to see if it's a Chrome browser, and then using getClientRecs() to calculate the correct height by multiplying the height of the first line by 1.55 * the number of rectangles (1.55 being the average difference between height on FireFox/Safari and Chrome). The results are extremely close and could work as a stop-gap measure until Google fixes this issue. I can post as a possible revision if you like. You can see it in action here jsfiddle.net/u4sge0k3
|
2

Try using range.getBoundingClientRect instead of range.getClientRects.

JSFiddle

2 Comments

Good. For some reason, it is not working in IE8, though it is working in firefox.
Fiddle results in 404

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.