Introduction to DOM Manipulation
Tags: tutorial, beginners, javascript, html
Published: 2020-01-02 00:38:41

**Subscribe to my email list now at http://jauyeung.net/subscribe/**

**Follow me on Twitter at https://twitter.com/AuMayeung**

**Many more articles at https://medium.com/@hohanga**

Making websites dynamic is important for a lot of websites. Many of them have animations and dynamically display data. To change data without refreshing the page, we have to manipulate the document being displayed. Web pages are displayed in the browser by parsing them in the tree model called the Document Object Model (DOM).

The DOM tree is made up of individual components, called _nodes._ All web pages’ DOMs start with the root node, which is the document node. The node under the document node is the root element node.

For web pages, the root element node is the HTML node. Below that, every other node is under the HTML node, and there lie nodes below some of the nodes which are linked to the parent node. Together, the nodes form something that’s like an inverted tree.

There are several types of nodes in the DOM:

*   Document node — the root of the DOM in all HTML documents
*   Element node — the HTML elements
*   Attribute nodes — attributes of the element nodes
*   Text nodes — text content of HTML elements
*   Comment nodes — HTML comments in a document

* * *

Relationship of Nodes
=====================

The DOM is a tree with a root node and elements linked to the root node.

Every node has one parent node — except the root node. Each node can have one or more children. Nodes can also have siblings that reside at the same level of the given node.

If there are multiple elements of the same type, then you can get the node by getting the same type of node as a node list and then get the one you want by its index. A node list looks like an array, but it’s not one. You can loop through the elements of a node list, but array methods aren’t available in node lists.

For example, if we have the following HTML document …

```html
<html>  
  <head>  
    <title>HTML Document</title>  
  </head>  
  <body>  
    <section>  
      <p>First</p>  
      <p>Second</p>  
      <p>Third</p>  
    </section>  
  </body>  
</html>
```

… then we can get the document `p` tags, by adding the following:

```javascript
const list = document.body.childNodes\[1\].childNodes;  
for (let i = 0; i < list.length; i++) {  
  console.log(list)  
}
```

In the script of the document to get the nodes, the script gets the body and then gets the second child node (which is the `section` tag). Then it gets the child node by accessing the `childNodes` property again, which will get the `p` tags.

Together, we have:

```html
<html>  
  <head>  
    <title>HTML Document</title>  
  </head>  
  <body>  
    <section>  
      <p>First</p>  
      <p>Second</p>  
      <p>Third</p>  
    </section>  
    <script>  
      const list = document.body.childNodes[1].childNodes;  
      for (let i = 0; i < list.length; i++) {  
        console.log(list)  
      }      
    </script>  
  </body>  
</html>
```

There are also convenience properties for accessing the first and last child and siblings of elements of a given node.

In a node element, we have the `firstChild` property to get the first child of a node. In the `lastChild` property, we can get the last child of a given node. `nextSibling` gets the next child node in the same parent node, and `previousSibling` gets the previous child node of the same parent node.

Each node has some properties and methods that allow us to get and set properties of a node. They are the following:

*   `anchors` gets a list of all anchors, elements with name attributes, in the document
*   `applets` gets an ordered list of all the applets in the document
*   `baseURI` gets the base URI of the document
*   `body` gets the `<body>` or the `<frameset>` node of the document body
*   `cookie` gets/sets a key value pair in the browser cookie
*   `doctype` gets the document type declaration of a document
*   `documentElement` gets the root document element
*   `documentMode` gets the mode used by the browser to render the document
*   `documentURI` gets/sets the location of the document
*   `domain` gets the domain name of the server that loaded the document
*   `embeds` gets all the `embed` elements in the document
*   `forms` gets all the `form` elements in the document
*   `head` gets the `head` element of the document
*   `images` gets all the `img` elements in the document
*   `implementation` gets the `DOMImplementation` object that handles the document
*   `lastModified` gets the latest date and time the document was modified
*   `links` gets all `area` and `a` tags that contain the `href` attribute
*   `readyState` gets the loading status of the document. `readyState` is `loading` when the document is loading, `interactive` when the document finishes parsing, and `complete` when it completes loading.
*   `referrer` gets the URL the current document is loaded from
*   `scripts` get the `script` elements in the document
*   `title` get the `title` element of the document
*   `URL` get the URL of of the document

The DOM has methods to get and manipulate elements and handle events by attaching event handlers. The methods are below:

*   `addEventListener()` attaches an event handler to the document
*   `adoptNode()` adopts a node from another document
*   `close()` closes the output writing stream of the document that was previously opened with `document.open()`
*   `createAttribute()` creates an attribute node
*   `createComment()` creates a common node
*   `createDocumentFragment()` creates an empty document fragment
*   `createElement()` creates an element node
*   `createTextNode()` creates a text node
*   `getElementById()` gets an element in the document with the given ID
*   `getElementByClassName()` gets all elements with the given class name
*   `getElementByName()` gets all elements with the given name attribute
*   `getElementsByTagName()` gets all elements with the given tag name
*   `importNode()` imports a node from another document
*   `normalize()` clears the text node and joins together adjacent nodes
*   `querySelector()` gets one element with the given CSS selector(s)
*   `querySelectorAll()` gets all elements with the given CSS selector(s)
*   `removeEventListener()` removes an event handler that’s been added using the `addEventListener()` method from the document
*   `renameNode()` renames an existing node
*   `write()` write JavaScript or HTML code to a document
*   `writeln()` write JavaScript or HTML code to a document and adds a new line after each statement

Element objects have special properties that can be get or set to modify the given element. The are:

*   `accessKey` gets/sets the `accessKey` attribute of an element
*   `attributes` gets all attributes of a node
*   `childElementCount` gets the number of child elements of a node
*   `childNodes` gets the child nodes of a node
*   `children` gets the child elements of an element
*   `classList` gets all the class names of an element
*   `className` gets or sets the class names of an element
*   `clientHeight` gets the height of an element including padding
*   `clientLeft` gets the left border width of an element
*   `clientTop` gets the top border width of an element
*   `clientWidth` gets the width of an element including padding
*   `contentEditable` gets or sets whether content is editable
*   `dir` gets or sets the `dir` attribute of an element
*   `firstChild` gets the first child node of an element
*   `firstElementChild` gets the first child element of an element
*   `id` gets or sets the ID of an element
*   `innerHTML` gets or sets the content of an element
*   `isContentEditable` gets whether the content ID is editable as a Boolean
*   `lang` gets or sets the language of the element or attribute
*   `lastChild` gets the last child node of an element
*   `lastElementChild` gets the last child element of an element
*   `namespaceURI` gets the namespace URI of the first node of an element
*   `nextSibling` gets the next node at the same node level
*   `nextElementSibling` gets the next element at the same level
*   `nodeName` gets the selected node’s name
*   `nodeType` gets the node type
*   `nodeValue` gets the value of the node
*   `offsetHeight` gets the height of the node, which includes padding, borders, and the scrollbar
*   `offsetWidth` gets the width of the node, which includes padding, borders, and the scrollbar
*   `offsetLeft` gets the horizontal offset of an element
*   `offsetParent` gets the offset container of an element
*   `offsetTop` gets the vertical offset of an element
*   `ownerDocument` gets the root element of an element
*   `parentNode` gets the parent node of an element
*   `parentElement` gets the parent element of an element
*   `previousSibling` gets the previous node of an element
*   `previousElementSibling` gets the previous element of an element at the same level
*   `scrollHeight` gets the height of an element, including padding
*   `scrollLeft` gets the number of pixels of the element that has been scrolled horizontally
*   `scrollTop` gets the number of pixels of the element that has been scrolled vertically
*   `scrollWidth` gets the width of an element, including padding
*   `style` gets the CSS styles of the element
*   `tabIndex` gets the `tabindex` attribute of an element
*   `tagName` gets the tag name of an element
*   `textContent` gets or sets the text content of an element
*   `title` gets or sets the `title` attribute of an element
*   `length` gets the number of nodes in a NodeList

An element has the following methods for manipulating it:

*   `addEventLIstener()` attaches an event handler to an element
*   `appendChild()` adds a child node to an element at the end
*   `blur()` removes the focus from an element
*   `click()` clicks on an element
*   `cloneNode()` clones the given node
*   `compareDocumentPosition()` compares the position of two elements
*   `contains()` checks if an element has a given node
*   `focus()` focuses on an element
*   `getAttribute()` gets an attribute of an element
*   `getAttributeNode()` gets an attribute of an element
*   `getElementsByClassName()` gets an element with the given class name
*   `getElementByTagName()` gets an element with the given tag name
*   `getFeature()` gets an object that implements the API of a given feature
*   `hasAttribute()` returns `true` if an element has the given attribute or `false` otherwise
*   `hasAttributes()` returns `true` if an element has the given attributes or `false` otherwise
*   `hasChildNodes()` returns `true` if an element has child node or `false` otherwise
*   `insertBefore()` adds a child node before the given element
*   `isDefaultNamespace()` returns `true` if the stated `namespaceURI` is the default or `false` otherwise
*   `isEqualNode()` checks whether two nodes are equal
*   `isSameNode()` checks if two nodes are the same
*   `isSupported()` returns `true` if a given feature is supported on an element
*   `querySelector()` gets the first element with the given CSS selector
*   `querySelectorAll()` gets all elements with the given CSS selector
*   `removeAttribute()` removes an attribute from the given element
*   `removeAttributeNode()` removes an attribute node from the given element
*   `removeChild()` removes the first child node
*   `replaceChild()` replaces a specified child node with another
*   `removeEventListener()` removes a specified event handler
*   `setAttribute()` sets the stated attribute to the specified value
*   `setAttributeNode()` sets the stated attribute node
*   `toString()` converts an element to a string
*   `item()` gets a node with the given index in the NodeList

* * *

Changing Element Content
========================

If we select an element, we can set the `innerHTML` property to set the content of the element. For example, if we have an `element` DOM element, then we can write:

```javascript
element.innerHTML = 'content';
```

We set the content inside the element and leave the rest unchanged.

* * *

Getting Elements
================

The most convenient way to work with elements is to get them with the methods listed above. The most commonly used ones are `getElementById`, `getElementsByTagName`, `getElementsByClassName`, and `querySelector`, `querySelectorAll`.

getElementById
--------------

`getElementById` lets us get an element by its ID, as its name suggested. It doesn’t matter where the element is, the browser will search the DOM until it finds an element with the given ID or returns `null` if it doesn’t exist.

We can use it as follows:

```html
<html> 
  <head>  
    <title>Hello</title>  
  </head> 
  <body>  
    <p>  
      Hello <span id='name'>  
      </span>  
    </p>  
    <script>  
     const nameEl = document.getElementById('name');  
     nameEl.innerHTML = 'Jane';  
    </script> 
  </body>
</html>
```

In the code above, we get the element with the ID `name` and set the content to Jane, so we get “‘Hello Jane” on the screen.

getElementsByTagName
--------------------

To get all the elements with the given tag name, we use the `getElementsByTagName` function to get all the elements with the given tag name.

We can use it as follows:

```html
<html> 
  <head>  
    <title>How are You</title>  
  </head> 
  <body>  
    <p>  
      Hello <span></span>  
    </p>  
    <p>  
      How are you <span></span>?  
    </p>  
    <p>  
      Goodbye <span></span>  
    </p>  
    <script>  
      const spanEls = document.getElementsByTagName('span');  
      for (let i = 0; i < spanEls.length; i++) {  
        spanEls[i].innerHTML = 'Jane';  
      }  
    </script>  
  </body>  
</html>
```

In the code above, we get all the `span` elements with `getElementsByTag` to get all the `span` elements.

getElementsByClassName
----------------------

To get all the elements with the given class name, we use the `getElementsByClassName` function.

We can use it as follows:

```html
<html>
  <head>  
    <title>How are You</title>  
  </head><body>  
    <p>  
      Hello <span class='name'>  
      </span>  
    </p>  
    <p>  
      How are you <span class='name'>  
      </span>?  
    </p>  
    <p>  
      Goodbye <span class='name'>  
      </span>  
    </p>  
    <script>  
      const nameEls = document.getElementsByClassName('name');  
      for (let i = 0; i < nameEls.length; i++) {  
        nameEls[i].innerHTML = 'Jane';  
      }  
    </script>  
  </body>  
</html>
```

* * *

Appending Element to an existing Element
========================================

We can create a new element and attach it to an existing element as a child by using the `createElement` method and then using the `appendChild` method and pass in the element created with `createElement` as the argument of the `appendChild` function. We can use it like in the following example:

```html
<html> 
  <head>  
    <title>Hello</title>  
  </head> 
  <body>  
    <h1>  
      Hello,  
    </h1>  
    <ul id='helloList'> </ul> <script>  
      const names = ['Mary', 'John', 'Jane'];  
      const helloList = document.getElementById('helloList');  
      for (let name of names) {  
        const li = document.createElement('li');  
        li.innerHTML = name;  
        helloList.appendChild(li);  
      }  
    </script>  
  </body>
</html>
```

* * *

Removing Elements
=================

We can remove elements with the `removeChild` function. This means you have to find the child you want to remove and then get the parent node of that node. Then you can pass in that element object to the `removeChild` function to remove it.

Below is an example of this:

```html
<html> 
  <head>  
    <title>Remove Items</title>  
  </head> 
  <body>  
    <ul>  
      <li id='1'>One <button onclick='remove(1)'>  
          remove  
        </button></li>  
      <li id='2'>Two <button onclick='remove(2)'>  
          remove  
        </button></li>  
      <li id='3'>Three <button onclick='remove(3)'>  
          remove  
        </button></li>  
    </ul> <script>  
      remove = function(id) {  
        const el = document.getElementById(id);  
        el.parentNode.removeChild(el);  
      }  
    </script>  
  </body>
</html>
```

As you can see, we have to get the node we want to remove and then get the parent node of that by using the `parentNode` property. Then we call `removeChild` on that. There’s no easier way to remove a node directly.

Now that we can create, manipulate, and remove nodes, we can make simple dynamic web pages without too much effort. Manipulating the DOM directly isn’t very sustainable for complex pages because lots of elements change in the DOM, making getting DOM elements directly difficult and error-prone. The DOM tree changes too much, so it’s very fragile if we make complex dynamic websites this way.