How to get the start and end points of selection in text area?

19,037

Solution 1

Revised answer, 5 September 2010

To account for trailing line breaks is tricky in IE, and I haven't seen any solution that does this. It is possible, however. The following is a new version of what I previously posted here.

Note that the textarea must have focus for this function to work properly in IE. If in doubt, call the textarea's focus() method first.

function getInputSelection(el) {
    var start = 0, end = 0, normalizedValue, range,
        textInputRange, len, endRange;

    if (typeof el.selectionStart == "number" && typeof el.selectionEnd == "number") {
        start = el.selectionStart;
        end = el.selectionEnd;
    } else {
        range = document.selection.createRange();

        if (range && range.parentElement() == el) {
            len = el.value.length;
            normalizedValue = el.value.replace(/\r\n/g, "\n");

            // Create a working TextRange that lives only in the input
            textInputRange = el.createTextRange();
            textInputRange.moveToBookmark(range.getBookmark());

            // Check if the start and end of the selection are at the very end
            // of the input, since moveStart/moveEnd doesn't return what we want
            // in those cases
            endRange = el.createTextRange();
            endRange.collapse(false);

            if (textInputRange.compareEndPoints("StartToEnd", endRange) > -1) {
                start = end = len;
            } else {
                start = -textInputRange.moveStart("character", -len);
                start += normalizedValue.slice(0, start).split("\n").length - 1;

                if (textInputRange.compareEndPoints("EndToEnd", endRange) > -1) {
                    end = len;
                } else {
                    end = -textInputRange.moveEnd("character", -len);
                    end += normalizedValue.slice(0, end).split("\n").length - 1;
                }
            }
        }
    }

    return {
        start: start,
        end: end
    };
}

Solution 2

Use the Rangy api and all of your problems are gone gone gone gone...

Using it

Read the documentation, or just use the below.
Very simple,

var selection = rangy.getSelection(),  // Whole lot of information, supports
                                       // multi-selections too.
    start   = selection.anchorOffset,  // Start position
    end     = selection.focusOffset;   // End position

Hope this api helps you out because it is really helpful in handling cross-browser ranges.

Solution 3

I needed to do something very similar and came up with this:

function getSelection(target) {
    var s = {start: 0, end:0};
    if (typeof target.selectionStart == "number"
        && typeof target.selectionEnd == "number") {
        // Firefox (and others)
        s.start = target.selectionStart;
        s.end = target.selectionEnd;
    } else if (document.selection) {
        // IE
        var bookmark = document.selection.createRange().getBookmark();
        var sel = target.createTextRange();
        var bfr = sel.duplicate();
        sel.moveToBookmark(bookmark);
        bfr.setEndPoint("EndToStart", sel);
        s.start = bfr.text.length;
        s.end = s.start + sel.text.length;
    }
    return s;
}

Notes:

  • The sel range must be created by target rather than using the range returned by document.selection, otherwise bfr.setEndPoint will complain about an invalid argument. This "feature" (discovered in IE8) does not appear to be documented in the spec.
  • target must have input focus for this function to work.
  • Only tested with <textarea>, might work with <input> as well.
Share:
19,037

Related videos on Youtube

Nayana Adassuriya
Author by

Nayana Adassuriya

Updated on April 25, 2022

Comments

  • Nayana Adassuriya
    Nayana Adassuriya about 2 years

    I want to get the cursor start and end position of a selected range in a text-field or text-area.

    I tried lot of functions in various forums, but when the last character of the selection is a new line character JavaScript ignore it in IE6.

    How do I get the start and end points of the selection?

  • Nayana Adassuriya
    Nayana Adassuriya almost 14 years
    thank you very much Tim Down, i already tried this thread. but the problem is when the last character of the selection is a new line character JavaScript ignore it in IE. otherwise those functions working fine
  • Tim Down
    Tim Down almost 14 years
    Answer now completely rewritten.
  • Nayana Adassuriya
    Nayana Adassuriya almost 14 years
    thank you very much Tim Down, this method working fine. for simple cursor position. but if we select a text range for get the start position of the selected text. that selected text automatically deleting. so how can i correct this. any way this is a nice trick and u make a gr8 invention.
  • Tim Down
    Tim Down almost 14 years
    Yes, that's the same problem that I spotted. I've fixed it now.
  • Nayana Adassuriya
    Nayana Adassuriya almost 14 years
    Ohooo gr8 it is working fine!!! thank you very much Tim Down, and another help for me!!. i want to fine the end point of the selection as well in same function. How can i implement that requirment.
  • Tim Down
    Tim Down almost 14 years
    I've added a parameter to specify start or end position.
  • Grรกvuj Miklรณs Henrich
    Grรกvuj Miklรณs Henrich over 10 years
    How can I use this function?
  • newenglander
    newenglander almost 10 years
    Rangy is great, but it doesn't seem to work for text areas and text inputs. For that there's rangyinputs (a jQuery plugin): code.google.com/p/rangyinputs
  • Edward Newell
    Edward Newell about 9 years
    Hey, is there any way to use Rangy without installing node then npm then bower then Rangy? Can I just include a minified js file in my website?
  • Derek ๆœ•ๆœƒๅŠŸๅคซ
    Derek ๆœ•ๆœƒๅŠŸๅคซ about 9 years
    @EdwardNewell I believe you can. Try using the core file here and see if it works. IIRC this is how I used it before it was being moved to github. For additional features just apply the different modules.
  • Stefan Steiger
    Stefan Steiger about 6 years
    ๏ผ‹1: It's not the solution, but sel.moveToBookmark(bookmark); helped a LOT.