views:

10718

answers:

7

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'

+2  A: 

See this question:

http://stackoverflow.com/questions/164147/character-offset-in-an-internet-explorer-textrange

and if you will have newlines, also the note about that here:

http://stackoverflow.com/questions/235411/is-there-an-internet-explorer-approved-substitute-for-selectionstart-and-select#235582

bobince
That linked answer doesn't entirely fix newlines in IE. I've written something that does: http://stackoverflow.com/questions/3053542/how-to-get-the-start-and-end-points-of-selection-in-text-area/3053640#3053640
Tim Down
+19  A: 

With Firefox, Safari (and other Gecko based browsers) you can easily use textarea.selectionStart, but for IE that doesn't works, 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.

CMS
@CMS that link appears to be broken
Sam Saffron
@Sam, fixed link thanks to archive.org ...
CMS
This doesn't distinguish between caret positions when the caret is placed on an empty line. See http://stackoverflow.com/questions/3053542/how-to-get-the-start-and-end-points-of-selection-in-text-area/3053640#3053640
Tim Down
thanks--lots of code samples for inputs but few that work for textareas!
joshs
+1  A: 

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.

bybor
A: 
textBox1.Text.Substring(0, textBox1.SelectionStart).Length

Hope the above line gives your answer.

Samir
A: 

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; 
}
mark
A: 

Updated 5 September 2010

Seeing as everyone seems to get directed here for this issue, I'm adding my answer to a similar question.

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 method, 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>:

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
    };
}
Tim Down