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();
});