5. DOM basics & events
JavaScript · 56 pages source format
The DOM is the browser's tree representation of HTML. querySelector finds elements. textContent and classList update them. addEventListener handles clicks, input, and keyboard. Build a todo app without React — this is how frameworks work under the hood.
What you'll learn
- querySelector / querySelectorAll
- Creating & removing nodes
- Events & delegation
- classList & data attributes
- localStorage preview
Select and modify
document.querySelector(".class") returns first match. querySelectorAll returns NodeList. Prefer textContent over innerHTML for user text (XSS safety).
<!-- index.html -->
<h1 id="title">Hello</h1>
<button id="btn">Change</button>
<script>
document.getElementById("btn").addEventListener("click", () => {
document.getElementById("title").textContent = "Updated!"
})
</script>Do this now
Create index.html with a heading and button. JS changes heading text on click.
Create and remove elements
document.createElement("li"), appendChild, remove. Template strings help build HTML snippets — sanitize if using innerHTML with user data.
Do this now
Build a list where typing in an input and pressing Enter adds a new li.
Event delegation
Attach one listener on a parent instead of many on children. event.target identifies which child was clicked. Essential for dynamic lists.
Do this now
Add delete buttons to each todo item. One listener on ul handles all delete clicks via event.target.closest("li").
Pro tip. event.preventDefault() stops form submit or link navigation when you handle it in JS.
Forms and input events
input fires on every keystroke; change fires on blur/select. Form submit — preventDefault, read FormData or individual fields.
Do this now
Add a filter input that hides todos not matching the search string in real time.
Persist with localStorage
localStorage.setItem(key, JSON.stringify(data)) survives refresh. Load on page init. No server needed for practice projects.
const save = (todos) => localStorage.setItem("todos", JSON.stringify(todos))
const load = () => JSON.parse(localStorage.getItem("todos") ?? "[]")Do this now
Save todos to localStorage on every change. Load on DOMContentLoaded.