使用link元素包装一些文本时的可疑错误

时间:2015-02-05 12:33:00

标签: javascript jquery html contenteditable

我试图弄清楚twitter如何使用contenteditable元素进行用户组和主题标签实现。当用户输入@#时,带有这些特殊字符的文字会包含一个链接。

在我的示例中,我可以使用链接包装文本,但是有一个我尚未解决的错误。当带有@的文本包含链接时,光标将移动到<div>的开头。

我不知道我错过了什么,所以我需要你的帮助!如果有人能解释我为什么会这样,那就会受到欢迎。

JSFiddle Link

1 个答案:

答案 0 :(得分:1)

欢迎来到contenteditable这个痛苦的世界!我发现这样的问题会随着解决方案变得越来越复杂而不断出现,尤其是如果您担心实现一致的跨浏览器行为。

我看到您在<div>中使用valueOfQuery上的值查询要插入的标记。由于您只是调用.html()并将其注入前一个标记,因此您的光标无法知道此处的位置。

您需要探索并熟悉Range API,在此示例中,我们在调用.html()之前保存当前选择,然后使用这两个函数恢复它 - { {1}}和saveSelection

restoreSelection

然后我们需要在var saveSelection, restoreSelection; if (window.getSelection && document.createRange) { saveSelection = function(containerEl) { var range = window.getSelection().getRangeAt(0); var preSelectionRange = range.cloneRange(); preSelectionRange.selectNodeContents(containerEl); preSelectionRange.setEnd(range.startContainer, range.startOffset); var start = preSelectionRange.toString().length; return { start: start, end: start + range.toString().length }; }; restoreSelection = function(containerEl, savedSel) { var charIndex = 0, range = document.createRange(); range.setStart(containerEl, 0); range.collapse(true); var nodeStack = [containerEl], node, foundStart = false, stop = false; while (!stop && (node = nodeStack.pop())) { if (node.nodeType == 3) { var nextCharIndex = charIndex + node.length; if (!foundStart && savedSel.start >= charIndex && savedSel.start <= nextCharIndex) { range.setStart(node, savedSel.start - charIndex); foundStart = true; } if (foundStart && savedSel.end >= charIndex && savedSel.end <= nextCharIndex) { range.setEnd(node, savedSel.end - charIndex); stop = true; } charIndex = nextCharIndex; } else { var i = node.childNodes.length; while (i--) { nodeStack.push(node.childNodes[i]); } } } var sel = window.getSelection(); sel.removeAllRanges(); sel.addRange(range); } } else if (document.selection) { saveSelection = function(containerEl) { var selectedTextRange = document.selection.createRange(); var preSelectionTextRange = document.body.createTextRange(); preSelectionTextRange.moveToElementText(containerEl); preSelectionTextRange.setEndPoint("EndToStart", selectedTextRange); var start = preSelectionTextRange.text.length; return { start: start, end: start + selectedTextRange.text.length } }; restoreSelection = function(containerEl, savedSel) { var textRange = document.body.createTextRange(); textRange.moveToElementText(containerEl); textRange.collapse(true); textRange.moveEnd("character", savedSel.end); textRange.moveStart("character", savedSel.start); textRange.select(); }; } 内修改我们当前的实现,如下所示

keyup

JSFiddle Link - 工作示例