Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get caret (cursor) position in contentEditable area containing HTML content

I have contentEditable element (can be p, div, ...) and I would like to get caret (cursor) position in it. I can normally achieve it with this piece of code:

var position = window.getSelection().getRangeAt(0).startOffset; 

This works fine while the element contains just text. But when the element contains some HTML formatting, the returned position is relative to caret position within included HTML element.

Let's assume contents of contentEditable element is this:

AB<b>CD</b>EF 

If caret is inside <b></b>, let's say between C and D, the returned position with above code is 1 instead of 3 (counted from the begining of the contentEditable element's content)

Can anybody come up with solution to this ?

like image 590
Frodik Avatar asked Jan 22 '11 12:01

Frodik


People also ask

How do you get the caret position in an editable div?

To get contentEditable caret position with JavaScript, we change the selection to start from the beginning and then get the length of the full selected string. const cursorPosition = () => { const sel = document. getSelection(); sel.

How do I get the cursor position in HTML?

If you ever had a specific case where you had to retrieve the position of a caret (your cursor's position) inside an HTML input field, you can do so using the selectionStart property of an input's value.

What is a caret position?

In computing, caret navigation (or caret browsing) is a kind of keyboard navigation where a caret (also known as a 'text cursor', 'text insertion cursor', or 'text selection cursor') is used to navigate within a text document.

What is caret position in JavaScript?

Javascript - Caret Position The caret is where text goes when typing into a text block.


2 Answers

UPDATE

I've written a simpler version of this that also works in IE < 9:

https://stackoverflow.com/a/4812022/96100

Old Answer

This is actually a more useful result than a character offset within the text of the whole document: the startOffset property of a DOM Range (which is what window.getSelection().getRangeAt() returns) is an offset relative to its startContainer property (which isn't necessarily always a text node, by the way). However, if you really want a character offset, here's a function that will do it.

Here's a live example: http://jsfiddle.net/timdown/2YcaX/

Here's the function:

function getCharacterOffsetWithin(range, node) {     var treeWalker = document.createTreeWalker(         node,         NodeFilter.SHOW_TEXT,         function(node) {             var nodeRange = document.createRange();             nodeRange.selectNode(node);             return nodeRange.compareBoundaryPoints(Range.END_TO_END, range) < 1 ?                 NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_REJECT;         },         false     );      var charCount = 0;     while (treeWalker.nextNode()) {         charCount += treeWalker.currentNode.length;     }     if (range.startContainer.nodeType == 3) {         charCount += range.startOffset;     }     return charCount; } 
like image 123
Tim Down Avatar answered Sep 25 '22 17:09

Tim Down


This is a very old post, but still one of the first results searching on Google, so maybe still useful. This works for me to get right position considering html tags and newlines as well (tested on Firefox):

function getCaretPosition (node) {     var range = window.getSelection().getRangeAt(0),         preCaretRange = range.cloneRange(),         caretPosition,         tmp = document.createElement("div");      preCaretRange.selectNodeContents(node);     preCaretRange.setEnd(range.endContainer, range.endOffset);     tmp.appendChild(preCaretRange.cloneContents());     caretPosition = tmp.innerHTML.length;     return caretPosition; } 

It uses the cloneContents functionality in order to get the actual html and appends the documentfragment to a temporary div in order to get the html length.

like image 42
Andrea Avatar answered Sep 25 '22 17:09

Andrea