Event bubbling and capturing in JavaScript.

Event bubbling and capturing are two ways of event propagation in the DOM tree.

In the bubbling, the event is "bubbled" up to the DOM tree. so from the targeted element to its parent elements and finally to the root.

image.png

Let's check with an example

<div id="ceo"> 
      CEO
      <div id="manager">
        manager
        <div id="developer">
          developer
        </div>
      </div>
    </div>

Here is the execution flow for bubbling. A click on Developer: Developer -> Manager -> CEO

A click on Manager: Manager -> CEO

A click on CEO: CEO

The process is called “bubbling” because events “bubble” from the inner element up through parents like a bubble in the water.

In the capturing the event starts from the root then go down the tree and stops at the target element. Event capturing is also called event trickling.

image.png

Let's check with an example

<div id="ceo"> 
      CEO
      <div id="manager">
        manager
        <div id="developer">
          developer
        </div>
      </div>
    </div>

Here is the execution flow for capturing. A click on Developer: CEO -> Manager -> Developer

A click on Manager: CEO -> Manager

A click on CEO: CEO

1 Event capturing

2 Event target

3 Event bubbling image.png

By default, event bubbling will execute if want to enable capturing then add true in addEventListener as the third argument.

addEventListener('click', () => {}, true);

To stop events from further execution we have to use the stopPropagation method. so execution will stop from that point

even.stopPropagation();
HTML
<div id="ceo"> 
      CEO
      <div id="manager">
        manager
        <div id="developer">
          developer
        </div>
      </div>
    </div>
JS
document.querySelector('#ceo").addEventListener('click', () => {
     console.log("CEO clicked")
});
document.querySelector("#manager").addEventListener('click', () => {
     console.log("Manager clicked")
});
document.querySelector('#developer").addEventListener('click', () => {
     console.log("Developer clicked")
});

Onclick of developer

output
Developer clicked
Manager clicked
CEO clicked

Onclick of manager

output
Developer clicked
Manager clicked
CEO clicked
JS
document.querySelector('#ceo").addEventListener('click', () => {
     console.log("CEO clicked")
}, true);
document.querySelector("#manager").addEventListener('click', () => {
     console.log("Manager clicked")
}, true);
document.querySelector('#developer").addEventListener('click', () => {
     console.log("Developer clicked")
}, true);

Onclick of developer

output
CEO clicked
Manager Clicked
Developer Clicked

Onclick of Manager

output
CEO clicked
Manager Clicked
JS
document.querySelector('#ceo").addEventListener('click', () => {
     console.log("CEO clicked")
}, true); 
document.querySelector("#manager").addEventListener('click', () => {
     console.log("Manager clicked")
}, false);
document.querySelector('#developer").addEventListener('click', () => {
     console.log("Developer clicked")
}, true);

onClick of developer

output
CEO clicked
Developer clicked
Manager clicked

Here as CEO and Developer execute because they are capturing and then bubbling starts to execute. (capturing -> target -> bubbling)

JS
document.querySelector('#ceo").addEventListener('click', () => {
     console.log("CEO clicked")
}, false); 
document.querySelector("#manager").addEventListener('click', (e) => {
     console.log("Manager clicked")
     e.stopPropagation();
}, false);
document.querySelector('#developer").addEventListener('click', () => {
     console.log("Developer clicked")
}, false);

onClick developer

output
Developer clicked
Manager clicked

Here due to stop propagation event will stop execution after the manager clicks.

JS
document.querySelector('#ceo").addEventListener('click', () => {
     console.log("CEO clicked")
     e.stopPropagation();
}, true); 
document.querySelector("#manager").addEventListener('click', (e) => {
     console.log("Manager clicked")

}, true);
document.querySelector('#developer").addEventListener('click', () => {
     console.log("Developer clicked")
}, true);

onClick developer

output
CEO clicked

as this is capturing it starts from ceo but due to stop propagation will stop further execution.

Read more: developer.mozilla.org/en-US/docs/Learn/Java..