Event Buddling and Capturing
Overview
Capturing phase – the event goes down to the element.
Target phase – the event reached the target element.
Bubbling phase – the event bubbles up from the element.
Buddling
When an event happens on an element, it first runs the handlers on it, then on its parent, then all the way up on other ancestors.
<style>
body * {
margin: 10px;
border: 1px solid blue;
}
</style>
<form onclick="console.log('form')">FORM
<div onclick="console.log('div')">DIV
<p onclick="console.log('p')">P</p>
</div>
</form>
Output:
p div form
Targeting
The most deeply nested element that caused the event is called a target element, accessible as
event.target
.Note the differences from event.currentTarget:
event.target – is the “target” element that initiated the event, it doesn’t change through the bubbling process.
event.currentTarget – is the “current” element, the one that has a currently running handler on it.
In form.onclick handler:
event.currentTarget is the <form> element, because the handler runs on it.
event.target is the actual element inside the form that was clicked.
event.stopPropagation() stop event budding up to parent element
Capturing
To catch an event on the capturing phase, we need to set the handler
capture
option totrue
:
elem.addEventListener(..., {capture: true})
// or, just "true" is an alias to {capture: true}
elem.addEventListener(..., true)
Example
<style>
body * {
margin: 10px;
border: 1px solid blue;
}
</style>
<form>FORM
<div>DIV
<p>P</p>
</div>
</form>
<script>
for(let elem of document.querySelectorAll('*')) {
elem.addEventListener("click", e => console.log(`Capturing: ${elem.tagName}`), true);
elem.addEventListener("click", e => console.log(`Bubbling: ${elem.tagName}`));
}
</script>
// output:
Capturing: html
Capturing: form
Capturing: div
Capturing: p
Buddling: p
Buddling: div
Buddling: form
Buddling: html
Custom Event
const form = document.querySelector("form");
const textarea = document.querySelector("textarea");
// Create a new event, allow bubbling, and provide any data you want to pass to the "detail" property
const eventAwesome = new CustomEvent("awesome", {
bubbles: true,
detail: { text: () => textarea.value },
});
// The form element listens for the custom "awesome" event and then consoles the output of the passed text() method
form.addEventListener("awesome", (e) => console.log(e.detail.text()));
// As the user types, the textarea inside the form dispatches/triggers the event to fire, and uses itself as the starting point
textarea.addEventListener("input", (e) => e.target.dispatchEvent(eventAwesome));
Reference
Last updated
Was this helpful?