简体   繁体   English

如何获取包含HTML的contentEditable中的光标位置?

[英]How to get the cursor position in contentEditable containing HTML?

I need to get the cursor position in a contentEditable div. 我需要在contentEditable div中获取光标位置。 I get some helpful function from Get a range's start and end offset's relative to its parent container and https://stackoverflow.com/a/4770562/2008261 . 我从获取范围相对于其父容器https://stackoverflow.com/a/4770562/2008261 的开始和结束偏移量得到了一些有用的功能。

But these function do NOT help because I need the actual position in the HTML, Here is what I need. 但是这些功能没有帮助,因为我需要HTML中的实际位置,这就是我所需要的。

if I have: 如果我有:

<div id="diva" contenteditable="true">Insert <b>text here</b></div>

and I put the cursor just before the word "text" it returns 7 as it deals with the text. 然后将光标放在“文本”一词之前,它处理文本时返回7。 But I need it to return 10 as if it deals with the inner HTML of the contentEditabe div. 但是我需要它返回10,就像它处理contentEditabe div的内部HTML一样。

These are the function I mentioned before : 这些是我之前提到的功能:

function getCaretCharacterOffsetWithin(element) {
var caretOffset = 0;
if (typeof window.getSelection != "undefined") {
    var range = window.getSelection().getRangeAt(0);
    var preCaretRange = range.cloneRange();
    preCaretRange.selectNodeContents(element);
    preCaretRange.setEnd(range.endContainer, range.endOffset);
    caretOffset = preCaretRange.toString().length;
} else if (typeof document.selection != "undefined" && document.selection.type != "Control") {
    var textRange = document.selection.createRange();
    var preCaretTextRange = document.body.createTextRange();
    preCaretTextRange.moveToElementText(element);
    preCaretTextRange.setEndPoint("EndToEnd", textRange);
    caretOffset = preCaretTextRange.text.length;
}
return caretOffset;
}

And : 和:

function getCharacterOffsetWithin(range, node) {
var treeWalker = document.createTreeWalker(
    node,
    NodeFilter.SHOW_TEXT,
    function(node) {
        var nodeRange = document.createRange();
        nodeRange.selectNode(node);
        return nodeRange.compareBoundaryPoints(Range.END_TO_END, range) < 1 ?
            NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_REJECT;
    },
    false
);

var charCount = 0;
while (treeWalker.nextNode()) {
    charCount += treeWalker.currentNode.length;
}
if (range.startContainer.nodeType == 3) {
    charCount += range.startOffset;
}
return charCount;
}

Having had to tackle this before ( I created an web based word processor ): the only viable solution is to walk up the DOM tree and count both innerHTML and outerHTML lengths, and then use the offset within the range if there is one. 之前必须解决这个问题(我创建了一个基于Web的文字处理器):唯一可行的解​​决方案是遍历DOM树并计算innerHTML和externalHTML的长度,然后在范围内使用偏移量(如果有)。

I also highly discourage the use of contentEditable implementations, you'll spend far more time trying to fix what is wrong with them and trying to override their behaviors than you will coding the features you actually want. 我也非常不鼓励使用contentEditable实现,与编码所需的功能相比,您将花费更多的时间来解决它们的问题并覆盖其行为。

My implementation was a function that took a range offset and walked up until it hit the specified boundary parent. 我的实现是一个函数,该函数具有范围偏移量,并向上移动直到到达指定的边界父级。 Some things to keep in mind, previous siblings are easy to add, but wrapping parents are tricky with attributes etc. to account for in length. 需要记住的事情是,以前的兄弟姐妹很容易添加,但是包装父母的包裹时很难用属性等来说明长度。

My calculation was to take the whole length of a node "<div id="" class="" foo="bar">sometext</div>" , subtract the length of the innerHTML , subtract the length of the tagname , and subtract 3 to get the length of <div id="" class="" foo="bar"> 我的计算是取节点"<div id="" class="" foo="bar">sometext</div>"整个长度,减去innerHTML的长度,减去tagname的长度,然后subtract 3得到<div id="" class="" foo="bar">的长度

BUT unless YOU controlled the creation of that HTML, your count could still be wrong, as depending on browser multiple spaces in a row are returned as either 1 char or multiple chars when testing length. 但是,除非您控制该HTML的创建,否则您的计数仍然可能是错误的,因为在测试长度时,根据浏览器的不同,一行中的多个空格将以1个字符或多个字符的形式返回。

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

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