I would like to run some code after event finish to bubble up the DOM for example
document.getElementById("myBtn").addEventListener("click", (event) => {
// run some code after event finish to bubble up
});
I would like to run some code after event finish to bubble up the DOM for example
document.getElementById("myBtn").addEventListener("click", (event) => {
// run some code after event finish to bubble up
});
Share
Improve this question
asked May 10, 2017 at 7:04
user1116377user1116377
6993 gold badges15 silver badges32 bronze badges
2 Answers
Reset to default 5You have at least two choices:
Queue an async task (
setTimeout
or a Promise resolution)Handle the event on
document
, but only if it passed through #myBtn en route to it; this isn't technically when it's fully pleted bubbling, just at the final stage of it
Note that some actions that must be in response to a user event (such as opening a window) may or may not work with #1.
Here's #1 using a Promise:
document.getElementById("myBtn").addEventListener("click", (event) => {
Promise.resolve().then(() => {
// Do the work here
});
});
The advantage to using a promise resolution is that on pliant browsers, the promise resolution will be run before any other queued events. (Promise resolutions are microtasks that run after the current task but before the next task.) So it'll run before any event handler callback for elements the event bubbles to. But that may not fit your definition of "after event finish bubble up the DOM." If not, use setTimeout
instead, because it queues a task (not a microtask):
Here's an example of both:
document.getElementById("promiseButton").addEventListener("click", (event) => {
console.log(`button click on #${event.currentTarget.id}`);
Promise.resolve().then(() => {
console.log("promise fulfillment");
});
});
document.getElementById("timeoutButton").addEventListener("click", (event) => {
console.log(`button click on #${event.currentTarget.id}`);
setTimeout(() => {
console.log("timer callback");
}, 0);
});
document.addEventListener("click", (event) => {
console.log("document click");
});
<input type="button" id="promiseButton" value="Using promise">
<input type="button" id="timeoutButton" value="Using setTimeout">
Here's #2:
document.addEventListener("click", (event) => {
const node = event.target.closest("#myBtn");
if (node) {
// Do the work here
}
});
Note that if the event is handled before it bubbles to the document and the handler uses stopPropagation
, you won't see the event (since that stops it bubbling to the document). Here's an example of both when it reaches the document and when it doesn't:
document.getElementById("workedButton").addEventListener("click", (event) => {
console.log(`button click on #${event.currentTarget.id}`);
});
document.getElementById("blockedButton").addEventListener("click", (event) => {
console.log(`button click on #${event.currentTarget.id}`);
});
document.getElementById("blocker").addEventListener("click", (event) => {
console.log("blocked");
event.stopPropagation();
});
document.addEventListener("click", (event) => {
const node = event.target.closest("#workedButton, #blockedButton");
if (node) {
console.log(`document click on #${node.id}`);
}
});
<input type="button" id="workedButton" value="Works">
<div id="blocker">
<input type="button" id="blockedButton" value="Blocked">
</div>
Then you should add an event listener to the document object, that is the last DOM "element" that recognizes an event, all of the events will have bubbled up to document.