How to set the cursor position in an editable element?

Asked

Viewed 2,183 times

6

I have the following structure:

<pre id="editor" contenteditable="true">
“Always pass on what you have learned.” - Yoda

> {|}

--
X    
</pre>

I want when someone clicks on a button I put the cursor instead of {|}. That text {|} actually exists in my element, I can replace it with an html element if necessary.

How can I set the cursor position, so that when I start typing my text appears there at that position?

  • http://jsfiddle.net/Td3pV/

2 answers

5


You need to use the objects Range and Selection to obtain a selected range within the element:

// marca lugar para posicionar o cursor em `editor`
var marker = '{|}';

// cria intervalo
var range = document.createRange();
var index = editor.innerText ? editor.innerText.indexOf(marker) : editor.textContent.indexOf(marker);
range.setStart(editor.childNodes[0], index);
range.setEnd(editor.childNodes[0], index + marker.length);

// faz seleção
var selection = window.getSelection();
selection.addRange(range);

editor.focus();

Fiddle here.

  • 1

    Under Linux with Firefox 25.0, none of the solutions puts the cursor in the indicated position to start writing. You can indicate which browsers support this solution?

  • I changed the code to use textContent when innerText not available and focus on the editor. Works in Firefox 23 for Windows. But, as mentioned by @utluiz, you must adapt the code if the div contains other elements (adapting childNodes[0]).

  • ... also works on Firefox 26 for Windows.

2

As Jordan has already responded, with a good response by the way, it is possible to locate the text inside the editor.

However, use the childNodes[0] will not work if there are html tags inside the editor that enclose the cursor marker. See an example in this jsfiddle, whose HTML is:

<pre id="editor" contenteditable="true">
“Always pass on what you have learned.” - Yoda
<div>
> {|}
</div>

--
X    
</pre>

I prepared a version using an HTML tag with a id special that avoids this problem and still allows to position the cursor without needing a visual element.

The code went like this:

function setCursor(node, cursorElement) {
    var range = document.createRange();
    range.setStart(cursorElement, 0);
    range.collapse(true);
    if (window.getSelection) {
        var sel = window.getSelection();
        sel.removeAllRanges();
        sel.addRange(range);
        node.focus();
    } else if (document.selection && range.select) {
        range.select();
    }
}

var editor = document.querySelector("#editor");
var button = document.querySelector("button");

button.addEventListener("click", function(e) {
    setTimeout(function () {
        setCursor(editor, document.querySelector("#cur"));
    }, 200);
}, false);

The marker is a tag span, as in the stretch below:

<pre id="editor" contenteditable="true">
“Always pass on what you have learned.” - Yoda

> <span id="cur"/>

--
X    
</pre>

See the Jsfiddle.

  • Under Linux with Firefox 25.0, none of the solutions puts the cursor in the indicated position to start writing. You can indicate which browsers support this solution?

  • +1 Yes! If the div in question has other elements, childNodes[0] should be adapted.

  • @Zuul In firefox you need a node.focus(). I updated the answer. I had tested it on Chrome and IE 9. :(

  • @utluiz Hi! I am having problems related to this question, however I am afraid to create another one. See, I have the numeric position where the cursor should be, however within this editable div there are tags like <img> which are emojis and which should be considered characters as well. My code does not consider them character, see: https://jsfiddle.net/3uvn0mqv/

Browser other questions tagged

You are not signed in. Login or sign up in order to post.