Skip to content
WANCODE
BM

Events: Making Pages React to People

18 minBeginnerHTML · CSS · JS

In this lesson

  • Attach listeners with addEventListener for click, input and submit
  • Read information from the event object and stop a form from reloading the page
  • Explain event bubbling and use it to handle many elements with one listener

The big idea

An event listener says: "when this happens to that element, run this function". Your code stops running top-to-bottom once and starts waiting for the user.

Last lesson your script changed the page once, as soon as it loaded. Real interfaces wait: nothing happens until someone clicks, types or submits. Each of those actions fires an event, and you can listen for it.

JavaScript
const button = document.querySelector("#like");

button.addEventListener("click", function () {
  console.log("Clicked!");
});

// The same with an arrow function:
button.addEventListener("click", () => console.log("Clicked!"));

Bug: calls the function immediately

JavaScript
button.addEventListener("click", sayHi());

Correct: hands the function over for later

JavaScript
button.addEventListener("click", sayHi);

With () you run sayHi right now and pass its result (usually undefined). Without (), the browser calls it on every click.

The event object

The browser passes your function an event object describing what happened. The most useful property is event.target: the element the event happened on. For text boxes, event.target.value is what's currently typed.

JavaScript
const message = document.querySelector("#message");

// "input" fires on every keystroke, paste or delete
message.addEventListener("input", (event) => {
  console.log(event.type);                // "input"
  console.log(event.target.value.length); // characters so far
});

document.addEventListener("keydown", (event) => {
  console.log(event.key); // "a", "Enter", "Escape", …
});

Forms and preventDefault

When a form is submitted, the browser's default action is to send the data and load a new page — wiping out your JavaScript state. To handle the form yourself, listen for submit on the form (not the button, so pressing Enter works too) and call event.preventDefault().

JavaScript
const form = document.querySelector("#guest-form");

form.addEventListener("submit", (event) => {
  event.preventDefault(); // "don't do your default thing — I've got this"
  const name = document.querySelector("#guest-name").value.trim();
  console.log("Welcome, " + name);
});

In WANCode's preview, a forgotten preventDefault() won't reload anything — the preview blocks it and prints a hint in the Console. On a real site the page would reload.

Event bubbling

An event doesn't stay on the element you clicked. After it fires there, it bubbles up through every parent — the list, the section, the body, the document — and any listener along the way runs too.

A click on a list item also reaches the list and everything above it.
JavaScript
// One listener on the <ul> handles clicks on ANY <li> inside it —
// even items added later. This is called event delegation.
list.addEventListener("click", (event) => {
  const li = event.target.closest("li"); // the <li> that was clicked (or null)
  if (li) {
    li.classList.toggle("done");
  }
});

// (Rarely needed) stop the event from bubbling further:
// event.stopPropagation();

Under Step 1, listen for click on #like. Each click should:

1. add 1 to likes,

2. show the new number in #likes,

3. give the button the class liked (it turns pink).

Checks

  • Each click adds 1 to #likes
  • A click gives the button the class liked

Check understanding

Q1

Why does button.addEventListener("click", save()) run save immediately instead of on click?

Q2

What does event.preventDefault() do in a form's submit listener?

Q3

A <ul> has a click listener. You click an <li> inside it. Does the <ul> listener run?

What you learned

  • element.addEventListener("type", fn) runs fn every time that event happens — pass fn, don't call it.
  • The event object tells you what happened: event.target, event.target.value, event.key.
  • Handle forms on submit and call event.preventDefault() to stay on the page.
  • Events bubble up, so one listener on a parent can handle all its children (delegation).
Preview

Console output from your code appears here.

Step 1 of 3