JavaScript · Lesson 6 of 6
The DOM and Events
Select elements, react to clicks and update the page.
- Intermediate
- 14 min read
- 3 objectives
Before this lessonLesson 5: Promises and async/await
What you will learn
- Query the DOM
- Add event listeners
- Update text and classes
When a browser loads an HTML page it builds the DOM (Document Object Model), a tree of objects representing every element. JavaScript can read and change that tree, which is how pages become interactive. Everything starts from the global document object.
What the DOM is
When a browser loads HTML it builds a live tree of objects in memory, one for every element. That tree is the DOM (Document Object Model). JavaScript can find any node in the tree, read it, change it, add new ones, and react when the user interacts with them. Everything dynamic on a web page, from a dropdown menu to a live search, is JavaScript editing the DOM.
Picture the HTML as a family tree: <html> is the ancestor, <body> a child, and each paragraph or button a leaf further down. To change the page you locate the right relative, then change it.
<body>
<h1 id="title">Todo</h1>
<ul id="list">
<li>Learn JS</li>
</ul>
</body>Selecting elements
const title = document.querySelector("h1"); // first match
const items = document.querySelectorAll(".item"); // all matches
const byId = document.getElementById("save");querySelector takes any CSS selector, so you already know the syntax. It returns null if nothing matches, so check before using the result.
Changing content and style
title.textContent = "Welcome back";
title.classList.add("highlight");
title.classList.toggle("hidden");
title.setAttribute("data-state", "ready");
title.style.color = "tomato";Prefer textContent over innerHTML for plain text. Setting innerHTML with user-supplied text opens the door to cross-site scripting (XSS) attacks. Prefer toggling CSS classes over setting inline styles.
Events
An event listener runs a function when something happens: a click, a key press, a form submit. The function receives an event object describing what occurred.
const button = document.querySelector("#save");
let clicks = 0;
button.addEventListener("click", (event) => {
clicks += 1;
button.textContent = `Saved ${clicks} times`;
});
const form = document.querySelector("form");
form.addEventListener("submit", (e) => {
e.preventDefault(); // stop the page reload
console.log(new FormData(form).get("email"));
});Creating elements
const li = document.createElement("li");
li.textContent = "New task";
document.querySelector("ul").append(li);Event delegation
Instead of attaching a listener to every list item, attach one to the parent and inspect event.target. It works for items added later, and uses less memory.
document.querySelector("ul").addEventListener("click", (e) => {
const li = e.target.closest("li");
if (li) li.classList.toggle("done");
});A complete example: a working to-do list
This page combines everything from the lesson: find elements, listen for a click, read an input, create an element and add it to the page. Save it as todo.html and open it in your browser.
<!DOCTYPE html>
<html>
<body>
<h1>My tasks</h1>
<input id="task" placeholder="New task">
<button id="add">Add</button>
<ul id="list"></ul>
<script>
const input = document.querySelector("#task");
const list = document.querySelector("#list");
document.querySelector("#add").addEventListener("click", () => {
const text = input.value.trim();
if (!text) return; // ignore empty input
const li = document.createElement("li");
li.textContent = text; // textContent is safe from HTML injection
list.append(li);
input.value = "";
input.focus();
});
</script>
</body>
</html>How to read that code
querySelectorfinds the first element matching a CSS selector.addEventListener("click", fn)registersfnto run each time the button is clicked.- Inside the handler we read the input's
value, create an<li>, set its text andappendit to the list. - Finally we clear the field and put the cursor back so the user can type the next task.
Toggling classes instead of styles
Rather than setting colours from JavaScript, add or remove a CSS class and let the stylesheet decide how it looks. This keeps design in CSS and behaviour in JavaScript.
<style>
.done { text-decoration: line-through; color: gray; }
</style>
<ul id="list"><li>Buy milk</li><li>Write code</li></ul>
<script>
document.querySelector("#list").addEventListener("click", (event) => {
if (event.target.matches("li")) {
event.target.classList.toggle("done");
}
});
</script>Debugging DOM code
nullerrors usually mean your selector found nothing. Check the spelling and that the script runs after the element exists.- Open DevTools, choose the Elements tab and confirm what the page really contains.
- Log the event:
console.log(event.target)shows exactly what was clicked.
Key takeaways
- The DOM is a live tree of objects the browser builds from your HTML.
- Find with
querySelector, change withtextContentandclassList, add withcreateElementandappend. - React to users with
addEventListener; use one listener on a parent for many children. - Prefer
textContentoverinnerHTMLfor user text.
// Write your solution here
