Kodokon kodokon.com

Manipulating the DOM: querySelector, event listeners

Select elements on the page, react to clicks, and adopt event delegation for performant code.

9 min · 3 questions

Open this lesson in Kodokon

The DOM is the living representation of your HTML page: manipulating it is how JavaScript makes an interface interactive. The essential duo: select an element, then listen to what happens to it. Let's start with a small initial structure.

HTML
<button id="save-btn" class="btn">Save</button>
<ul class="task-list">
  <li>Buy groceries</li>
  <li>Call the client</li>
</ul>
The HTML page we will manipulate in the following examples.

querySelector accepts any CSS selector (#id, .class, ul li, [data-id]) and returns the first matching element, or null. querySelectorAll returns all matching elements in a NodeList, which you can iterate over with forEach.

JAVASCRIPT
const button = document.querySelector("#save-btn");
const firstTask = document.querySelector(".task-list li");
const tasks = document.querySelectorAll(".task-list li");

console.log(tasks.length); // 2
console.log(firstTask.textContent); // "Buy groceries"
A single element with querySelector, a NodeList with querySelectorAll.

To react to a user action, addEventListener attaches a function to an event type: click, input, submit, keydown... The function receives an event object describing what happened. You can then change content with textContent and styling with classList.

JAVASCRIPT
const button = document.querySelector("#save-btn");

button.addEventListener("click", () => {
  button.textContent = "Saved!";
  button.classList.add("success");
});
On click, the text changes and a CSS class is added.

A good professional habit: a list of 200 items does not deserve 200 listeners. Attach a single listener to the parent and identify the clicked element with event.target. This is event delegation: it even works for elements added later on.

JAVASCRIPT
const list = document.querySelector(".task-list");

list.addEventListener("click", (event) => {
  const item = event.target.closest("li");
  if (item) {
    item.classList.toggle("done");
  }
});
A single listener on the ul handles clicks for every li.

Knowledge check

Make sure you remember the key points of this lesson.

  1. What does document.querySelector(".btn") return if several elements have the btn class?
    • All matching elements
    • Only the first matching element
    • An error, because the selector is ambiguous
  2. What is the role of the second argument of addEventListener?
    • It's the function executed each time the event fires
    • It's the delay before listening starts
    • It's the CSS selector of the target element
  3. In a listener attached to a parent, what does event.target represent?
    • The parent that holds the listener
    • The exact element on which the event occurred
    • The browser window