Sunday, 3 March, 2019 UTC


Summary

Oftentimes software libraries are created to help fill the shortcomings of a particular language. Libraries like jQuery introduced us to the idea of using CSS selectors to grab elements from the DOM, something that didn’t really exist at the time. Eventually, JavaScript started to catch up by expanding beyond getElementById() to allow for selecting elements by way of things like class and tag names.

🐊 Alligator.io recommends:

ES6 for Everyone → A video course to learn modern JavaScript
ⓘ About this affiliate link
Get Element by ID
Tried and true. The O.G. of the element “getters”.
This Document method does exactly what it says it’s going to do. Pass it the string of the ID you’d like to return and you’re good to go:
<div></div> <div id="alligator"></div> <div></div> 
const element = document.getElementById('alligator'); 
Easy, right?
A few things to mention though. First, take note that it’s get “element”, singular and not “elements”. Remember that the id attribute is supposed to be unique across your entire HTML document, so this method will only ever return a single element.
Next, keep in mind that the method name is case sensitive. If you’re like me, you probably type “getElementByID” (capital ID) thanks to muscle memory. If so, the method won’t work and hopefully you have a linter in the mix that will bark about the problem before you waste a few hours trying to figure out what the heck you did wrong.
Lastly, the ID string supplied to the method should not include a pound sign. I couldn’t tell you how many time’s I’ve written getElementById('#someId') forgetting that I’ve switched gears and wasn’t writing a CSS selector.
Get Elements by Tag Name
Next up is getElementsByTagName(). Give it a tag name and it will return all of the elements for that tag:
<ul> <li></li> <li></li> <li></li> </ul> 
const ulElements = document.getElementsByTagName('ul'); 
This method only lets you pull a single tag name at a time, but if you pass in * as the tag name, you will receive every element in the DOM tree:
const allElements = document.getElementsByTagName('*'); 
Get Elements by Name
Want to grab the elements that have a specific name attribute? You can use getElementsByName(), pass it a name value, and it will return all of the elements with that name attribute:
<input name="alligator" /> <input name="crocodile" /> 
const namedElements = document.getElementsByName('alligator'); 
Get Elements by Class Name
And finally, getElementsByClassName(). You can give it a class name and it will return all of the elements that have said class in it’s class name list:
<div class="alligator"></div> <div class="crocodile"></div> 
const elements = document.getElementsByClassName('alligator'); 
A bit more robust than some of the other “getter” methods, getElementsByClassName() also accepts multiple class names. The class names will need to be separated by spaces and then the method will return the elements that match all of the class names provided:
<div class="reptile alligator"></div> <div class="reptile crocodile"></div> 
const elements = document.getElementsByClassName('reptile alligator'); 
Remember, the class names provided don’t need to be prefixed with a period, as with CSS selectors. That’s another one that’s gotten me before ;)

These methods are all well and good, but they are still lacking compared to using a raw CSS selector.
Chaining is possible, but it only really works when you chain to getElementById(). Even then, all you can do is get elements inside of the element that was selected by ID. Outside of looping through and interrogating each element, there’s not a great way to get the power of multiple selectors.
Fortunately, modern JavaScript also includes some additional methods that allow you to select elements based on CSS selectors!
Query Selector
The first of two methods that use CSS selectors is querySelector(). Pass it a CSS selector (as crazy or as tame as you’d like) and you will receive the first matched element back:
<form id="form"> <input type="checkbox" name="gator"> <input type="checkbox" name="gator" class="reptile"> <input type="checkbox" name="gator"> </form> 
const elements = document.querySelector('#form input[name="gator"].reptile'); 
Query Selector All
Looking for more than just the first element that matched? If so, you can use querySelectorAll() which also takes a CSS selector as an argument:
<form id="reptiles"> <input name="gator-01"> <input name="gator-02"> <input name="gator-03"> </form> 
const elements = document.querySelectorAll('form#reptiles input[name^="gator-"]'); 

Working with HTMLCollection
Most of the methods we’ve discussed (except getElementById() and querySelector()) return multiple elements as an HTMLCollection.
The HTMLCollection is similar to an array, but does deviate a bit as it lacks looping methods like forEach().
Let’s take a look at how to work with our elements now that we “got” them.

Length

Not much to grabbing the length, just append .length to the HTMLCollection and you’ll be greeted with an integer value:
const numberOfElements = elements.length; 

First Element

The first element of an HTMLCollection is the element that first matched the selection criteria when the method scanned the DOM. Grabbing the first element is quite simple:
const firstElement = elements[0]; 

Last Element

At the other end of the spectrum, or should I say HTMLCollection, is the last element that happened to have matched the selection criteria. It’s a bit more work to get, but nothing too crazy:
const lastElement = elements[elements.length - 1]; 

Looping

Okay, so everything thus far has been exactly like working with an array. Looping on the other hand is a bit more complex.
As mentioned HTMLCollection doesn’t have the array looping methods we know and love, like .forEach() or .map() but we can tap into the Array.prototype to access those looping methods anyway:
Array.prototype.forEach.call(elements, (element) => { console.log(element); });