JavaScript Events and Interactivity
CMU422: Fundamentals of Web Design - Session 7
Birmingham Newman University
Lecturer: James Williams
Building responsive user interfaces
3-hour session • 25 slides • 2 interactive tasks
Session Timeline:
10 min: Registration & waiting
20 min: Opening slides
45 min: Task 1
15 min: Break/Catch up
20 min: Secondary slides
45 min: Task 2
Remaining: Self-study
Learning Objectives
Understand JavaScript event handling
Master different types of events
Create interactive user interfaces
Handle form submissions and validation
Build responsive and accessible interactions
What are JavaScript Events?
Events are actions or occurrences that happen in the browser
User interactions (clicks, key presses, mouse movements)
Browser actions (page load, resize, scroll)
Form submissions and input changes
Network events (AJAX responses)
// Event example
button.addEventListener('click', function() {
console.log('Button clicked!');
});
Common Event Types
// Mouse events
'click', 'dblclick', 'mouseenter', 'mouseleave'
// Keyboard events
'keydown', 'keyup', 'keypress'
// Form events
'submit', 'change', 'input', 'focus', 'blur'
// Document events
'load', 'DOMContentLoaded', 'resize', 'scroll'
Mouse events for user interactions
Keyboard events for text input
Form events for data handling
Document events for page lifecycle
Event Handling Methods
// Method 1: addEventListener (recommended)
element.addEventListener('click', function(event) {
console.log('Clicked!');
});
// Method 2: Inline event handlers
<button onclick="handleClick()">Click me</button>
// Method 3: Event properties
element.onclick = function() {
console.log('Clicked!');
};
addEventListener
is the modern approach
Allows multiple event listeners
Better control over event handling
Try It: Interactive DOM Manipulation
Add
Element
Remove
Element
Highlight All
Clear
Highlights
Click the buttons to manipulate me!
This demo shows DOM manipulation, event handling, and dynamic styling!
The Event Object
element.addEventListener('click', function(event) {
console.log(event.type); // 'click'
console.log(event.target); // Element that was clicked
console.log(event.clientX); // Mouse X position
console.log(event.clientY); // Mouse Y position
event.preventDefault(); // Prevent default behavior
event.stopPropagation(); // Stop event bubbling
});
Contains information about the event
Provides methods to control event behavior
Automatically passed to event handlers
Event Bubbling and Capturing
// Event bubbling (default)
parent.addEventListener('click', function() {
console.log('Parent clicked');
});
// Event capturing
parent.addEventListener('click', function() {
console.log('Parent clicked');
}, true); // true enables capturing
// Stop propagation
child.addEventListener('click', function(event) {
event.stopPropagation();
});
Events bubble up from child to parent
Capturing goes from parent to child
Use stopPropagation()
to prevent bubbling
Form Events
const form = document.querySelector('form');
// Form submission
form.addEventListener('submit', function(event) {
event.preventDefault();
// Handle form data
});
// Input changes
input.addEventListener('input', function(event) {
console.log('Input value:', event.target.value);
});
// Focus events
input.addEventListener('focus', function() {
this.style.borderColor = 'blue';
});
submit
: Form submission
input
: Value changes
focus/blur
: Field focus
change
: Value confirmed
Keyboard Events
document.addEventListener('keydown', function(event) {
console.log('Key pressed:', event.key);
console.log('Key code:', event.code);
// Check for specific keys
if (event.key === 'Enter') {
console.log('Enter pressed!');
}
// Check for modifier keys
if (event.ctrlKey && event.key === 's') {
event.preventDefault();
console.log('Save shortcut!');
}
});
keydown
: Key pressed down
keyup
: Key released
keypress
: Character input
Check for specific keys and modifiers
Mouse Events
element.addEventListener('click', function(event) {
console.log('Click at:', event.clientX, event.clientY);
});
element.addEventListener('mouseenter', function() {
this.style.backgroundColor = 'yellow';
});
element.addEventListener('mouseleave', function() {
this.style.backgroundColor = 'white';
});
element.addEventListener('mousemove', function(event) {
// Track mouse movement
});
click
: Single click
dblclick
: Double click
mouseenter/mouseleave
: Hover effects
mousemove
: Mouse tracking
Event Delegation
// Instead of adding listeners to each item
const list = document.querySelector('ul');
list.addEventListener('click', function(event) {
if (event.target.tagName === 'LI') {
console.log('List item clicked:',
event.target.textContent);
}
});
// Works for dynamically added items too
Attach event listener to parent element
Use event.target
to identify specific elements
Efficient for multiple similar elements
Works with dynamically added content
Client-Side Form Validation
form.addEventListener('submit', function(event) {
event.preventDefault();
const email = document.getElementById('email').value;
const password = document.getElementById('password').value;
if (!email.includes('@')) {
showError('Please enter a valid email');
return;
}
if (password.length < 8) {
showError('Password must be at least 8
characters');
return;
}
// Form is valid, submit it
this.submit();
});
Validate before form submission
Provide immediate user feedback
Always validate on server side too
Use HTML5 validation attributes
AJAX and Fetch API
// Fetch data from server
fetch('/api/data')
.then(response => response.json())
.then(data => {
console.log('Data received:', data);
updateUI(data);
})
.catch(error => {
console.error('Error:', error);
});
// POST data to server
fetch('/api/submit', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(data)
});
Fetch API for HTTP requests
Promise-based approach
Handle success and error cases
Update UI with received data
Local Storage
// Store data
localStorage.setItem('username', 'john');
localStorage.setItem('preferences', JSON.stringify({theme: 'dark'}));
// Retrieve data
const username = localStorage.getItem('username');
const preferences = JSON.parse(localStorage.getItem('preferences'));
// Remove data
localStorage.removeItem('username');
localStorage.clear(); // Remove all
// Session storage (cleared when tab closes)
sessionStorage.setItem('temp', 'value');
Store data in browser
Persists between sessions
Limited to strings (use JSON for objects)
5-10MB storage limit
Animation and Transitions
// CSS transitions
element.style.transition = 'all 0.3s ease';
element.style.transform = 'scale(1.1)';
// JavaScript animations
function animate(element, duration) {
const start = performance.now();
function update(currentTime) {
const elapsed = currentTime - start;
const progress = Math.min(elapsed / duration, 1);
element.style.opacity = progress;
if (progress < 1) {
requestAnimationFrame(update);
}
}
requestAnimationFrame(update);
}
CSS transitions for simple animations
JavaScript for complex animations
Use requestAnimationFrame
for smooth animations
Consider performance and accessibility
Accessibility Best Practices
Use semantic HTML elements
Provide keyboard navigation
Add ARIA attributes when needed
Ensure focus management
Test with screen readers
Provide alternative text for images
Use sufficient color contrast
// Keyboard navigation
element.addEventListener('keydown', function(event) {
if (event.key === 'Enter' || event.key === ' ') {
event.preventDefault();
handleClick();
}
});
// ARIA attributes
element.setAttribute('aria-label', 'Close dialog');
element.setAttribute('role', 'button');
Error Handling
// Try-catch for synchronous code
try {
const result = riskyOperation();
console.log(result);
} catch (error) {
console.error('Error occurred:', error.message);
showUserFriendlyError();
}
// Promise error handling
fetch('/api/data')
.then(response => {
if (!response.ok) {
throw new Error('Network response was not
ok');
}
return response.json();
})
.catch(error => {
console.error('Fetch error:', error);
showErrorMessage(error.message);
});
Handle errors gracefully
Provide user-friendly error messages
Log errors for debugging
Use try-catch and promise error handling
Task 1: Interactive Form
Instructions:
Create a new HTML file called interactive-form.html
Build a registration form with:
Name, email, password, and confirm password fields
Real-time validation as user types
Password strength indicator
Submit button with loading state
Add event listeners for:
Input validation on blur and input events
Form submission with preventDefault
Password strength calculation
Use local storage to remember form data
Add visual feedback for validation states
Time: 45 minutes
This task will help you understand form events and validation
Break Time
15 Minutes
Take a break, ask questions, or catch up on the previous task.
Next: Secondary slides and Task 2
Event Handling Best Practices
Use addEventListener
instead of inline handlers
Remove event listeners when elements are destroyed
Use event delegation for multiple elements
Prevent default behavior when appropriate
Handle errors gracefully
Consider performance for frequent events
Test across different browsers
// Remove event listener
const handler = function() { console.log('clicked'); };
element.addEventListener('click', handler);
element.removeEventListener('click', handler);
// Throttle frequent events
let timeout;
element.addEventListener('scroll', function() {
clearTimeout(timeout);
timeout = setTimeout(handleScroll, 100);
});
Performance Considerations
Throttle or debounce frequent events
Use event delegation for many elements
Avoid inline event handlers
Remove unused event listeners
Use passive event listeners when possible
Consider using Intersection Observer for scroll events
// Passive event listener
element.addEventListener('touchstart', handler, { passive: true });
// Intersection Observer
const observer = new IntersectionObserver(entries => {
entries.forEach(entry => {
if (entry.isIntersecting) {
entry.target.classList.add('visible');
}
});
});
Debugging Event Issues
Use browser developer tools
Check event listener attachment
Verify event target and currentTarget
Monitor event propagation
Check for JavaScript errors
Test event timing
// Debug event listeners
element.addEventListener('click', function(event) {
console.log('Event target:', event.target);
console.log('Current target:', event.currentTarget);
console.log('Event phase:', event.eventPhase);
console.trace('Event call stack');
});
// Monitor all events
const originalAddEventListener = EventTarget.prototype.addEventListener;
EventTarget.prototype.addEventListener = function(type, listener, options) {
console.log('Adding listener:', type, 'to', this);
return originalAddEventListener.call(this, type, listener,
options);
};
Mobile-Specific Events
// Touch events
element.addEventListener('touchstart', function(event) {
console.log('Touch started');
event.preventDefault(); // Prevent default touch behavior
});
element.addEventListener('touchmove', function(event) {
console.log('Touch moved');
});
element.addEventListener('touchend', function(event) {
console.log('Touch ended');
});
// Device orientation
window.addEventListener('orientationchange', function() {
console.log('Orientation changed');
});
Touch events for mobile interactions
Orientation change events
Consider touch targets (minimum 44px)
Handle both touch and mouse events
Task 2: Interactive Dashboard
Instructions:
Create a new HTML file called interactive-dashboard.html
Build an interactive dashboard with:
Navigation: Tabbed interface with smooth
transitions
Widgets: Collapsible panels with toggle
functionality
Charts: Simple data visualization (use CSS or basic
canvas)
Search: Real-time search with debouncing
Settings: Theme toggle and preferences
Implement event handling for:
Tab switching with keyboard navigation
Widget collapse/expand animations
Search input with live filtering
Theme switching with local storage
Add accessibility features (ARIA attributes, keyboard support)
Make it responsive for mobile devices
Time: 45 minutes
This task will help you understand complex event handling and UI
interactions
Session Summary
Events are the foundation of interactive web applications
Use modern event handling methods
Implement proper form validation
Consider accessibility and performance
Handle errors gracefully
Test across different devices and browsers
Next Session:
JavaScript Advanced Concepts - Functions, objects, and modern JavaScript