Skip to Content

Event

The object the browser passes to every event handler. It describes what happened (click, keypress, submit) and gives you methods to control how it propagates.

When to use it

  • User interactions — clicks, key presses, form submissions
  • Preventing defaults — stopping a form from reloading or a link from navigating
  • Delegation — one listener on a parent handles clicks for many children
  • Custom events — fire your own events between components

Anatomy

element.addEventListener('click', (event) => { event.type // 'click' — the event name event.target // the element that was actually clicked event.currentTarget // the element the listener is attached to event.timeStamp // ms since page load event.preventDefault() // stop the default browser behavior event.stopPropagation() // stop the event from bubbling up the DOM // mouse events event.clientX // x position relative to viewport event.clientY // y position relative to viewport // keyboard events event.key // 'Enter', 'a', 'Escape', etc. event.code // 'KeyA', 'Enter' — physical key event.shiftKey // true if shift was held event.ctrlKey // true if ctrl/cmd was held })

At a glance

Property / MethodWhat it gives you
.typeEvent name as a string
.targetThe element the event originated from
.currentTargetThe element the listener is on
.preventDefault()Cancel the browser’s default action
.stopPropagation()Stop bubbling to parent elements
.clientX / .clientYMouse position (viewport-relative)
.keyWhich key was pressed (keyboard events)
.codePhysical key identifier
.shiftKey / .ctrlKey / .altKeyModifier key state
.timeStampWhen the event fired (ms since page load)

Common event types

TypeWhen it fires
clickMouse click or tap
submitForm submitted
inputInput value changes (fires on every keystroke)
changeInput loses focus after value changed
keydown / keyupKey pressed / released
focus / blurElement gains / loses focus
mouseover / mouseoutPointer enters / leaves an element
DOMContentLoadedHTML parsed, DOM ready
loadPage and all resources fully loaded

1. Simple — listen and inspect

const btn = document.querySelector('button') btn.addEventListener('click', (e) => { e.type // 'click' e.target // the <button> element e.target.textContent // the button's text })

2. Intermediate — event delegation

// one listener on the parent handles clicks for all <li> children const list = document.querySelector('ul') list.addEventListener('click', (e) => { const item = e.target.closest('li') // find the <li> that was clicked if (!item) return // click wasn't on an <li> item.classList.toggle('done') // e.target = the exact element clicked (could be a <span> inside <li>) // e.currentTarget = the <ul> the listener is on })

3. Advanced — custom events

// define a custom event with a detail payload const cartUpdate = new CustomEvent('cart:update', { detail: { itemId: 42, qty: 2 }, bubbles: true, // allow it to bubble up like native events }) // listen anywhere up the DOM tree document.addEventListener('cart:update', (e) => { e.detail.itemId // 42 e.detail.qty // 2 }) // dispatch from any element document.querySelector('.add-btn').dispatchEvent(cartUpdate)

Custom events let loosely coupled components communicate without direct references to each other.


Gotchas

target vs currentTarget

// <ul> listener, user clicks a <span> inside an <li> list.addEventListener('click', (e) => { e.target // <span> — the deepest element clicked e.currentTarget // <ul> — the element with the listener // use .closest() to find the ancestor you actually care about e.target.closest('li') // the <li> containing the <span> })

Removing listeners requires a named function

// this won't work — anonymous functions can't be matched el.addEventListener('click', () => console.log('hi')) el.removeEventListener('click', () => console.log('hi')) // no effect // use a named function instead function handleClick() { console.log('hi') } el.addEventListener('click', handleClick) el.removeEventListener('click', handleClick) // works

  • FormData — reads form field values after a submit event
  • .forEach() — loop through a NodeList to add listeners
Last updated on