Charles
Charles

Reputation: 4538

Get range of selected text, relative to element

I found this function from another StackOverflow post, which highlights text based on a specified start and end range, relative to a parent element. Unfortunately, however, I am not entirely sure how it works. This is the method:

function setSelectionRange(el, start, end) {
    if (document.createRange && window.getSelection) {
        var range = document.createRange();
        range.selectNodeContents(el);
        var textNodes = getTextNodesIn(el);
        var foundStart = false;
        var charCount = 0, endCharCount;

        for (var i = 0, textNode; textNode = textNodes[i++]; ) {
            endCharCount = charCount + textNode.length;
            if (!foundStart && start >= charCount && (start < endCharCount || (start == endCharCount && i < textNodes.length))) {
                range.setStart(textNode, start - charCount);
                foundStart = true;
            }
            if (foundStart && end <= endCharCount) {
                range.setEnd(textNode, end - charCount);
                break;
            }
            charCount = endCharCount;
        }

        var sel = window.getSelection();
        sel.removeAllRanges();
        sel.addRange(range);
    } else if (document.selection && document.body.createTextRange) {
        var textRange = document.body.createTextRange();
        textRange.moveToElementText(el);
        textRange.collapse(true);
        textRange.moveEnd("character", end);
        textRange.moveStart("character", start);
        textRange.select();
    }
}

Now I want to do the opposite. I want to get the selection range relative to an element, specifically the start and end values that getSelectionRange explicitly defined.

How would I write a "getSelectionRange" method relative to a parent element, using similar methods that are used in setSelectionRange, such that I could use both methods to get/set selection ranges?

Upvotes: 0

Views: 3165

Answers (2)

Tim Down
Tim Down

Reputation: 324727

The inverse process is simpler: given a range and a parent element, the process is

  1. Create a new range that encompasses the contents of the element
  2. Set the end of that range to the start boundary of the range you're measuring
  3. Get the length of the string returned by calling toString() on the measuring range. This is your start offset.
  4. Get the length of the string returned by calling toString() on the original range and add it to the start offset. This is your end offset.

See the saveSelection function here for an example.

Upvotes: 1

Julien Gr&#233;goire
Julien Gr&#233;goire

Reputation: 17144

The Selection object that you can retrieve using window.getSelection() already has a getRange method that'll give you the range object currently selected. This range object is the same used in the function you mention and contains all info regarding what is currently selected, meaning start nodes, end nodes, startOffset, endOffset and much more. See https://developer.mozilla.org/en-US/docs/Web/API/Range

And it's pretty much the inverse of what you have here meaning if you select content in a page, you can do this to get and set what you selected.

var current_range = window.getSelection().getRangeAt(0);
window.getSelection().removeAllRanges();
window.getSelection().addRange(current_range);

Upvotes: 0

Related Questions