|
1 | | -/* _ _ |
| 1 | +/* |
| 2 | + _ _ |
2 | 3 | | | (_) |
3 | 4 | _____ _____ _ __ | |_ ___ _ __ __ _ _ _ __ ___ |
4 | 5 | / _ \ \ / / _ \ '_ \| __/ / _ \ '_ \ / _` | | '_ \ / _ \ |
|
7 | 8 | __/ | JS LIBRARY |
8 | 9 | |___/ |
9 | 10 | */ |
| 11 | + |
10 | 12 | /*! |
11 | 13 | * Event Engine - A High-Performance JavaScript DOM Events Library |
12 | 14 | * |
|
25 | 27 | * Roles: Developer, Architect, Maintainer, Designer, Project Lead, Author |
26 | 28 | */ |
27 | 29 |
|
| 30 | + |
| 31 | + |
| 32 | +const isNode = typeof window === 'undefined'; |
| 33 | +const context = isNode ? {} : window; // Fallback to an empty object in Node.js |
| 34 | + |
| 35 | +// Mock addEventListener in Node.js environment |
| 36 | +if (isNode) { |
| 37 | + context.addEventListener = () => {}; // No-op |
| 38 | +} |
| 39 | + |
28 | 40 | /** |
29 | 41 | * Events Module |
30 | 42 | * Provides an API for handling browser events with features like namespacing, |
|
49 | 61 | global.Events = factory(global); |
50 | 62 | } |
51 | 63 |
|
52 | | -}(typeof global !== 'undefined' ? global : typeof window !== 'undefined' ? window : this, function (window) { |
| 64 | +}(typeof window !== 'undefined' ? window : global, function (window) { |
53 | 65 | 'use strict'; |
54 | 66 |
|
55 | | - const { throttle, debounce, doEvent } = EventUtils; // Import utility methods |
| 67 | + // import { throttle, debounce, doEvent } from './EventUtils'; |
| 68 | + const EventUtils = require('./EventUtils'); // Adjust the path as needed |
| 69 | + |
| 70 | + // Destructure the utilities |
| 71 | + const { throttle, debounce, doEvent } = EventUtils; |
| 72 | + |
| 73 | + if (isNode) { |
| 74 | + console.warn('Events library is running in a Node.js environment. DOM operations are disabled.'); |
| 75 | + } |
56 | 76 |
|
57 | 77 | /** |
58 | 78 | * Container for all event handling functionalities. |
|
64 | 84 | * @private |
65 | 85 | */ |
66 | 86 | const liveEvents = new Map(); |
| 87 | + |
67 | 88 | /** |
68 | 89 | * Stores debugging and analytics data. |
69 | 90 | * @private |
|
84 | 105 | */ |
85 | 106 | const groups = new Map(); |
86 | 107 |
|
| 108 | + // Refactor selector validation |
| 109 | + const isValidSelector = selector => |
| 110 | + selector instanceof HTMLElement || |
| 111 | + selector === window || |
| 112 | + selector === document; |
| 113 | + |
87 | 114 | /** |
88 | 115 | * Enables debugging mode for event tracking. |
89 | 116 | */ |
|
147 | 174 | * @param {boolean} [once=false] - If true, the listener is removed after the first execution. |
148 | 175 | * @param {string} [group=''] - Optional group to organize listeners. |
149 | 176 | */ |
150 | | - Events.add = function (types, selector, callback, options = {}, namespace = '', once = false, group = '') { |
| 177 | + Events.add = function (types, target, callback, options = {}, namespace = '', once = false, group = '') { |
| 178 | + if (!(target instanceof context.HTMLElement || target === context || target === context.document)) { |
| 179 | + throw new Error('Invalid target. Must be an instance of HTMLElement, Window, or Document.'); |
| 180 | + } |
| 181 | + |
151 | 182 | types.split(',').forEach(type => { |
152 | 183 | type = type.trim(); |
153 | | - let handler = callback; |
154 | | - |
155 | | - if (options.throttle) handler = throttle(callback, options.throttle); |
156 | | - if (options.debounce) handler = debounce(callback, options.debounce); |
157 | 184 |
|
158 | | - const listener = { |
159 | | - selector, |
160 | | - callback: handler, |
161 | | - originalCallback: callback, |
162 | | - namespace, |
163 | | - options, |
164 | | - once, |
165 | | - priority: options.priority || 0, |
166 | | - }; |
| 185 | + const handler = options.throttle |
| 186 | + ? throttle(callback, options.throttle) |
| 187 | + : options.debounce |
| 188 | + ? debounce(callback, options.debounce) |
| 189 | + : callback; |
167 | 190 |
|
168 | 191 | if (!liveEvents.has(type)) liveEvents.set(type, []); |
169 | | - liveEvents.get(type).push(listener); |
| 192 | + liveEvents.get(type).push({ target, callback: handler }); |
| 193 | + |
| 194 | + target.addEventListener(type, handler, { capture: options.capture || false }); |
170 | 195 |
|
171 | 196 | if (group) { |
172 | 197 | if (!groups.has(group)) groups.set(group, []); |
173 | | - groups.get(group).push({ type, listener }); |
| 198 | + groups.get(group).push({ type, target, handler }); |
174 | 199 | } |
175 | | - |
176 | | - window.addEventListener(type, function eventHandlerWrapper(event) { |
177 | | - handler.call(selector, event); |
178 | | - if (once) { |
179 | | - Events.remove(type, selector, callback, namespace); |
180 | | - window.removeEventListener(type, eventHandlerWrapper, options.capture || false); |
181 | | - } |
182 | | - }, { capture: options.capture || false, passive: options.passive || false }); |
183 | 200 | }); |
184 | 201 | }; |
185 | 202 |
|
186 | 203 | /** |
187 | 204 | * Removes an event listener or all listeners for a type/namespace. |
188 | 205 | */ |
189 | | - Events.remove = function (types, selector, callback, namespace = '') { |
| 206 | + /** |
| 207 | + * Removes an event listener. |
| 208 | + */ |
| 209 | + Events.remove = function (types, target, callback) { |
190 | 210 | types.split(',').forEach(type => { |
191 | | - const listeners = liveEvents.get(type) || []; |
192 | | - const updatedListeners = listeners.filter(listener => |
193 | | - !(listener.selector === selector && listener.originalCallback === callback && (!namespace || listener.namespace === namespace)) |
194 | | - ); |
195 | | - |
196 | | - if (updatedListeners.length) liveEvents.set(type, updatedListeners); |
197 | | - else { |
198 | | - liveEvents.delete(type); |
199 | | - window.removeEventListener(type, eventHandler, true); |
| 211 | + target.removeEventListener(type.trim(), callback); |
| 212 | + |
| 213 | + if (liveEvents.has(type)) { |
| 214 | + liveEvents.set( |
| 215 | + type, |
| 216 | + liveEvents.get(type).filter(e => e.target !== target || e.callback !== callback) |
| 217 | + ); |
200 | 218 | } |
201 | 219 | }); |
202 | 220 | }; |
|
0 commit comments