Ray Arnold leads you deeper into the control center. "This is where it all begins," he points to a massive panel with thousands of buttons and indicators. "Every element of this system is an event listener - a watcher waiting for a signal."
"In Jurassic Park," he continues, "we have motion sensors, temperature detectors, cameras, microphones. Each one constantly listens, waiting for something unusual. When it detects something, it reacts immediately. In JavaScript, we have
addEventListener() - a method that works exactly the same way."The
addEventListener() method is the foundation of event handling in modern JavaScript. It allows you to assign a handler function to a specific event type on a chosen element.1element.addEventListener(eventType, handlerFunction, options);"Let's start with something simple," says Ray. "The Velociraptor feeding button."
1// Get the button element
2const feedButton = document.getElementById('velociraptor-feed');
3
4// Register a listener
5feedButton.addEventListener('click', function(event) {
6 console.log('Starting Velociraptor feeding procedure');
7 console.log('Clicked on:', event.target);
8
9 // Feeding logic
10 feedVelociraptors();
11});
12
13function feedVelociraptors() {
14 console.log('Safety cage: LOCKED');
15 console.log('Food dispenser: ACTIVE');
16 console.log('Monitoring: ENABLED');
17 console.log('Procedure completed successfully');
18}"What if we need multiple reactions to the same event?" asks Ray. "In the park systems, that's normal - one event can trigger multiple protocols."
1const emergencyButton = document.getElementById('emergency');
2
3// First listener - alarm activation
4emergencyButton.addEventListener('click', function() {
5 console.log('ALARM: Activating sirens');
6 activateSirens();
7});
8
9// Second listener - closing gates
10emergencyButton.addEventListener('click', function() {
11 console.log('SECURITY: Closing all gates');
12 lockAllGates();
13});
14
15// Third listener - notifying staff
16emergencyButton.addEventListener('click', function() {
17 console.log('COMMUNICATIONS: Sending notifications to the team');
18 notifySecurityTeam();
19});
20
21// All three functions will execute on clickRay shows you different ways to define handlers:
1const enclosureGate = document.getElementById('gate-5');
2
3// 1. Anonymous function
4enclosureGate.addEventListener('click', function(event) {
5 console.log('Gate clicked', event.target.id);
6});
7
8// 2. Arrow function (modern JavaScript)
9enclosureGate.addEventListener('click', (event) => {
10 console.log('Gate clicked', event.target.id);
11});
12
13// 3. Named function (best practice)
14function handleGateClick(event) {
15 console.log('Gate clicked', event.target.id);
16
17 if (event.target.dataset.status === 'open') {
18 closeGate(event.target.id);
19 } else {
20 openGate(event.target.id);
21 }
22}
23
24enclosureGate.addEventListener('click', handleGateClick);"Named functions are the best," Ray explains, "because you can remove them later, test them separately, and the code is more readable."
"When a sensor detects movement," Ray shows a report on the screen, "we get a complete data package: where, when, what type of movement, how fast. The Event object in JavaScript works the same way."
1document.addEventListener('click', function(event) {
2 // Basic event information
3 console.log('Event type:', event.type); // 'click'
4 console.log('Timestamp:', event.timeStamp); // time in ms since page load
5
6 // The element that was the target of the event
7 console.log('Target element:', event.target);
8 console.log('Current element:', event.currentTarget);
9
10 // Position information (for mouse events)
11 console.log('Screen position - X:', event.screenX, 'Y:', event.screenY);
12 console.log('Window position - X:', event.clientX, 'Y:', event.clientY);
13 console.log('Page position - X:', event.pageX, 'Y:', event.pageY);
14
15 // Modifier keys
16 console.log('Shift:', event.shiftKey);
17 console.log('Ctrl:', event.ctrlKey);
18 console.log('Alt:', event.altKey);
19 console.log('Meta (Cmd/Win):', event.metaKey);
20
21 // Mouse button
22 console.log('Button:', event.button); // 0=left, 1=middle, 2=right
23});"Let's see it in a real system," says Ray, opening the code for the interactive park map.
1const parkMap = document.getElementById('interactive-park-map');
2
3parkMap.addEventListener('click', function(event) {
4 // Get click coordinates
5 const x = event.clientX;
6 const y = event.clientY;
7
8 // Check if Ctrl was held (multiple selection)
9 if (event.ctrlKey) {
10 console.log('Multiple selection - adding to selection');
11 addToSelection(event.target);
12 } else {
13 console.log('Single selection - clearing previous selection');
14 clearSelection();
15 selectSingle(event.target);
16 }
17
18 // Different actions for different mouse buttons
19 switch(event.button) {
20 case 0: // Left button
21 showEnclosureDetails(event.target);
22 break;
23 case 2: // Right button
24 showContextMenu(x, y);
25 event.preventDefault(); // Block default context menu
26 break;
27 }
28
29 // Save position for later use
30 lastClickPosition = { x, y };
31});
32
33// Blocking the default context menu (right button)
34parkMap.addEventListener('contextmenu', function(event) {
35 event.preventDefault();
36 console.log('Custom context menu instead of default');
37});Ray shows more screens with different systems. "Each type of sensor detects something different. Similarly, we have different types of events."
1const dinoCard = document.getElementById('trex-card');
2
3// Clicks
4dinoCard.addEventListener('click', (e) => {
5 console.log('Single click');
6 showBasicInfo();
7});
8
9dinoCard.addEventListener('dblclick', (e) => {
10 console.log('Double click');
11 showDetailedView();
12});
13
14// Entering and leaving
15dinoCard.addEventListener('mouseenter', (e) => {
16 console.log('Mouse entered the card');
17 e.target.classList.add('highlighted');
18 showQuickPreview();
19});
20
21dinoCard.addEventListener('mouseleave', (e) => {
22 console.log('Mouse left the card');
23 e.target.classList.remove('highlighted');
24 hideQuickPreview();
25});
26
27// Mouse movement (use carefully - can generate hundreds of events)
28dinoCard.addEventListener('mousemove', (e) => {
29 // Update tooltip position
30 updateTooltipPosition(e.clientX, e.clientY);
31});
32
33// Button press and release
34dinoCard.addEventListener('mousedown', (e) => {
35 console.log('Mouse button pressed');
36 startDrag(e);
37});
38
39dinoCard.addEventListener('mouseup', (e) => {
40 console.log('Mouse button released');
41 endDrag(e);
42});"Many systems are controlled via keyboard," Ray explains. "Access codes, keyboard shortcuts, navigation."
1// Listen on the entire document
2document.addEventListener('keydown', function(event) {
3 console.log('Key pressed:', event.key);
4 console.log('Key code:', event.code);
5 console.log('Is it a repeat:', event.repeat);
6
7 // Keyboard shortcuts
8 if (event.ctrlKey && event.key === 's') {
9 event.preventDefault(); // Block default browser save
10 saveParkConfiguration();
11 console.log('Configuration saved');
12 }
13
14 if (event.key === 'Escape') {
15 closeAllModals();
16 console.log('All windows closed');
17 }
18
19 // Arrow key navigation
20 switch(event.key) {
21 case 'ArrowUp':
22 moveCamera('north');
23 break;
24 case 'ArrowDown':
25 moveCamera('south');
26 break;
27 case 'ArrowLeft':
28 moveCamera('west');
29 break;
30 case 'ArrowRight':
31 moveCamera('east');
32 break;
33 }
34});
35
36// Listen on a specific field
37const securityCodeInput = document.getElementById('security-code');
38
39securityCodeInput.addEventListener('keypress', function(event) {
40 // Only digits
41 if (event.key < '0' || event.key > '9') {
42 event.preventDefault();
43 console.log('Only digits are allowed');
44 }
45});"Forms are a critical part of the park systems," says Ray. "Incident reporting, guest registration, monitoring."
1const incidentForm = document.getElementById('incident-report');
2const severitySelect = document.getElementById('severity');
3const descriptionArea = document.getElementById('description');
4
5// Submit - form submission
6incidentForm.addEventListener('submit', function(event) {
7 event.preventDefault(); // IMPORTANT: block default submission
8
9 console.log('Form submitted');
10
11 // Collect data
12 const formData = new FormData(incidentForm);
13 const data = {
14 severity: formData.get('severity'),
15 location: formData.get('location'),
16 description: formData.get('description'),
17 reporter: formData.get('reporter'),
18 timestamp: new Date().toISOString()
19 };
20
21 // Validation
22 if (validateIncidentReport(data)) {
23 submitIncidentReport(data);
24 incidentForm.reset();
25 } else {
26 console.error('Invalid form data');
27 }
28});
29
30// Change - value changed (after leaving the field)
31severitySelect.addEventListener('change', function(event) {
32 const severity = event.target.value;
33 console.log('Threat level changed to:', severity);
34
35 // Adjust priority and color
36 if (severity === 'critical') {
37 incidentForm.classList.add('critical');
38 setPriority('HIGH');
39 } else {
40 incidentForm.classList.remove('critical');
41 setPriority('NORMAL');
42 }
43});
44
45// Input - value changing (in real time)
46descriptionArea.addEventListener('input', function(event) {
47 const length = event.target.value.length;
48 const maxLength = 500;
49
50 console.log(`Characters: ${length}/${maxLength}`);
51 updateCharacterCounter(length, maxLength);
52
53 if (length > maxLength) {
54 event.target.classList.add('error');
55 } else {
56 event.target.classList.remove('error');
57 }
58});
59
60// Focus and Blur - field activation and deactivation
61descriptionArea.addEventListener('focus', function(event) {
62 console.log('Description field active - showing help tips');
63 showHelpTips();
64});
65
66descriptionArea.addEventListener('blur', function(event) {
67 console.log('Description field inactive - hiding tips');
68 hideHelpTips();
69});"Systems that are no longer needed," Ray shows a disabled panel, "should be shut down. It saves energy and resources."
1// The function must be named to be removable
2function handleClick(event) {
3 console.log('Clicked');
4}
5
6const button = document.getElementById('temp-button');
7
8// Add listener
9button.addEventListener('click', handleClick);
10
11// Later remove it (must be the same function)
12button.removeEventListener('click', handleClick);
13
14// ❌ This WON'T WORK - these are two different functions
15button.addEventListener('click', () => console.log('Test'));
16button.removeEventListener('click', () => console.log('Test'));1function setupMaintenanceMode() {
2 console.log('Enabling maintenance mode for 5 minutes');
3
4 const maintenanceAlert = function(event) {
5 event.preventDefault();
6 alert('Park is in maintenance mode. Please try again later.');
7 };
8
9 // Block all actions
10 document.addEventListener('click', maintenanceAlert, true); // true = capture
11
12 // After 5 minutes disable maintenance mode
13 setTimeout(() => {
14 document.removeEventListener('click', maintenanceAlert, true);
15 console.log('Maintenance mode disabled');
16 }, 5 * 60 * 1000);
17}Ray shows the advanced configuration panel. "Sometimes we need special settings for sensors."
1element.addEventListener(eventType, handler, {
2 capture: false, // Use capture phase instead of bubbling
3 once: false, // Remove listener after first invocation
4 passive: false // Don't call preventDefault()
5});1const welcomeScreen = document.getElementById('welcome');
2
3// Show welcome only once
4welcomeScreen.addEventListener('click', function() {
5 console.log('Welcome to Jurassic Park!');
6 showTour();
7}, { once: true });
8
9// After the first click, the listener is automatically removed1// For scroll performance
2window.addEventListener('scroll', function(event) {
3 updateScrollPosition();
4 // Cannot use event.preventDefault() with passive: true
5}, { passive: true });"Let's combine everything into one system," says Ray, opening the main monitoring code.
1class ParkMonitoringSystem {
2 constructor() {
3 this.alerts = [];
4 this.isActive = false;
5 this.initialize();
6 }
7
8 initialize() {
9 console.log('Initializing monitoring system...');
10
11 // Document events
12 document.addEventListener('DOMContentLoaded', () => {
13 this.onSystemReady();
14 });
15
16 // Window events
17 window.addEventListener('beforeunload', (e) => {
18 return this.onBeforeExit(e);
19 });
20
21 // Error events
22 window.addEventListener('error', (e) => {
23 this.logError(e);
24 });
25
26 this.isActive = true;
27 }
28
29 onSystemReady() {
30 console.log('Monitoring system ready');
31 this.setupEnclosureMonitors();
32 this.setupSecuritySystem();
33 this.startPeriodicChecks();
34 }
35
36 setupEnclosureMonitors() {
37 const enclosures = document.querySelectorAll('.enclosure');
38
39 enclosures.forEach(enclosure => {
40 // Enclosure status
41 enclosure.addEventListener('click', (e) => {
42 this.showEnclosureStatus(enclosure.id);
43 });
44
45 // Details on double click
46 enclosure.addEventListener('dblclick', (e) => {
47 this.showDetailedView(enclosure.id);
48 });
49
50 // Highlight on hover
51 enclosure.addEventListener('mouseenter', (e) => {
52 e.target.classList.add('active');
53 this.showQuickInfo(enclosure.id);
54 });
55
56 enclosure.addEventListener('mouseleave', (e) => {
57 e.target.classList.remove('active');
58 this.hideQuickInfo();
59 });
60 });
61 }
62
63 setupSecuritySystem() {
64 // Keyboard shortcuts
65 document.addEventListener('keydown', (e) => {
66 if (e.ctrlKey && e.shiftKey && e.key === 'E') {
67 this.triggerEmergency();
68 }
69
70 if (e.key === 'F1') {
71 e.preventDefault();
72 this.showHelp();
73 }
74 });
75
76 // Emergency button
77 const emergencyBtn = document.getElementById('emergency');
78 if (emergencyBtn) {
79 emergencyBtn.addEventListener('click', () => {
80 this.triggerEmergency();
81 });
82 }
83 }
84
85 startPeriodicChecks() {
86 // Check all systems every 30 seconds
87 this.checkInterval = setInterval(() => {
88 if (this.isActive) {
89 this.performSystemCheck();
90 }
91 }, 30000);
92 }
93
94 performSystemCheck() {
95 console.log(`[${new Date().toLocaleTimeString()}] Checking systems...`);
96 // Check logic
97 }
98
99 triggerEmergency() {
100 console.error('🚨 EMERGENCY ALARM!');
101 this.addAlert({
102 type: 'emergency',
103 message: 'Emergency alarm activated',
104 timestamp: new Date()
105 });
106 }
107
108 addAlert(alert) {
109 this.alerts.push(alert);
110 const event = new CustomEvent('parkAlert', { detail: alert });
111 document.dispatchEvent(event);
112 }
113
114 onBeforeExit(event) {
115 if (this.alerts.some(a => a.type === 'emergency')) {
116 event.returnValue = 'There are active alerts! Are you sure you want to leave?';
117 return event.returnValue;
118 }
119 }
120
121 logError(event) {
122 console.error('System error:', event.error);
123 this.addAlert({
124 type: 'error',
125 message: event.error.message,
126 timestamp: new Date()
127 });
128 }
129
130 destroy() {
131 // Disable monitoring
132 this.isActive = false;
133 clearInterval(this.checkInterval);
134 console.log('Monitoring system disabled');
135 }
136}
137
138// Initialization
139const parkMonitoring = new ParkMonitoringSystem();"Event listeners are the core of every interactive system," Ray summarizes. "Just as sensors in Jurassic Park watch over safety, event listeners watch over the functionality of your application."
Key rules:
addEventListener() for all listenersremoveEventListener() when a listener is no longer needed{ once: true } option for one-time operations{ passive: true } for scroll/touch for performance