⚡ Phase 1 · Foundations
🟡 Intermediate
MODULE 11
JavaScript Events
Your progress in Phase 185%
🎯 What you'll learn: Events are how users interact with web pages. You'll master addEventListener, the event object, event delegation, keyboard and mouse events, custom events, form validation, and preventing default browser behavior.
Section 1
addEventListener Basics
The addEventListener method attaches a function to fire when a specific event occurs on an element. This is the modern, preferred way to handle events.
addEventListener Syntax & Common Events
JS
// Syntax: element.addEventListener(event, handler, options) const btn = document.querySelector('#myBtn'); // Click events btn.addEventListener('click', () => console.log('Clicked!')); btn.addEventListener('dblclick', () => console.log('Double click!')); // Mouse events btn.addEventListener('mouseover', () => btn.style.opacity = '0.8'); btn.addEventListener('mouseout', () => btn.style.opacity = '1'); btn.addEventListener('mousemove', e => console.log(e.clientX, e.clientY)); // Keyboard events (on document or input) document.addEventListener('keydown', e => console.log(e.key)); document.addEventListener('keyup', e => console.log(e.key)); // Form/Input events const input = document.querySelector('input'); input.addEventListener('change', e => console.log(e.target.value)); input.addEventListener('input', e => console.log(e.target.value)); // fires every keystroke input.addEventListener('focus', () => input.classList.add('focused')); input.addEventListener('blur', () => input.classList.remove('focused')); // Window events window.addEventListener('resize', () => console.log(window.innerWidth)); window.addEventListener('scroll', () => console.log(window.scrollY), {passive:true});
Section 2
The Event Object
Every event handler receives an event object (usually called e or event) containing useful information about what happened.
Event Object: target, preventDefault, stopPropagation
JS
// e.target — the element that was clicked document.addEventListener('click', e => { console.log(e.target); // element that was clicked console.log(e.target.tagName); // 'BUTTON', 'DIV', etc. console.log(e.target.id); // element's id console.log(e.target.dataset.id); // data-id attribute }); // e.preventDefault() — stop default browser action const link = document.querySelector('a'); link.addEventListener('click', e => { e.preventDefault(); // don't navigate console.log('Link clicked but not followed'); }); // Form submission — prevent page reload const form = document.querySelector('form'); form.addEventListener('submit', e => { e.preventDefault(); const data = new FormData(form); console.log(data.get('username')); }); // e.stopPropagation() — stop event bubbling up the DOM const inner = document.querySelector('.inner'); inner.addEventListener('click', e => { e.stopPropagation(); // parent click handler won't fire });
Section 3
Event Delegation
Instead of adding listeners to many elements, attach one listener to the parent and check e.target. This is more efficient and works for dynamically added elements.
Event Delegation Pattern
JS
// BAD — adding listener to each button (inefficient) document.querySelectorAll('.delete-btn').forEach(btn => { btn.addEventListener('click', handleDelete); }); // GOOD — one listener on the parent (event delegation) const list = document.getElementById('taskList'); list.addEventListener('click', e => { // Check if the clicked element is a delete button if (e.target.matches('.delete-btn')) { e.target.closest('li').remove(); } // Check for complete button if (e.target.matches('.complete-btn')) { e.target.closest('li').classList.toggle('done'); } }); // Now works for dynamically added items too! function addTask(text) { list.insertAdjacentHTML('beforeend', `<li>${text}<button class="delete-btn">Delete</button></li>` ); }
💡
Why delegation matters
If you have 1000 list items and add a click listener to each, that's 1000 event listeners in memory. With delegation, it's just 1 listener on the parent — much more efficient. It also handles dynamically-added elements automatically.
Section 4
Keyboard Events & Custom Events
Keyboard Shortcuts & Custom Events
JS
// Keyboard shortcuts document.addEventListener('keydown', e => { // Ctrl+S — save if (e.ctrlKey && e.key === 's') { e.preventDefault(); saveDocument(); } // Escape — close modal if (e.key === 'Escape') closeModal(); // Arrow keys — navigate if (e.key === 'ArrowUp') moveUp(); if (e.key === 'ArrowDown') moveDown(); // Check modifiers console.log(e.key, e.ctrlKey, e.shiftKey, e.altKey); }); // Removing event listeners function handleClick() { console.log('clicked'); } btn.addEventListener('click', handleClick); btn.removeEventListener('click', handleClick); // must be same reference! // Custom Events const event = new CustomEvent('taskCompleted', { detail: { taskId: 42, taskName: 'Learn Events' }, bubbles: true }); document.dispatchEvent(event); // Listen for custom event document.addEventListener('taskCompleted', e => { console.log('Task done:', e.detail.taskName); });
Section 5
Real-World: Form Validation
Real-Time Form Validation
JS
const form = document.getElementById('signupForm'); const emailInput = document.getElementById('email'); const passwordInput = document.getElementById('password'); // Real-time validation as user types emailInput.addEventListener('input', () => { const valid = emailInput.value.includes('@'); emailInput.classList.toggle('invalid', !valid); document.getElementById('emailError').textContent = valid ? '' : 'Please enter a valid email'; }); passwordInput.addEventListener('input', () => { const val = passwordInput.value; const strength = val.length >= 12 ? 'Strong' : val.length >= 8 ? 'Medium' : 'Weak'; document.getElementById('strengthLabel').textContent = strength; }); // Form submit form.addEventListener('submit', e => { e.preventDefault(); const data = { email: emailInput.value.trim(), password: passwordInput.value }; if (!data.email || !data.password) return; submitForm(data); });
🧩 Knowledge Check — Events
5 questions about JavaScript events.
1. What is the purpose of
e.preventDefault()?2. What does
e.target refer to in an event handler?3. What is event delegation?
4. Which keyboard event fires when a key is pressed down?
5. To remove an event listener you must pass the same ___.
Challenge — Interactive Quiz Game
Build a quiz with keyboard navigation · Intermediate
Build an Interactive Quiz with Keyboard Support
Create
1. Array of 5 quiz questions (each with options array and correctIndex)
2. Display one question at a time
3. Click option buttons OR press 1-4 on keyboard to answer
4. Press Enter/Space to go to next question
5. Show visual feedback: correct (green) / wrong (red)
6. Track score, show final result screen
7. Press 'R' to restart the quiz
Create
quiz-game.html:1. Array of 5 quiz questions (each with options array and correctIndex)
2. Display one question at a time
3. Click option buttons OR press 1-4 on keyboard to answer
4. Press Enter/Space to go to next question
5. Show visual feedback: correct (green) / wrong (red)
6. Track score, show final result screen
7. Press 'R' to restart the quiz
💡 Show hints
- Use a
currentQuestionindex variable to track state - Listen for keydown:
if (e.key === '1') selectOption(0) - Use event delegation on the options container for click events
- Disable options after answering:
btn.disabled = true
Finished this lesson?
Mark it complete to track your progress.
Module 11 of 13Phase 1 — JS Foundations