Skip to content
Related Articles
Open in App
Not now

Related Articles

What is Event Bubbling and Capturing in JavaScript ?

Improve Article
Save Article
  • Last Updated : 11 Feb, 2022
Improve Article
Save Article

Events are a fundamental construct of the modern web. They are a special set of objects that allow for signaling that something has occurred within a website. By defining Event listeners, developers can run specific code as the events happen. This allows for implementing complex control logic on a web application.

Every time you press a key, click a button, or tap on your phone, the browser dispatches an Event. Even more, you can define your own Events and dispatch them at your will! This goes from simulating a user’s keystroke to a custom domain-specific event.

As you can imagine, understanding how Events work and behave is key to building robust, modern web applications; And a key concept to master as a skilled web developer.

Example 1: Let’s say we have the following HTML document. The document renders a single button nested within two different divs, attached to each element is an Event Handler, which will be called when a “click” event is detected.  Try running it, clicking on the button, and inspecting your Developer Tools Console.

HTML




<!DOCTYPE html>
<html lang="en">
 
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content=
        "width=device-width, initial-scale=1.0">
    <title>
        GeeksForGeeks: What is Event
        Bubbling and Capturing?
    </title>
</head>
 
<body>
    <div class="button-list"
        onclick="console.log('button-list')">
        <div class="button-container"
            onclick="console.log('container')">
            <button class="button"
                onclick="console.log('button')">
                Click me!
            </button>
        </div>
    </div>
</body>
 
</html>


Output: The output will be display on the console, in the following order.
 

Output for Example 1

So, what happened? You clicked on the button and yet three logs were printed in the console. There are a couple things going on, let’s work through them.

Creating an event

Whenever you interact with a DOM element, the browser creates a new DOM Event. In this case, when clicking on the button, the browser composes a specific DOM Event: the PointerEvent. Here are a few its properties.

{
  target: button.button,
  type: "click",
  x: 33,
  y: 9,
  ...
}

Note how the type property is set to “click”, stating that the event represents a mouse click (in contrast, for example, with a single press of a key on a keyboard).
 

Dispatching an event

After creating the Event object, the browser dispatches it. The event then traverses the DOM in what is called Event Propagation. There are three phases in the Event Propagation process.

Event propagation of the “click” event through the example DOM

  1. Capture phase: The event starts from the root of the DOM, and starts traversing down the tree until it finds the element that triggered the event. For each element it traverses, it checks if there’s an Event Listener with the capture flag set to true, attached to it. If not, it just ignores it. Note that in our example, the first log message we saw in the console was the button message. That’s because, by default, event listeners do not listen for events on the capture phase.
     
  2. Target phase: The event reaches the target element, and runs the event listener attached to it, if any. This phase got us the first message in the console in our example: “button
     
  3. Bubbling phase: Similar to the capturing phase, the event will traverse the DOM checking for Event Listeners, but this time it will start in the element that dispatched the event and finish on the DOM’s root (the html element). It is in this phase that we got the logs “container” and “button list” in our example, because they are the closest ancestors to the button in that order! Note that Event Listeners, by default, will be called in this phase.

  
 

Listening to events

 

There are a couple ways to listen to events passing through the DOM. In the article’s example, we used the “onclick Event Attribute. This method to listen to events is straightforward but not too versatile. The most versatile, spec-valid method is using the element’s Javascript method “addEventListener“. Here’s how it works.

 

To attach an Event Listener, call “addEventListener” on an element, with the following signature.

 

element.addEventListener(type, handler, useCapture);
  • type: This is the type of Event you want to listen to, as defined by its type property. As mentioned before, in the example document, the fired event has for type the value “click”.
  • handler: This is the reference to a javascript function that will run when the event passes through the DOM (in the correct phase)
  • useCapture: This is a boolean value that indicates in which Event Propagation phase, the Event Listener should trigger the Event handler. If set to true, the listener will call the handler in the Capture phase. Otherwise, it will be called in the default Bubbling phase.

 

Example 2: Let’s test this with another example. Update the example document with this code. Here, we removed the Event Attributes for the list and the container and attached two different Event Listeners to the document: One in the Capture phase, and one in the Bubbling phase. Now, open the document and click on the button.

 

HTML




<!DOCTYPE html>
<html lang="en">
 
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content=
        "width=device-width, initial-scale=1.0">
    <title>
        GeeksForGeeks: What is Event
        Bubbling and Capturing
    </title>
</head>
 
<body>
    <div class="button-list">
        <div class="button-container">
            <button class="button"
                onClick="console.log('button')">
                Click me!
            </button>
        </div>
    </div>
    <script>
        document.addEventListener("click", () =>
            console.log('Capture!'), true);
        document.addEventListener("click", () =>
            console.log('Bubbling!'), false);
    </script>
</body>
 
</html>


Output: The output will display on the console, in the following order.

Output for Example 2

As you can see, the events are handled in the expected order, as defined by the event propagation process.

Handling an event’s propagation through the DOM

There are a couple of Event methods that control the propagation of the event across the DOM tree.

Event propagation stopped by calling event.stopPropagation()

  • event.preventDefault(): Stops the default browser behavior for that event.
  • event.stopPropagation(): Stops the propagation of the event on the next elements (whether descendants in the Capture phase, or ancestors in the Bubbling phase)
  • event.stopImmediatePropagation(): Similar to “event.stopPropagation()”, but also stops the propagation on other listeners in the same element.

Conclusion

In this article we have learned what Events are, when they are fired by the browser, and how they propagate through the DOM to be handled by different Event Listeners. Now it’s time to learn more about Events and How to handle them.


My Personal Notes arrow_drop_up
Related Articles

Start Your Coding Journey Now!