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
| Property | Description |
|---|---|
e.type | Event name string, e.g. 'click' |
e.target | Element that triggered the event |
e.currentTarget | Element the listener is attached to |
e.timeStamp | ms since page load (DOMHighResTimeStamp) |
e.isTrusted | true for user-initiated, false for dispatched |
e.composed | Whether 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
| Event | When |
|---|---|
mousedown | Button pressed |
mouseup | Button released |
click | Full press + release (left button) |
dblclick | Double click |
contextmenu | Right-click (before menu shows) |
mousemove | Pointer moves over element |
mouseenter | Pointer enters element (no bubble) |
mouseleave | Pointer leaves element (no bubble) |
mouseover | Pointer enters element or child (bubbles) |
mouseout | Pointer 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
| Event | When |
|---|---|
keydown | Key pressed (fires repeatedly on hold) |
keyup | Key released |
keypress | Deprecated — 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 Event | Equivalent |
|---|---|
pointerdown | mousedown / touchstart |
pointerup | mouseup / touchend |
pointermove | mousemove / touchmove |
pointerenter | mouseenter |
pointerleave | mouseleave |
pointercancel | touchcancel |
gotpointercapture | after setPointerCapture |
lostpointercapture | after 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 callpreventDefault()— 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
| Event | Bubbles | When |
|---|---|---|
focus | No | Element gains focus |
blur | No | Element loses focus |
focusin | Yes | Like focus but bubbles |
focusout | Yes | Like blur but bubbles |
input | Yes | Value changed (fires continuously) |
change | Yes | Value committed (blur / Enter / select) |
select | Yes | Text 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
| Event | Target |
|---|---|
dragstart | Dragged element |
drag | Dragged element (continuous) |
dragend | Dragged element |
dragenter | Drop target entered |
dragover | Drop target (must preventDefault to allow drop) |
dragleave | Drop target left |
drop | Drop 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
| Event | When |
|---|---|
loadstart | Loading begins |
loadedmetadata | Duration, dimensions known |
loadeddata | Current frame loaded |
canplay | Can start playing (may buffer) |
canplaythrough | Can play without buffering |
play | Playback started |
pause | Paused |
timeupdate | currentTime updated |
ended | Reached end |
error | Load or decode error |
volumechange | Volume or muted changed |
ratechange | playbackRate changed |
seeking / seeked | Seek 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 });