Module 5 — DOM Manipulation
Make your pages come alive — read and update content, respond to events, and build interactivity.
Overview 📋
The DOM (Document Object Model) is the browser's live representation of your HTML. JavaScript can read any element on the page, change its content, modify its styles, add or remove elements, and respond to user interactions like clicks, keypresses, and form submissions. This is the foundation of all browser interactivity before you get to React.
Why This Matters 💡
Even though you will spend most of the program working in React, React is a layer on top of the DOM. Understanding how the DOM works — and how JavaScript manipulates it directly — gives you a foundation that makes React make sense. You will also occasionally need raw DOM skills even in React projects.
Learning Goals 🎯
By the end of this module you should be able to:
- Select elements using
querySelectorandquerySelectorAll - Read and update element content using
textContentandinnerHTML - Add, remove, and toggle CSS classes on elements
- Listen for and handle events:
click,input,submit - Create and append new elements to the DOM
- Read values from form inputs
- Prevent default browser behavior (e.g., form submission)
Vocabulary 📖
| Term | Definition |
|---|---|
| DOM | The browser's tree-structured representation of an HTML document |
| Node | Any item in the DOM tree (element, text, comment) |
| Event | Something that happens in the browser (click, scroll, submit) |
| Event listener | A function that runs when a specific event fires on an element |
| Event object | The argument passed to a listener, containing data about the event |
preventDefault() | Stops the browser's default behavior for an event |
querySelector | Returns the first element matching a CSS selector |
classList | A DOM API for adding, removing, and toggling CSS classes |
Core Concepts 🧠
Selecting elements
// select the first match
const btn = document.querySelector('#submit-btn')
const heading = document.querySelector('h1')
const card = document.querySelector('.card')
// select all matches (returns a nodelist)
const items = document.querySelectorAll('.list-item')
items.forEach((item) => console.log(item.textContent))
Reading and updating content
const heading = document.querySelector('h1')
// read
console.log(heading.textContent)
// update text (safe — no html parsing)
heading.textContent = 'New Title'
// update html (use only with trusted content)
heading.innerHTML = '<em>New</em> Title'
Handling events
const btn = document.querySelector('#submit-btn')
btn.addEventListener('click', (event) => {
console.log('button clicked', event)
})
// form submit
const form = document.querySelector('form')
form.addEventListener('submit', (event) => {
event.preventDefault() // stop the page from reloading
const input = document.querySelector('#name-input')
console.log('submitted:', input.value)
})
Modifying classes
const card = document.querySelector('.card')
card.classList.add('active')
card.classList.remove('hidden')
card.classList.toggle('expanded') // add if absent, remove if present
card.classList.contains('active') // true or false
Creating and appending elements
const list = document.querySelector('#todo-list')
const newItem = document.createElement('li')
newItem.textContent = 'Learn the DOM'
list.appendChild(newItem)
Examples 💻
A counter button:
let count = 0
const display = document.querySelector('#count')
const btn = document.querySelector('#increment')
btn.addEventListener('click', () => {
count++
display.textContent = count
})
Rendering a list from an array:
const students = ['Alex', 'Jordan', 'Sam']
const list = document.querySelector('#student-list')
students.forEach((name) => {
const item = document.createElement('li')
item.textContent = name
list.appendChild(item)
})
Filtering visible items by search input:
const searchInput = document.querySelector('#search')
const items = document.querySelectorAll('.item')
searchInput.addEventListener('input', () => {
const query = searchInput.value.toLowerCase()
items.forEach((item) => {
const match = item.textContent.toLowerCase().includes(query)
item.classList.toggle('hidden', !match)
})
})
Common Mistakes ⚠️
- Running DOM code before the page loads. If your
<script>tag is in<head>, the elements do not exist yet. Put scripts at the bottom of<body>, or useDOMContentLoaded. - Using
innerHTMLwith user input. This creates XSS vulnerabilities. UsetextContentfor user-supplied text. - Selecting an element that does not exist. If
querySelectorreturnsnull, calling methods on it throws aTypeError. Always check that the element exists. - Forgetting
event.preventDefault()on form submit. Without it, the page reloads and you lose your work. - Adding event listeners inside loops. Each iteration creates a new listener. Attach one listener to the parent and use event delegation instead.
Debugging Tips 🔍
- If your code runs but nothing changes, use
console.logto confirm thatquerySelectorfound the element (notnull). - Open DevTools → Console and check for errors before assuming the code is wrong.
- Use DevTools → Elements to watch attributes and class names change in real time as you interact with the page.
- If a form is reloading the page,
event.preventDefault()is missing. - Add
debuggerin your event listener to pause execution and step through it.
Exercise 🏋️
The exercise for this module is in the class repository:
ttpr-lagcc-spring-2026 → Module 5 Exercise (opens in new tab)
Build a simple to-do list using only HTML, CSS, and vanilla JavaScript. Add items from a form input, display them in a list, and allow the user to mark items as complete (toggle a class) and delete them.
Additional Resources 📚
- MDN — Introduction to the DOM (opens in new tab) — how the DOM works
- MDN — EventTarget.addEventListener (opens in new tab) — complete event listener reference
- MDN — Document.querySelector (opens in new tab) — selector API
- javascript.info — Document (opens in new tab) — excellent chapter on DOM manipulation
- javascript.info — Events (opens in new tab) — everything about events
Recap Checklist ✔️
- I can select elements using
querySelectorandquerySelectorAll - I can read and update element content with
textContent - I can attach event listeners for
click,input, andsubmit - I can prevent form default behavior with
event.preventDefault() - I can create and append new DOM elements
- I can toggle CSS classes using
classList - I understand why
innerHTMLwith user input is dangerous