Consider
<javascript>
function onClick() {
console.log("onclick");
}
function onMouseDown() {
const child = document.querySelector("#child");
child.replaceWith(child.cloneNode(true));
console.log("onmousedown");
}
</javascript>
<body>
<div id="child" onclick="onClick()" onmousedown="onMouseDown()">click me</div>
</body>
The output onclick
does not appear in the browser console unless I comment out the statement child.replaceWith(child.cloneNode(true))
. I think that this is because the event target is replaced in the onmousedown
event handler, which is invoked before onclick
.
Is there a way to make this work? Basically I need to modify div
contents in my onmousedown
and onmouseup
handlers and receive a click
event as well.
3
Answers
As @boreddad420 pointed out, "when you clone the node and replace it,
you remove all of the event listeners for that node".
If you try to add the click handler back in (on the new node),
the onClick() function will still not be called, since the mouse activity
was destined for the node that you have replaced.
"Basically I need to modify div contents", so do just that, modify
the existing div, don’t replace it. What is it about the div that
you want to change? Perhaps we can help you out with that.
Use setTimeout to simulate onClick.
The click event will fire on the node that received both the mousedown and the mouseup events of a same gesture. At the time the mousedown event is fired, your clone didn’t exist it thus can’t have received it.
What you can do, is to replicate this behavior yourself, by adding a mouseup event on the document and checking if the next such event fired on your clone (or one of its descendants). In this case, you can fire a new synthetic click event based on the mouseup event so that all its properties are set.
One thing to note, for non-synthetic events (the "normal" ones), the click event would occur right after the mouseup event has finished bubbling. We don’t have a way to access this time precisely. So we have a few possibilities: