loading...

JavaScript (ES5) - Working With Selectors

martyhimmel profile image Martin Himmel ・4 min read

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 by:

martyhimmel profile

Martin Himmel

@martyhimmel

Web dev and aspiring game dev who loves to teach and dabbles in various languages.

Discussion

markdown guide