在有孩子的'contenteditable'div中设置Caret Position

Joh*_*984 6 javascript jquery html5

我有这样的HTML结构:

<div contenteditable="true">This is some plain, boring content.</div>
Run Code Online (Sandbox Code Playgroud)

我也有这个功能,允许我将插入位置设置到div中我想要的任何位置:

// Move caret to a specific point in a DOM element
function SetCaretPosition(object, pos)
{
    // Get key data
    var el = object.get(0); // Strip inner object from jQuery object
    var range = document.createRange();
    var sel = window.getSelection();

    // Set the range of the DOM element
    range.setStart(el.childNodes[0], pos);
    range.collapse(true);

    // Set the selection point
    sel.removeAllRanges();
    sel.addRange(range);
}
Run Code Online (Sandbox Code Playgroud)

这个代码完全正常,直到我开始向(span, b, i, u, strike, sup, sub)div 添加子标签,例如

<div contenteditable="true">
    This is some <span class="fancy">plain</span>, boring content.
</div>
Run Code Online (Sandbox Code Playgroud)

当这些子标签最终带有自己的子标签时,事情变得更加复杂

<div contenteditable="true">
    This is some <span class="fancy"><i>plain</i></span>, boring content.
</div>
Run Code Online (Sandbox Code Playgroud)

本质上,发生了什么,是setStart抛出IndexSizeError当我尝试SetCaretPosition比的子标签的起始较高的指数.setStart只有到达第一个子标记才有效.

我需要的是,SetCaretPosition函数处理未知数量的这些子标记(以及可能是未知数量的嵌套子标记),以便设置位置的工作方式与没有标记时相同.

所以对于这两个:

<div contenteditable="true">This is some plain, boring content.</div>
Run Code Online (Sandbox Code Playgroud)

还有这个:

<div contenteditable="true">
    This is <u>some</u> <span class="fancy"><i>plain</i></span>, boring content.
</div>
Run Code Online (Sandbox Code Playgroud)

SetCaretPosition(div, 20); 将插入符号放在"b"之前的"无聊"中.

我需要什么代码?非常感谢!

Sor*_*ome 10

所以,我遇到了同样的问题,并决定快速编写自己的例程,它递归遍历所有子节点并设置位置.注意这是如何将DOM节点作为参数,而不是原始帖子所做的jquery对象

// Move caret to a specific point in a DOM element
function SetCaretPosition(el, pos){

    // Loop through all child nodes
    for(var node of el.childNodes){
        if(node.nodeType == 3){ // we have a text node
            if(node.length >= pos){
                // finally add our range
                var range = document.createRange(),
                    sel = window.getSelection();
                range.setStart(node,pos);
                range.collapse(true);
                sel.removeAllRanges();
                sel.addRange(range);
                return -1; // we are done
            }else{
                pos -= node.length;
            }
        }else{
            pos = SetCaretPosition(node,pos);
            if(pos == -1){
                return -1; // no need to finish the for loop
            }
        }
    }
    return pos; // needed because of recursion stuff
}
Run Code Online (Sandbox Code Playgroud)

我希望这对你有所帮助!