event.target.closest

Eric mentioned the JavaScript closest method. I use it all the time.

When I wrote the book DOM Scripting back in 2005, I’d estimate that 90% of the JavaScript I was writing boiled down to:

  1. Find these particular elements in the DOM and
  2. When the user clicks on one of them, do something.

It wasn’t just me either. I reckon that was 90% of most JavaScript on the web: progressive disclosure widgets, accordions, carousels, and so on.

That’s one of the reasons why jQuery became so popular. That first step (“find these particular elements in the DOM”) used to be a finicky affair involving getElementsByTagName, getElementById, and other long-winded DOM methods. jQuery came along and allowed us to use CSS selectors.

These days, we don’t need jQuery for that because we’ve got querySelector and querySelectorAll (and we can thank jQuery for their existence).

Let’s say you want to add some behaviour to every button element with a class of special. Or maybe you use a data- attribute instead of the class attribute; the same principle applies. You want something special to happen when the user clicks on one of those buttons.

  1. Use querySelectorAll('button.special') to get a list of all the right elements,
  2. Loop through the list, and
  3. Attach addEventListener('click') to each element.

That’s fine for a while. But if you’ve got a lot of special buttons, you’ve now got a lot of event listeners. You might be asking the browser to do a lot of work.

There’s another complication. The code you’ve written runs once, when the page loads. Suppose the contents of the page have changed in the meantime. Maybe elements are swapped in and out using Ajax. If a new special button shows up on the page, it won’t have an event handler attached to it.

You can switch things around. Instead of adding lots of event handlers to lots of elements, you can add one event handler to the root element. Then figure out whether the element that just got clicked is special or not.

That’s where closest comes in. It makes this kind of event handling pretty straightforward.

To start with, attach the event listener to the document:

document.addEventListener('click', doSomethingSpecial, false);

That function doSomethingSpecial will be executed whenever the user clicks on anything. Meanwhile, if the contents of the document are updated via Ajax, no problem!

Use the closest method in combination with the target property of the event to figure out whether that click was something you’re interested in:

function doSomethingSpecial(event) {
  if (event.target.closest('button.special')) {
    // do something
  }
}

There you go. Like querySelectorAll, the closest method takes a CSS selector—thanks again, jQuery!

Oh, and if you want to reduce the nesting inside that function, you can reverse the logic and return early like this:

function doSomethingSpecial(event) {
  if (!event.target.closest('button.special')) return;
  // do something
}

There’s a similar method to closest called matches. But that will only work if the user clicks directly on the element you’re interested in. If the element is nested within other elements, matches might not work, but closest will.

Like Eric said:

Very nice.

Have you published a response to this? :

Responses

Andrew

@adactio oh, that’ll save me writing a lot of cursed for-loops 😃

(although i do enjoy a for loop where the variable isn’t a number)

# Posted by Andrew on Thursday, October 12th, 2023 at 11:23am

Ollie Boermans

@adactio As a student of your DOM Scripting book (thank-you!), searching for a JavaScript library that found elements using CSS selectors was exactly how I discovered a very early version of jQuery. This feature was transformative!

8 Shares

# Shared by Sara Joy ✨ on Thursday, October 12th, 2023 at 10:55am

# Shared by Stuart :progress_pride: on Thursday, October 12th, 2023 at 11:50am

# Shared by David O'Brien on Thursday, October 12th, 2023 at 12:22pm

# Shared by Gerardo Rodriguez on Thursday, October 12th, 2023 at 12:22pm

# Shared by Robin Whittleton on Thursday, October 12th, 2023 at 1:23pm

# Shared by Jon Lunman on Thursday, October 12th, 2023 at 3:01pm

# Shared by Valentino Gagliardi on Friday, October 13th, 2023 at 8:35pm

# Shared by Clearleft on Tuesday, October 17th, 2023 at 3:50pm

15 Likes

# Liked by yuanchuan on Thursday, October 12th, 2023 at 10:55am

# Liked by Sara Joy ✨ on Thursday, October 12th, 2023 at 10:55am

# Liked by Scott H. on Thursday, October 12th, 2023 at 11:21am

# Liked by Stuart :progress_pride: on Thursday, October 12th, 2023 at 11:50am

# Liked by Gerardo Rodriguez on Thursday, October 12th, 2023 at 12:22pm

# Liked by Sam Nabi on Thursday, October 12th, 2023 at 12:22pm

# Liked by Manuel Strehl 🫏 on Thursday, October 12th, 2023 at 12:22pm

# Liked by Jason Neel on Thursday, October 12th, 2023 at 12:22pm

# Liked by Chris Armstrong on Thursday, October 12th, 2023 at 12:52pm

# Liked by gcollazo on Thursday, October 12th, 2023 at 2:30pm

# Liked by Jon Lunman on Thursday, October 12th, 2023 at 3:01pm

# Liked by Zearin on Thursday, October 12th, 2023 at 4:32pm

# Liked by Jan on Thursday, October 12th, 2023 at 7:12pm

# Liked by Clearleft on Tuesday, October 17th, 2023 at 3:50pm

# Liked by James Basoo on Tuesday, October 17th, 2023 at 4:23pm

1 Bookmark

# Bookmarked by Brent Lineberry on Thursday, October 12th, 2023 at 2:00pm

Related posts

Custom properties

Don’t touch that DOM.

Saving forms

A defensive enhancement to avoid losing everything you just typed into a textarea.

Service workers in Samsung Internet browser

Samsung Internet browser doesn’t yet support asynchronous `waitUntil`, but that’s okay.

JavaScript

Inside me there are two wolves. They’re both JavaScript.

Trust

I’m trying to understand why developers would trust third-party code more than a native browser feature.

Related links

Light-DOM-Only Web Components are Sweet – Frontend Masters Boost

The main reason I’m so hot on Light DOM is that I find the styling story of Web Components using Shadow DOM annoying.

Tagged with

The elevator pitch for Web Components | Go Make Things

I’ve worked with Web Components a little bit over the last few, but really struggled to understand the use case for them.

Until this week.

Between Jeremy Keith’s article on HTML Web Components, plus using one for a client project with NASA, something just clicked in my brain finally.

I’m now convinced that they’re the best way to author DOM manipulation libraries.

Tagged with

Shadow DOM is for hiding your shame

This is an excellent step-by-step walkthrough by Tess of creating a web component, with real thought given to what should be in the HTML (which will act as a fallback) and what’s better generated in the Shadow DOM (like buttons for interactivity).

This perfectly mirrors something Chris was saying in a recent episode of the Shop Talk Show:

I think of the image comparison one. That’s a classic example in Web component. What’s inside is just two IMG tags. That’s it. When it fails, you don’t want a weird div with little arrows on it being rendered on the page. That’s not doing anything because it has failed to load the JavaScript.

Tagged with

Blinded By the Light DOM – Eric’s Archived Thoughts

You just take some normal HTML markup, wrap it with a custom element, and then write some JS to add capabilities which you can then style with regular CSS! Everything’s of the Light Side of the Web. No need to pierce the Vale of Shadows or whatever.

I think Eric’s approach here should be the default for most web components: you probably don’t need to mess around with the shadow DOM, and you should definitely be wrapping your web component around existing HTML instead of witing opening and closing tags with nothing in between.

As Chris puts it:

Augment, don’t replace.

Tagged with

CSS Quick Tip: Animating in a newly added element | Stephanie Eckles

I can see myself almost certainly needing to use this clever technique at some point so I’m going to squirrel it away now for future me.

Tagged with

Previously on this day

4 years ago I wrote The Web History podcast

Narrated by yours truly.

4 years ago I wrote Owning Clearleft

After fifteen years, it’s time to commit.

10 years ago I wrote Habitasteroids

What I did at Science Hack Day San Francisco.

14 years ago I wrote Stevens

Who’s on first?

14 years ago I wrote Sea change

Oh, the humanity!

20 years ago I wrote Apple documentation

There’s a very old joke about a man who goes to the doctor and says:

20 years ago I wrote Farewell to Erin

I’m back from my trip to Ireland. It was a short visit but I managed to pack in quite a bit of activity.

21 years ago I wrote Okkervil River

Another day, another great gig courtesy of local promoters The Gilded Palace Of Sin.

22 years ago I wrote Lost in Translation

I bet these guys would have loved to get hold of Jessica’s other domain name.

22 years ago I wrote podLob

A beautiful site with some fantastic DHTML widgets to play with.

22 years ago I wrote More Wired News

Following up my last post about the redesign of Wired News, here’s an interview with Douglas Bowman who led the development team.

23 years ago I wrote Apple - W3C Statement

This is very good news indeed.

23 years ago I wrote 240 Miles Up, Seeing Tragedy

There have been a lot of eyewitness accounts of the events of September 11th posted on the web but this has to be the most unusual: