Reputation: 699
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
});
Upvotes: 4
Views: 7216
Reputation: 1075309
You 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 completed 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 compliant 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>
Upvotes: 5
Reputation: 871
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.
Upvotes: 0