4

I'm trying to add html to a content editable div at the specific cursor position. The insert works fine, however, the exception is raised when the cursor needs to be placed after the newly inserted html.

Here is my jQuery extension:

$.fn.extend({
insertTextAtCaret: function (content) {
    var contentLength = 0;
    if (content.indexOf("<") == 0) {
        $(content).each(function (i) {
            contentLength += $($(content)[i]).text().length;
        });
    }
    else
        contentLength = content.length;
    console.log(contentLength);
    var position = window.getSelection().getRangeAt(0).startOffset;
    var innerHtml = $(this).html();
    var pre = innerHtml.substring(0, position);
    var post = innerHtml.substring(position, innerHtml.length + (contentLength - 1));
    if (position == innerHtml.length && content == "\n")
        content += content;
    $(this).html(pre + content + post);
    var remove = $(this).find("a.remove-placeholder");
    if (remove)
        remove.click(function () {
            $(this).parent().remove();
        });
    var textNode = $(this)[0].firstChild;
    var range = document.createRange();
    range.setStart(textNode, position + contentLength);
    range.setEnd(textNode, position + contentLength);
    var sel = window.getSelection();
    sel.removeAllRanges();
    sel.addRange(range);

}

});

And here is my control:

var editableDiv = div.find("#command-expectedResult-" + uuid);
editableDiv.insertTextAtCaret("<span class=\"remove-placeholder-wrapper\" contenteditable=\"false\"><span>[PLACEHOLDER]</span><a class=\"remove-placeholder\">X</a></span>");

So the exception

Uncaught IndexSizeError: Failed to execute 'setStart' on 'Range': The offset 21 is larger than or equal to the node's length (7). gets raised on range.setStart.

I think it has to do with the fact that after the html has been inserted at the cursor position, the length is now out of bounds when trying to set the range.

Any help on how to fix this please?

Auguste
  • 2,007
  • 2
  • 17
  • 25
Rudolf Lamprecht
  • 1,050
  • 1
  • 14
  • 37
  • It sounds like `textNode` isn't getting updated, which then means you're trying to place the cursor somewhere that doesn't exist. You'll need to figure out how to update the text node. Edit - looks like this has been solved before: http://stackoverflow.com/questions/2920150/insert-text-at-cursor-in-a-content-editable-div – dlsso Jun 22 '16 at 20:32
  • Possible duplicate of [Insert text at cursor in a content editable div](http://stackoverflow.com/questions/2920150/insert-text-at-cursor-in-a-content-editable-div) – dlsso Jun 22 '16 at 20:32
  • Long time after, I'm having same problem in 2022. And I just realized that, when div contains only text, then passing `node.childNodes[0]` will work, as it passes a TextNode as you did it. But once the div get a span tag for example inside, let's say `
    Hello World coders!
    `, the node is having 3 childNodes `[text, span, text]`. And by passing only `node.childNodes[0]`, you only passing TextNode with value `Hello `, 6 characters only, which is outside of range when you expect to deal with span node `World` and text node ` coders!`. Don't know how to collapse them yet.
    – KeitelDOG Jun 14 '22 at 19:00
  • I finally found the solution for it, it's even documented on the official mozilla docs. I may post an answer at a later time since it's an old question probably solved. If it's active and anyone is interested, tell me so I can make it sooner. The hint is: `If the startNode is a Node of type Text ..., then startOffset is the number of characters from the start of startNode. For other Node types, startOffset is the number of child nodes between the start of the startNode.` – KeitelDOG Jun 14 '22 at 19:44

0 Answers0