3

我有一个 eventHandler,每次将节点插入到 contenteditable div 时都会触发它。此 eventHandler 将新插入的替换div nodep node.

问题是在替换后放置光标。基本上光标没有正确放置,也就是说,光标在预期放置在新创建的 p 节点中时消失了。奇怪的是,内容可编辑 div 仍然具有焦点,并且转储window.selection对象显示正确设置的范围。

我可以解决此问题的唯一方法是使用 setTimeout 进行脏修复。


问:为什么使用 setTimeout 调用 placeCursor() 但不使用它时它会起作用?


相关代码:

JSFiddle

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

有关更多上下文,请参阅此帖子

4

1 回答 1

2

我不知道如何做一个很好的解释,但是是因为 DOM 持久化延迟。我有很多手机问题。所以当监听器回调被执行时,dom 还没有准备好。

所以它不起作用,因为您正在尝试管理选择。如果您设置了超时,该函数将在 4 毫秒后执行,因此有足够的时间 DOM 将您的更改与范围保持一致并进行您尝试做的更改。

实际上,浏览器不应该需要延迟函数的执行才能工作,理论上你的代码没有setTimeout.

只是为了你知道。在我的桌面浏览器中,它可以正常工作,但是,当我在上网本中运行它时,我需要使用 setTimout 才能工作。

于 2013-01-18T01:25:41.407 回答