Web APIs Cheatsheet

Events

Use this Web APIs reference while you build software engineering projects, review code for technical interview prep, or polish examples for a software engineer resume.

addEventListener and removeEventListener

// Add
el.addEventListener('click', handler);
el.addEventListener('click', handler, { capture: true }); // capture phase
el.addEventListener('click', handler, { once: true });     // auto-removes
el.addEventListener('click', handler, { passive: true });  // cannot call preventDefault
el.addEventListener('click', handler, { signal: controller.signal }); // abortable

// Remove (must pass the same function reference)
el.removeEventListener('click', handler);

// Using AbortController to remove multiple listeners at once
const ac = new AbortController();
el.addEventListener('click', onClick, { signal: ac.signal });
el.addEventListener('keydown', onKey, { signal: ac.signal });
ac.abort(); // removes both

Event Phases and Propagation

event.eventPhase; // 1 CAPTURING, 2 AT_TARGET, 3 BUBBLING

event.stopPropagation();        // stop bubbling/capturing further
event.stopImmediatePropagation(); // stop + prevent other listeners on same el
event.preventDefault();         // suppress default browser action
event.cancelable;               // can preventDefault() have effect?
event.defaultPrevented;         // was preventDefault() called?
event.bubbles;                  // does this event bubble?
// Delegation — listen on parent, act on child
ul.addEventListener('click', e => {
  const li = e.target.closest('li');
  if (!li || !ul.contains(li)) return;
  console.log('clicked', li.dataset.id);
});

Event Object Properties

PropertyDescription
e.typeEvent name string, e.g. 'click'
e.targetElement that triggered the event
e.currentTargetElement the listener is attached to
e.timeStampms since page load (DOMHighResTimeStamp)
e.isTrustedtrue for user-initiated, false for dispatched
e.composedWhether event crosses Shadow DOM boundary

Dispatching Custom Events

// Simple
el.dispatchEvent(new Event('refresh', { bubbles: true, cancelable: true }));

// With data
el.dispatchEvent(new CustomEvent('item:select', {
  bubbles: true,
  cancelable: true,
  composed: true,          // cross shadow DOM
  detail: { id: 42, name: 'Alice' },
}));

// Listen
el.addEventListener('item:select', e => console.log(e.detail));

Mouse Events

EventWhen
mousedownButton pressed
mouseupButton released
clickFull press + release (left button)
dblclickDouble click
contextmenuRight-click (before menu shows)
mousemovePointer moves over element
mouseenterPointer enters element (no bubble)
mouseleavePointer leaves element (no bubble)
mouseoverPointer enters element or child (bubbles)
mouseoutPointer leaves element or child (bubbles)
el.addEventListener('mousemove', e => {
  e.clientX; e.clientY;       // viewport coords
  e.pageX;   e.pageY;         // page coords (includes scroll)
  e.offsetX; e.offsetY;       // relative to target element
  e.screenX; e.screenY;       // screen coords
  e.buttons;                  // bitmask: 1=left,2=right,4=middle
  e.button;                   // 0=left,1=middle,2=right (click/down/up only)
  e.altKey; e.ctrlKey; e.shiftKey; e.metaKey; // modifier keys
  e.movementX; e.movementY;   // delta since last event (in Pointer Lock)
});

Keyboard Events

EventWhen
keydownKey pressed (fires repeatedly on hold)
keyupKey released
keypressDeprecated — use keydown
el.addEventListener('keydown', e => {
  e.key;          // 'a', 'Enter', 'ArrowUp', 'Escape', ' '
  e.code;         // 'KeyA', 'Enter', 'ArrowUp' (physical key, layout-agnostic)
  e.keyCode;      // Deprecated number
  e.repeat;       // true when key is held down
  e.altKey; e.ctrlKey; e.shiftKey; e.metaKey;
  e.getModifierState('CapsLock'); // boolean

  if (e.key === 'Enter' && e.shiftKey) { /* shift+enter */ }
  if (e.key === 's' && (e.ctrlKey || e.metaKey)) { e.preventDefault(); save(); }
});

Pointer Events

Unified API replacing mouse + touch; preferred for drawing and drag interactions.

el.addEventListener('pointerdown', e => {
  e.pointerId;      // unique id per pointer
  e.pointerType;    // 'mouse' | 'pen' | 'touch'
  e.pressure;       // 0–1
  e.tiltX; e.tiltY; // stylus tilt degrees
  e.width; e.height; // contact geometry
  e.isPrimary;      // true for first finger in multi-touch
});

// Capture pointer to receive events even if pointer leaves element
el.addEventListener('pointerdown', e => el.setPointerCapture(e.pointerId));
el.addEventListener('pointermove', onMove);
el.addEventListener('pointerup', e => el.releasePointerCapture(e.pointerId));
Pointer EventEquivalent
pointerdownmousedown / touchstart
pointerupmouseup / touchend
pointermovemousemove / touchmove
pointerentermouseenter
pointerleavemouseleave
pointercanceltouchcancel
gotpointercaptureafter setPointerCapture
lostpointercaptureafter releasePointerCapture

Touch Events

el.addEventListener('touchstart', e => {
  e.touches;           // all current touches (TouchList)
  e.targetTouches;     // touches on this target
  e.changedTouches;    // touches that changed this event
  const t = e.touches[0];
  t.clientX; t.clientY;
  t.identifier;        // unique per touch
}, { passive: true });

Mark touch handlers { passive: true } when you don't call preventDefault() — enables the browser to scroll without waiting for JS.

Scroll Events

window.addEventListener('scroll', e => {
  window.scrollX; window.scrollY;
}, { passive: true });

// throttle scroll with rAF
let ticking = false;
window.addEventListener('scroll', () => {
  if (!ticking) {
    requestAnimationFrame(() => { update(); ticking = false; });
    ticking = true;
  }
}, { passive: true });

Focus and Input Events

EventBubblesWhen
focusNoElement gains focus
blurNoElement loses focus
focusinYesLike focus but bubbles
focusoutYesLike blur but bubbles
inputYesValue changed (fires continuously)
changeYesValue committed (blur / Enter / select)
selectYesText selected in input/textarea
input.addEventListener('input', e => {
  e.target.value;          // current value
  e.data;                  // character(s) inserted (InputEvent)
  e.inputType;             // 'insertText', 'deleteContentBackward', …
  e.isComposing;           // true during IME composition
});

Clipboard Events

el.addEventListener('copy', e => {
  e.clipboardData.setData('text/plain', 'custom text');
  e.preventDefault();
});

el.addEventListener('paste', e => {
  const text = e.clipboardData.getData('text/plain');
  e.preventDefault();
});

Drag Events

EventTarget
dragstartDragged element
dragDragged element (continuous)
dragendDragged element
dragenterDrop target entered
dragoverDrop target (must preventDefault to allow drop)
dragleaveDrop target left
dropDrop target
source.setAttribute('draggable', 'true');
source.addEventListener('dragstart', e => {
  e.dataTransfer.setData('text/plain', 'payload');
  e.dataTransfer.effectAllowed = 'move'; // 'copy' | 'move' | 'link' | 'all'
});

target.addEventListener('dragover', e => e.preventDefault());
target.addEventListener('drop', e => {
  e.preventDefault();
  const data = e.dataTransfer.getData('text/plain');
  e.dataTransfer.dropEffect = 'move';
});

Media Events

EventWhen
loadstartLoading begins
loadedmetadataDuration, dimensions known
loadeddataCurrent frame loaded
canplayCan start playing (may buffer)
canplaythroughCan play without buffering
playPlayback started
pausePaused
timeupdatecurrentTime updated
endedReached end
errorLoad or decode error
volumechangeVolume or muted changed
ratechangeplaybackRate changed
seeking / seekedSeek started / finished

Page Lifecycle Events

window.addEventListener('load', () => { /* all resources loaded */ });
document.addEventListener('DOMContentLoaded', () => { /* DOM ready, no resources */ });
window.addEventListener('beforeunload', e => {
  e.preventDefault();
  e.returnValue = ''; // show browser "leave?" dialog
});
window.addEventListener('unload', () => { /* last chance, no async */ });
window.addEventListener('pagehide', e => { e.persisted; /* BFCache */ });
window.addEventListener('pageshow', e => { e.persisted; });
document.addEventListener('visibilitychange', () => {
  if (document.hidden) pauseVideo();
});
window.addEventListener('online', () => { /* network restored */ });
window.addEventListener('offline', () => { /* network lost */ });
window.addEventListener('resize', handler, { passive: true });

Animation and Transition Events

el.addEventListener('animationstart', e => e.animationName);
el.addEventListener('animationend', e => e.animationName);
el.addEventListener('animationiteration', e => e.elapsedTime);
el.addEventListener('transitionstart', e => e.propertyName);
el.addEventListener('transitionend', e => e.propertyName);
el.addEventListener('transitioncancel', e => {});

Error Events

window.addEventListener('error', e => {
  e.message; e.filename; e.lineno; e.colno; e.error;
  return true; // suppress default browser error reporting
});

window.addEventListener('unhandledrejection', e => {
  e.promise; e.reason;
  e.preventDefault(); // suppress console error
});

window.addEventListener('rejectionhandled', e => {
  // promise rejection was caught late
});