繁体   English   中英

如何在 contenteditable 中获取和设置插入符号位置?

[英]How do you get and set the caret position in a contenteditable?

这个问题在这里有一些答案但有一些问题。

基本上我想做以下事情:

  1. 获得插入位置
  2. 设置 contenteditable 的 innerHTML(这会重置插入符号位置)
  3. 将插入符号位置设置为步骤 1 中获得的值。

许多现有的答案似乎因跨浏览器支持而变得复杂,但我只需要它在现代 chrome 上工作。 它还需要使用 html。 理想情况下,它看起来完全像这样:

var index = getCaretPosition(contentEditableDiv);
onEdit(contentEditableDiv); // <-- callback function that manipulates the text and sets contentEditableDiv.innerHTML = theManipulatedText
setCaretPosition(contentEditableDiv, index);

我试过查看文档,但这并不简单,我认为这个问题无论如何都应该得到更简洁的答案。

这似乎对我有用,但我只针对我的用例进行了测试。

得到

function getCaretIndex(win, contentEditable) {
    var index = 0;
    var selection = win.getSelection();
    var textNodes = textNodesUnder(contentEditable);

    for(var i = 0; i < textNodes.length; i++) {
        var node = textNodes[i];
        var isSelectedNode = node === selection.focusNode;

        if(isSelectedNode) {
            index += selection.focusOffset;
            break;
        }
        else {
            index += node.textContent.length;
        }
    }

    return index;
}

function setCaretIndex(win, contentEditable, newCaretIndex) {
    var cumulativeIndex = 0;
    var relativeIndex = 0;
    var targetNode = null;

    var textNodes = textNodesUnder(contentEditable);

    for(var i = 0; i < textNodes.length; i++) {
        var node = textNodes[i];
        
        if(newCaretIndex <= cumulativeIndex + node.textContent.length) {
            targetNode = node;
            relativeIndex = newCaretIndex - cumulativeIndex;
            break;
        }

        cumulativeIndex += node.textContent.length;
    }

    var range = win.document.createRange();
    range.setStart(targetNode, relativeIndex);
    range.setEnd(targetNode, relativeIndex);
    range.collapse();

    var sel = win.getSelection();
    sel.removeAllRanges();
    sel.addRange(range);
}

需要的帮手

function textNodesUnder(node) { // https://stackoverflow.com/a/10730777/3245937
    var all = [];
    for (node=node.firstChild;node;node=node.nextSibling){
        if (node.nodeType==3) {
            all.push(node);
        }
        else {
            all = all.concat(textNodesUnder(node));
        }
    }
    return all;
}

TEST (只需调用此函数)

它遍历 contenteditable 中的文本,设置插入符号索引,然后读取它。 控制台输出是: (setIndex | getIndex)

function testContentEditable() {
    document.body.innerHTML = "<div contenteditable></div>"
    var ce = document.querySelector("[contenteditable]");
    ce.focus();
    ce.innerHTML = "HELLO <span data-foo='true' style='text-decoration: underline;'><span style='color:red;'>WORLD</span> MY</span> NAME IS BOB";
    
    var i = 0;
    var intv = setInterval(function() {
        if(i == ce.innerText.length) {
            clearInterval(intv);
        }

        setCaretIndex(window, ce, i);

        var currentIndex = getCaretIndex(window, ce);
        console.log(i + " | " + currentIndex);

        i++;
    }, 100);
}






小提琴

 function getCaretIndex(win, contentEditable) { var index = 0; var selection = win.getSelection(); var textNodes = textNodesUnder(contentEditable); for(var i = 0; i < textNodes.length; i++) { var node = textNodes[i]; var isSelectedNode = node === selection.focusNode; if(isSelectedNode) { index += selection.focusOffset; break; } else { index += node.textContent.length; } } return index; } function setCaretIndex(win, contentEditable, newCaretIndex) { var cumulativeIndex = 0; var relativeIndex = 0; var targetNode = null; var textNodes = textNodesUnder(contentEditable); for(var i = 0; i < textNodes.length; i++) { var node = textNodes[i]; if(newCaretIndex <= cumulativeIndex + node.textContent.length) { targetNode = node; relativeIndex = newCaretIndex - cumulativeIndex; break; } cumulativeIndex += node.textContent.length; } var range = win.document.createRange(); range.setStart(targetNode, relativeIndex); range.setEnd(targetNode, relativeIndex); range.collapse(); var sel = win.getSelection(); sel.removeAllRanges(); sel.addRange(range); } function textNodesUnder(node) { // https://stackoverflow.com/a/10730777/3245937 var all = []; for (node=node.firstChild;node;node=node.nextSibling){ if (node.nodeType==3) { all.push(node); } else { all = all.concat(textNodesUnder(node)); } } return all; } function testContentEditable() { document.body.innerHTML = "<div contenteditable></div>" var ce = document.querySelector("[contenteditable]"); ce.focus(); ce.innerHTML = "HELLO <span data-foo='true' style='text-decoration: underline;'><span style='color:red;'>WORLD</span> MY</span> NAME IS BOB"; var i = 0; var intv = setInterval(function() { if(i == ce.innerText.length) { clearInterval(intv); } setCaretIndex(window, ce, i); var currentIndex = getCaretIndex(window, ce); console.log(i + " | " + currentIndex); i++; }, 100); } testContentEditable();

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM