21

SEE BEFORE MARKING DUPLICATE/DOWNVOTING

  1. The contenteditable div will not have child elements
  2. I do not want to set the position at the end of the div
  3. I do not want a cross-browser solution, only Chrome support required
  4. Only vanilla JS, no libraries.

I have seen many many solutions. Many by Tim Down, and others. But none does work. I have seen window.getSelection, .addRange etc. but don't see how they apply here.

Here's a jsfiddle.

(Tried) Code:

var node = document.querySelector("div");
node.focus();
var caret = 10; // insert caret after the 10th character say
var range = document.createRange();
range.setStart(node, caret);
range.setEnd(node, caret);
var sel = window.getSelection();
sel.removeAllRanges();
sel.addRange(range);
Gaurang Tandon
  • 6,504
  • 11
  • 47
  • 84
  • Sorry, why do you need the line: **SEE BEFORE MARKING DUPLICATE/DOWNVOTING**? – Tân Jul 27 '16 at 09:25
  • 3
    @HappyCoding There have already been plenty of questions on Stackoverflow regarding setting the cursor position in a contenteditable div, however, my question is different. Thus, I wrote that line to warn a hasty downvoter. – Gaurang Tandon Jul 27 '16 at 10:49

1 Answers1

44

You need to position the caret within the text node inside your element, not the element itself. Assuming your HTML looks something like <div contenteditable="true">Some text</div>, using the firstChild property of the element will get the text node.

Updated jsFiddle:

http://jsfiddle.net/xgz6L/8/

Code:

var node = document.querySelector("div");
node.focus();
var textNode = node.firstChild;
var caret = 10; // insert caret after the 10th character say
var range = document.createRange();
range.setStart(textNode, caret);
range.setEnd(textNode, caret);
var sel = window.getSelection();
sel.removeAllRanges();
sel.addRange(range);
Tim Down
  • 318,141
  • 75
  • 454
  • 536
  • Ok, so the `textarea`s and contenteditable div's have a text node child, right? And is there a specific reason why contenteditable div's don't have `selectionStart` and `selectionEnd` properties? Thanks! – Gaurang Tandon Jun 09 '14 at 13:42
  • A `contenteditable` element can contain arbitrary HTML, including elements such as `
    ` and block elements that imply but don't contain white space characters. There is also CSS, which can also hide DOM content or even add visible text that isn't represented in the DOM. Character-based offsets are therefore complicated in contenteditable. They're also imprecise: the same point within the visible text of an element could correspond to several different points in the DOM. DOM ranges are precise.
    – Tim Down Jun 09 '14 at 14:04
  • 1
    Could you please help me with just one more query? I am using the exact same code from [this fiddle](http://jsfiddle.net/cpatik/3QAeC/) of the function `getCaretPosition`. I have tried making the element argument both the original `div` and also its `.firstChild`. All the time I keep getting: "Uncaught IndexSizeError: Failed to execute 'getRangeAt' on 'Selection': 0 is not a valid index." I don't want to trouble you much but I have wasted >2 hours on this. Please help me. Big thanks! – Gaurang Tandon Jun 09 '14 at 15:23
  • No worries! Fixed thanks to: http://stackoverflow.com/questions/22935320/uncaught-indexsizeerror-failed-to-execute-getrangeat-on-selection-0-is-not – Gaurang Tandon Jun 09 '14 at 15:31
  • on enter div add
    in text itself..and after that this code wont work..any suggestion? @TimDown
    – Dhara Dec 24 '15 at 10:58
  • Can I expand it? The code was getting eror if the `
    ` has a child element at least (``).
    – Tân Jul 27 '16 at 09:29
  • This is the ONLY solution that worked for me for IE, good work – Scription Jun 17 '20 at 09:09