JavaScript and TypeScript course Β· Module 8: Events and the DOM
Events and Interactions in JavaScript
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 clickmouseenter/mouseleave- mouse entering/leavingmousemove- mouse movement (like a motion sensor)mousedown/mouseup- pressing/releasing a mouse button
Keyboard events:
keydown- key pressedkeyup- key releasedkeypress- deprecated, do not use it (usekeydownorinputinstead)
Form events:
submit- form submissionchange- field value changedinput- text inputfocus/blur- field activation/deactivation
Document events:
DOMContentLoaded- DOM ready (like a system going online)load- all resources loadedscroll- page scrollingresize- 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:
- Interactivity - responding to user actions
- Performance - code runs only when needed
- Asynchrony - different parts of the application can operate independently
- 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. Which method is the primary method for handling events in JavaScript?