The DOM and Events
Select elements, react to clicks and update the page.
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.
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.
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"));
});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");
});Scripts placed in the <head> run before the elements exist. Add defer to the script tag, or place it at the end of <body>.
Try it yourself
Build a counter: a button that increments a number shown on the page each time it is clicked, plus a reset button.
Show solution
// HTML: <p id="n">0</p> <button id="inc">+1</button> <button id="reset">Reset</button>
let n = 0;
const out = document.querySelector("#n");
document.querySelector("#inc").addEventListener("click", () => {
out.textContent = ++n;
});
document.querySelector("#reset").addEventListener("click", () => {
n = 0;
out.textContent = n;
});