如何获得可编辑内容中的插入符号位置并设置它? [英] How do you get and set the caret position in a contenteditable?

查看:46
本文介绍了如何获得可编辑内容中的插入符号位置并设置它?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

此问题有一些答案此处,但存在一些问题.

This question has some answers here but there's a few problems.

基本上我想执行以下操作:

Basically I want to do the following:

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

跨浏览器支持似乎使许多现有答案变得复杂,但是我只需要在现代chrome上使用它即可.它还需要使用html.理想情况下,它看起来应该像这样:

A lot of the existing answers seem to be complicated by cross-browser support but I only need it to work on modern chrome. It also needs to work with 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.

获取

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

必需的帮助

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

测试(只需调用此功能)

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

It loops through the text in a contenteditable, sets the caret index, then reads it. Console output is: (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();

这篇关于如何获得可编辑内容中的插入符号位置并设置它?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆