JavaScript and TypeScript course Β· Module 8: Events and the DOM

Events and Interactions in JavaScript

6 min read
In this lesson3

"Welcome back to Jurassic Park," greets you Ray Arnold, the chief systems engineer. "Today I'll show you how the most critical aspect of our systems works - interactivity. Every system in the park, from the security gates to the dinosaur monitoring, must respond to various signals in real time."

Ray leads you to the central control panel, where hundreds of indicators blink and pulse. "Look," he points at the screen, "all these systems listen for events - a gate opening, movement in an enclosure, a temperature change. In JavaScript, we work exactly the same way."

What Are Events in JavaScript?

Events are a fundamental communication mechanism in the browser. Every user interaction - a click, a mouse movement, a key press - generates an event that we can respond to.

1// Similar to a motion sensor in a dinosaur enclosure
2const motionSensor = document.getElementById('dino-enclosure');
3
4motionSensor.addEventListener('click', function() {
5  console.log('Activity detected in the enclosure!');
6  checkDinosaurStatus();
7});

"In Jurassic Park," Ray continues, "we have thousands of sensors. Each one sends signals to the control center. If we had to constantly check every sensor, the system would collapse. Instead, sensors send events only when something happens."

The Browser Event Model

The browser implements a so-called Event-Driven Architecture - an architecture driven by events. This means that code doesn't execute sequentially from top to bottom, but reacts to events occurring in the system.

1// Code registers listeners and waits for events
2console.log('System active - listening...');
3
4document.addEventListener('click', () => {
5  console.log('Click registered!');
6});
7
8document.addEventListener('keydown', () => {
9  console.log('Key pressed!');
10});
11
12// The program doesn't end - it waits for events
13console.log('All systems ready');

Types of Events

Ray shows you a list on the screen. "We have dozens of sensor types in the park. Similarly, JavaScript has dozens of event types:"

Mouse events:

  • click - click (like an emergency button)
  • dblclick - double click
  • mouseenter / mouseleave - mouse entering/leaving
  • mousemove - mouse movement (like a motion sensor)
  • mousedown / mouseup - pressing/releasing a mouse button

Keyboard events:

  • keydown - key pressed
  • keyup - key released
  • keypress - deprecated, do not use it (use keydown or input instead)

Form events:

  • submit - form submission
  • change - field value changed
  • input - text input
  • focus / blur - field activation/deactivation

Document events:

  • DOMContentLoaded - DOM ready (like a system going online)
  • load - all resources loaded
  • scroll - page scrolling
  • resize - window resize

Anatomy of an Event

"Every event carries information with it," Ray explains, showing a detailed sensor report. "Similarly, every Event object in JavaScript contains data about what happened."

1const enclosureMap = document.getElementById('park-map');
2
3enclosureMap.addEventListener('click', function(event) {
4  // The event object contains detailed information
5
6  console.log('Event type:', event.type); // 'click'
7  console.log('Target element:', event.target); // the clicked element
8  console.log('Position X:', event.clientX); // X coordinate
9  console.log('Position Y:', event.clientY); // Y coordinate
10  console.log('Mouse button:', event.button); // 0=left, 1=middle, 2=right
11  console.log('Ctrl pressed?', event.ctrlKey); // true/false
12  console.log('Shift pressed?', event.shiftKey); // true/false
13
14  // We can use this information for precise reactions
15  if (event.ctrlKey) {
16    selectMultipleDinosaurs(event.target);
17  } else {
18    selectSingleDinosaur(event.target);
19  }
20});

Why Are Events Important?

Ray points to the large screen showing maps of all enclosures. "Without the event system, we'd have to check every sensor every second. That would be inefficient and resource-heavy. Events allow systems to react instantly and only when needed."

In web applications, events enable:

  1. Interactivity - responding to user actions
  2. Performance - code runs only when needed
  3. Asynchrony - different parts of the application can operate independently
  4. Modularity - different components can communicate through events

First Practical Example

"Let's see it in action," says Ray, opening a code panel. "Let's create a simple enclosure monitoring system."

1// T-Rex enclosure monitoring system
2const trexEnclosure = {
3  temperature: 28,
4  humidity: 65,
5  feedingSchedule: '14:00',
6  lastActivity: null,
7
8  initialize() {
9    // Registering listeners for various systems
10    const tempSensor = document.getElementById('temp-sensor');
11    const feedButton = document.getElementById('feed-button');
12    const activityMonitor = document.getElementById('activity-monitor');
13
14    // Temperature monitoring
15    tempSensor.addEventListener('change', (e) => {
16      this.temperature = parseFloat(e.target.value);
17      this.checkConditions();
18    });
19
20    // Feeding system
21    feedButton.addEventListener('click', () => {
22      this.feedDinosaur();
23    });
24
25    // Activity detection
26    activityMonitor.addEventListener('motion', (e) => {
27      this.lastActivity = new Date();
28      this.logActivity(e.detail);
29    });
30
31    console.log('T-Rex monitoring system active');
32  },
33
34  checkConditions() {
35    if (this.temperature > 35) {
36      this.triggerAlert('Temperature too high!', 'warning');
37    } else if (this.temperature < 20) {
38      this.triggerAlert('Temperature too low!', 'warning');
39    } else {
40      console.log('Conditions optimal');
41    }
42  },
43
44  feedDinosaur() {
45    console.log('Starting T-Rex feeding procedure...');
46    this.triggerAlert('Feeding in progress', 'info');
47
48    setTimeout(() => {
49      console.log('Feeding completed successfully');
50      this.triggerAlert('Feeding completed', 'success');
51    }, 3000);
52  },
53
54  logActivity(details) {
55    console.log(`Activity registered: ${details.type} at ${this.lastActivity.toLocaleTimeString()}`);
56  },
57
58  triggerAlert(message, level) {
59    const alertEvent = new CustomEvent('parkAlert', {
60      detail: { message, level, timestamp: new Date() }
61    });
62    document.dispatchEvent(alertEvent);
63  }
64};
65
66// System initialization
67document.addEventListener('DOMContentLoaded', () => {
68  trexEnclosure.initialize();
69});
70
71// Central alert system
72document.addEventListener('parkAlert', (e) => {
73  const { message, level, timestamp } = e.detail;
74  console.log(`[${timestamp.toLocaleTimeString()}] ${level.toUpperCase()}: ${message}`);
75});

Best Practices - Ray Arnold's Rules

"Through years of working on Jurassic Park systems," says Ray, "I've learned a few key rules:"

1. Always check if the element exists

1const emergencyButton = document.getElementById('emergency');
2
3if (emergencyButton) {
4  emergencyButton.addEventListener('click', evacuatePark);
5} else {
6  console.error('CRITICAL ERROR: Emergency button not found!');
7}

2. Remove listeners when they're no longer needed

1function setupTemporaryMonitoring() {
2  const sensor = document.getElementById('temp-sensor');
3
4  function handleReading(e) {
5    console.log('Reading:', e.target.value);
6  }
7
8  sensor.addEventListener('change', handleReading);
9
10  // After 1 hour, disable monitoring
11  setTimeout(() => {
12    sensor.removeEventListener('change', handleReading);
13    console.log('Monitoring ended');
14  }, 3600000);
15}

3. Use named functions for readability

The function's name tells you at once what the listener does, and when something goes wrong, you will see it in the call stack in the developer tools.

1// Better
2function handleEmergencyClick(event) {
3  console.log('Activating emergency protocol');
4  evacuatePark();
5}
6
7emergencyButton.addEventListener('click', handleEmergencyClick);
8
9// Than
10emergencyButton.addEventListener('click', function(e) {
11  console.log('Activating emergency protocol');
12  evacuatePark();
13});

4. Group similar events

1class EnclosureMonitor {
2  constructor(enclosureId) {
3    this.enclosure = document.getElementById(enclosureId);
4    this.initializeEvents();
5  }
6
7  initializeEvents() {
8    // All event listeners in one place
9    this.enclosure.addEventListener('click', (e) => this.handleClick(e));
10    this.enclosure.addEventListener('mouseenter', (e) => this.handleMouseEnter(e));
11    this.enclosure.addEventListener('mouseleave', (e) => this.handleMouseLeave(e));
12  }
13
14  handleClick(event) {
15    console.log('Enclosure clicked');
16  }
17
18  handleMouseEnter(event) {
19    this.enclosure.classList.add('highlighted');
20  }
21
22  handleMouseLeave(event) {
23    this.enclosure.classList.remove('highlighted');
24  }
25}

Summary

"Events are the core of every interactive system," Ray summarizes. "Without them, our applications would be static and useless - like a park without security systems."

Key concepts:

  • Events are generated by the browser in response to user actions
  • addEventListener() allows you to listen for events
  • The event object contains detailed information about the event
  • Proper listener management is crucial for performance

In the following lessons, we'll dive deeper into advanced event handling techniques, learning about propagation, delegation, and custom events.

Code for this lesson: index.html
1<!DOCTYPE html>
2<html lang="en">
3<head>
4    <meta charset="UTF-8">
5    <meta name="viewport" content="width=device-width, initial-scale=1.0">
6    <title>Jurassic Park - Alarm Panel</title>
7    <style>
8        body {
9            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
10            background: linear-gradient(135deg, #2c3e50 0%, #34495e 100%);
11            margin: 0;
12            padding: 20px;
13            color: white;
14        }
15
16        .emergency-panel {
17            max-width: 400px;
18            margin: 50px auto;
19            background: rgba(0, 0, 0, 0.8);
20            border-radius: 15px;
21            padding: 30px;
22            box-shadow: 0 10px 30px rgba(0, 0, 0, 0.5);
23            border: 2px solid #e74c3c;
24        }
25
26        .emergency-button {
27            width: 100%;
28            height: 100px;
29            background: linear-gradient(45deg, #e74c3c, #c0392b);
30            border: none;
31            border-radius: 10px;
32            color: white;
33            font-size: 24px;
34            font-weight: bold;
35            cursor: pointer;
36            transition: all 0.3s ease;
37            margin-bottom: 20px;
38            box-shadow: 0 5px 15px rgba(231, 76, 60, 0.4);
39        }
40
41        .emergency-button:hover {
42            transform: translateY(-2px);
43            box-shadow: 0 10px 25px rgba(231, 76, 60, 0.6);
44            background: linear-gradient(45deg, #c0392b, #a93226);
45        }
46
47        .emergency-button:active {
48            transform: translateY(0);
49            box-shadow: 0 5px 15px rgba(231, 76, 60, 0.4);
50        }
51
52        .status-display {
53            background: rgba(255, 255, 255, 0.1);
54            border-radius: 8px;
55            padding: 15px;
56            margin-top: 20px;
57            border: 1px solid rgba(255, 255, 255, 0.2);
58        }
59
60        .alert-message {
61            display: none;
62            background: #e74c3c;
63            color: white;
64            padding: 15px;
65            border-radius: 8px;
66            margin-top: 15px;
67            text-align: center;
68            font-weight: bold;
69            animation: pulse 1s infinite;
70        }
71
72        @keyframes pulse {
73            0% { opacity: 1; }
74            50% { opacity: 0.7; }
75            100% { opacity: 1; }
76        }
77
78        h1 {
79            text-align: center;
80            margin-bottom: 30px;
81            color: #ecf0f1;
82        }
83
84        .last-activation {
85            color: #bdc3c7;
86            font-size: 14px;
87        }
88    </style>
89</head>
90<body>
91    <div class="emergency-panel">
92        <h1>T-REX ALARM PANEL</h1>
93        <button id="emergency-button" class="emergency-button">
94            ACTIVATE EMERGENCY ALARM
95        </button>
96
97        <div class="status-display">
98            <div>System status: <span id="system-status">READY</span></div>
99            <div class="last-activation">Last activation: <span id="last-activation">NEVER</span></div>
100        </div>
101
102        <div id="alert-message" class="alert-message">
103            ALARM! T-REX ESCAPED FROM THE PADDOCK!
104        </div>
105    </div>
106
107    <script>
108        // Getting references to DOM elements
109        const emergencyButton = document.getElementById('emergency-button');
110        const systemStatus = document.getElementById('system-status');
111        const lastActivation = document.getElementById('last-activation');
112        const alertMessage = document.getElementById('alert-message');
113
114        // Adding an event listener to the button
115        emergencyButton.addEventListener('click', function() {
116            // Displaying alert
117            alert('EMERGENCY ALARM ACTIVATED!\n\nT-Rex escaped from the paddock!\nEvacuation in progress...');
118
119            // Updating the system status
120            systemStatus.textContent = 'ALARM ACTIVE';
121            systemStatus.style.color = '#e74c3c';
122
123            // Saving the time of the last activation
124            const now = new Date();
125            lastActivation.textContent = now.toLocaleTimeString('en-US');
126
127            // Showing the alarm message
128            alertMessage.style.display = 'block';
129
130            // Changing the button text
131            emergencyButton.textContent = 'ALARM ACTIVE';
132            emergencyButton.style.background = 'linear-gradient(45deg, #27ae60, #2ecc71)';
133
134            // After 5 seconds we reset the system
135            setTimeout(function() {
136                systemStatus.textContent = 'READY';
137                systemStatus.style.color = '#2ecc71';
138                alertMessage.style.display = 'none';
139                emergencyButton.textContent = 'ACTIVATE EMERGENCY ALARM';
140                emergencyButton.style.background = 'linear-gradient(45deg, #e74c3c, #c0392b)';
141            }, 5000);
142        });
143
144        // Adding mouse hover handling
145        emergencyButton.addEventListener('mouseenter', function() {
146            console.log('Cursor over the emergency button - CAUTION!');
147        });
148
149        emergencyButton.addEventListener('mouseleave', function() {
150            console.log('Cursor left the emergency button');
151        });
152    </script>
153</body>
154</html>

Spotted a mistake in this lesson?

Check yourself

Answer the questions from this lesson. Pick an answer to see right away whether it is correct.

  1. 1. Which method is the primary method for handling events in JavaScript?

Useful articles