我需要在contenteditablediv中实现数字的突出显示(将来我会添加更复杂的规则)。问题是当我用JavaScript替换插入新内容时,DOM更改和contenteditablediv失去了焦点。我需要的是将div放在当前位置上,以使注意力集中在div上,这样用户就可以键入而不会出现任何问题,而我的功能只需突出显示数字即可。谷歌搜索我认为Rangy库是最好的解决方案。我有以下代码:
function formatText() { var savedSel = rangy.saveSelection(); el = document.getElementById('pad'); el.innerHTML = el.innerHTML.replace(/(<([^>]+)>)/ig,""); el.innerHTML = el.innerHTML.replace(/([0-9])/ig,"<font color='red'>$1</font>"); rangy.restoreSelection(savedSel); } <div contenteditable="true" id="pad" onkeyup="formatText();"></div>
问题是功能结束工作的重点重新回到div之后,但是插入符号始终指向div开始,我可以在任何地方键入,除了div开始。下面还有console.log类型,Rangywarning: Module SaveRestore: Marker element has been removed. Cannot restore selection. 请帮助我实现此功能。我对另一种解决方案开放,不仅是杂乱无章的图书馆。谢谢!
Rangywarning: Module SaveRestore: Marker element has been removed. Cannot restore selection.
这是jsfiddle,但无法正常工作(当我在div中键入数字时什么也没有发生),dunno也许是我(通过jsfiddle首次发布代码)或资源不支持contenteditable。UPD*我在stackoverflow上读到类似的问题,但是解决方案不适合我的情况:(
问题在于,Rangy的保存/恢复选择模块通过将不可见的标记元素插入到选择边界所在的DOM中来工作,然后您的代码会去除所有HTML标签,包括Rangy的标记元素(如错误消息所示)。您有两种选择:
innerHTML
更新
我已经为Rangy(上面的选项2)取消了基于字符索引的选择保存/恢复。这有点粗糙,但是可以解决这种情况。它通过遍历文本节点来工作。我可以以某种形式将其添加到Rangy中。(
码:
function saveSelection(containerEl) { var charIndex = 0, start = 0, end = 0, foundStart = false, stop = {}; var sel = rangy.getSelection(), range; function traverseTextNodes(node, range) { if (node.nodeType == 3) { if (!foundStart && node == range.startContainer) { start = charIndex + range.startOffset; foundStart = true; } if (foundStart && node == range.endContainer) { end = charIndex + range.endOffset; throw stop; } charIndex += node.length; } else { for (var i = 0, len = node.childNodes.length; i < len; ++i) { traverseTextNodes(node.childNodes[i], range); } } } if (sel.rangeCount) { try { traverseTextNodes(containerEl, sel.getRangeAt(0)); } catch (ex) { if (ex != stop) { throw ex; } } } return { start: start, end: end }; } function restoreSelection(containerEl, savedSel) { var charIndex = 0, range = rangy.createRange(), foundStart = false, stop = {}; range.collapseToPoint(containerEl, 0); function traverseTextNodes(node) { 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); throw stop; } charIndex = nextCharIndex; } else { for (var i = 0, len = node.childNodes.length; i < len; ++i) { traverseTextNodes(node.childNodes[i]); } } } try { traverseTextNodes(containerEl); } catch (ex) { if (ex == stop) { rangy.getSelection().setSingleRange(range); } else { throw ex; } } } function formatText() { var el = document.getElementById('pad'); var savedSel = saveSelection(el); el.innerHTML = el.innerHTML.replace(/(<([^>]+)>)/ig,""); el.innerHTML = el.innerHTML.replace(/([0-9])/ig,"<font color='red'>$1</font>"); // Restore the original selection restoreSelection(el, savedSel); }