JavaScript: Events & Event Handling

Learn how to respond to user interactions using event listeners, the event object, and event propagation.

What Are Events?

An event is something that happens in the browser, such as a user clicking a button, pressing a key, or the page finishing loading. JavaScript lets you react to these events by running code when they occur.

Events

Events are signals fired by the browser when something happens. You can listen for these signals and run a function in response.

  • event: an action or occurrence in the browser (click, keypress, load, etc.)
  • event handler: a function that runs when a specific event fires
  • Events can be triggered by the user or by the browser itself

Common Event Types

A sample of events available in the browser.

Adding Event Listeners

The preferred way to attach a handler is addEventListener(). It accepts the event type, a callback function, and an optional options object.

addEventListener()

Attaches a named or anonymous callback to an element for the specified event type.

  • element.addEventListener(type, handler): basic usage
  • Multiple listeners of the same type can be added to one element
  • Preferred over inline handlers (onclick=) for separation of concerns

addEventListener Example

Attach a click handler to a button.

Removing Event Listeners

Use removeEventListener() to detach a handler. The same function reference must be passed: anonymous functions cannot be removed this way.

removeEventListener()

Removes a previously attached event listener. The handler must be a named function reference, not an anonymous one.

  • element.removeEventListener(type, handler): exact function reference required
  • Useful for one-time events or cleanup when an element is removed
  • Anonymous arrow functions passed inline cannot be removed later

Remove After One Click

The listener removes itself after the first click.

Inline Event Handlers

You can set event handlers directly as HTML attributes or DOM properties. These are simpler but limit you to one handler per event per element.

Inline Handlers

Inline handlers are quick but inflexible. They work but are generally discouraged in modern JavaScript.

  • onclick attribute: <button onclick="fn()"> in HTML
  • DOM property: element.onclick = fn; in JS
  • Only one handler per event type: a second assignment overwrites the first
  • Prefer addEventListener() which allows multiple handlers

Inline Handler Methods

Two ways to set handlers without addEventListener.

The Event Object

When an event fires, the browser passes an event object to your handler. It contains details about what happened: which element was clicked, which key was pressed, mouse position, and more.

Event Object (e)

The event object is automatically passed as the first argument to every event handler.

  • e.type: the type of event ("click", "keydown", etc.)
  • e.target: the element that triggered the event
  • e.currentTarget: the element the listener is attached to
  • e.timeStamp: when the event occurred (in ms)

Inspecting the Event Object

Read properties from the event object passed to the handler.

preventDefault()

Some events have default browser behaviors: a link navigates, a form submits, right-clicking opens a context menu. Call e.preventDefault() inside your handler to block that default action.

e.preventDefault()

Cancels the browser's built-in behavior for an event while still running your handler code.

  • Common use: stop a form from submitting and handle it with JS instead
  • Common use: prevent a link from navigating to its href
  • Does NOT stop the event from bubbling up the DOM

Prevent Default Navigation

Prevent a link from navigating when clicked.

stopPropagation()

Events bubble up the DOM by default: clicking a child element also triggers handlers on its parents. Use e.stopPropagation() to stop this bubbling at any point.

e.stopPropagation()

Stops the event from traveling further up (or down) the DOM tree after your handler runs.

  • Event bubbling: child fires first, then parent, then grandparent
  • Event capturing: parent fires first (third arg true in addEventListener)
  • Use stopPropagation() when a child click should not trigger the parent's handler

Stop Propagation Demo

The button click does not bubble to the outer div.

Event Bubbling and Capturing

Events travel through the DOM in two phases: capturing (top-down) and bubbling (bottom-up). By default, listeners fire during the bubbling phase. Pass true as the third argument to listen in the capture phase instead.

Propagation Phases

Understanding event flow helps you control exactly when and where a handler fires.

  • Capture phase: event travels from window down to the target
  • Target phase: event reaches the element that triggered it
  • Bubble phase: event travels back up to window (default listener phase)
  • Pass { capture: true } or just true to listen in the capture phase

Bubbling Order

Events fire from the target element upward during the bubble phase.

Event Delegation

Instead of attaching a listener to every child element, attach one listener to the parent and use e.target to identify which child was clicked. This is called event delegation.

Event Delegation

A single parent listener handles events for all current and future children: efficient and works with dynamically added elements.

  • Fewer listeners means less memory usage
  • Works automatically for elements added to the DOM later
  • e.target.matches(selector): check if the clicked element matches a CSS selector

Event Delegation on a List

One listener on the parent handles clicks on all list items.

Mouse Events

Mouse events fire in response to pointer interactions. Common ones include click, dblclick, mouseenter, and mouseleave.

Mouse Events

Mouse events expose extra properties like clientX, clientY (viewport position) and button (which mouse button was pressed).

  • click: single click (mousedown + mouseup)
  • dblclick: two rapid clicks
  • mouseenter / mouseleave: hover in/out, do not bubble
  • mouseover / mouseout: similar but do bubble
  • e.clientX, e.clientY: cursor position in the viewport

Mouse Events Demo

Track hover and click states on a div.

Keyboard Events

Keyboard events fire when the user presses or releases a key. Use e.key to get a readable key name like "Enter" or "ArrowUp".

Keyboard Events

keydown fires first (repeats while held), keyup fires when released. keypress is deprecated.

  • keydown: fires when key is pressed (fires repeatedly if held)
  • keyup: fires when key is released
  • e.key: human-readable key name ("Enter", "a", "ArrowLeft")
  • e.code: physical key code ("KeyA", "Space"), layout-independent

Keyboard Event Demo

Display each key pressed in the input field.

Form Events

Forms have their own events for tracking user input and submission. The submit event fires when the form is submitted, and input fires on every keystroke.

Form Events

Handle form events to validate input, update UI live, or send data via fetch instead of a page reload.

  • submit: fires when the form is submitted
  • input: fires on every value change (live)
  • change: fires when focus leaves and value changed
  • focus / blur: element gains or loses focus

Form Submit and Input Events

Handle live input and prevent default form submission.

Window Events

Window events relate to the page itself: loading, resizing, or scrolling. Attach these listeners to the window object.

Window Events

Window events let you run code when the page finishes loading, the user scrolls, or the browser window is resized.

  • load: all resources (images, scripts) have loaded
  • DOMContentLoaded: HTML parsed, before images load (faster)
  • resize: window dimensions changed
  • scroll: user scrolled the page

Window Events

Resize and scroll events attached to the window object.

Custom Events

You can create and dispatch your own events using new CustomEvent(). This is useful for communication between components or modules.

CustomEvent

Custom events let different parts of your code communicate without tight coupling: one part fires an event, another listens for it.

  • new CustomEvent(name, { detail }): create with optional data payload
  • element.dispatchEvent(event): fire the event
  • Listeners use addEventListener with your custom event name

Custom Event Example

Dispatch and listen for a custom event with a data payload.

Knowledge Check

1. Which method is used to attach an event listener to an element?

2. What does e.preventDefault() do?

3. What is event bubbling?

4. What property of the event object refers to the element that triggered the event?

5. What is event delegation?

6. Which method removes an event listener?

7. What does stopPropagation() do?

8. Which event fires when a key is pressed down?