Topic 20 of 26 · UI Designer

Topic 5 : JavaScript DOM

Lesson TL;DRTopic 5: JavaScript DOM 📖 6 min read · 🎯 intermediate · 🧭 Prerequisites: formbuttons, javascriptbom Why this matters Up until now, you've been building pages that look good — but they sit still. A ...
6 min read·intermediate·javascript · dom · event-handling · web-interactivity

Topic 5: JavaScript DOM

📖 6 min read · 🎯 intermediate · 🧭 Prerequisites: form-buttons, javascript-bom

Why this matters

Up until now, you've been building pages that look good — but they sit still. A user clicks a button and nothing moves. A form submits and the page just reloads. That gap between "a design" and "a living interface" is where JavaScript and the DOM come in.

The DOM — Document Object Model — is the bridge. It's how JavaScript sees your HTML: not as text, but as a tree of live objects it can grab, change, or delete in real time. Once you understand the DOM, you stop building static screens and start building things that actually respond.

What You'll Learn

  • Understand what the DOM is and how it represents an HTML document as a node tree
  • Access DOM elements using getElementById, getElementsByClassName, getElementsByTagName, querySelector, and querySelectorAll
  • Modify element content, attributes, and inline styles at runtime
  • Create new elements and remove existing ones programmatically
  • Attach and detach event listeners to make pages interactive
  • Build a working interactive to-do list that ties all techniques together

The Analogy

Think of a web page as a city's electrical grid. The HTML file is the blueprint — lines on paper showing where every light, switch, and outlet lives. The DOM is the live grid itself: actual wires carrying current, switches you can flip, bulbs you can swap out while the city is running. JavaScript is the electrician who walks the grid with a toolkit. She can read the meter on any circuit (getElementById), rewire a junction box (setAttribute), swap a bulb for a brighter one (textContent), or run a brand-new line to a section of the city that didn't exist in the original blueprint (createElement). None of those changes require shutting the city down — everything happens while residents go about their day.

Chapter 1: What Is the DOM?

The Document Object Model (DOM) is a programming interface for web documents. It represents the page so that programs can change the document structure, style, and content. The DOM represents the document as a tree of nodes, with each node representing part of the document.

graph TD
    document --> html
    html --> head
    html --> body
    head --> title
    body --> h1
    body --> ul
    ul --> li1["li #task-1"]
    ul --> li2["li #task-2"]

Every tag becomes an element node. Text inside a tag becomes a text node. Attributes live directly on their element node. Because it is a tree, every node knows its parent, its children, and its siblings — relationships JavaScript can traverse in any direction.

In short: the DOM is the bridge that lets JavaScript interact with HTML and CSS, making it possible to create dynamic, interactive web pages without ever reloading.

Chapter 2: Accessing DOM Elements

Before you can modify anything, you need a reference to it. The browser exposes several methods on the global document object.

getElementById

Returns the single element whose id attribute matches the given string.

let element = document.getElementById("myElement");
console.log(element);

getElementsByClassName

Returns a live HTMLCollection of all elements that carry the specified class name. Multiple elements can share a class, so you get a collection.

let elements = document.getElementsByClassName("myClass");
console.log(elements);

getElementsByTagName

Returns a live HTMLCollection of all elements with the given tag name.

let elements = document.getElementsByTagName("p");
console.log(elements);

querySelector and querySelectorAll

These accept any valid CSS selector — the most flexible option. querySelector returns the first match; querySelectorAll returns a static NodeList of all matches.

let element = document.querySelector(".myClass");
console.log(element);

let elements = document.querySelectorAll(".myClass");
console.log(elements);
MethodReturnsLive?Selector syntax
getElementByIdSingle elementID string
getElementsByClassNameHTMLCollectionYesClass string
getElementsByTagNameHTMLCollectionYesTag string
querySelectorSingle elementNoCSS selector
querySelectorAllNodeListNoCSS selector

Chapter 3: Modifying DOM Elements

Once you hold a reference to an element, you can change its content, attributes, and styles.

Changing Content

Use textContent to set plain text (safe — no HTML parsing). Use innerHTML when you deliberately need to inject markup.

let element = document.getElementById("myElement");
element.textContent = "New content here!";

Changing Attributes

setAttribute accepts any attribute name and its new value.

let element = document.getElementById("myElement");
element.setAttribute("class", "newClass");

You can also read attributes with getAttribute("name") and remove them with removeAttribute("name").

Changing Styles

The style property maps to inline CSS. Each CSS property is written in camelCase.

let element = document.getElementById("myElement");
element.style.color = "red";
element.style.backgroundColor = "yellow";

For bulk style changes, prefer toggling a CSS class (via classList) over setting individual style properties — it keeps your CSS in one place and is easier to override.

Chapter 4: Creating and Removing DOM Elements

The DOM is not frozen at page load — you can add and delete nodes at any time.

Creating Elements

document.createElement makes a new element node (not yet in the page). Attach it to the live tree with appendChild or insertBefore.

let newElement = document.createElement("p");
newElement.textContent = "This is a new paragraph.";
document.body.appendChild(newElement);

Removing Elements

removeChild detaches a child node from its parent.

let element = document.getElementById("myElement");
element.parentNode.removeChild(element);

A modern shorthand — available in all current browsers — is calling element.remove() directly, without needing a reference to the parent.

Chapter 5: Event Handling

Static pages display information. Interactive pages respond to the user. Events are the mechanism: the browser fires a named event whenever something happens (a click, a keypress, a form submission), and your code listens for it.

Adding Event Listeners

addEventListener(type, handler) registers a function to run whenever the named event fires on that element.

let button = document.getElementById("myButton");
button.addEventListener("click", function() {
    alert("Button was clicked!");
});

Common event types: "click", "input", "change", "submit", "keydown", "mouseover", "load".

Removing Event Listeners

To remove a listener, you must pass the exact same function reference that was used to add it. Anonymous functions cannot be removed this way — always assign named functions when you intend to clean up.

function handleClick() {
    alert("Button was clicked!");
}

let button = document.getElementById("myButton");
button.addEventListener("click", handleClick);

// Later — detach the same handler:
button.removeEventListener("click", handleClick);

Chapter 6: Putting It Together — Interactive To-Do List

The class's capstone example: a fully working interactive to-do list that exercises every technique covered above — element creation, content setting, event listening, and class toggling.

HTML (index.html)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Interactive To-Do List</title>
    <style>
        .completed {
            text-decoration: line-through;
            color: gray;
        }
    </style>
</head>
<body>
    <h1>To-Do List</h1>
    <input type="text" id="newTask" placeholder="Enter a new task">
    <button id="addTaskButton">Add Task</button>
    <ul id="taskList"></ul>
    <script src="todo.js"></script>
</body>
</html>

JavaScript (todo.js)

document.getElementById("addTaskButton").addEventListener("click", function() {
    let taskInput = document.getElementById("newTask");
    let taskText = taskInput.value;

    if (taskText === "") {
        alert("Please enter a task.");
        return;
    }

    let taskItem = document.createElement("li");
    taskItem.textContent = taskText;

    taskItem.addEventListener("click", function() {
        taskItem.classList.toggle("completed");
    });

    document.getElementById("taskList").appendChild(taskItem);
    taskInput.value = "";
});

What each line does:

  1. Listen for a click on the "Add Task" button.
  2. Read the current value of the #newTask input.
  3. Guard against empty submissions.
  4. Create a new <li> element and set its text.
  5. Attach a click listener to that <li> — clicking it toggles the .completed class (strike-through styling).
  6. Append the new list item to #taskList.
  7. Clear the input field so the user can type the next task immediately.
sequenceDiagram
    participant User
    participant Button
    participant JS as todo.js
    participant DOM

    User->>Button: click "Add Task"
    Button->>JS: fires "click" event
    JS->>DOM: createElement("li")
    JS->>DOM: appendChild(taskItem) to #taskList
    User->>DOM: click a task item
    DOM->>JS: fires "click" on li
    JS->>DOM: classList.toggle("completed")

🧪 Try It Yourself

Task: Extend the to-do list so each task item also has a Delete button that removes just that item from the list.

Success criterion: After adding three tasks and clicking a delete button on one of them, only two tasks remain in the list — no page reload required.

Starter snippet (paste this inside the taskItem.addEventListener("click", ...) block, after you create taskItem):

let deleteBtn = document.createElement("button");
deleteBtn.textContent = " ✕";
deleteBtn.addEventListener("click", function(event) {
    event.stopPropagation(); // prevent toggling .completed at the same time
    taskItem.parentNode.removeChild(taskItem);
});
taskItem.appendChild(deleteBtn);

🔍 Checkpoint Quiz

Q1. The DOM represents an HTML document as what kind of data structure?

A) A flat array of elements
B) A key-value map of IDs to tags
C) A tree of nodes
D) A doubly-linked list of sibling elements

Q2. Given this snippet, what is logged to the console?

let items = document.querySelectorAll(".card");
console.log(items.length);

Assume the page has exactly three elements with class card.

A) "NodeList"
B) 3
C) undefined
D) A live HTMLCollection

Q3. What is the bug in the following code?

function onResize() { console.log("resized"); }
window.addEventListener("resize", onResize);
window.removeEventListener("resize", function() { console.log("resized"); });

A) removeEventListener is not a valid method on window
B) removeEventListener receives a different function reference than the one added, so the listener is never removed
C) The event name "resize" is not a real browser event
D) There is no bug

Q4. You want to add a new <section> element directly before an existing <footer> inside document.body. Which DOM method would you use?

A) appendChild
B) insertBefore
C) setAttribute
D) createElement alone (no insertion method needed)

A1. C — The DOM models the document as a tree of nodes; every tag, text run, and attribute is a node with parent/child relationships.

A2. B — querySelectorAll returns a static NodeList; .length on a NodeList with three matches is 3.

A3. B — removeEventListener must receive the exact same function reference that was passed to addEventListener. An anonymous function that happens to have identical source text is still a different object in memory, so it doesn't match and the listener remains attached.

A4. B — parentNode.insertBefore(newSection, footer) inserts newSection immediately before footer in the DOM tree. createElement only creates the node; a separate insertion call is always required.

🪞 Recap

  • The DOM is a live, tree-shaped programming interface that lets JavaScript read and rewrite any part of a loaded HTML document.
  • Five selector methods — getElementById, getElementsByClassName, getElementsByTagName, querySelector, querySelectorAll — give you references to existing elements.
  • textContent, setAttribute, and the style property let you change content, attributes, and inline styles on any element reference.
  • createElement + appendChild adds new nodes; removeChild (or element.remove()) deletes them.
  • addEventListener and removeEventListener wire up and tear down event-driven behavior; always use named functions when you need to remove a listener later.

📚 Further Reading

Like this topic? It’s one of 26 in UI Designer.

Block your seat for ₹2,500 and join the next cohort.