首页 文章

在包含HTML内容的contentEditable区域中获取插入符号(光标)位置

提问于
浏览
54

我有contentEditable元素(可以是p,div,...),我想在其中得到插入符号(光标) . 我通常可以用这段代码实现它:

var position = window.getSelection().getRangeAt(0).startOffset;

这个工作正常,而元素只包含文本 . 但是当元素包含一些HTML格式时,返回的位置相对于包含的HTML元素中的插入位置 .

我们假设contentEditable元素的内容是这样的:

AB<b>CD</b>EF

如果插入符号在 <b></b> 内,请's say between C and D, the returned position with above code is 1 instead of 3 (counted from the begining of the contentEditable element'的内容)

任何人都可以提出解决方案吗?

3 回答

  • 5

    如果你想插入元素,那么你可以尝试这样做:

    // Get range
    var range = document.caretRangeFromPoint(event.clientX, event.clientY);
    if (range)
      range.insertNode(elementWhichYouWantToAddToContentEditable);
    
  • 51

    更新

    我写了一个更简单的版本,也适用于IE <9:

    https://stackoverflow.com/a/4812022/96100

    旧答案

    这实际上是一个比整个文档的文本中的字符偏移更有用的结果:DOM范围的 startOffset 属性(这是 window.getSelection().getRangeAt() 返回的)是相对于其 startContainer 属性的偏移量(这不是't necessarily always a text node, by the way). However, if you really want a character offset, here' sa将执行的操作它 .

    这是一个实例:http://jsfiddle.net/timdown/2YcaX/

    这是功能:

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

    这是一篇非常古老的帖子,但仍然是在Google上搜索的第一个结果之一,所以可能仍然有用 . 考虑到html标签和换行符(在Firefox上测试),这对我来说也是合适的位置:

    function getCaretPosition (node) {
        var range = window.getSelection().getRangeAt(0),
            preCaretRange = range.cloneRange(),
            caretPosition,
            tmp = document.createElement("div");
    
        preCaretRange.selectNodeContents(node);
        preCaretRange.setEnd(range.endContainer, range.endOffset);
        tmp.appendChild(preCaretRange.cloneContents());
        caretPosition = tmp.innerHTML.length;
        return caretPosition;
    }
    

    它使用cloneContents功能来获取实际的html并将documentfragment附加到临时div以获得html长度 .

相关问题