JavaScript (ES5) - Working With Selectors
Martin Himmel
Posted on November 27, 2018
This was originally posted on my site at https://martyhimmel.me on December 22, 2016. Like a number of others on dev.to, I've decided to move my technical blog posts to this site.
DOM - Document Object Model
JavaScript works with HTML elements via the Document Object Model (DOM). You can think of the DOM as the hierarchical structure of HTML elements on a page. Here's an example of that structure:
<html>
<head>
<title>Page Title</title>
</head>
<body>
<p id="foo">Some text in a paragraph</p>
<ul class="my-list">
<li>List Item 1</li>
<li>List Item 2</li>
<li>List Item 3</li>
</ul>
</body>
</html>
JavaScript uses the DOM's structure to traverse, find, and manipulate elements. In the above example, the DOM structure states that the head
and body
elements are children of the html
element, and the inverse - the html
element is the parent of the head
and body
elements. This relationship is true for every element on the page (e.g. ul
is the parent to the li
elements, p
is a child of the body
element, etc.) and is important to know when using selectors.
The first step is usually done through the document
selector methods. The document
selectors allow you to get elements on a page and start working with them. For example:
var paragraphFoo = document.getElementById('foo');
Would set paragraphFoo
to this:
<p id="foo">Some text in a paragraph</p>
Now, you have access to all the properties on that paragraph element. Here are a couple examples.
Note: Anywhere paragraphFoo
is used, document.getElementById('foo')
could be used in its place. Setting the paragraphFoo
var and using that is a slight performance boost - the DOM doesn't have to be queried/traversed every time we want to target that paragraph element.
// element.innerHTML
// As a getter, it returns the current HTML inside of the opening and closing tags
paragraphFoo.innerHTML; // Some text in a paragraph
// As a setter, it changes the HTML inside the opening and closing tags
paragraphFoo.innerHTML = 'Change the paragraph text';
console.log(paragraphFoo); // <p id="foo">Change the paragraph text</p>
// element.classList
// By itself, it returns an array of classes. You can also use element.classList.add() and
// element.classList.remove() to add and remove classes on the element.
paragraphFoo.classList; // []
paragraphFoo.classList.add('foo');
paragraphFoo.classList.add('bar');
paragraphFoo.classList; // ['foo', 'bar']
paragraphFoo.classList.remove('foo');
paragraphFoo.classList; // ['bar']
There are several more methods that can be used on an element. You can check the Mozilla developer docs for a list of the available methods.
Selectors
Disclaimer
In this section, when I describe a selector as returning an array, that's technically not true. They're either an HTMLCollection
or a NodeList
of elements. They're not technically arrays, in that you can't use the array methods (map
, reduce
, etc.) on them, but you can loop through and access the individual elements the same way you would an array (for
loop, bracket notation, etc). That also means when describing the console.log()
result of one of these, it's not entirely accurate either. Instead of the full element (e.g. [<li class="foo">]Some item</li>]
), it returns a dot notation version of the elements returned (e.g. [li.foo]
). For simplicity's sake, I'm calling them arrays and using the full element. Just keep in mind that's not right from a technical standpoint, but is usable from a practical standpoint.
getElementById
Takes an HTML id as an argument. Returns a single element.
<p id="foo">Some text in a paragraph</p>
var paragraphFoo = document.getElementById('foo');
console.log(paragraphFoo); // <p id="foo">Some text in a paragraph</p>
getElementsByClassName
Takes an HTML/CSS class name as an argument. Returns an array of elements.
<p class="bar">paragraph 1</p>
<p>paragraph 2</p>
<p class="bar">paragraph 3</p>
var paragraphArray = document.getElementsByClassName('bar');
console.log(paragraphArray);
// [<p class="bar">paragraph 1</p>, <p class="bar">paragraph 3</p>]
getElementsByTagName
Takes an HTML tag ('p', 'div', etc.) as an argument. Returns an array of elements.
// Using the structure example near the top
var listItems = document.getElementsByTagName('li');
console.log(listItems);
// [<li>List Item 1</li>, <li>List Item 2</li>, <li>List Item 3</li>]
getElementsByName
Takes a "name" attribute value as an argument. Returns an array of elements.
<input name="first_name" type="text">
<input name="last_name" type="text">
var firstName = document.getElementsByName('first_name');
console.log(firstName);
// [<input name="first_name" type="text>]
querySelector
Takes a CSS style selector as an argument. Returns the first matching element.
<p>I have <span class="num">2</span> cats.</p>
<div>I have <span class="num">3</span> dogs.</div>
var spanNumOfCats = document.querySelector('p .num');
console.log(spanNumOfCats);
// <span class="num">2</span>
querySelectorAll
Same as querySelector except that it returns an array containing all matched values.
<p>I have <span class="num cats">2</span> cats.</p>
<p>I have <span class="num dogs">3</span> dogs.</p>
<p>I have <span class="num rabbits">4</span> rabbits.</p>
var spanNonRabbitAnimals = document.querySelector('p .num:not(.rabbits)');
console.log(spanNonRabbitAnimals);
// [<span class="num cats">2</span>, <span class="num rabbits">4</span>]
In modern browsers and code, you'll generally only see/use querySelector
and querySelectorAll
as they greatly simplified the process and have made code a bit easier to read and understand. For example, if you need a single element with a class of foo
, document.querySelector('.foo');
is simpler than document.getElementsByClassName('foo')[0];
.
Posted on November 27, 2018
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.
Related
November 29, 2024