我有一个eventHandler,每当一个节点插入一个contenteditable div时就会被触发。此eventHandler将新插入的div node
替换为p node
。
问题是在更换后放置光标。基本上光标没有正确放置,也就是说,光标在预期放置在新创建的p节点中时消失。奇怪的是,内容可编辑div仍然具有焦点并且转储window.selection
对象显示正确设置的范围。
解决此问题的唯一方法是使用setTimeout进行脏修复。
问。为什么在使用setTimeout调用placeCursor()时却有效呢?
obj.addEventListener("DOMNodeInserted", onNodeInsert, false);
function onNodeInsert(e) {
var range = document.createRange(),
sel = window.getSelection(),
newNode = e.target,
tagName = newNode.tagName.toLowerCase(),
lnbrNode = document.createElement('br'),
pNode = document.createElement('p');
if (tagName === 'div' && newNode.getAttribute("id") === null) {
// First we remove the event listener so that it doesn't get triggered again
this.removeEventListener('DOMNodeInserted', onNodeInsert, false);
// Creates a p node and removes the div
newNode.parentNode.replaceChild(pNode, newNode);
pNode.appendChild(lnbrNode);
// Places the caret where it belongs
var placeCursor = function () {
range.setStart(pNode, 0);
sel.removeAllRanges();
sel.addRange(range);
}
//placeCursor(); // DOES NOT WORK (cursor disappears)
setTimeout(placeCursor,1); // WORKS
//We can restore the event listener now
this.addEventListener("DOMNodeInserted", onNodeInsert, false);
}
}
有关更多背景信息,请参阅this post
答案 0 :(得分:2)
我不知道如何做好解释,但是因为DOM持久性延迟。移动设备有很多问题。所以当执行监听器回调时,dom还没有准备好。
所以它不会起作用,因为你正在尝试管理一个选择。如果你设置超时,那么该函数将在4ms后执行,所以DOM有足够的时间来保持你的变化范围并进行你想要做的改变。
确实浏览器不需要推迟执行函数的工作,理论上你的代码在没有setTimeout
的情况下是正确的,但是在处理由触发的侦听器时你可以通过多种方式找到这个“bug” DOM改变。
只是你知道。在我的桌面浏览器中,它的工作方式应该如此,但是,当我在上网本中运行它时,我需要使用setTimout来工作。