×Welcome to Q&A for professional and enthusiast programmers — check out the FAQ!
up vote 45 down vote favorite
34
share [fb]

How do you get the cursor position in text area using JavaScript?

For example:
This is| a text

This should return 7.

How would you get it to return the strings surrounding the cursor/selection? eg:

'This is', '', ' a text'
If the word "is" is highlighted, then it would return 'This ', 'is', ' a text'

link|improve this question
feedback

7 Answers

up vote 50 down vote accepted

With Firefox, Safari (and other Gecko based browsers) you can easily use textarea.selectionStart, but for IE that doesn't work, so you will have to do something like this:

function getCaret(node) {
 
if (node.selectionStart) {
   
return node.selectionStart;
 
} else if (!document.selection) {
   
return 0;
 
}

 
var c = "\001",
      sel
= document.selection.createRange(),
      dul
= sel.duplicate(),
      len
= 0;

  dul
.moveToElementText(node);
  sel
.text = c;
  len
= dul.text.indexOf(c);
  sel
.moveStart('character',-1);
  sel
.text = "";
 
return len;
}

(complete code here)

I also recommend you to check the jQuery FieldSelection Plugin, it allows you to do that and much more...

Edit: I actually re-implemented the above code:

function getCaret(el) { 
 
if (el.selectionStart) {
   
return el.selectionStart;
 
} else if (document.selection) {
    el
.focus();

   
var r = document.selection.createRange();
   
if (r == null) {
     
return 0;
   
}

   
var re = el.createTextRange(),
        rc
= re.duplicate();
    re
.moveToBookmark(r.getBookmark());
    rc
.setEndPoint('EndToStart', re);

   
return rc.text.length;
 
}  
 
return 0;
}

Check an example here.

link|improve this answer
@CMS that link appears to be broken – Sam Saffron Sep 2 '09 at 6:11
@Sam, fixed link thanks to archive.org ... – CMS Sep 2 '09 at 6:23
1  
This doesn't distinguish between caret positions when the caret is placed on an empty line. See stackoverflow.com/questions/3053542/… – Tim Down Jul 12 '10 at 0:07
thanks--lots of code samples for inputs but few that work for textareas! – joshs Aug 8 '10 at 17:37
3  
For some reason this seems to be the most popular of the many copies of this question on Stack Overflow, which is unfortunate because the accepted answer is imperfect (despite @CMS's excellent track record). Please have a look at my answer, which deals with the empty lines problem. – Tim Down Nov 15 '10 at 16:05
feedback

Updated 5 September 2010

Seeing as everyone seems to get directed here for this issue, I'm adding my answer to a similar question, which contains the same code as this answer but with full background for those who are interested:

IE's document.selection.createRange doesn't include leading or trailing blank lines

To account for trailing line breaks is tricky in IE, and I haven't seen any solution that does this correctly, including any other answers to this question. It is possible, however, using the following function, which will return you the start and end of the selection (which are the same in the case of a caret) within a <textarea> or text <input>.

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
   
};
}
link|improve this answer
Great answer! Also, to nitpick: you should be declaring variables with var so as not to pollute the global namespace. – adurdin May 27 at 11:02
1  
@adurdin: Ah, you changed your comment :) All variables are declared with var, at the top. – Tim Down May 27 at 11:13
Excuse me but what does 'range && range.parentElement()' mean? – s.zakharov Aug 19 at 21:32
There is a problem if we want to get position of caret in IE (if selection is empty). In this case it returns 0 as start and string length as end (if we use true instead of range && range.parentElement() == el). – s.zakharov Aug 19 at 21:55
2  
@Misha: That's not the fault of the function: that's what is actually selected by the time the function executes. You can see it visually after dismissing the alert box. As I mentioned in my answer to your recent question, two possible workarounds are using the mousedown event or adding unselectable="on" to the <div> element. – Tim Down Aug 25 at 13:46
show 6 more comments
feedback

If you are using jQuery you can use jquery caret plugin

$('textarea').getSelection().start

http://plugins.jquery.com/plugin-tags/caret

@++

link|improve this answer
The plugin takes care of a lot of heavy lifting I didn't want to deal with. – metric152 Oct 25 at 20:20
feedback

Small addition to CMS answer. When in IE 7 this code returns -1 if the last character is space and the caret is after it. Checking return value does the trick in this case.

link|improve this answer
feedback

I modified the above function to account for carriage returns in IE. It's untested but I did something similar with it in my code so it should be workable.

function getCaret(el) {
 
if (el.selectionStart) {
   
return el.selectionStart;
 
} else if (document.selection) {
    el
.focus();

   
var r = document.selection.createRange();
   
if (r == null) {
     
return 0;
   
}

   
var re = el.createTextRange(),
    rc
= re.duplicate();
    re
.moveToBookmark(r.getBookmark());
    rc
.setEndPoint('EndToStart', re);

   
var add_newlines = 0;
   
for (var i=0; i<rc.text.length; i++) {
     
if (rc.text.substr(i, 2) == '\r\n') {
        add_newlines
+= 2;
        i
++;
     
}
   
}

   
return rc.text.length + add_newlines;
 
}  
 
return 0;
}
link|improve this answer
feedback
textBox1.Text.Substring(0, textBox1.SelectionStart).Length

Hope the above line gives your answer.

link|improve this answer
What language is this? – pimvdb Jul 3 at 21:25
feedback

Your Answer

 
or
required, but never shown

Not the answer you're looking for? Browse other questions tagged or ask your own question.