Member preview

Calling JavaScript code on multiple DIV elements without ID attribute

Written by @js_tut (Twitter)

In this tutorial, we’ll take a look at how to call JavaScript code on multiple DIV elements on the page, when they are missing the id attribute (or when calling an individual element is not permitted, for some reason.)

This happens more often than you may think. For example, you have an image gallery (or any other list of elements) and you want to do some action on each element but don’t want to access each element individually.

Let’s say you have a few arbitrary HTML DIV elements:

  <div class = "image">content 1</div>
<div class = "image">content 2</div>
<div class = "image">content 3</div>

You can select these DIV elements, even though they don’t have id attributes. In fact, they share the same class name “image”.

Let’s see a few alternatives we have when it comes to selecting a collection of HTML elements. There are at least three ways of doing this in JavaScript.

1. Using document.getElementsByClassName

In order to select the elements in question, you can use the document.getElementsByClassName function.

It returns a non-iterable collection of all elements.

Which is just a list of elements, similar to (but not exactly as) Array.

let divs = document.getElementsByClassName("image");

2. Using document.getElementsByTagName

Same thing here, only using a different JavaScript function.

let divs = document.getElementsByTagName("div");

3. Using document.querySelectorAll

You can do the same exact thing with document.querySelectorAll function.

let divs = document.querySelectorAll("div");

Return Value

What do these functions return?

console.log(divs); // Let's output the results

Different types of objects.

Yet, containing the same selected elements:

1.) Functions getElementsByClassName or getElementsByTagName:

HTMLCollection(3) [div.image, div.image, div.image]
0 : div.image
1 : div.image
2 : div.image
length : 3, __proto__ : HTMLCollection

2.) Function querySelectorAll returns same thing but as a NodeList object:

NodeList(3) [div.image, div.image, div.image]
0 : div.image
1 : div.image
2 : div.image
length : 3, __proto__ : NodeList

The querySelectorAll returns a NodeList object.

getElementsByClassName / getElementsByTagName an HTMLCollection.

They all return a list of all selected DIV elements that can be iterated.

You can take the divs object, which will not contain the 3 elements, and iterate them one by one by calling Objects.entries:

Object.entries(divs).map((object) => { console.log(object) });

You can alternatively the forEach method of the Array object. But there are so many different ways of doing the same thing in JavaScript. I usually use Object.entries and .map method and sometimes forEach. But it’s up to you.

The nature of problems we solve as web developers 99% of the time isn’t as difficult as to make it necessary to seek performance optimization from choosing “the right” function.

Most for-loop alternative look cleaner at expense of a function call per iteration step. But from performance standpoint it doesn’t matter which iterator/loop method you use if you only have to list 10–50 or even 1000 items. Which is the case with most front end UI-based software.

Let’s attach an addEventListener method to each DIV in the collection:

Now that we got the link to each HTML element on the list as a JavaScript object, let’s do something with them:

/* Add event listeners to all elements by hand */
divs[0].addEventListener("click", function() {
console.log("Hello " + this + " (" + this.innerHTML + ") from event listener [0]");
/* Here, "this" refers to 1st div */
});
divs[1].addEventListener("click", function() {
console.log("Hello " + this + " (" + this.innerHTML + ") from event listener [1]");
/* Here, "this" refers to 2nd div */
});
divs[2].addEventListener("click", function() {
console.log("Hello " + this + " (" + this.innerHTML + ") from event listener [2]");
/* Here, "this" refers to 3rd div */
});

Now whenever you click on any of the DIVs, you will have its object and innerHTML printed to the console.

In some cases, you will want to do this individually. But that kind of defeats the whole purpose. Couldn’t we just do this via an onClick attribute?

However — in most cases — you will probably want to not only reduce the size of your code but also scroll through all existing elements in a collection one by one and execute the same JavaScript code on all of them.

One way of doing that is to use the Array.map method.

But the .map method works only on Arrays.

It will not work on an HTMLCollection. (Returned in the examples above.)

No problem. You can convert our collection to an array. And this can be usually done using the Object.entries method.

First, convert your HTMLCollection using Object.entries(collection). Then, since at that point it’s an iterable you can now use the .map method on it.

Using .map method with Object.entries(collection)

/* Walk through the entire set of items in a HTMLCollection
by first converting it to an Array using Object.entries */
Object.entries(divs).map(( object ) => {
    // Here, object = Array[index, object] (object is the
// HTML element object). This means that the actual element
// is stored in object[1], not object. Do whatever you need
// with it here. In this case we attach a click event:
    object[1].addEventListener("click", function() {
    // Output innerHTML of the clicked element
console.log("Hello " + this +
" (" + this.innerHTML + ") from map method...");
});
});

Create an argument object for the map arrow function. This object will receive the data we’re looking for (index and actual DIV element.)

Within loop object[0] refers to index of currently looping item from HTMLCollection. (In this case 3 of them because we started out with 3 <div> HTML elements so they will — one by one — become available as object[0]

In the code above we don’t even have to use index. But just know it’s available.

Also object[1] will actually point to the JavaScript object of the element.

You can do whatever you want with it. Attach mouse hover/blur events. Check their attributes. Remove them. Or any other thing that you would normally do to JavaScript objects, depending on your case.

The idea is that you write JavaScript code once, and you can apply it to a collection of HTML elements, without having to do it for every single element individually by hand. That’s pretty much all there is to it.

JavaScript School Bus

Want to learn more about JavaScript? Hop on the JavaScript School Bus!

www.javascriptteacher.com by @js_tut (Twitter)

For more tutorials you can visit my JavaScript Tutorial Site / See you there!