Docs

Module-17-DOM-Manipulation

10.1 DOM Basics

Overview

The Document Object Model (DOM) is a programming interface that represents HTML and XML documents as a tree structure. Each element, attribute, and piece of text becomes a node in this tree, allowing JavaScript to dynamically access and manipulate the document's content, structure, and styles.


The DOM Tree Structure

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                      DOM TREE STRUCTURE                         β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚                                                                 β”‚
β”‚                          document                               β”‚
β”‚                              β”‚                                  β”‚
β”‚                           <html>                                β”‚
β”‚                         /        \                              β”‚
β”‚                    <head>        <body>                         β”‚
β”‚                      β”‚             β”‚                            β”‚
β”‚                   <title>       <div>                           β”‚
β”‚                      β”‚         /     \                          β”‚
β”‚                   "Page"    <h1>     <p>                        β”‚
β”‚                              β”‚        β”‚                         β”‚
β”‚                          "Hello"  "World"                       β”‚
β”‚                                                                 β”‚
β”‚  Each box is a NODE:                                            β”‚
β”‚  - Element nodes: <html>, <body>, <div>, etc.                   β”‚
β”‚  - Text nodes: "Page", "Hello", "World"                         β”‚
β”‚  - Attribute nodes: id, class, href, etc.                       β”‚
β”‚  - Comment nodes: <!-- comments -->                             β”‚
β”‚                                                                 β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Node Types

TypenodeTypeDescriptionExample
Element1HTML tags<div>, <p>
Text3Text content"Hello World"
Comment8HTML comments<!-- note -->
Document9The documentdocument
DocumentFragment11Lightweight containercreateDocumentFragment()
const element = document.body;
console.log(element.nodeType); // 1 (Element)
console.log(element.nodeName); // "BODY"
console.log(element.nodeValue); // null (elements have no value)

const text = element.firstChild;
console.log(text.nodeType); // 3 (Text)
console.log(text.nodeValue); // The text content

Selecting Elements

Single Element Selection

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚              SINGLE ELEMENT SELECTORS                          β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚                                                                β”‚
β”‚  getElementById('id')                                          β”‚
β”‚  β”œβ”€β”€ Returns: Single element or null                           β”‚
β”‚  β”œβ”€β”€ Speed: Fastest                                            β”‚
β”‚  └── Usage: document.getElementById('header')                  β”‚
β”‚                                                                β”‚
β”‚  querySelector('selector')                                     β”‚
β”‚  β”œβ”€β”€ Returns: First matching element or null                   β”‚
β”‚  β”œβ”€β”€ Speed: Moderate                                           β”‚
β”‚  └── Usage: document.querySelector('.nav-item')                β”‚
β”‚             element.querySelector('span')                      β”‚
β”‚                                                                β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
// By ID - fastest method
const header = document.getElementById('header');

// By CSS selector - most flexible
const firstButton = document.querySelector('button');
const navLink = document.querySelector('.nav-link');
const emailInput = document.querySelector('input[type="email"]');
const firstChild = document.querySelector('ul > li:first-child');

Multiple Element Selection

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚              MULTIPLE ELEMENT SELECTORS                        β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚                                                                β”‚
β”‚  querySelectorAll('selector')                                  β”‚
β”‚  β”œβ”€β”€ Returns: Static NodeList                                  β”‚
β”‚  β”œβ”€β”€ Iterable: Yes (forEach, for...of)                         β”‚
β”‚  └── Live: No (doesn't update)                                 β”‚
β”‚                                                                β”‚
β”‚  getElementsByClassName('class')                               β”‚
β”‚  β”œβ”€β”€ Returns: Live HTMLCollection                              β”‚
β”‚  β”œβ”€β”€ Iterable: No (use Array.from)                             β”‚
β”‚  └── Live: Yes (updates automatically)                         β”‚
β”‚                                                                β”‚
β”‚  getElementsByTagName('tag')                                   β”‚
β”‚  β”œβ”€β”€ Returns: Live HTMLCollection                              β”‚
β”‚  β”œβ”€β”€ Iterable: No                                              β”‚
β”‚  └── Live: Yes                                                 β”‚
β”‚                                                                β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
// Static NodeList - use when you want a snapshot
const items = document.querySelectorAll('.menu-item');
items.forEach((item) => console.log(item.textContent));

// Live HTMLCollection - updates when DOM changes
const buttons = document.getElementsByClassName('btn');
console.log(buttons.length); // Changes as buttons are added/removed

// Convert to array for array methods
const buttonsArray = Array.from(buttons);
buttonsArray.filter((btn) => btn.classList.contains('primary'));

Static vs Live Collections

const container = document.getElementById('container');

// Static - querySelectorAll
const staticList = container.querySelectorAll('p');
console.log(staticList.length); // e.g., 3

// Live - getElementsByTagName
const liveList = container.getElementsByTagName('p');
console.log(liveList.length); // e.g., 3

// Add a new paragraph
const newP = document.createElement('p');
container.appendChild(newP);

console.log(staticList.length); // Still 3 (static)
console.log(liveList.length); // Now 4 (live)

DOM Traversal

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                    DOM TRAVERSAL                                β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚                                                                 β”‚
β”‚                     β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                             β”‚
β”‚                     β”‚ parentNode  β”‚                             β”‚
β”‚                     β”‚parentElementβ”‚                             β”‚
β”‚                     β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”˜                             β”‚
β”‚                            β”‚                                    β”‚
β”‚  previousSibling ◄─────────┼─────────► nextSibling              β”‚
β”‚  previousElement           β”‚           nextElement              β”‚
β”‚  Sibling                   β”‚           Sibling                  β”‚
β”‚                     β”Œβ”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”                             β”‚
β”‚                     β”‚   element   β”‚                             β”‚
β”‚                     β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”˜                             β”‚
β”‚                            β”‚                                    β”‚
β”‚              β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                      β”‚
β”‚              β”‚                           β”‚                      β”‚
β”‚        firstChild                  lastChild                    β”‚
β”‚        firstElementChild           lastElementChild             β”‚
β”‚                                                                 β”‚
β”‚              β”‚           β”‚           β”‚                          β”‚
β”‚              β–Ό           β–Ό           β–Ό                          β”‚
β”‚           child       child       child                         β”‚
β”‚                                                                 β”‚
β”‚         children (HTMLCollection of element children)           β”‚
β”‚         childNodes (NodeList of all child nodes)                β”‚
β”‚                                                                 β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Parent Navigation

const item = document.querySelector('.item');

// Parent element
const parent = item.parentElement; // <ul> or whatever contains it
const parentNode = item.parentNode; // Usually same, can be #document

// Go up multiple levels
const grandparent = item.parentElement.parentElement;

// Find closest ancestor matching selector
const container = item.closest('.container');
const form = item.closest('form'); // null if not in a form

Child Navigation

const list = document.querySelector('ul');

// Element children only (no text nodes)
const firstItem = list.firstElementChild;
const lastItem = list.lastElementChild;
const allItems = list.children; // HTMLCollection

// All nodes including text (whitespace)
const firstNode = list.firstChild; // Could be text node
const allNodes = list.childNodes; // NodeList

// Check if has children
const hasChildren = list.hasChildNodes();
const childCount = list.children.length;

Sibling Navigation

const middle = document.querySelector('.middle');

// Element siblings
const prev = middle.previousElementSibling;
const next = middle.nextElementSibling;

// All sibling nodes (including text)
const prevNode = middle.previousSibling;
const nextNode = middle.nextSibling;

// Get all siblings
function getSiblings(element) {
  return Array.from(element.parentElement.children).filter(
    (child) => child !== element
  );
}

Common DOM Properties

Element Properties

PropertyDescriptionExample
idElement's IDelement.id = 'main'
classNameClass stringelement.className = 'a b'
classListClass manipulationelement.classList.add('new')
tagNameTag name (uppercase)element.tagName // "DIV"
innerHTMLHTML contentelement.innerHTML = '<b>Hi</b>'
textContentText onlyelement.textContent = 'Hello'
innerTextVisible textelement.innerText

textContent vs innerHTML vs innerText

const div = document.createElement('div');
div.innerHTML = '<p>Hello <strong>World</strong></p>';

console.log(div.innerHTML); // '<p>Hello <strong>World</strong></p>'
console.log(div.textContent); // 'Hello World'
console.log(div.innerText); // 'Hello World' (respects CSS)

// Security: textContent is safer (no HTML parsing)
const userInput = '<script>alert("XSS")</script>';
div.textContent = userInput; // Safe - displays as text
div.innerHTML = userInput; // DANGER - could execute script

The classList API

const element = document.querySelector('.box');

// Add classes
element.classList.add('active');
element.classList.add('visible', 'highlight'); // Multiple

// Remove classes
element.classList.remove('hidden');
element.classList.remove('a', 'b', 'c'); // Multiple

// Toggle class
element.classList.toggle('active'); // Add or remove
element.classList.toggle('dark', isDarkMode); // Force add/remove

// Check for class
const isActive = element.classList.contains('active');

// Replace class
element.classList.replace('old-class', 'new-class');

// Iterate classes
element.classList.forEach((cls) => console.log(cls));

// Get class at index
const firstClass = element.classList.item(0);

Attributes

const link = document.querySelector('a');

// Get attribute
const href = link.getAttribute('href');
const target = link.getAttribute('target');

// Set attribute
link.setAttribute('href', 'https://example.com');
link.setAttribute('target', '_blank');

// Check if attribute exists
const hasTitle = link.hasAttribute('title');

// Remove attribute
link.removeAttribute('target');

// Data attributes
const card = document.querySelector('.card');
card.dataset.id = '123'; // Sets data-id="123"
const id = card.dataset.id; // Gets data-id value
card.dataset.userName = 'John'; // Sets data-user-name="John"

Document Properties and Methods

// Document references
document.documentElement; // <html>
document.head; // <head>
document.body; // <body>
document.title; // Page title

// Document information
document.URL; // Current URL
document.domain; // Domain name
document.referrer; // Previous page URL

// All forms, images, links
document.forms; // HTMLCollection of <form>
document.images; // HTMLCollection of <img>
document.links; // HTMLCollection of <a> with href

Performance Considerations

Selector Performance

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚              SELECTOR PERFORMANCE (Fastest to Slowest)          β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚                                                                β”‚
β”‚  1. getElementById('id')           β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ  Fastest β”‚
β”‚                                                                β”‚
β”‚  2. getElementsByClassName('cls')  β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ    Fast    β”‚
β”‚                                                                β”‚
β”‚  3. getElementsByTagName('tag')    β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ     Fast    β”‚
β”‚                                                                β”‚
β”‚  4. querySelector('#id')           β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ      Good    β”‚
β”‚                                                                β”‚
β”‚  5. querySelector('.class')        β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ        Good    β”‚
β”‚                                                                β”‚
β”‚  6. querySelectorAll('.items')     β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ          Medium  β”‚
β”‚                                                                β”‚
β”‚  7. querySelector('complex > sel') β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ            Slower  β”‚
β”‚                                                                β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Best Practices

// ❌ Avoid repeated queries
for (let i = 0; i < 100; i++) {
  document.querySelector('.item').style.color = 'red';
}

// βœ… Cache the reference
const item = document.querySelector('.item');
for (let i = 0; i < 100; i++) {
  item.style.color = 'red';
}

// ❌ Avoid querying in loops
items.forEach(() => {
  const container = document.getElementById('container');
  // ...
});

// βœ… Query once outside loop
const container = document.getElementById('container');
items.forEach(() => {
  // Use container
});

// βœ… Scope queries to parent elements
const form = document.getElementById('myForm');
const input = form.querySelector('input'); // Only searches within form

Key Takeaways

  1. β€’DOM is a tree - HTML becomes a hierarchical node structure
  2. β€’Use querySelector/querySelectorAll - Most flexible selection methods
  3. β€’Cache DOM references - Avoid repeated queries
  4. β€’getElementById is fastest - Use when selecting by ID
  5. β€’Static vs Live - querySelectorAll is static, getElementsBy* is live
  6. β€’Use textContent over innerHTML - Safer and faster for text
  7. β€’classList for classes - Modern API for class manipulation
  8. β€’Scope your queries - Search within parent elements when possible
Module 17 DOM Manipulation - JavaScript Tutorial | DeepML