Finding selection start and end position in a textarea, in Internet Explorer

Published June 29th, 2005

[UPDATED 1st July 2005 -- a better method!]

I’m sure I’m missing something obvious here — I’m sure this can’t be true. If you can put me out of my misery then please do so. In the meantime…

I want to get the start and end positions of selected text in a TEXTAREA element. I don’t mean I want to manipulate the contents of the selection — you can do that easily like this:

document.selection.createRange().text = 'Some new text';

I need to know where in a piece of text the selection begins and ends. It’s easy enough in Mozilla: element.selectionStart and element.selectionEnd do the trick.

In IE, you can get just about every other bit of information you could possibly want — the position and size of the selection in pixels, for example — but not the start and end points of the selection. Bonkers.

I tried a number of ideas, and ended up with (yet another) ugly but functional fix. It goes like this:

  • Use document.selection.createRange() to get the current selection
  • Create a duplicate of that range with textRange.duplicate()
  • Use range.moveToElementText() to select all text in the duplicate range
  • Now use textRange.setEndPoint() to move the end of the range to the same place as the original range (ie. the original end point of the selection)
  • Subtract the length of the original selection from the length of the new selection, to get the start point of the original selection
  • Add the length of the original selection to the newly-calculated start point, to get the end point

Phew! Way too complicated for what should be a simple operation, but it does work.

Here’s some code:

var element = document.getElementById( 'my_textarea' );
if( document.selection ){
	// The current selection
	var range = document.selection.createRange();
	// We'll use this as a 'dummy'
	var stored_range = range.duplicate();
	// Select all text
	stored_range.moveToElementText( element );
	// Now move 'dummy' end point to end point of original range
	stored_range.setEndPoint( 'EndToEnd', range );
	// Now we can calculate start and end points
	element.selectionStart = stored_range.text.length - range.text.length;
	element.selectionEnd = element.selectionStart + range.text.length;
}

Because this sets the selectionStart and selectionEnd properties for the element, you can use the same methods for getting/setting selection contents as you would for Mozilla.

I made extensive use of this Microsoft reference page to work all this stuff out.

Get a Trackback link

1 Trackbacks/Pingbacks

  1. Pingback: Modificando un textarea desde javascript « Penyaskito on August 28, 2007

34 Comments

  1. Rafi B. on August 4, 2005

    Thank you for posting this helpful tip.
    I’ve been trying to use it on the input type=”text” element,
    but with no success. Is this just for a textarea element?

    I’ve found a solution though:

    function getCaretPos(el) {
    if (typeof el.selectionStart != “undefined”)
    return el.selectionStart;
    else if (document.selection)
    return Math.abs(document.selection.createRange().moveStart(”character”, -1000000));
    }

  2. Ratty on August 25, 2005

    This code seems to stop keyboard navigation working. ie. pressing the arrows to move around the text box do nothing. is there a fix for this?

  3. Ratty on August 25, 2005

    Sorry, I was wrong. It was my fault for only testing it under Wine in Linux. Works perfectly in Windows. Thanks dude :)

  4. ike on September 6, 2005

    well, your solution doesn`t work if i apply it to a body of a html… it goes close but….not close enough! the region seems shifted by a few characters. if the body does not have tags it works wonderfully but i need a solution for full html documents. any ideas? i`ve tried to eliminate the tags from region.htmlText and count it like that but it still doesn`t work. i`m desperate.

  5. Sebastian Werner on September 29, 2005

    The length of the current selection you can get from:

    document.selection.createRange().text.length;

    Then you only need to detect where the start point is, to get the matching end.

    var yourrange = yourtextfield.createTextRange();
    yourrange.setEndPoint(”EndToStart”, document.selection.createRange());
    var yourselstart = yourrange.text.length;

    Just my two cents. But your solution is not so much different.

  6. Sébastien CRAMATTE on November 6, 2005

    I need to handle selection with IE on keyPress event ? have you got an idea or some code snippet ?

  7. Tobias on December 11, 2005

    The shown code only works for textareas but not for input fields of type ‘text’. Therefore, the line

    “stored_range.moveToElementText( element );”

    can be replaced by

    “stored_range.expand(’textedit’);”

    This works for me

  8. Abhishek Iyer on December 29, 2005

    Pity that there couldnt be a simpler soln. In the meantime , might i add that this shlould be handled in “onMouseDown” else you might loose the selection. Great work StickMan!

  9. suraj on April 21, 2006

    this guy is the fucking MAN! fucking LIFE SAVER…

    p.s. - these security codes are REALLY TOO difficult to read :S

  10. suraj on April 21, 2006

    after experimenting, this code seems to struggle in textareas…

    For the first line - it works fine to reposition the caret however, as you move further down the textarea it runs into problems and adds the caret to a silly position

  11. Stine on August 3, 2006

    Hi:) This seems to work for me:

    function js_countTextAreaChars(text) {
        var n = 0;
        for (var i = 0; i

  12. Stine on August 3, 2006

    Maybe it’s not possible to post more than a few lines? I’ll try again:

    function js_countTextAreaChars(text) {
        var n = 0;
        for (var i = 0; i

  13. Stine on August 3, 2006

    function js_countTextAreaChars(text) {
    var n = 0;
    for (var i = 0; i

  14. Stine on August 3, 2006

    Well, I give up;)

  15. Stine on August 3, 2006

    function js_countTextAreaChars(text) {
        var n = 0;
        for (var i = 0; i < text.length; i++) {
            if (text.charAt(i) != ‘\r’) {
                n++;
            }
        }
        return n;
    }

    function js_CursorPos(start, end) {
        this.start = start;
        this.end = end;
    }

    function js_getCursorPosition(textArea) {
        var start = 0;
        var end = 0;
        if (document.selection) { // IE…
            textArea.focus();
            var sel1 = document.selection.createRange();
            var sel2 = sel1.duplicate();
            sel2.moveToElementText(textArea);
            var selText = sel1.text;
            sel1.text = “01″;
            var index = sel2.text.indexOf(”01″);
            start = js_countTextAreaChars((index == -1) ? sel2.text : sel2.text.substring(0, index));
            end = js_countTextAreaChars(selText) + start;
            sel1.moveStart(’character’, -1);
            sel1.text = selText;
        } else if (textArea.selectionStart || (textArea.selectionStart == “0″)) { // Mozilla/Netscape…
            start = textArea.selectionStart;
            end = textArea.selectionEnd;
        }
        return new js_CursorPos(start, end);
    }

    function js_setCursorPosition(textArea, cursorPos) {
        if (document.selection) { // IE…
            var sel = textArea.createTextRange();
            sel.collapse(true);
            sel.moveStart(”character”, cursorPos.start);
            sel.moveEnd(”character”, cursorPos.end - cursorPos.start);
            sel.select();
        } else if (textArea.selectionStart || (textArea.selectionStart == “0″)) { // Mozilla/Netscape…
            textArea.selectionStart = cursorPos.start;
            textArea.selectionEnd = cursorPos.end;
        }
        textArea.focus();
    }

  16. Stine on August 3, 2006

    There it is;)

  17. Original Sin on November 23, 2006

    Very sweet piece of code. I changed the Element to be a div tag, and it worked like a treat when combined with Javascript that fetches your selection. Thanks!

  18. AmigoJack on November 28, 2006

    Stines code doesnt work for me. it inserts “0″ into the text where my caret is. plus: if somewhere within the text “01″ occurs before, it doesnt work as expected of course :(
    not to mention what will happen if the textarea isnt the only input on the document… *ARGH* the MSIE is really painful when it comes down on determining selection positions

  19. Jayakrishnan G on April 16, 2007

    What about licensing terms for using the above script.

    Is the permission, to use this code, under the terms of GNU LGPL (www.gnu.org/licenses/lgpl.html) ?

  20. roncli on May 3, 2007

    AmigoJack,

    - There’s a bug in Stine’s code. In the line — sel1.moveStart(’character’, -1); — the number “-1″ should be equal to zero minus the length of the dummy text. In the case of his code, the dummy text is “01″, so the number should be changed to “-2″.

    - You don’t have to use “01″ as your dummy text, just change it to something that user’s won’t be likely to use, like “|pos|”, as the pipes aren’t something users often type in. Of course, you’d now have to change the “-1″ in my above point to the length of that dummy text, which is a three letter word plus two pipes… that makes it “-5″.

  21. Tiny on May 4, 2007

    quicker than Stine’s countTextAreaChars() one can, for textarea text say:

    var iLen=text.length-text.split(’\r’).length-1;

    This will account for IE’s funny way of *sometimes* counting \r

    Also, instead of adding “01″ or “|pos|” try adding something truely obscure like

    String.fromCharCode(28)

    There is a character that your users will have a hard time typing! …And also, it works well for me. I’m not using Stine’s method, or even StickMan’s, but one like it. Since IE also insists on ignoring newlines that appear at the end of my text selections (anyone else experience that?) I’ve efforted to make sure there would be a non-newline at the end of my textarea, but also a character that would not confuse the user. I found decimal 28 (octal 34) to be good for that, then, I measure my positions from the end, because IE does count leading newlines.

    if (oTextarea.value.charCodeAt(oTextarea.value.length-1) < 14) {
    oTextarea.value=oTextarea.value.replace(/34/g,”)+String.fromCharCode(28);
    }
    var oRng = document.selection.createRange();
    var oRng2 = oRng.duplicate();
    oRng2.moveToElementText(oTextarea);
    oRng2.setEndPoint(’StartToEnd’, oRng);
    iEnd = oTextarea.value.length-oRng2.text.length;
    oRng2.setEndPoint(’StartToStart’, oRng);
    iStart = oTextarea.value.length-oRng2.text.length;

  22. Tiny on May 5, 2007

    by
    var iLen=text.length-text.split(’\r’).length-1;
    I of course meant
    var iLen=text.length-(text.split(’\r’).length-1);

  23. Tiny on May 5, 2007

    and the regex

    /34/g reads (let me try this again) /\34/g

  24. Tiny on May 5, 2007

    and trying one more time

    / \ 0 3 4 / g

    (take out the spaces)
    its too bad the comment preview doesn’t show us how special characters are handled.

  25. Lázaro on August 16, 2007

    Thanks for this solution. I spent many time in that Microsoft’s page, but I couldn’t find anything, unitl I “fall” here…thanks again.

  26. arash on December 9, 2007

    is there a solution to get cursor position coordinates in a input text html tag?
    i have tooltip which should be always above the cursor. and where ever cursor moves (by typing,arrowkeys or mouse) it must move.

  27. Vikrant Mohite on March 25, 2008

    I want to split(”\n”) my textarea at charAt(50). can you guys help me out for the same.

  28. Steve on May 6, 2008

    Nice article, but your code ist difficult to read. Thanks for peoples for useful information :)

  29. Stickman on May 6, 2008

    Thanks for the heads-up, Steve. Looks like the ‘code’ tag I’ve been using doesn’t really work properly any more, for some reason. I’ve fixed the formatting for this article, now I need to find any other articles that have similar problems.

  30. yohi on June 12, 2008

    dear Stine,

    your 15 th posting is very effective , but , when text area is having scroll box the code doesn’t focus on correct scroll position . plz give me a solution

    thanks
    yohi

  31. nayana adassuriya on July 25, 2008

    Thanks Stine, ur code is very use full, good work keep posting!!!!

  32. Andrew on September 18, 2008

    Thanks for this very useful function. I don’t know or even care how it works, but it works! Its ridiculous that ie doesn’t support selectionStart and selectionEnd properties.

  33. anon on October 1, 2008

    Solved elegantly at
    http://www.webdeveloper.com/forum/archive/index.php/t-74982.html

    m2pc
    08-24-2005, 01:48 PM

    var oSel = document.selection.createRange ();

    // Move selection start to 0 position
    oSel.moveStart (’character’, -oField.value.length);

    // The caret position is selection length
    iCaretPos = oSel.text.length;

  34. Mau on October 16, 2008

    Thank you so much for this trick. It works great for me.
    Chreers!

Leave a comment

Comment Policy: First time comments are moderated. Please be patient.

OpenID

Anonymous