Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save jeremiahjstanley/c5dc09d410e2d17d0690cf3ae05c293d to your computer and use it in GitHub Desktop.
Save jeremiahjstanley/c5dc09d410e2d17d0690cf3ae05c293d to your computer and use it in GitHub Desktop.
Event Bubbling in Vanilla JS

A Series of Unfortunate Events?

Events in JavaScript are the backbone of interactivity in the browser. In August 6, 1991, Sir Tim Berners-Lee released the very first website to the world! The World Wide Web was born, but there was no JavaScript, and no one really knew what the internet was anyway. In January 1993, the first commercial web browser, Mosaic, was released. We still didn't have JavaScript, but we had the unstandardized version of the DOM (Document Object Model). In 1995, the very first version of JS was born and was famously written in ten days.

Today we can leverage JavaScript to write web applications, and we can use browser events to make our web applications interactive.

Lesson Goals

  1. Understanding events in JavaScript
  2. Setting up Event Handlers
  3. Understanding Event Propagation and specifically Event Bubbling
  4. Implementing Event Delegation for dynamically created elements

Let's Get Interactive

Let's imagine web development as a marionette. It's a creepy image, but we're going with it anyway.

Web development has three essential parts.

The HTML is the body of the marionette. CSS comprises the marionette's clothing and haunting, vacant expression. JavaScript is the marionette's strings.

Without the strings, the marionette would be lifeless.

Events are one of the ways we can "pull" the marionette's strings.

Events in JavaScript are a means of "call and response." We can write code to capture users' actions, and made our web applications respond!

So, How do we make our website interactive?

Events are constantly happening in the browser, and most of them go unnoticed. To capture events, we have to add Event Handlers to our code - Event Handlers are scripts that are automatically executed when an event occurs.

We're able to reference HTML elements in our JavaScript code to capture specific events - querySelector and querySelectorAll are methods on the Document object (the DOM) that we can use to reference HTML elements.

We can bind Event Handlers to DOM Nodes with the addEventListener method. The first argument on the addEventListener method is the event case, and the second is a callback function.

There are tons of Document selector methods and Event Handlers but let's focus on the basics for now.

Further Reading: Event MDN

So, What is a JavaScript Event Anyway?

Events are objects.


Your Turn

Let's take a look at this code. We have a button that's bound to an event listener. On click, we execute an anonymous function. This function is going to log the event object to the console. We're also using the typeof operator to log the event's datatype. Take a couple of minutes to look at the properties on the MouseEvent object. What are some of the potential use cases for these properties?


Event Propagation and Bubbling

So, now that we know what events are, and we've talked a little about how events work, let's talk about Event Propagation. Sometimes the terms Event Propagation and Event Bubbling are used interchangeably, but Event Bubbling is only one phase of Event Propagation.

Let's look at this following HTML code.

<HTML>
  ...
  <body>
    <main>
      <button>
        Click me!
      </button>
    </main>
  </body>
</HTML>

Let's say we click the button in the above example. What happens?

Our click starts Event Propagation, Event Propagation encapsulates the entire lifecycle of a DOM Event.

The standard DOM event lifecycle describes three phases of Event Propagation: capturing, targeting, and bubbling.

  1. Capturing phase – the event traverses the DOM tree to the target element.
  2. Target phase – the event has reached the target element.
  3. Bubbling phase – the event bubbles up from the target element.

An event begins at the Document object, traverses its way down the DOM Tree to find its target - remember that target property on the event object? The target property now comes into play. Once we reach the event.target, the last phase begins: Event Bubbling.

Event Bubbling is probably the easiest part of this process to remember. Like bubbles, events float to the top of the DOM tree. In general, we're going to focus on Event Bubbling.

Note: The capturing phase rarely gets used in code. It usually is invisible to us, but we can expose the capturing phase under special circumstances

Your Turn


Partner up and copy this HTML into a codepen:

<style>
  body * {
    background-color: rgba(0, 0, 0, .2);
    border: 1px solid black;
    border-radius: 10px;
    min-height: 150px;
    margin: 2rem;
    padding: 1rem;
  }
</style>

<main class="grandparent">
  Grandparent
  <section class="parent">
    Parent
    <div class="target">Click me!</div>
  </section>
</main>

After you've created a codepen with this boilerplate HTML and styling, add event listeners to the grandparent, parent, and target elements. These event listeners should execute a function that triggers an alert on a click event.


How does our event bubble?

  1. On the <div> tag.
  2. Then on the parent <section> tag.
  3. Then on the grandparent <main> tag.
  4. And so on upwards until we reach the document object.

You'll notice that clicking the Click Me! <div> has the same effect as clicking all the elements "above" the <div> tag.

So if we click on the <div> tag, then we’ll see 3 alerts: <div><section><main>.

This code is an example of "Event Bubbling" because events "bubble" to the top of the Document from the inner <div> element.

What about dynamically created objects?

A lot of developers struggle to understand when eventListeners are bound to DOM nodes. This process happens when the browser loads our JavaScript code! In our JavaScript code, we can select and bind event listeners to DOM nodes, but! we've only added event listeners to the nodes that are currently on the page when our JS is initialized. We are not adding listeners to nodes that might get added to the page in the future.

Let's look at codepen together. What do you notice about this code?

Event Delegation

Capturing and bubbling allow us to implement a powerful event handling pattern, Event Delegation.

The idea is that if we have a lot of elements handled similarly, then instead of assigning a handler to each of them – we put a single handler on their common parent element.

We're still able to reference the element where the event occurred; the handler gives us event.target, so we can see where the event happened and handle it.

Your Turn

Let's look at this example This handler is assigned to <div> tags, but also runs if you click any nested tag like <p> or <code> tags. 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 - usually ending with the Document.

Benefits of Event Delegation

  • Event Delegation: Simplifies initialization and saves memory
  • Less code: when adding or removing elements you do not need to add/remove handlers - if you remove an element from the DOM without removing its event listeners you can cause a memory leak
  • DOM modifications: we can add and remove HTML elements while retaining interactivity!

Event Delegation is super useful. It's one of the common patterns for handling DOM events, and it can be simplified into three parts.

  1. Put a single event handler on the parent event.
  2. In the event handler – check the event source element using event.target.
  3. If the event happened inside an element that interests us, we can handle the event!

Your Turn

Let's look at this example. Can you set up an event handler to utilize Event Delegation in this example?


Discussion and Q&A

  1. What is an event?
  2. What is the difference between Event Bubbling and Event Delegation
  3. What happens when an event bubbles?
  4. Why can't we attached eventListeners to dynamically created elements?
  5. What does Event Delegation reference, why is it important?

On Your Own

Methods on the Event Object

A bubbling event bubbles from the target element straight up the DOM tree. Typically, an event bubbles upwards until it reaches the <html> tag, and then to document object, and some events even reach the window, calling all handlers on the path.

There are several occasions where you may want to stop an event from bubbling.

What are some use cases where you might want to stop Event Bubbling?

Look at this example. Partner up and do a little research and see if you can find a way to prevent Event Bubbling in this codepen.

JavaScript's Single Thread and Events

You might have heard that JavaScript is a single-threaded programming language. What the heck does that mean? The simplest way to explain this concept is that JavaScript can only do one computation at a time.

We can see this concept in action. Open your console (option-command-i) and write a while loop that never ends. As a quick note, do this at your own risk.

while(true){}

Now try interacting with this browser tab. Nothing happens! JavaScript doesn't capture any events because it is preoccupied with the pesky while loop you wrote in the console. The single thread is stuck and cannot move on to the next event. If you go to Chrome's task manager (under settings → more tools), you should see this tab utilizing nearly 100% of this tab's CPU core resources. Select the tab, click "End Process" and refresh the browser tab to return everything to normal.

Performance and Crawlers

Did you know that you can turn off JavaScript in Chrome? Open your dev tools and navigate to the Sources tab. Press "Command-Shift-P" to run a command. Start typing JavaScript, select Disable JavaScript, and then press Enter to run the command. JavaScript is now disabled!

Turing off JavaScript is a useful exercise for auditing your performance site's performance and SEO! SEO can be a handy thing to understand if you're a web developer. If the concept is new to you, this video gives a handy quick rundown. If you disable JavaScript, you can see how your web application "looks" to a search engine or web crawler.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment