Event Bubbling and Capturing in JavaScript

How to Handle JavaScript Event Propagation Life Cycle

Dulanka Karunasena
Bits and Pieces

--

JavaScript event bubbling is there to capture and handle events propagated inside the DOM. But do you know, there are differences between event bubbling and capturing?

So, in this article, I will discuss all you need to know about the topic with relevant examples.

Understanding the Event Flow

Before jumping to bubbling and capturing, let’s find out how an event is propagated inside the DOM.

If we have several nested elements handling the same event, we get confused about which event handler will trigger first. This is where understanding the event order becomes necessary.

Usually, an event is propagated towards the target element starting from its parents, and then it will propagate back towards its parent element.

There are three phases in a JavaScript event,

  • Capture Phase: Event propagates starting from ancestors towards the parent of the target. Propagation starts from Window object.
  • Target Phase: The event reaches the target element or the element which started the event.
  • Bubble Phase: This is the reverse of capture. Event is propagated towards ancestors until Window object.

The following diagram will give you a further understanding of the event propagation life cycle.

DOM event flow

Since now you understand event flow inside DOM, let’s see how event capturing and bubbling come into the picture.

What is Event Capturing?

Event capturing is the scenario in which the events will propagate, starting from the wrapper elements down to the target element that initiated the event cycle.

If you had an event bound to browser’s Window, it would be the first to execute. So, in the following example, the order of event handling will be Window, Document, DIV 2, DIV 1, and finally, the button.

Event capturing sample

Here we can see that event capturing occurs only until the clicked element or the target. The event will not propagate to child elements.

We can use the useCapture argument of the addEventListener()method to register events for capturing phase.

target.addEventListener(type, listener, useCapture)

You can use the following snippet to test out the above example and get hands-on experience in event capturing.

What is Event Bubbling?

Event bubbling is pretty simple to understand if you know event capturing. It is the exact opposite of event capturing.

Event bubbling will start from a child element and propagate up the DOM tree until the topmost ancestor’s event is handled.

Omitting or setting the useCapture argument to ‘false’ inside addEventListener() will register events for bubbling. So, the default behavior of Event Listeners is to bubble events.

Event bubbling sample

In our examples, we used either event capturing or event bubbling for all events. But what if we want to handle events inside both phases?

Let’s take an example of handling the click events of Document and DIV 2 during the bubbling phase while others are handled during capturing.

Registering events for both phases

The click events attached to Window, DIV 1, and button will fire respectively during the capturing, while DIV 2 and Document listeners are fired in order during the bubbling phase.

I think now you have a good understanding of event flow, event bubbling, and event capturing. So, let’s see when we can use event bubbling and event capturing.

Usage of Event Capturing & Bubbling?

Usually, event propagation can be used whenever we need to execute a function globally. So, for example, we can register document-wide listeners, which will run if an event occurs inside the DOM.

Similarly, we can use bubbling and capturing to perform UI changes.

Suppose we have a table that allows users to select cells, and we need to indicate the selected cells to the user.

In this case, assigning event handlers to each cell will not be a good practice. It will ultimately result in code repetition.

As a solution, we can use a single event listener and make use of event bubbling and capturing to handle these events.

So, I have created a single event listener for table and it will be used to change the styles of the cells.

document.querySelector("table").addEventListener("click", (event) =>
{
if (event.target.nodeName == 'TD')
event.target.style.background = "rgb(230, 226, 40)";
}
);

Inside the event listener, I have used nodeName to match the clicked cell and if it matches, the cell color will be changed.

Preventing Event Propagation

Sometimes event bubbling and capturing can be annoying if it starts to fire events without our control.

This can also cause performance issues if you have a heavily nested element structure because every event will create a new Event Cycle.

When bubbling becomes annoying!

In the above scenario, when I click the ‘Delete’ button, the click event of the wrapper element is also triggered. This happens due to the event bubbling.

We can use the stopPropagation() method to avoid this behavior. It will stop events from propagating further up or down along the DOM tree.

document.querySelector(".card").addEventListener("click", () => {
$("#detailsModal").modal();
});
document.querySelector("button").addEventListener("click",(event)=>{
event.stopPropagation(); //stop bubbling
$("#deleteModal").modal();
});
After using stopPropagation()

Build applications differently

OSS Tools like Bit offer a new paradigm for building modern apps.

Instead of developing monolithic projects, you first build independent components. Then, you compose your components together to build as many applications as you like. This isn’t just a faster way to build, it’s also much more scalable and helps to standardize development.

It’s fun, give it a try →

An independently source-controlled and shared “card” component. On the right => its dependency graph, auto-generated by Bit.

Conclusion

JavaScript event bubbling and capturing can be used to handle events effectively inside web applications. Understanding the event flow and how capturing and bubbling works will help you optimize your application with correct event handling.

For example, if there are any unexpected event firings in your application, understanding event capturing and bubbling can save you time to investigate the issue.

So, I invite you to try out the above examples and share your experience in the comments section.

Thank you for Reading !!!

--

--