JavaScript DOM Events & Event Handling
Master event handling, different event types, event delegation, and modern event patterns for building responsive user interfaces
55 min•By Priygop Team•Last updated: Feb 2026
Event System
Events are actions or occurrences that happen in the browser, such as clicks, form submissions, or page loads. JavaScript can listen for these events and execute code in response, creating interactive web applications.
Event Types
Example
// Common event types
// Mouse Events
const button = document.querySelector('button');
button.addEventListener('click', (e) => {
console.log('Button clicked!');
});
button.addEventListener('dblclick', (e) => {
console.log('Button double-clicked!');
});
button.addEventListener('mouseenter', (e) => {
console.log('Mouse entered button');
});
button.addEventListener('mouseleave', (e) => {
console.log('Mouse left button');
});
button.addEventListener('mousedown', (e) => {
console.log('Mouse button pressed');
});
button.addEventListener('mouseup', (e) => {
console.log('Mouse button released');
});
// Keyboard Events
const input = document.querySelector('input');
input.addEventListener('keydown', (e) => {
console.log('Key pressed:', e.key);
});
input.addEventListener('keyup', (e) => {
console.log('Key released:', e.key);
});
input.addEventListener('keypress', (e) => {
console.log('Character typed:', e.key);
});
// Form Events
const form = document.querySelector('form');
form.addEventListener('submit', (e) => {
e.preventDefault(); // Prevent form submission
console.log('Form submitted');
});
form.addEventListener('reset', (e) => {
console.log('Form reset');
});
// Document Events
document.addEventListener('DOMContentLoaded', () => {
console.log('DOM fully loaded');
});
window.addEventListener('load', () => {
console.log('Page fully loaded');
});
window.addEventListener('resize', () => {
console.log('Window resized');
});
window.addEventListener('scroll', () => {
console.log('Page scrolled');
});Event Object & Properties
Example
// Event object properties
const button = document.querySelector('button');
button.addEventListener('click', (event) => {
// Event target
console.log('Target element:', event.target);
console.log('Current target:', event.currentTarget);
// Mouse position
console.log('Mouse X:', event.clientX);
console.log('Mouse Y:', event.clientY);
console.log('Page X:', event.pageX);
console.log('Page Y:', event.pageY);
// Event type
console.log('Event type:', event.type);
// Timestamp
console.log('Event timestamp:', event.timeStamp);
// Event phase
console.log('Event phase:', event.eventPhase);
// Prevent default behavior
event.preventDefault();
// Stop propagation
event.stopPropagation();
// Stop immediate propagation
event.stopImmediatePropagation();
});
// Keyboard event properties
const input = document.querySelector('input');
input.addEventListener('keydown', (event) => {
console.log('Key:', event.key);
console.log('Code:', event.code);
console.log('Alt key:', event.altKey);
console.log('Ctrl key:', event.ctrlKey);
console.log('Shift key:', event.shiftKey);
console.log('Meta key:', event.metaKey);
// Check for specific keys
if (event.key === 'Enter') {
console.log('Enter key pressed');
}
if (event.ctrlKey && event.key === 's') {
event.preventDefault();
console.log('Save shortcut pressed');
}
});
// Form event properties
const form = document.querySelector('form');
form.addEventListener('submit', (event) => {
event.preventDefault();
const formData = new FormData(event.target);
const data = Object.fromEntries(formData);
console.log('Form data:', data);
});Event Delegation
Example
// Event delegation example
// Instead of adding listeners to each item
const todoList = document.getElementById('todo-list');
// Add listener to parent (event delegation)
todoList.addEventListener('click', (event) => {
const target = event.target;
// Check if clicked element is a delete button
if (target.classList.contains('delete-btn')) {
const todoItem = target.closest('.todo-item');
const todoId = todoItem.dataset.id;
deleteTodo(todoId);
}
// Check if clicked element is a checkbox
if (target.type === 'checkbox') {
const todoItem = target.closest('.todo-item');
const todoId = todoItem.dataset.id;
toggleTodo(todoId, target.checked);
}
});
// Benefits of event delegation
// 1. Fewer event listeners
// 2. Works with dynamically added elements
// 3. Better performance
// 4. Memory efficient
// Example with dynamically added elements
function addTodoItem(text) {
const li = document.createElement('li');
li.className = 'todo-item';
li.dataset.id = Date.now();
li.innerHTML = `
<input type="checkbox">
<span class="todo-text">${text}</span>
<button class="delete-btn">Delete</button>
`;
todoList.appendChild(li);
// No need to add event listeners - delegation handles it!
}
// Event delegation with multiple event types
todoList.addEventListener('click', handleTodoClick);
todoList.addEventListener('mouseenter', handleTodoHover);
todoList.addEventListener('mouseleave', handleTodoLeave);
function handleTodoClick(event) {
const target = event.target;
const todoItem = target.closest('.todo-item');
if (!todoItem) return;
if (target.classList.contains('delete-btn')) {
deleteTodo(todoItem.dataset.id);
} else if (target.type === 'checkbox') {
toggleTodo(todoItem.dataset.id, target.checked);
} else if (target.classList.contains('todo-text')) {
editTodo(todoItem.dataset.id);
}
}
function handleTodoHover(event) {
const todoItem = event.target.closest('.todo-item');
if (todoItem) {
todoItem.classList.add('hovered');
}
}
function handleTodoLeave(event) {
const todoItem = event.target.closest('.todo-item');
if (todoItem) {
todoItem.classList.remove('hovered');
}
}Custom Events
Example
// Creating and dispatching custom events
// Create custom event
const customEvent = new CustomEvent('todoAdded', {
detail: {
id: 123,
text: 'New todo item',
timestamp: Date.now()
},
bubbles: true,
cancelable: true
});
// Dispatch custom event
document.dispatchEvent(customEvent);
// Listen for custom event
document.addEventListener('todoAdded', (event) => {
console.log('Todo added:', event.detail);
updateTodoCount();
showNotification('Todo added successfully!');
});
// Custom event class
class TodoEvent extends CustomEvent {
constructor(type, todoData) {
super(type, {
detail: todoData,
bubbles: true,
cancelable: true
});
}
}
// Usage
const todoAddedEvent = new TodoEvent('todoAdded', {
id: 456,
text: 'Another todo',
completed: false
});
document.dispatchEvent(todoAddedEvent);
// Event bus pattern
class EventBus {
constructor() {
this.events = {};
}
on(event, callback) {
if (!this.events[event]) {
this.events[event] = [];
}
this.events[event].push(callback);
}
off(event, callback) {
if (this.events[event]) {
this.events[event] = this.events[event].filter(cb => cb !== callback);
}
}
emit(event, data) {
if (this.events[event]) {
this.events[event].forEach(callback => {
callback(data);
});
}
}
}
// Usage
const eventBus = new EventBus();
eventBus.on('todoAdded', (todo) => {
console.log('Todo added via event bus:', todo);
});
eventBus.on('todoDeleted', (todoId) => {
console.log('Todo deleted via event bus:', todoId);
});
eventBus.emit('todoAdded', { id: 789, text: 'Event bus todo' });
eventBus.emit('todoDeleted', 789);Practice Exercise: Event Handling
Example
// Exercise: Build an Interactive Color Picker
class ColorPicker {
constructor() {
this.currentColor = '#000000';
this.isDrawing = false;
this.init();
}
init() {
this.createCanvas();
this.createControls();
this.bindEvents();
}
createCanvas() {
const canvas = document.createElement('canvas');
canvas.id = 'drawing-canvas';
canvas.width = 600;
canvas.height = 400;
canvas.style.border = '2px solid #333';
canvas.style.cursor = 'crosshair';
document.body.appendChild(canvas);
this.canvas = canvas;
this.ctx = canvas.getContext('2d');
// Set initial background
this.ctx.fillStyle = '#ffffff';
this.ctx.fillRect(0, 0, canvas.width, canvas.height);
}
createControls() {
const controls = document.createElement('div');
controls.id = 'color-controls';
controls.style.marginBottom = '10px';
controls.innerHTML = `
<input type="color" id="color-picker" value="${this.currentColor}">
<input type="range" id="brush-size" min="1" max="50" value="5">
<span id="brush-size-display">5px</span>
<button id="clear-canvas">Clear Canvas</button>
<button id="save-canvas">Save Image</button>
`;
document.body.insertBefore(controls, this.canvas);
this.colorPicker = document.getElementById('color-picker');
this.brushSize = document.getElementById('brush-size');
this.brushSizeDisplay = document.getElementById('brush-size-display');
}
bindEvents() {
// Color picker events
this.colorPicker.addEventListener('change', (e) => {
this.currentColor = e.target.value;
});
// Brush size events
this.brushSize.addEventListener('input', (e) => {
const size = e.target.value;
this.brushSizeDisplay.textContent = size + 'px';
});
// Canvas events
this.canvas.addEventListener('mousedown', (e) => this.startDrawing(e));
this.canvas.addEventListener('mousemove', (e) => this.draw(e));
this.canvas.addEventListener('mouseup', () => this.stopDrawing());
this.canvas.addEventListener('mouseleave', () => this.stopDrawing());
// Control events
document.getElementById('clear-canvas').addEventListener('click', () => this.clearCanvas());
document.getElementById('save-canvas').addEventListener('click', () => this.saveCanvas());
}
startDrawing(e) {
this.isDrawing = true;
this.draw(e);
}
draw(e) {
if (!this.isDrawing) return;
const rect = this.canvas.getBoundingClientRect();
const x = e.clientX - rect.left;
const y = e.clientY - rect.top;
this.ctx.lineWidth = this.brushSize.value;
this.ctx.lineCap = 'round';
this.ctx.strokeStyle = this.currentColor;
this.ctx.lineTo(x, y);
this.ctx.stroke();
this.ctx.beginPath();
this.ctx.moveTo(x, y);
}
stopDrawing() {
this.isDrawing = false;
this.ctx.beginPath();
}
clearCanvas() {
this.ctx.fillStyle = '#ffffff';
this.ctx.fillRect(0, 0, this.canvas.width, this.canvas.height);
}
saveCanvas() {
const link = document.createElement('a');
link.download = 'drawing.png';
link.href = this.canvas.toDataURL();
link.click();
}
}
// Initialize the color picker
// const colorPicker = new ColorPicker();Try It Yourself — JavaScript DOM Events & Event Handling
Try It Yourself — JavaScript DOM Events & Event HandlingJavaScript
JavaScript Editor
✓ ValidTab = 2 spaces
JavaScript|17 lines|438 chars|✓ Valid syntax
UTF-8