[How To] addEventListener by class name
4 ways to handle addEventListener by class name!
Jul 12, 2023 | Read time 9 minutes🔔 Table of contents
Introduction
One thing that I have wondered a few times when working with legacy Javascript applications is how to use the addEventListener
by only giving it a class name.
In JavaScript, the addEventListener()
can only be used directly on a single DOM object.
The problem is that functions like getElementsByClassName()
will return a list of objects instead of a single one.
In this post I will go over 4 ways that I have used to do this over the years:
- Loop through all elements
- Using Event Delegation
- Using forEach
- jQuery option
1. Loop through all elements
One option to get addEventListener
to work with class names is that we just need to go through the whole list and attach addEventListener
to each of the DOM objects in that list:
As an example:
// Get all elements that have a specific class
var elements = document.getElementsByClassName("box");
// Iterate over the elements
for (var i = 0; i < elements.length; i++) {
// Add event listener to each element
elements[i].addEventListener('click', function() {
console.log('Element was clicked!');
});
}
The idea is that We find all elements with the class “box” using the getElementsByClassName
function.
Since the functions returns a list, we look over all of the elements and add the event handler.
2. Using Event Delegation
One technique that I have used in some of my web apps is to rely on “event delegation”.
“Event” what you say?? This just means that we will only add the event handler to the containing element and figure out which child element triggered the event.
The way this works is due to event bubbling in JavaScript.
When an event (like a click) happens on an child element, the event will “bubble up” and also fire on all of that element’s ancestors (parent, grandparent, etc).
So, if you set an event listener on a parent element, it can catch events that are fired on its children.
An example is as follows consider we have the following HTML:
<!DOCTYPE html>
<html>
<head>
<title>Event Listener Example</title>
</head>
<body>
<div class="databox"></div>
<div class="databox"></div>
<div class="databox"></div>
</body>
</html>
document.body.addEventListener('click', function (evt) {
if (evt.target.classList.contains('databox')) {
alert('A databox was clicked!');
}
}, false);
In the above, instead of directly attaching the listener to each individual element we attach it to the body (document.body
).
Then in our handler, we use the event object (evt
) and check the target
property. The target
property here refers to the DOM element that was clicked.
We then can check its className to see if it has the class that we want.
Why event delegation?
Generally, we can use this method for the following reasons:
Performance - Adding an event listener to one parent element is less resource-intensive than adding event listeners to each individual child element, especially if there are a large number of them. This can result in a performance benefit.
Easy to work with dynamic elements - when elements are added to the application dynamically (eg created by your code), the event listener would not need to be added each time a new element is created. The parent already has the event listener and it will handle events for the new child elements automatically.
Simple - As we can see this option compared to the looping options, it is a lot simpler. Instead of keeping track of many individual event listeners, you only have one listener at the parent level.
3. Using forEach
This is a sort of variant of option 1, we can use the forEach to iterate over the NodeList returned by document.querySelectorAll().
This lets you select elements based on CSS class names.
As an example consider the HTML:
<!DOCTYPE html>
<html>
<head>
<title>Event Listener Example</title>
</head>
<body>
<div class="databox"></div>
<div class="databox"></div>
<div class="databox"></div>
</body>
</html>
And in our JavaScript using the querySelectorAll
function:
document.querySelectorAll('.databox').forEach(item => {
item.addEventListener('click', event => {
alert('A databox was clicked!');
});
});
In this case, we’re using querySelectorAll()
to get all elements with the class “databox”.
querySelectorAll()
returns a NodeList (which is not exactly an Array, but an Array-like object), but it does have the forEach() method, so we can use that to iterate over the NodeList and add an event listener to each element.
Remember that querySelectorAll()
is more modern and may not be available in older browsers, though it is supported in all current major browsers.
Tip on browser support
If you need to support old browsers, you may need to use an older method such as getElementsByClassName() and a traditional for loop, as shown in the first example.
👉 NOTE: forEach
vs for
One thing to keep in mind is browser compatibility.
The traditional for loop has been part of JavaScript since its earliest versions, so it’s supported in all browsers, including Internet Explorer.
The forEach method was added to JavaScript with ES5, which came out in 2009. It’s supported in all modern browsers, but it’s not supported in Internet Explorer 8 or earlier.
If you need to support very old browsers, you should use the traditional for loop. However, keep in mind that Internet Explorer is no longer being updated as of 2021, and its usage has become very low. For most projects, it’s fine to use forEach and other ES5 features.
You can also use a transpiler like Babel to compile your JavaScript into a version that can be understood by older browsers. This lets you write modern JavaScript while still maintaining compatibility with older browsers.
4. jQuery option
Absolutely, jQuery simplifies the process of attaching event listeners to elements. Here’s how you can do it:
$(document).ready(function() {
$('.databox').on('click', function() {
alert('A databox was clicked!');
});
});
Here’s how the code works:
- $(document).ready(function() { … }); ensures that the code inside it will only run after the DOM is fully loaded.
- $('.databox') selects all elements with the class “databox”.
- .on(‘click’, function() { … }); attaches a click event listener to all the selected elements. When any of the selected elements is clicked, the code inside the function will run.
Just as with the JavaScript examples, you would replace ‘A databox was clicked!’ with your own code that should run when the event is triggered.
Remember, to use jQuery, you need to include the jQuery library in your HTML document. Usually, you would put this in the ``` section of your HTML, like this:
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
</head>
Summary
In this post we went over 4 ways to call addEventListener
by the class name.
The problem with addEventListener
is that it only accepts a single DOM element as the target.
Generally, the traditional approach is to loop through all of the elements and then attach the handler individually. We can do this with a simple for loop.
If you want a more modern approach then, using the forEach
option is another way to simplify the code.
Alternatively, we can use “event delegation”. This approach, we just attach the event handler to the parent element (eg <body>
) and then check the target
property in the event handler!
If you still have jQuery handy, then its a simple function using the $(jqueryObject).on('click', .... )
.