I would like to share my thoughts (and very little experience), as a junior web developer, on Kirupa’s very interesting tutorial “Handling events for many elements”. I tried using it in a project I am currently working on (as a student enrolled in a JavaScript/React online course). I’m basically building an image slider that opens when you click any of the images in a gallery. Following Kirupa’s idea, I added an event listener to the closest common ancestor of my image elements (or the div that serves as a container for my images rather), which happens to be the div that contains my entire image gallery. So I have another div element between that ancestor and my “div.image” elements. Therefore, I end up with intermediary elements which also have that event listener on them when they absolutely do not need it. It even creates a bug when I click slightly below an image in the gallery because I am targeting an element that should not be listening to the click event. So I was wondering whether Kirupa’s solution is adequate in case there are other descendents in between the common ancestor and the elements we want to add the event listeners to. I’d be interested to have other developers’ view on this. As I mentioned above, I am a JavaScript beginner, so any advice from more experienced developers would be much appreciated.
Below is the code that deals with listening and reacting to the click event:
// Handle click event on media elements
const handleClickOnMedia = ($event) => {
let clickedItemParentId;
if ($event.target !== $event.currentTarget) {
clickedItemParentId = $event.target.parentElement.id;
openLightbox(clickedItemParentId);
}
$event.stopPropagation();
return clickedItemParentId;
};
// We target the nearest common ancestor of all media elements
const mediaCommonAncestor = document.querySelector('.photographer__portfolio-images');
// We can then add an event listener on that element
// instead of adding multiple event listeners on all media elements
mediaCommonAncestor.addEventListener('click', handleClickOnMedia);
const listenHandler = function(e){
if(e.target === e.currentTarget) return
let run = events[e.target.dataset.event] || events["no_event"];
e.stopPropogation()
return run(e)
}
FYI you can just add an eventListener() and an event object (all your event functions in one object) for an entire page IF there’s no shadow DOM.
And also… you don’t have to use div all over your page.
There are elements that are semantic e.g. <nav> <a> <button>but<div> and <span> mean nothing to the browser without e.g. role = "navigation".
If you have an undefined customElement e.g.<portfolio-carousel> (not registered with e.g customElements.define("portfolio-carousel", portf_carousel)… then the browser will treat it as a <div> by default…
something like this is way more readable than <div> soup:
Thanks a lot for your very detailed answer! Lots of new stuff for me here. The only thing I knew about was the div soup you’re supposed to avoid, which I do as best I can. I just feel that once you’ve used all the semantic tags you’re supposed to and find yourself deep inside your HTML structure there’s not much you can do about it. I had no clue you could create your own custom HTML tags. I mean, really, what have they been teaching me?!
I had never thought of Tailwind as a potential gas hazard but now that you mention it…
Ok I’m off to put all the new stuff to the practice. I’ll let you know how it worked out.