DEV Community

Cover image for Manipulating the DOM using Javascript - traversing the DOM(part 2)✂️🕹
Arika O
Arika O

Posted on

Manipulating the DOM using Javascript - traversing the DOM(part 2)✂️🕹

In the last article we learned what the DOM is and that it can be manipulated (change the nodes inside it). We also learned about one way we can target DOM nodes using different selectors (if you didn't read the first article of the series, I recommend doing so before going any further). We basically learned how to make use of the built-in methods of the document object to access HTML elements by class, id, tage name or query selectors.

Another way of targeting nodes is by traversing the DOM. Traversing simply means to move throught the DOM using the relation between nodes (when having access to a certain DOM node, we can reach its related nodes). This means we can stay on the same DOM level (branch) while moving up, down or even sideways.

But why would we need to do that? We would think that using document.querySelector() would be enough for every situation we encounter when trying to manipulate the DOM. Well, yes and no.

Let's think of an analogy

Imagine you are inside of your favorite book store, where the books in a series are sorted in ascending order, from left to right. You are looking at the first Harry Potter volume that's sitting on a shelf. You're missing the first two volumes and you would like to buy them, so after you found the first one, you know the second should be next to it. Now you have two possibilities to get the second volume:

  • You get it directly from the shelf, since you can move a bit to the right and find it right away.
  • You go to the cash register and ask for the person working there to look for the book in their system, tell you where in the store it's located and then go get it.

Which approach would be faster? The first one, of course. We found the second volume based on the position (relation) to the first one, instead of interogating the system (do a search by name). Based on this analogy, it will always be easier to move from one node to the other than doing a full search.

TRAVERSING THE DOM

Before moving forward, let's write some simple HTML code so we can visualize our examples better:

<!DOCTYPE html>
<html>
 <head>
   <title>Traversing the DOM is fun!</title>
 </head>
 <body>
  <h2>How to</h2>
  <p>If you want to learn how to traverse the DOM, you should continue reading this 
   tutorial.</p>
  <h2>We can traverse the DOM based on the relation between:</h2>
  <ul id="nodesList">
    <li>Parent nodes</li>
    <li>Children nodes</li>
    <li>Siblings nodes</li>
  </ul>
 </body>
</html>
Enter fullscreen mode Exit fullscreen mode

A real representation of the DOM based on the above HTML looks like bellow (if you want to generate real DOM trees, you can use this tool)

Image description

We can traverse the DOM based on the relation between parent, children and sibling nodes. We have the first node in the tree which is called the root node. This is the only node that doesn't have a parent since it's positioned on the highest level. Every other node has exactly one parent and can have any number of children. We call nodes with the same parent sibling nodes.

In our example above, the simplest parent-child relationship between nodes is:

  • the document is the root node and it has two children: the DOCTYPE declaration and the html
  • the html is the parent of head and body
  • the body is the parent of h2, p, h2 and ul
  • the ul is parent to the lis

Also, let's remember that everything in an HTML document is considered a node and we have:

  • the Document, which in itself is a node
  • HTML elements, which are Element Nodes
  • the text inside the HTML elements, which are Text Nodes
  • comments, which are Comment Nodes

TRAVERSING BASED ON THE PARENT NODE RELATION

A parent node is any node that is one level above another node, or closer to the document node in the DOM hierarchy. There are two ways to get the parent of a node: parentNode and parentElement. So, in our example, if we would want to get the parent node of the first h2, we would say:

// first we target the h2 tag
const headerTwo = document.getElementsByTagName("h2")[0];
const parent = headerTwo.parentNode;
console.log(parent);
 (1) [body]
Enter fullscreen mode Exit fullscreen mode

What we are going to get is the <body></body> tag, since it's one level above the <h2></h2> tag. If we want to go even one more level up, we can chain multiple parentNode properties, like so:

const headerTwo = document.getElementsByTagName("h2")[0];
const parent = headerTwo.parentNode.parentNode;
console.log(parent);
 (1) [html]
Enter fullscreen mode Exit fullscreen mode

Now we 'll be targeting the <html></html> tag since it's one level above the <body></body>.

TRAVERSING BASED ON THE CHILDREN NODES RELATION

The children of a node are considered to be all nodes that are positioned one level bellow that node (that is one level of nesting).

The properties that help us target children nodes are: childNodes, firstChild, lastChild, children, firstElementChild and lastElementChild.

An interesting situation

If we would want to target the children of the <body></body> element in our example, we would probably say:

const bodyChildren = document.body.childNodes;
console.log(bodyChildren);
Enter fullscreen mode Exit fullscreen mode

I assume you would expect to see a list of four items printed to the console.

 (4) [h2, p, h2, ul]
Enter fullscreen mode Exit fullscreen mode

Instead you will see this:

 (9) [text, h2, text, p, text, h2, tex, ul, text]
Enter fullscreen mode Exit fullscreen mode

This is happening because the childNodes property is targeting all nodes, including text nodes. In our example, the indentation between the HTML lines of code are interpreted as text.

I think now is the perfect time to clarify what nodes (which were targeted by the childNodes property) and elements (h2, p, h2, ul, which we were expecting to see in the console) are.

A node is any object represented in the DOM. Nodes can be of multiple types but the ones we are going to encounter most often are document, element and text. So, elements are just nodes of the type element. A complete list of all node types can be found here.

Coming back to out example, where instead of four nodes we got back nine, this is because childNodes selects all node types (including text), not only the element ones, which we were interested in.

If we want to select only the children of the type node element, we can use the children, firstElementChild and lastElementChild properties. So, to rewrite our example:

const bodyChildren = document.body.children;
console.log(bodyChildren);
 (4) [h2, p, h2, ul]
Enter fullscreen mode Exit fullscreen mode

TRAVERSING BASED ON THE SIBLING NODES RELATION

A sibling node is any node that is on the same DOM level with any other node. In our example, h2, p, h2 and ul are all siblings since they are on the same DOM level. The property we can use to select sibling nodes are: previousSibling, nextSibling, previousElementSibling and nextElementSibling. Keep in mind that, just like in the case of child nodes, previousSibling and nextSibling select siblings of any type, whether previousElementSibling and nextElementSibling will only select nodes of type element.

So, if we want to select the second <li> element in the <ul>, we need to write:

// we target the list based on its id
const list = document.getElementById("nodesList");
// we target the first node of element type
const firstElement = list.firstElementChild;
// we use nextElementSibling to get to the second list item
const thirdElement = firstElement.nextElementSibling;
console.log(thirdElement )
 (1) [li]
Enter fullscreen mode Exit fullscreen mode

If instead we would have used the nextSibling property, the return value would have been a text node since the indentation in the HTML is considered text, so we would have targeted white space (a node of type text) instead of the next list item element.

const thirdElement = firstElement.nextSibling;
console.log(thirdElement )
 (1) [text]
Enter fullscreen mode Exit fullscreen mode

Now that we know how to traverse the DOM, in the next article we will focus on how we can actually change things in the DOM, with examples. See you next time!

Header source image: Paul Esch-Laurent on Unsplash

Refrence articles:

Top comments (1)

Collapse
 
nghihs profile image
Hồ Sỹ Nghi

Looking forward to the next part. thanks so much :D