Skip to main content
Course/Module 7/Topic 2 of 3Intermediate

JavaScript DOM Events & Event Handling

Master event handling, different event types, event delegation, and modern event patterns for building responsive user interfaces

55 minBy Priygop TeamLast 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
Chat on WhatsApp
Priygop - Leading Professional Development Platform | Expert Courses & Interview Prep