Event Listeners Practice Solution

Understanding the Problem

We need to add interactivity to an HTML page by implementing various event listeners. The key requirements are:

Input:

Output:

Devising a Plan

Whiteboard Plan:

  1. Create references to all needed DOM elements
  2. Define callback functions for each event
  3. Add event listeners with appropriate event types
  4. Store references to event listeners for removal
  5. Implement remove listeners functionality

Basic Solution


// Store references to elements and callbacks for later removal
let redInput, addItemBtn, colorSelect, removeBtn;
let redInputCallback, addItemCallback, colorSelectCallback;

// Wait for DOM to load before adding listeners
document.addEventListener('DOMContentLoaded', () => {
    // Alert user that DOM is loaded
    alert('DOM has finished loading!');
    
    // Get element references
    redInput = document.getElementById('red-input');
    addItemBtn = document.getElementById('add-item');
    colorSelect = document.getElementById('color-select');
    removeBtn = document.getElementById('remove-listeners');
    
    // Define and store callback functions
    redInputCallback = (e) => {
        // Check if input contains 'red'
        if (e.target.value.toLowerCase().includes('red')) {
            e.target.style.backgroundColor = 'red';
        } else {
            e.target.style.backgroundColor = 'transparent';
        }
    };
    
    addItemCallback = () => {
        // Get input value
        const input = document.getElementById('list-add');
        const value = input.value;
        
        // Create and append new list item
        const li = document.createElement('li');
        li.textContent = value;
        document.querySelector('ul').appendChild(li);
        
        // Clear input
        input.value = '';
    };
    
    colorSelectCallback = (e) => {
        // Change section background color
        e.target.closest('section').style.backgroundColor = e.target.value;
    };
    
    // Add event listeners
    redInput.addEventListener('input', redInputCallback);
    addItemBtn.addEventListener('click', addItemCallback);
    colorSelect.addEventListener('change', colorSelectCallback);
    
    // Remove listeners when remove button clicked
    removeBtn.addEventListener('click', () => {
        redInput.removeEventListener('input', redInputCallback);
        addItemBtn.removeEventListener('click', addItemCallback);
        colorSelect.removeEventListener('change', colorSelectCallback);
        alert('Event listeners removed!');
    });
});
    

Code Explanation

Let's break down how this code works:

Event Delegation and Bubbling

Think of event listeners like security guards at different entrances of a building. When something happens (an event), the guard closest to the action responds first, then passes the information up to other guards if needed. This is similar to how events in the DOM "bubble up" through parent elements.

Key Concepts

DOMContentLoaded: This is like waiting for all the furniture to be set up in a room before letting people in. We wait for the HTML to be fully loaded before adding our event listeners.

Event Callbacks: These are like instruction manuals that tell the program exactly what to do when specific events happen. We store references to them so we can both add and remove them later.

Event Types: Different events require different handling:

Advanced Solutions

Here are some more sophisticated approaches:

Using Event Delegation


// Instead of multiple listeners, use one listener on a parent element
document.querySelector('main').addEventListener('click', (e) => {
    if (e.target.id === 'add-item') {
        // Handle add item
    } else if (e.target.id === 'remove-listeners') {
        // Handle remove listeners
    }
});
    

Using Classes for State Management


// Use classList instead of directly setting styles
redInputCallback = (e) => {
    e.target.classList.toggle('red-background', 
        e.target.value.toLowerCase().includes('red'));
};
    

Real World Applications

Event listeners are fundamental to web development. You'll find them in:

Further Examples

Here's how you might implement the bonus challenges:


// Global space bar listener
document.addEventListener('keydown', (e) => {
    if (e.code === 'Space') {
        alert('Space bar pressed!');
    }
});

// Hover effect
const hoverDiv = document.querySelector('.hover-div');
hoverDiv.addEventListener('mouseenter', () => {
    hoverDiv.textContent = 'Currently hovering!';
});
hoverDiv.addEventListener('mouseleave', () => {
    hoverDiv.textContent = '';
});
    

Additional Resources

To deepen your understanding of event listeners, consider exploring: