Question

I am using jQuery and trying to find a cross browser way to get the pixel coordinates of the caret in <textarea>s and input boxes such that I can place an absolutely positioned div around this location.

Is there some jQuery plugin? Or JavaScript snippet to do just that?

Was it helpful?

Solution

I've looked for a textarea caret coordinates plugin for meteor-autocomplete, so I've evaluated all the 8 plugins on GitHub. The winner is, by far, textarea-caret-position from Component.

Features

  • pixel precision
  • no dependencies whatsoever
  • browser compatibility: Chrome, Safari, Firefox (despite two bugs it has), IE9+; may work but not tested in Opera, IE8 or older
  • supports any font family and size, as well as text-transforms
  • the text area can have arbitrary padding or borders
  • not confused by horizontal or vertical scrollbars in the textarea
  • supports hard returns, tabs (except on IE) and consecutive spaces in the text
  • correct position on lines longer than the columns in the text area
  • no "ghost" position in the empty space at the end of a line when wrapping long words

Here's a demo - http://jsfiddle.net/dandv/aFPA7/

enter image description here

How it works

A mirror <div> is created off-screen and styled exactly like the <textarea>. Then, the text of the textarea up to the caret is copied into the div and a <span> is inserted right after it. Then, the text content of the span is set to the remainder of the text in the textarea, in order to faithfully reproduce the wrapping in the faux div.

This is the only method guaranteed to handle all the edge cases pertaining to wrapping long lines. It's also used by GitHub to determine the position of its @ user dropdown.

OTHER TIPS

Note: this answer describes how to get the character co-ordinates of the text-cursor/caret. To find the pixel-co-ordinates, you'll need to extend this further.

The first thing to remember is that the cursor can be in three states

  • a regular insertion cursor at a specific position
  • a text selection that has a certain bounded area
  • not active: textarea does not have focus. Has not been used.

The IE model uses the Object document.selection, from this we can get a TextRange object which gives us access to the selection and thus the cursor position(s).

The FF model/Opera uses the handy variables [input].selectionStart and selectionEnd.

Both models represent a regular ative cursor as a zero-width selection, with the left bound being the cursor position.

If the input field does not have focus, you may find that neither is set. I have had good success with the following code to insert a piece of text at the current cursor location, also replacing the current selection, if present. Depending on the exact browser, YMMV.

function insertAtCursor(myField, myValue) {

/* selecion model - ie */
if (document.selection) {
  myField.focus();
  sel = document.selection.createRange();
  sel.text = myValue;
}

/* field.selectionstart/end  firefox */ 
else if (myField.selectionStart || myField.selectionStart == '0' ) {

  var startPos = myField.selectionStart;
  var endPos = myField.selectionEnd;
  myField.value = myField.value.substring(0, startPos)
    + myValue
    + myField.value.substring(endPos, myField.value.length);

  myField.selectionStart = startPos + myValue.length;
  myField.selectionEnd = startPos + myValue.length;
  myField.focus();
} 

// cursor not active/present
else {
  myField.value += myValue;
}

Bug Note: links are not being correctly marked up in the top para.

Selection object: http://msdn.microsoft.com/en-us/library/ms535869(VS.85).aspx
TextRange object: http://msdn.microsoft.com/en-us/library/ms535872(VS.85).aspx

I don't think it can be done in every browser. Someone has done it in IE6, but it does not work in FF or Opera (AFAIK). Maybe you can get it to work in all the browsers.

Here's a blog post from 2005.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top