【问题标题】:How to get the cursor position in contentEditable containing HTML?如何在包含 HTML 的 contentEditable 中获取光标位置?
【发布时间】:2013-02-08 20:22:12
【问题描述】:

我需要在 contentEditable div 中获取光标位置。我从Get a range's start and end offset's relative to its parent containerhttps://stackoverflow.com/a/4770562/2008261 获得了一些有用的功能。

但是这些函数没有帮助,因为我需要 HTML 中的实际位置,这就是我需要的。

如果我有:

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

我将光标放在“文本”一词之前,它在处理文本时返回 7。但我需要它返回 10,就好像它处理 contentEditabe div 的内部 HTML。

这些是我之前提到的功能:

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

还有:

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

【问题讨论】:

  • 您是否尝试过使用像rangy 这样的跨浏览器库?
  • @VladMagdalin ,朗吉很棒。它比我需要的要多

标签: javascript contenteditable cursor-position


【解决方案1】:

之前必须解决这个问题(我创建了一个基于 Web 的文字处理器):唯一可行的解​​决方案是遍历 DOM 树并计算 innerHTML 和 outerHTML 的长度,然后使用范围内的偏移量(如果有的话) .

我也强烈反对使用 contentEditable 实现,你将花费更多的时间来尝试修复它们的问题并尝试覆盖它们的行为,而不是编写你真正想要的功能。

我的实现是一个函数,它接受一个范围偏移并向上走,直到它到达指定的边界父级。有些事情要记住,以前的兄弟姐妹很容易添加,但是包装父母在属性等方面很棘手。

我的计算是取节点"&lt;div id="" class="" foo="bar"&gt;sometext&lt;/div&gt;"的全长,减去innerHTML的长度,减去tagname的长度,subtract 3得到&lt;div id="" class="" foo="bar"&gt;的长度

但除非您控制了该 HTML 的创建,否则您的计数仍然可能是错误的,因为根据浏览器,在测试长度时,一行中的多个空格会以 1 个字符或多个字符的形式返回。

【讨论】:

  • 如果我不使用 contentEditable 实现,我应该使用什么来代替。我无法实现 textarea 来满足我的需求。我同意你的观点,因为我编写了很多代码,所以它有很多问题并且非常混乱,但是其他解决方案是什么?
  • 为什么不能实现一个textarea?隐藏文本区域是比 iframe 或内容可编辑项更有用的技巧。
  • 实际上我正在使用它们,textarea 和 contentEditable。 contentEditable 是用户与之交互的内容,而 textarea 是隐藏的。当用户在 contentEditable 中写一些东西或设计一些东西时,它会反映在隐藏的文本区域中。因此,textarea 保留了 html 标记,然后 jQuery 代码在它们之间架起了一座桥梁。但我不能单独使用 textarea,因为它不支持以 HTML 格式显示文本。我认为您的文字处理器实现了相同的概念。不是吗?
  • 不,它没有,我的使用 javascript 通过使用 textarea 捕获键和粘贴事件来主动编辑实际的 html。
  • 对于您的实现,如果您正在遍历 DOM,为什么需要查看 innerHTMLouterHTML?由于浏览器可以生成许多潜在的 DOM 树的有效 HTML 表示,因此其中一个中的偏移量是没有意义的。
猜你喜欢
  • 2023-03-14
  • 2018-07-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-10-12
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多