Useful Cheatsheetsusefulcheatsheets.com
JavaScript Events
Chapter 16 · Page 129
Intermediate

JavaScript Events

Handle browser events, event delegation, bubbling, capturing, and preventDefault with vanilla JavaScript.

TL;DR

  1. 01Attach event listeners with addEventListener for flexible handling.
  2. 02Use event delegation to handle many items with one listener.
  3. 03Control event flow with stopPropagation and preventDefault when needed.

Tips

  1. 01Use event delegation to attach a single listener to a container instead of many listeners on child elements.
  2. 02Pass the { once: true } option to addEventListener when a handler should only run a single time.
  3. 03Check event.cancelable before calling preventDefault, since some events like scroll cannot be canceled at all.

Warnings

  1. 01preventDefault only works on cancelable events — always check if the event is cancelable before calling it.
  2. 02Inline handlers like onclick can only hold one function, so a second assignment silently replaces the first one.
  3. 03Forgetting removeEventListener on elements you remove from the DOM can leak memory in long-running single-page applications.
Notes
Useful Cheatsheetsusefulcheatsheets.com
JavaScript Events
Chapter 16 · Page 130
Intermediate

JavaScript Events

(continued)

Basic Event Listeners

  • addEventListener()

    Attach event handlers for flexible, composable event handling.

    const button = document.querySelector("button");
    button.addEventListener("click", (event) => {
      console.log("Button clicked");
    });
  • The event object

    Contains details about what happened, like type, target, and position.

    button.addEventListener("click", (e) => {
      console.log(e.type);      // "click"
      console.log(e.target);    // the button element
      console.log(e.clientX);   // mouse position
    });
  • removeEventListener()

    Removes a listener when it's no longer needed.

    const handler = (e) => console.log("clicked");
    button.addEventListener("click", handler);
    button.removeEventListener("click", handler);
  • Avoid inline handlers

    Inline event handlers like onclick are outdated compared to addEventListener.

    // Avoid: <button onclick="handleClick()">Click</button>
    // Use addEventListener instead
  • { once: true }

    Fires a listener only one time, then removes it automatically.

    button.addEventListener("click", handler, { once: true });
    // Handler is automatically removed after first click
Notes
Useful Cheatsheetsusefulcheatsheets.com
JavaScript Events
Chapter 16 · Page 131
Intermediate

JavaScript Events

(continued)

Event Bubbling and Capturing

  • Bubbling by default

    Events bubble up from child to parent by default.

    div.addEventListener("click", () => console.log("div clicked"));
    button.addEventListener("click", () => console.log("button clicked"));
    // Clicking button logs both "button clicked" and "div clicked"
  • stopPropagation()

    Prevents an event from bubbling up to parent listeners.

    button.addEventListener("click", (e) => {
      e.stopPropagation();
      console.log("button only");
    });
  • Capture phase

    Pass true as the third argument to listen during the capture phase.

    div.addEventListener("click", handler, true);
    // Capture phase runs before bubble phase
  • Most events bubble

    Most events bubble, but check the MDN docs for specific events that don't.

  • Blocking parent handlers

    Use stopPropagation to prevent parent handlers from running at all.

Notes
Useful Cheatsheetsusefulcheatsheets.com
JavaScript Events
Chapter 16 · Page 132
Intermediate

JavaScript Events

(continued)

Preventing Default Behavior

  • preventDefault()

    Stops the browser's default action for an event.

    form.addEventListener("submit", (e) => {
      e.preventDefault();
      // Form does not submit to server
      console.log("Form submission intercepted");
    });
  • Common use cases

    Works on clickable links, form submissions, and other cancelable events.

    link.addEventListener("click", (e) => {
      e.preventDefault();
      // Link does not navigate to href
    });
  • event.defaultPrevented

    Check whether preventDefault was already called on the event.

    if (!event.defaultPrevented) {
      // Default action will occur
    }
  • Not all events cancelable

    Not all events can be prevented — check if the event is cancelable first.

  • event.cancelable

    Verify the event supports preventDefault before calling it.

    link.addEventListener("click", (e) => {
      if (e.cancelable) {
        e.preventDefault();
      }
    });
Notes
Useful Cheatsheetsusefulcheatsheets.com
JavaScript Events
Chapter 16 · Page 133
Intermediate

JavaScript Events

(continued)

Event Delegation

  • One listener, many children

    Attach a single listener to a parent to handle children efficiently.

    const list = document.querySelector("ul");
    list.addEventListener("click", (e) => {
      if (e.target.tagName === "LI") {
        console.log("Clicked item:", e.target.textContent);
      }
    });
  • Fewer listeners

    This pattern is efficient when there are many similar elements.

    // Instead of attaching listeners to each item:
    items.forEach(item => item.addEventListener("click", handler));
    
    // Attach one listener to the container:
    container.addEventListener("click", handler);
  • e.target.closest()

    Finds the closest matching ancestor from the actual clicked element.

    document.addEventListener("click", (e) => {
      const button = e.target.closest("button");
      if (button) console.log("Button clicked");
    });
  • Works with dynamic elements

    Delegation works with elements added to the DOM after the listener was attached.

Notes
Useful Cheatsheetsusefulcheatsheets.com
JavaScript Events
Chapter 16 · Page 134
Intermediate

JavaScript Events

(continued)

Common Events

  • Mouse events

    click, dblclick, mousedown, mouseup, and mousemove track pointer activity.

    element.addEventListener("mousemove", (e) => {
      console.log(`Mouse at ${e.clientX}, ${e.clientY}`);
    });
  • Keyboard events

    keydown and keyup track key presses; keypress is deprecated.

    document.addEventListener("keydown", (e) => {
      console.log(`Key pressed: ${e.key}`);
    });
  • Form events

    change, input, submit, reset, focus, and blur track form interaction.

    input.addEventListener("input", (e) => {
      console.log(`Current value: ${e.target.value}`);
    });
  • Window events

    load, unload, scroll, and resize track the page and viewport.

    window.addEventListener("scroll", () => {
      console.log("Page scrolled");
    });
Notes
Useful Cheatsheetsusefulcheatsheets.com
JavaScript Events
Chapter 16 · Page 135
Intermediate

JavaScript Events

(FAQ)

FAQ

Bubbling propagates events from the target element up to the root; capturing goes from root down to the target. Pass true as the third argument to addEventListener to use capturing phase instead of the default bubbling.

Call event.stopPropagation() inside your handler to prevent the event from bubbling up. Use event.stopImmediatePropagation() if you also want to block other listeners on the same element.

Attach one listener to a parent element and use event.target to identify which child triggered the event. This is especially useful for dynamically added elements or large lists. Listeners on the parent automatically cover new children.

Not all events are cancelable — for example, scroll events cannot be prevented after they fire. Check event.cancelable before calling preventDefault(), and for scroll/touch performance consider using a passive event listener ({passive: true}).

onclick can only hold one handler at a time and overwrites any previously assigned function. addEventListener supports multiple handlers on the same element. It also gives you control over phase (capture vs bubble) and one-time execution via {once: true}.

Useful Cheatsheetsusefulcheatsheets.com
JavaScript Events
Chapter 16 · Page 136
Intermediate

JavaScript Events

(In Practice)
In Practice

Validating a Form with Delegated Listeners

One delegated submit listener validates required fields and prevents submission until every field passes.

  1. 01The submit listener checks every required field before the browser submits the form.
  2. 02e.preventDefault() only runs when validation fails, so a valid form submits normally.
  3. 03A single delegated input listener clears the error class as the user types, without per-field listeners.
  4. 04closest('[required]') confirms the input that fired the event is actually one that needs validation.
const form = document.querySelector('#signup-form');

form.addEventListener('submit', (e) => {
  const invalid = [...form.querySelectorAll('[required]')].filter(field => !field.value.trim());

  if (invalid.length > 0) {
    e.preventDefault();
    invalid.forEach(field => field.classList.add('error'));
    console.log(`${invalid.length} field(s) missing`);
  }
});

form.addEventListener('input', (e) => {
  const field = e.target.closest('[required]');
  if (field) field.classList.remove('error');
});
Takeaway

Two delegated listeners — submit and input — validate an entire form without attaching a listener to each field.