Reputation: 18923
I have an eventHandler that is trigered every time a node is inserted in a contenteditable div. This eventHandler replaces a newly inserted div node
with a p node
.
The problem is placing the cursor after the replacement. Basically the cursor isn't placed properly, that is, the cursor disappears while it was expected to be placed in the new created p node. Strangely the content editable div still has focus and dumping the window.selection
object shows the range correctly set.
The only way I could workaround this issue was with a dirty fix using setTimeout.
Q. Why does it work when placeCursor() is called with setTimeout but not without it?
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);
}
}
for more context see this post
Upvotes: 3
Views: 208
Reputation: 2870
I don't know how to do a good explain, but is because the DOM persistence delay. I have lot of problems with mobile. So the dom isn't ready when the listener callback is executed.
So it wont work because you are trying to manage a selection. If you put a timeout, that function will be execute after 4ms, so it's enough time to DOM persist your changes with range and make the changes you are trying to do.
Indeed the browser should not need defer the executing of function to work, in theory your code is correct without the setTimeout
, but this "bug" you can find in many ways when working with listeners that are triggered by DOM changing.
Just to you know. In my desktop browser, it work like it should, but, when I ran it in my netbook, I need to use setTimout to work.
Upvotes: 2