Event Bubbling and Event Capturing

Event Bubbling and Event Capturing

Β·

5 min read

If you are into web dev, I am pretty much sure that you might come across the term Event Bubbling as well as Event Capturing.

Introduction

IntroMarmotGIF.gif

Event Bubbling

As the name suggests is an event that bubbles out. I assume you all are familiar with events in javascript. It replicates the same behavior as that bubbling Up. It starts at the bottom and then rises to the top. (basically every rapper story πŸ˜‚). gif

Event Capturing

It is a little bit confusing like what are we capturing, so some people also like to call it Event Trickling to help them understand better. In Event Capturing/Trickling events are trickled down i.e from top to bottom Gif description

We will see how they function in the latter part of the blog.

History πŸ§“

THAT'S MY FAVOURITE !! Gif description

Back in old days Netscape advocate event capturing as the main fundamental of event propagation. At the same time, MicroSoft is the opposite of Netscape, they double down on event bubbling as it would make more sense for events to bubble up rather than trickling down.

So, World Wide Web Consortium (W3C) puts an end to this argument by allowing both to be accepted. It is up to us(developers) to use whichever we want.

Event Listener πŸ‘‚

ImAllEarsImListeningGIF.gif

An event listener is basically a function that waits for an event to occur. That event can be anything like a mouse click event, submitting a form, pressing keys of a keyboard, etc.

<element>.addEventListener(<eventName>, 
    <callbackFunction>, {capture : boolean});
  • <element>: The element to which an event listener is attached.
  • <eventName>: It can be 'click', 'key up', 'key down' etc. events.
  • <callbackFunction>: This function fires after the event happened.
  • {capture: boolean}: It tells whether the event will be in the capture phase or in the bubbling phase (optional)

Remember we were just discussing how W3C allows developers to use event bubbling and event capturing according to our free will. In order to achieve that we have the third parameter of addEventListener that is {capture: boolean}. It accepts a boolean value. If we don't pass any value, it's by default set to false and acts as in event bubbling mode. If we set it true it will act as in event capturing mode

Event Bubbling πŸ’¦

KstrKochstrasseGIF.gif When an event happens on an element, it first runs the handlers on it, then on its parent, then all the way up on other ancestors.

A click on the inner <p> first runs on click:

  1. On that <p>.
  2. Then on the outer <div>.
  3. Then on the outer <form>.
  4. And so on upwards till the document object.

Similarly, if we click on <div> it will first run on click on <div> then bubble onto the next parent element. img

So if we click on <p>, then we’ll see 3 output in console.log : p β†’ div β†’ form.

Event Capturing πŸ₯…

When an event happens on an element, it first runs the handlers on the topmost ancestor in the hierarchy, then onto its child then all the way down to other children. It basically trickled down from parent to child.

A click on the inner <p> first runs on click:

  1. On that <form>.
  2. Then on the inner <div>.
  3. Then on the inner <p>.
  4. And so on downwards till the last children.

Similarly, if we click on <div> it will first run on click on <form> then trickled down to the next child element.

So if we click on <p>, then we’ll see 3 output in console.log : formβ†’ div β†’ p.

How to stop Event Bubbling and Event Capturing πŸ›‘

StopStickmanGIF.gif

There are various scenarios where we wouldn't want either event bubbling or event capturing. So we need to stop these processes. Fortunately, our javascript which is more like doremon has a solution for this.

img

Event in javascript comes with a method known as event.stopPropagation();

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

Let us understand this through code.

document.getElementById("form").addEventListener(
  "click",
  () => {
    console.log("form clicked!!");
  },
  { capture: false }
);

document.getElementById("div").addEventListener(
  "click",
  (event) => {
    console.log("div clicked!!");
    event.stopPropagation();
  },
  { capture: false }
);

document.getElementById("p").addEventListener(
  "click",
  () => {
    console.log("p clicked!!");
  },
  { capture: false }
);

In the above code snippet, we can see that the event bubbling will happen as the capture value is false.

In the code block given below we added event.stopPropagation();. Now what will happen here is as soon as we clicked on <p> It will execute the code of <p> and print p in console.. After that, it will move up to its parent as it is bubbling. Then the div block code will be executed which in turn first print <div> in console then it will reach to event.stopPropagtion(); which will stop the execution of the event of bubbling and it would not move further to the <form> element.

So if we click on <p>, then we’ll see 2 outputs in console.log : pβ†’ div.

document.getElementById("div").addEventListener(
  "click",
  (event) => {
    console.log("div clicked!!");
    event.stopPropagation();
  },
  { capture: false }
);
`

Similarly, the same thing can be done with Event Capturing.

Note πŸ“

WritingNotesGIF.gif As WC3 allows us to use both Event Capturing & Event Bubbling, we can use both in the same program according to our requirements. This can be simply done by providing the value to the capture parameter. Remember, All capturing event handlers are run first, then all the bubbling event handlers.

document.getElementById("form").addEventListener(
  "click",
  () => {
    console.log("form clicked!!");
  },
  { capture: false }
);

document.getElementById("div").addEventListener(
  "click",
  (event) => {
    console.log("div clicked!!");
    event.stopPropagation();
  },
  { capture: true }
);

document.getElementById("p").addEventListener(
  "click",
  () => {
    console.log("p clicked!!");
  },
  { capture: false }
);

Here instead of writing { capture: false }, one can simply write thee boolean value true/false and it will also work.

For more clarity, you can watch Event Bubbling, Capturing aka Trickling in Javascript

First of all thank you for reading. πŸ™Hope you learned something. This is my attempt to pen down what I understand of the topic. Please let me know if there are any errors and also how can i improve. You can reach out to me on Twitter and LinkedIn

Β