JavaScript Events - Exercise 3

Create a CustomEvent, place application data in detail, and dispatch it from an element.

const event = new CustomEvent('cart:updated', {
  detail: { total: 42 }
});
cart.dispatchEvent(event);

Subscribe using the same event name and read the payload from event.detail.

cart.addEventListener('cart:updated', (event) => {
  totalLabel.textContent = `$${event.detail.total}`;
});

Create an AbortController and pass its signal to each listener. Calling abort() removes them together.

const controller = new AbortController();
window.addEventListener('resize', refresh, { signal: controller.signal });
document.addEventListener('visibilitychange', refresh, { signal: controller.signal });
controller.abort();

Use an async callback with try/catch so a rejected request is handled instead of becoming an unhandled rejection.

button.addEventListener('click', async () => {
  try {
    const response = await fetch('/api/profile');
    render(await response.json());
  } catch (error) {
    showError(error);
  }
});

Store the latest coordinates and schedule one visual update with requestAnimationFrame().

let frameId;
window.addEventListener('pointermove', (event) => {
  latestPoint = event;
  if (!frameId) frameId = requestAnimationFrame(updateCursor);
});

Use passive: true for high-frequency listeners when the handler will not call preventDefault().

window.addEventListener('touchmove', trackTouch, {
  passive: true
});

Keep setup and teardown together: register listeners during initialization and abort their shared signal during destruction.

function mountPanel(panel) {
  const controller = new AbortController();
  panel.addEventListener('click', handleClick, { signal: controller.signal });
  return () => controller.abort();
}

Ignore editable targets before matching the shortcut, then prevent the default action only when the shortcut is handled.

document.addEventListener('keydown', (event) => {
  const editable = event.target.matches('input, textarea, [contenteditable]');
  if (editable || event.key !== 'k' || !event.ctrlKey) return;
  event.preventDefault();
  openSearch();
});