boundingclientrect of range

by sangelee

HTML

<p id='test'>click the <a href='javascript:;'>sample words</a> here</p>
<pre id='result'></pre>
<p class='tips'>
    click the "sample" or "words" above,and the corresponding range will be lighlighted.The word "sample" not work properly.
</p>
<div id='client-rect'></div>

CSS

#result {
    border:1px dashed green;
}
.tips {
    color:brown;
}
#client-rect {
    position:absolute;
    background-color:rgba(255,0,0,0.5);
    pointer-events:none;
}

JavaScript

var getRangeAtPoint = function(elem, x, y) {
    if (elem.nodeType == elem.TEXT_NODE) {
        var range = elem.ownerDocument.createRange();
        range.selectNodeContents(elem);
        var currentPos = 0;
        var endPos = range.endOffset;
        while (currentPos + 1 < endPos) {
            range.setStart(elem, currentPos);
            range.setEnd(elem, currentPos + 1);
            var range_rect = range.getBoundingClientRect();
            if (range_rect.left <= x && range_rect.right >= x &&
                range_rect.top <= y && range_rect.bottom >= y) {
                range.expand("word");
                return range;
            }
            currentPos += 1;
        }
    } else {
        for (var i = 0; i < elem.childNodes.length; i++) {
            var range = elem.childNodes[i].ownerDocument.createRange();
            range.selectNodeContents(elem.childNodes[i]);
            var range_rect = range.getBoundingClientRect();
            if (range_rect.left <= x && range_rect.right >= x &&
                range_rect.top <= y && range_rect.bottom >= y) {
                range.detach();
                var computed_range = getRangeAtPoint(elem.childNodes[i], x, y);
                if(computed_range){
                    return computed_range;
                }
            } else {
                range.detach();
            }
        }
    }
    return (null);
};

document.querySelector('#test').addEventListener('mousedown',function(e){
    var page_x = e.pageX - document.body.scrollLeft;
    var page_y = e.pageY - document.body.scrollTop;
    var target_ele = e.target;
    var range = getRangeAtPoint(target_ele,page_x,page_y);
    var rect = range.getBoundingClientRect();
    document.querySelector('#result').innerText = JSON.stringify(rect,null,4);
    //highlight the range
    var clientRectDiv = document.querySelector('#client-rect');
    clientRectDiv.style.width = rect.width+'px';
    clientRectDiv.style.height = rect.height+'px';
   ...