If you are into web dev, I am pretty much sure that you might come across the term Event Bubbling as well as Event Capturing.
Introduction
Event Bubbling
As the name suggests is an event that bubbles out. I assume you all are familiar with events in javascript. It replicates the same behavior as that bubbling Up. It starts at the bottom and then rises to the top. (basically every rapper story π).
Event Capturing
It is a little bit confusing like what are we capturing, so some people also like to call it Event Trickling to help them understand better. In Event Capturing/Trickling events are trickled down i.e from top to bottom
We will see how they function in the latter part of the blog.
History π§
THAT'S MY FAVOURITE !!
Back in old days Netscape advocate event capturing as the main fundamental of event propagation. At the same time, MicroSoft is the opposite of Netscape, they double down on event bubbling as it would make more sense for events to bubble up rather than trickling down.
So, World Wide Web Consortium (W3C) puts an end to this argument by allowing both to be accepted. It is up to us(developers) to use whichever we want.
Event Listener π
An event listener is basically a function that waits for an event to occur. That event can be anything like a mouse click event, submitting a form, pressing keys of a keyboard, etc.
<element>.addEventListener(<eventName>,
<callbackFunction>, {capture : boolean});
<element>
: The element to which an event listener is attached.<eventName>
: It can be 'click', 'key up', 'key down' etc. events.<callbackFunction>
: This function fires after the event happened.- {capture: boolean}: It tells whether the event will be in the capture phase or in the bubbling phase (optional)
Remember we were just discussing how W3C allows developers to use event bubbling and event capturing according to our free will. In order to achieve that we have the third parameter of addEventListener
that is {capture: boolean}. It accepts a boolean value. If we don't pass any value, it's by default set to false
and acts as in event bubbling mode. If we set it true
it will act as in event capturing mode
Event Bubbling π¦
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.
A click on the inner <p>
first runs on click:
- On that
<p>
. - Then on the outer
<div>
. - Then on the outer
<form>
. - And so on upwards till the document object.
Similarly, if we click on <div>
it will first run on click on <div>
then bubble onto the next parent element.
So if we click on <p>
, then weβll see 3 output in console.log
: p β div β form.
Event Capturing π₯
When an event happens on an element, it first runs the handlers on the topmost ancestor in the hierarchy, then onto its child then all the way down to other children. It basically trickled down from parent to child.
A click on the inner <p>
first runs on click:
- On that
<form>
. - Then on the inner
<div>
. - Then on the inner
<p>
. - And so on downwards till the last children.
Similarly, if we click on <div>
it will first run on click on <form>
then trickled down to the next child element.
So if we click on <p>
, then weβll see 3 output in console.log
: formβ div β p.
How to stop Event Bubbling and Event Capturing π
There are various scenarios where we wouldn't want either event bubbling or event capturing. So we need to stop these processes. Fortunately, our javascript which is more like doremon has a solution for this.
Event in javascript comes with a method known as event.stopPropagation();
The stopPropagation()
method of the Event
interface prevents the further propagation of the current event in the capturing and bubbling phases.
Let us understand this through code.
document.getElementById("form").addEventListener(
"click",
() => {
console.log("form clicked!!");
},
{ capture: false }
);
document.getElementById("div").addEventListener(
"click",
(event) => {
console.log("div clicked!!");
event.stopPropagation();
},
{ capture: false }
);
document.getElementById("p").addEventListener(
"click",
() => {
console.log("p clicked!!");
},
{ capture: false }
);
In the above code snippet, we can see that the event bubbling will happen as the capture value is false
.
In the code block given below we added event.stopPropagation();
. Now what will happen here is as soon as we clicked on <p>
It will execute the code of <p>
and print p in console.
.
After that, it will move up to its parent as it is bubbling. Then the div block code will be executed which in turn first print <div>
in console
then it will reach to event.stopPropagtion();
which will stop the execution of the event of bubbling and it would not move further to the <form>
element.
So if we click on <p>
, then weβll see 2 outputs in console.log
: pβ div.
document.getElementById("div").addEventListener(
"click",
(event) => {
console.log("div clicked!!");
event.stopPropagation();
},
{ capture: false }
);
`
Similarly, the same thing can be done with Event Capturing.
Note π
As WC3 allows us to use both Event Capturing & Event Bubbling, we can use both in the same program according to our requirements. This can be simply done by providing the value to the capture
parameter.
Remember, All capturing event handlers are run first, then all the bubbling event handlers.
document.getElementById("form").addEventListener(
"click",
() => {
console.log("form clicked!!");
},
{ capture: false }
);
document.getElementById("div").addEventListener(
"click",
(event) => {
console.log("div clicked!!");
event.stopPropagation();
},
{ capture: true }
);
document.getElementById("p").addEventListener(
"click",
() => {
console.log("p clicked!!");
},
{ capture: false }
);
Here instead of writing { capture: false }
, one can simply write thee boolean value true/false
and it will also work.
Links and Resources π
For more clarity, you can watch Event Bubbling, Capturing aka Trickling in Javascript
First of all thank you for reading. πHope you learned something. This is my attempt to pen down what I understand of the topic. Please let me know if there are any errors and also how can i improve. You can reach out to me on Twitter and LinkedIn