O'Reilly logo

DOM Enlightenment by Cody Lindley

Stay ahead with the world's most comprehensive technology and business learning platform.

With Safari, you learn the way you learn best. Get unlimited access to videos, live online training, learning paths, books, tutorials, and more.

Start Free Trial

No credit card required

Chapter 4. Element Node Selection

4.1 Selecting a Specific Element Node

The most common methods for getting a reference to a single element node are:

  • querySelector()

  • getElementById()

In the following code, I leverage both of these methods to select an element node from the HTML document.

Live code

<!DOCTYPE html>
<html lang="en">
<body>

<ul>
<li>Hello</li>
<li>big</li>
<li>bad</li>
<li id="last">world</li>
</ul>

<script>

console.log(document.querySelector('li').textContent); //logs Hello
console.log(document.getElementById('last').textContent); //logs world

</script>
</body>
</html>

The getElementById() method is pretty simple compared to the more robust querySelector() method. The querySelector() method permits a parameter in the form of a CSS selector syntax. Basically, you can pass this method a CSS3 selector (e.g., #score>tbody>tr>td:nth-of-type(2)), which it will use to select a single element in the DOM.

Notes

querySelector() will return the first node element found in the document based on the selector. For example, in the preceding code, I pass a selector that will select all the <li> elements in CSS, but only the first one is returned.

querySelector() is also defined on element nodes. This allows the method to limit its results to a specific vein of the DOM tree, thereby enabling context quering.

4.2 Selecting/Creating a List (a.k.a. NodeList) of Element Nodes

The most common methods for selecting/creating a list of nodes in an HTML document are:

  • querySelectorAll()

  • getElementsByTagName()

  • getElementsByClassName()

In the following code, I use all three of these methods to create a list of the <li> elements in the document.

Live code

<!DOCTYPE html>
<html lang="en">
<body>

<ul>
<li class="liClass">Hello</li>
<li class="liClass">big</li>
<li class="liClass">bad</li>
<li class="liClass">world</li>
</ul>

<script>

/* all of the methods below create/select the same list of <li> elements from the DOM 
*/
console.log(document.querySelectorAll('li'));
console.log(document.getElementsByTagName('li'));
console.log(document.getElementsByClassName('liClass'));

</script>
</body>
</html>

Note that the methods used in the preceding code example do not select a specific element; instead, they create a list of elements [a NodeList] from which you can choose.

Notes

NodeLists created from getElementsByTagName() and getElementsByClassName() are considered live and will always reflect the state of the document, even if the document is updated after the list is created/selected.

The querySelectorAll() method does not return a live list of elements. This means the list created from querySelectorAll() is a snapshot of the document at the time it was created and does not reflect the document as it changes. The list is static, not live.

querySelectorAll(), getElementsByTagName(), and getElementsByClassName are also defined on element nodes. This allows the methods to limit their results to a specific vein (or set of veins) of the DOM tree (e.g., document.getElementById('header').getElementsByClassName('a')).

I did not mention the getElementsByName() method, as it does not commonly leverage over other solutions, but you should be aware of its existence for selecting from a document form, img, frame, embed, and object elements that all have the same name attribute value.

Passing either querySelectorAll() or getElementsByTagName() the string '*', which generally means “all,” will return a list of all elements in the document.

Keep in mind that childNodes will also return a NodeList, just like querySelectorAll(), getElementsByTagName(), and getElementsByClassName.

The NodeLists are array-like lists/collections and have a read-only length property (but they do not inherit array methods).

4.3 Selecting All Immediate Child Element Nodes

Using the children property from an element node, we can get a list [an HTMLCollection] of all the immediate child nodes that are element nodes. In the following code, I use children to create a selection/list of all the <li>s contained within the <ul>.

Live code

<!DOCTYPE html>
<html lang="en">
<body>

<ul>
<li><strong>Hi</strong></li>
<li>there</li>
</ul>

<script>

var ulElement = document.querySelector('ul').children;

//logs a list/array of all immediate child element nodes
console.log(ulElement); //logs [<li>, <li>]

</script>
</body>
</html>

Notice that using children only gives us the immediate element nodes, excluding any nodes (e.g., text nodes) that are not elements. If the element has no children, children will return an empty array-like list.

Notes

HTMLCollections contain elements in document order; that is, they are placed in the array in the order the elements appear in the DOM.

HTMLCollections are live, which means any change to the document will be reflected dynamically in the collection.

4.4 Selecting Contextual Elements

The methods querySelector(), querySelectorAll(), getElementsByTagName(), and getElementsByClassName, typically accessed from the document object, are also defined on element nodes. This allows these methods to limit their results to a specific vein (or set of veins) of the DOM tree. In other words, you can select a specific context in which you would like the methods to search for element nodes by invoking these methods on element node objects.

Live code

<!DOCTYPE html>
<html lang="en">
<body>

<div>
<ul>
<li class="liClass">Hello</li>
<li class="liClass">big</li>
<li class="liClass">bad</li>
<li class="liClass">world</li>
</ul>
</div>

<ul>
<li class="liClass">Hello</li>
</ul>

<script>

/* select a div as the context to run the selecting methods only on the contents of the div */
var div = document.querySelector('div');

console.log(div.querySelector('ul'));
console.log(div.querySelectorAll('li'));
console.log(div.getElementsByTagName('li'));
console.log(div.getElementsByClassName('liClass'));

</script>
</body>
</html>

These methods operate not only on the live DOM, but also on programmatic DOM structures that are created in code.

Live code

<!DOCTYPE html>
<html lang="en">
<body>

<script>
//create DOM structure
var divElm = document.createElement('div');
var ulElm = document.createElement('ul');
var liElm = document.createElement('li');
liElm.setAttribute('class','liClass');
ulElm.appendChild(liElm);
divElm.appendChild(ulElm);

//use selecting methods on DOM structure
console.log(divElm.querySelector('ul'));
console.log(divElm.querySelectorAll('li'));
console.log(divElm.getElementsByTagName('li'));
console.log(divElm.getElementsByClassName('liClass'));

</body>
</html>

4.5 Preconfigured Selections/Lists of Element Nodes

You should be aware that there are some preconfigured, legacy array-like lists, containing element nodes from an HTML document. In the following list, I cover a few of these that might be handy to be aware of:

document.all

All elements in the HTML document

document.forms

All <form> elements in the HTML document

document.images

All <img> elements in the HTML document

document.links

All <a> elements in the HTML document

document.scripts

All <script> elements in the HTML document

document.styleSheets

All <link> or <style> elements in the HTML document

Notes

These preconfigured arrays are constructed from the HTMLCollection interface/object, except for document.styleSheets, which uses StyleSheetList.

HTMLCollection is live, just like NodeList [except for querySelectorAll()].

Oddly, document.all is constructed from an HTMLAllCollection, not an HTMLCollection, and is not supported in Firefox.

4.6 Using matchesSelector() to Verify That an Element Will Be Selected

Using the matchesSelector() method, we can determine whether an element will match a selector string. For example, say we want to determine whether an <li> is the first child element of a <ul>. In the following code example, I select the first <li> inside the <ul> and then ask whether that element matches the selector, li:first-child. Because if it in fact does, the matchesSelector() method returns true.

Live code

<!DOCTYPE html>
<html lang="en">
<body>

<ul>
<li>Hello</li>
<li>world</li>
</ul>

<script>

//fails in modern browser must use browser prefix moz, webkit, o, and ms
console.log(document.querySelector('li').matchesSelector('li:first-child'));
//logs false

//prefix moz
/* console.log(document.querySelector('li').mozMatchesSelector('li:first-child')); 
      */

//prefix webkit
/* console.log(document.querySelector('li').webkitMatchesSelector('li:first-child')); 
      */

//prefix o
/* console.log(document.querySelector('li').oMatchesSelector('li:first-child'));
       */

//prefix ms
/* console.log(document.querySelector('li').msMatchesSelector('li:first-child'));
       */

</script>
</body>
</html>

Notes

matchesSelector() has not seen much love from the browsers, as its usage is behind that of the browser prefixes mozMatchesSelector(), webkitMatchesSelector(), oMatchesSelector(), and msMatchesSelector().

In the future, matchesSelector() will be renamed to matches().

With Safari, you learn the way you learn best. Get unlimited access to videos, live online training, learning paths, books, interactive tutorials, and more.

Start Free Trial

No credit card required