简体   繁体   English

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

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

This question has some answers here but there's a few problems.这个问题在这里有一些答案但有一些问题。

Basically I want to do the following:基本上我想做以下事情:

  1. get caret position获得插入位置
  2. set innerHTML of the contenteditable (this resets the caret position)设置 contenteditable 的 innerHTML(这会重置插入符号位置)
  3. set the caret position to the value obtained in step 1.将插入符号位置设置为步骤 1 中获得的值。

A lot of the existing answers seem to be complicated by cross-browser support but I only need it to work on modern chrome.许多现有的答案似乎因跨浏览器支持而变得复杂,但我只需要它在现代 chrome 上工作。 It also needs to work with html.它还需要使用 html。 Ideally it would look exactly like this:理想情况下,它看起来完全像这样:

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

I've tried looking through the documentation but it's not straightforward and I think this question is due for a leaner answer anyways.我试过查看文档,但这并不简单,我认为这个问题无论如何都应该得到更简洁的答案。

This seems to work for me but I've only tested it for my use cases.这似乎对我有用,但我只针对我的用例进行了测试。

GET得到

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;
}

SET

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);
}

REQUIRED HELPER需要的帮手

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 (just call this function) TEST (只需调用此函数)

It loops through the text in a contenteditable, sets the caret index, then reads it.它遍历 contenteditable 中的文本,设置插入符号索引,然后读取它。 Console output is: (setIndex | getIndex)控制台输出是: (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);
}






FIDDLE小提琴

 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.

相关问题 如何在特定的contenteditable div上设置插入符/光标位置? - How do I set the caret/cursor position on a specific contenteditable div? Chrome扩展程序内容可编辑,可获取并设置插入符号 - Chrome Extension contenteditable get and set caret position 在contentEditable iframe中获取&设置插入位置(Firefox) - Get & set caret position in contentEditable iframe (Firefox) 获取内容Editable caret position - Get contentEditable caret position 如何在子节点的contenteditable中设置插入符位置? - How to set caret position in contenteditable with childs nodes? 如何在contentedable span中设置插入位置然后发送Keys? - How to set caret position in contenteditable span and then sendKeys? 在contenteditable div中设置插入符位置 - Set caret position in contenteditable div 将插入符号位置设置在contenteditable div中的特定位置 - Set caret position at a specific position in contenteditable div 如何在 contenteditable 元素(div)中设置插入符号(光标)position? - How to set the caret (cursor) position in a contenteditable element (div)? 如何在Firefox和旧版IE中的contenteditable div中设置插入符位置 - How to set the caret position in a contenteditable div in Firefox and old IE versions
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM