What is Event Bubbling in JavaScript?
Introduction
Before we talk about event bubbling in JavaScript, let’s revise about what events and event handlers are. In short, events are dynamic responses that happen on a web page due to user or browser interactions such as clicking on a button, submitting a form, reloading a page etc. JavaScript provides us with event listeners such as addEventListener to handle such triggers and execute a set of useful tasks upon event trigger.
The syntax of addEventListener itself gives a hint of event bubbling and capturing.
Here, the third argument ‘useCapture’ is a boolean value, which determines the type of event propagation.
What is the Event Propagation?
We already know the fact that events are fired as a result of some activity performed by the user or the browser. Now, once the event is triggered, the way in which it traverses through the DOM tree elements to reach its target element is called event propagation.
It is of 2 types :
- Event bubbling
- Event capturing or trickling
Both of these types of event propagation can be best explained through nested HTML elements.
Event Bubbling in JavaScript
Event bubbling in JavaScript can be defined as the method by which an event which got triggered within a nested set of HTML elements gets captured by the innermost element and travels up the DOM tree hierarchy to its outermost element. Hence, as the event bubbles up through the various outer elements, the event listeners attached with them also get invoked in that same order.
For event bubbling, the syntax for writing addEventListener remains the same except that we have to set the value for useCapture to false.
For example, assume three nested div tags with ids tree, branch and leaf as shown below.
Now, let us provide some basic styling for the divs in order to be visible on the browser.
Now run the code in the browser and the following must be the result.
Next, in order to implement event bubbling, we can add three event listeners respectively for each div. The event listeners print a console message on their corresponding click event as shown below.
Now, try clicking on each div and observe the console.
- When the innermost leaf div is clicked, the order of console messages is : a. Leaf was clicked b. Branch was clicked c. Tree was clicked
- When the middle branch div is clicked, the order of console messages is: a. Branch was clicked b. Tree was clicked
- When the outermost tree div is clicked, the order of console messages is: a. Tree was clicked
By this behavior of DOM, we can understand the way in which the click event propagates or bubbles from the innermost leaf towards the outermost tree element.
Now, if we observe the way in which the event listeners are written, we can see that we haven’t mentioned the third argument in the addEventListener. Omitting the third argument by default will assume the browser to perform event bubbling. Hence, if we want to implement event bubbling, we can either omit the third argument or specify it as false. If we rewrite the same JavaScript code in the following way, it will yield the same result.
Event Capturing
This process is also called event trickling and is the exact opposite of event bubbling in which an event which got triggered within a nested set of HTML elements gets captured by the outermost element and travels down the DOM tree hierarchy to its innermost element. Hence, as the event trickles down through the various inner elements, the event listeners attached with them also get invoked in that same order. For event capturing, the third argument useCapture in the syntax of addEventListener should be set to true.
To illustrate event capturing, we will use the same example we chose above. The only change that we need to do is in the javaScript code where we need to add the third argument in each addEventListener as true.
Now, try clicking on each div and observe the console.
- When the innermost leaf div is clicked, the order of console messages is : a. Tree was clicked b. Branch was clicked c. Leaf was clicked
- When the middle branch div is clicked, the order of console messages is : a. Tree was clicked b. Branch was clicked
- When the outermost tree div is clicked, the order of console messages is : a. Tree was clicked
By this behavior of DOM, we can understand the way in which the click event propagates or trickles down from the outermost tree towards the innermost leaf element.
The above two examples were shown for better understanding purposes while ideally the event propagations must be talked w.r.t to the global window object.
- During event bubbling the order of event propagation starts from the target element and bubbles up through various outer elements via the body tag, html tag, document and ends up at the global window object.
- During event capturing the order of event propagation starts from the window object and trickles down via the document, html tag, body tag, inner elements and ends up at the innermost element.
The Event Target Phase
This is a phase which intrinsically happens in between event capturing and bubbling. It is the phase when the triggered event finally reaches the target element that caused the event to happen.
Hence, now the the event propagation can be explained the following way:
- Event capture phase : Event capturing starting from the window object directed towards the target element.
- Event target phase : Event reaching the target element.
- Event bubbling phase : Event bubbling up from the target element and directed towards the window object as its destination. The above mentioned steps can be pictorially represented as shown below.
Accessing Event Propagation Information
The event object provides us with a lot of information regarding the properties of the triggered event and the element which invoked it. The event listener can access these propagation information from this event object and can also manipulate the element. Some of the most commonly used properties are the following:
- e.target - gives us the value of the the event target
- e.currentTarget - the DOM element on which the event listener is registered on. This value will be the same as the ‘this’ keyword.
- e.eventPhase - returns an integer that describes the four event constructor constants (NONE (0), CAPTURING_PHASE (1), AT_TARGET (2), BUBBLING_PHASE (3))
Stopping Propagation
One of the main drawbacks of using event bubbling and capturing is sometimes due to lack of user control on the event firing, it may cause performance issues. Hence, we have a method to stop the vent propagation as we need. This is carried out by using the e.stopPropagation() method.
In the above code, we have added e.stopPropagation() on line 7. So, now when we click on the leaf div, the event bubbles up till the branch div and ends there. Hence, the following output will be shown on the console :
- “Leaf was clicked”
- “Branch was clicked”
If we had written the stop propagation event inside the event listener of the leaf element, the console would have only printed “Leaf was clicked” as the event propagation got stopped at the target element itself. Hence, neither event bubbling nor capturing would have happened.
Stopping Immediate Propagation
While event bubbling, assume for a single click event there are multiple (say three) event listeners registered for the same element. Next, assume for one of the event listeners (say second), we have written a stopPropagation method.
Now, the problem with the above scenario is that when the click event happens, all the three listeners get invoked even after specifying the stopPropagation method. Hence, we can use another method called stopImmediatePropagation() to immediately stop the propagation of the event and prevent the following events from invoking the same element again.
The output of the above code will result in the following messages in the console :
- First leaf was clicked
- Second leaf was clicked
As the stopImmediatePropagation is encountered, the control ends there by stopping the event propagation immediately.
Event Cancellation
Very often we face this situation where when we click on a link or submit a form, the browser reloads the page. Another example is when we click on a checkbox, the box gets checked. All these events are the default actions made by the browser at the end of event propagation. These events can be terminated at once using stopPropagation or stopImmediatePropagation as we saw earlier. But, there exists another method named e.preventDefault which entirely cancels the default behaviour of DOM.
For better understanding, consider a button wrapped inside a form tag. We can also add an alert message function on submitting the form as shown below.
Now, when we click on the ‘Submit’ button, the form submits and the message gets displayed as an alert on the screen.
Next, let’s add the JavaScript code to prevent this action as shown below.
Now when we try to click the button, the event associated with the form submission gets canceled and hence the alert message won’t get displayed like before.
Summary
- Events that occur as a result of user or browser action are handled by event listeners provided by the DOM API by JavaScript.
- The way in which these events travel up and down the DOM tree is called event propagation.
- Event bubbling is when the triggered event travels up the nested elements from the target element to the global window object.
- Event capturing is when the triggered event travels down the DOM tree from the window object till it reaches the target element.
- The third argument in the addEventListener is a boolean value by which we can control the event bubbling and capturing as per our wish. If it’s true, the event will be captured and if it’s false or omitted the event will be bubbled up.
- Event capturing phase is when the event reaches the target element of the event.
- The Event object provides us with various methods like event.target, event.currentTarget that gives us information regarding the type of event that just occurred.
- event.stopPropagation and event.stopImmediatePropagation are two methods used to terminate the propagation of an event.
- event.preventDefault is a method that enables us to cancel out default browser actions.