Skip to content

Instantly share code, notes, and snippets.

@DavidJCobb
Created March 13, 2023 11:38
Show Gist options
  • Save DavidJCobb/add6aca3fdfc5553f571a32200f30b67 to your computer and use it in GitHub Desktop.
Save DavidJCobb/add6aca3fdfc5553f571a32200f30b67 to your computer and use it in GitHub Desktop.
JavaScript event bubbling: simple example

JavaScript event bubbling example

When JavaScript fires an event, like click, it doesn't just fire it on the event target (i.e. the thing that was clicked). It also fires the event on every ancestor element. This means that an event listener on an ancestor can handle clicks on any of its children.

The code below demonstrates this with a list, where we want to react to the user clicking any list item, and we want our reaction to take into account which list item they clicked. We use a listener on the entire list, and just check e.target to see what list item was clicked.

Getting the right target

The e.target value is whatever element was clicked on directly. You would expect this to be a list item; however, it could also be a child or descendant element of any list item. One of our list items has italicized text using the <em> tag; if the user clicks directly on that italicized text, then the EM element will be the event target. For that reason, we actually want to use e.target.closest("li").

That isn't perfect, however. If something that isn't an LI element gets added to our list, then there are two ways that that can fail:

  • If the user clicks on the non-LI child of the list, then e.target.closest("li") will be null, because the element that the user clicked on won't be inside of a list item...

  • ...unless the entire list is inside of an LI, in which case e.target.closest("li") will be that LI outside of the list.

If we want to be paranoid, we can handle both of these cases: make sure that e.target.closest("li") isn't null, and make sure that it's actually inside of our list (via Element.prototype.contains).

<ul id="example">
<li> List item 1 </li>
<li> List item 2 </li>
<li> List item 3 <em>with italics in it!</em> </li>
</ul>
// when the user clicks on any list item, we want to run some code.
// the code we want to run depends on which list item they clicked.
// (for this example, we'll just show the list item's text in an
// alert box.)
// we could add a listener to each list item, but it's more efficient
// to take advantage of bubbling.
{
let list = document.getElementById("example");
list.addEventListener("click", function(e) {
let item = e.target.closest("li");
if (!item) { // paranoid check
return;
}
if (!list.contains(item)) { // paranoid check
return;
}
alert(item.textContent);
});
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment