Event bubbling and Event capturing In Javascript

Event bubbling and Event capturing In Javascript

Event propagation, capturing, bubbling, stop Propagation, Once method

Hello fellow Developers 👋

this is new img.gif

In this blog, I will explain the Event Propagation in detail. So, let's dive right into it...

What is Event Propagation ?

As we all know, the meaning of propagation is a general term is circulation or distribution. So, In simple terms, the Event Propagation is the circulation of events.

Event propagation is a way to describe the “stack” of events that are fired in a web browser. The event propagation mode determines in which order the elements receive the event.

In all the modern browsers there are three phases of event propagation.

  1. Event capturing phase
  2. Event target phase
  3. Event bubbling phase

Although there are officially three phases, the second phase target occurs when the event.target element is reached. This phase is not handled separately like the others. Both event capturing and event bubbling handlers will trigger this phase automatically as they finish and begin with the target element.

Whenever we have an event in JavaScript, we have access to the event.eventPhase property. This will give us one of three values :

  1. It will either give us the value of 1 meaning that we are in the capturing phase. (where everything above the element is notified)
  2. 2, meaning that we are at the target phase. (where we reach the actual element where the event occurred)
  3. And 3, we are in the bubbling phase. (where everything above has notified again)

It could also return us the value of 0, meaning that there is no event current occurring.

event-propagation-img.png

Setup

To understand these concepts more clearly, first we'll create nested HTML elements and attach event listeners to them.

index.html file:

<!DOCTYPE html>
<html>
  <head>
    <title>Parcel Sandbox</title>
    <meta charset="UTF-8" />
  </head>

  <body>
    <div class="grandParent">
      <p>Grand Parent</p>
      <div class="parent">
        <p>Parent</p>
        <div class="child">
          <p>Child</p>
        </div>
      </div>
    </div>

    <script src="src/index.js"></script>
  </body>
</html>

image.png

index.js file:

const divs = document.querySelectorAll('div');

function logText(e) {
    console.log(this.classList.value);
}

divs.forEach((div) => div.addEventListener('click', logText, {
    capture: false, //set Event Capturing to false (You can simply use true or false here)
}));

In the above code, we have created 3 nested divs and attached a click event listener on each of them.

addEventListener( ) sets up a function that will be called whenever the specified event is delivered to the target.

Syntax : target.addEventListener(type, listener [, useCapture]);

  • type: A case-sensitive string representing the event type to listen for.
  • listener: The object that receives a notification when an event of the specified type occurs.
  • useCapture (optional): A Boolean indicating whether events of this type will be dispatched to the registered listener before any other Event in the DOM tree dispatches.

If not specified, useCapture defaults to false. i.e. by default Event Bubbling is enabled.

Event Capturing

Event capturing is the first phase of event propagation.
Event capturing is the event that starts from the top element and trickles down to the target element.

Event Capturing is also known as Event Trickling.

In the case of Event capturing, the event is captured from upward up to down the DOM tree. Let's see it with an example:

const divs = document.querySelectorAll('div');

function logText() {
    console.log(this.classList.value);
}

divs.forEach(div => div.addEventListener('click', logText, {
    capture: true, //set Event Capturing to true
}));

event-capturing-preview.gif

As shown in the example above, if we click the child then the event is triggered. And everything above the element is notified of the event occurrence, Starting from the topmost in the DOM tree.

grandParent (2).png

So, the event is first handled by the outermost element(i.e. grandParent in this case) and then propagates to the inner elements.
And the event for the innermost element, Which is the target element(i.e. Child in this case), will be handled at last.

Event Bubbling

Event capturing is the third phase of event propagation.

The meaning of bubbling in real life is when a bubble goes from the bottom of the glass to the top of the glass. I’m sure you’ve noticed that when you pour soda into a glass and all those bubbles happen.

Event bubbling is the event that starts from the target element and bubbles up to the topmost element in the DOM tree.

Let's see it with an example:

const divs = document.querySelectorAll('div');

function logText() {
    console.log(this.classList.value);
}

divs.forEach(div => div.addEventListener('click', logText, {
    capture: true, //set Event Capturing to false, i.e. deafult value.
}));

event-bubbling-preview.gif

As shown in the example above, if we click the child then the event is triggered. And everything above the element is notified again of the event occurrence, Starting from the target element in the DOM tree and propagates upwards.

grandParent (1).png

So, the event is first handled by the innermost element, Which is our current target(i.e. Child in this case) and then propagates to the outer elements.
And the event for the outermost element(i.e. grandParent in this case), will be handled at last.

Stop Propagation

Now you know how the propagation of events happens. But what if you want to stop it?

The stopPropagation() method of the Event interface prevents further propagation of the current event in the capturing and bubbling phases.

const divs = document.querySelectorAll('div');

function logText(event) {
    console.log(this.classList.value);
    event.stopPropagation(); // stop further bubbling and capturing
}

divs.forEach(div => div.addEventListener('click', logText, {
    capture: true, //set Event Capturing to true
}));

If you add event.stopPropagation( ) then It’ll only trigger the event of the current element and will stop the propagation. Let's understand this using an example:

stop-propagation-preview.gif

In the above example, event capturing is true so it first notifies the outermost element, which is grandParent in this case, and prints its output in the console. And as soon as it encounters event.stopPropagation it stops further propagation and does not move down the target element.

And in case of event bubbling, it won't notify any other element above the current target element and stops propagating further up the hierarchy.

Once method

A Boolean indicating that the listener should be invoked at most once after being added. If true, the listener would be automatically removed when invoked.

const divs = document.querySelectorAll("div");

function logText(e) {
  console.log(this.classList.value);
}

divs.forEach((div) =>
  div.addEventListener("click", logText, {
    capture: true,
    once: true // Listener is invoked atmost once
  })
);

once-preview.gif

If we set once: true then the listener will only be invoked once and after that, it is removed automatically.

Conclusion

  • Event Propagation: The event propagation mode determines in which order the elements receive the event. It has 3 phases Capturing, Target and Bubbling.
  • Capturing: Event capturing is the event that starts from the top element and trickles down to the target element. It is also known as Event Trickling.
  • Bubbling: Event bubbling is the event that starts from the target element and bubbles up to the topmost element in the DOM tree.
  • Stop Propagation: The stopPropagation() method of the Event interface prevents further propagation of the current event in the capturing and bubbling phases.
  • Once method: The Once method indicates that the listener should be invoked at most once after being added and would be automatically removed when invoked.

Thanks for your time!!

chaalaa.gif

I've covered a few more JavaScript and React topics before, do check them out.

Let's connect Twitter | LinkedIn.

Let me know how if this blog was helpful for you in the comments section below.