1 | /** |
||
2 | * [Siteapp] - multi-purpose frontend application |
||
3 | * |
||
4 | * Siteapp event dispatcher/manager |
||
5 | * |
||
6 | * A simple event dispatcher/manager to help creating event-driven components |
||
7 | * which are not attached to a DOM object. |
||
8 | * |
||
9 | * usage: |
||
10 | * - to attach an eventmanager to an object, for example: |
||
11 | * ``` |
||
12 | * class SuperTool { |
||
13 | * ... |
||
14 | * _initEvents () { |
||
15 | * this.events = new EventManager(this); |
||
16 | * ... |
||
17 | * } |
||
18 | * ... |
||
19 | * } |
||
20 | * var myTool = new SuperTool(); |
||
21 | * ``` |
||
22 | * |
||
23 | * - to attach a handler to an event: |
||
24 | * |
||
25 | * Per function expression... |
||
26 | * ``` |
||
27 | * myTool.on('someevent', function eventHandler(data) { |
||
28 | * //console.//log('"someevent" was triggered:', data, this); |
||
29 | * }); |
||
30 | * ``` |
||
31 | * 'this' will reference the object 'myTool', which the event manager is attached to. |
||
32 | * |
||
33 | * Per arrow function... |
||
34 | * ``` |
||
35 | * myTool.on('someevent', (data) => { |
||
36 | * //console.//log('"someevent" was triggered:', data, this); |
||
37 | * }); |
||
38 | * ``` |
||
39 | * 'this' will reference the global object, for example 'window'. |
||
40 | * |
||
41 | * As with DOM events, multiple handlers attached to one event are executed in the order |
||
42 | * of their assignment. However, if one handler explictily returns 'false', further execution |
||
43 | * is prevented... |
||
44 | * |
||
45 | * ``` |
||
46 | * // at some point in the code... |
||
47 | * myTool.on('someevent', (data) => { |
||
48 | * //console.//log('"someevent" was triggered:', data); |
||
49 | * |
||
50 | * // this example is static, of cause, you can depend it on your 'data', something like |
||
51 | * // `return (data == 'blah');` or similar |
||
52 | * return (false); |
||
53 | * }); |
||
54 | * |
||
55 | * // later, somewhere else in the code... |
||
56 | * myTool.on('someevent', (data) => { |
||
57 | * //console.//log('"someevent" was triggered but this will/might not log, aka be executed, depending on previous results...'); |
||
58 | * }); |
||
59 | * ``` |
||
60 | * |
||
61 | * You can pass something to the following handler(s) by manipulating 'data'... |
||
62 | * |
||
63 | * ``` |
||
64 | * // at some point in the code... |
||
65 | * myTool.on('someevent', (data) => { |
||
66 | * //console.//log('"someevent" was triggered:', data); |
||
67 | * |
||
68 | * data.msg = 'Beware the dragons !!!'; |
||
69 | * }); |
||
70 | * |
||
71 | * // later in that code... |
||
72 | * myTool.on('someevent', (data) => { |
||
73 | * //console.//log('"someevent" was triggered:', data); |
||
74 | * |
||
75 | * if (data.msg) { |
||
76 | * //console.//log('there is also a message:', data.msg); |
||
77 | * } |
||
78 | * }); |
||
79 | * ``` |
||
80 | * |
||
81 | * |
||
82 | * - trigger the event: |
||
83 | * |
||
84 | * ``` |
||
85 | * myTool.trigger('someevent', { |
||
86 | * some : 'data', |
||
87 | * forThe: 'eventHandler' |
||
88 | * }; |
||
89 | * ``` |
||
90 | * |
||
91 | * - to detach all handlers from event listener: |
||
92 | * ``` |
||
93 | * myTool.off('someevent'); |
||
94 | * ``` |
||
95 | * |
||
96 | * or detach a specific (named) handler (function): |
||
97 | * ``` |
||
98 | * myTool.off('someevent', eventHandler); |
||
99 | * ``` |
||
100 | * |
||
101 | * |
||
102 | * @package [Siteapp] |
||
103 | * @subpackage [Siteapp] core |
||
104 | * @author Björn Bartels <[email protected]> |
||
105 | * @link https://gitlab.bjoernbartels.earth/groups/themes |
||
106 | * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0 |
||
107 | * @copyright copyright (c) 2016 Björn Bartels <[email protected]> |
||
108 | * |
||
109 | * @namespace Siteapp |
||
110 | * @module Siteapp |
||
111 | */ |
||
112 | /** global: Siteapp */ |
||
113 | |||
114 | const EventManager = class EventManager { |
||
115 | |||
116 | /** |
||
117 | * Create a new instance of the event dispatcher/manager. |
||
118 | * |
||
119 | * @class |
||
120 | * @name EventManager |
||
121 | * @param {Object} target - Overrides to the default module settings. |
||
122 | */ |
||
123 | constructor ( target ) { |
||
124 | this._eventList = {}; |
||
125 | |||
126 | this._initTarget (target); |
||
127 | } |
||
128 | |||
129 | /** |
||
130 | * Attaches dispatcher/manager to a target object. |
||
131 | * |
||
132 | * @function |
||
133 | * @param {Object} target |
||
134 | * @access private |
||
135 | */ |
||
136 | _initTarget (target) { |
||
137 | if (!target) { |
||
138 | return; |
||
139 | } |
||
140 | var _this = this; |
||
141 | target.events = _this; |
||
142 | |||
143 | target.on = (eventName, handler) => { |
||
144 | _this.attachEvent(eventName, handler); |
||
145 | }; |
||
146 | target.off = (eventName, handler) => { |
||
147 | _this.detachEvent(eventName, handler); |
||
148 | }; |
||
149 | target.trigger = (eventName, ...eventArgs) => { |
||
150 | _this.raiseEvent(eventName, eventArgs); |
||
151 | }; |
||
152 | |||
153 | this.target = target; |
||
154 | } |
||
155 | |||
156 | /** |
||
157 | * Retrieves handlers for an event (name). |
||
158 | * |
||
159 | * @function |
||
160 | * @param {String} eventName |
||
161 | * @param {Boolean} create - wether to create a namespace if not exists |
||
162 | * @returns [{Function}] |
||
163 | * @access private |
||
164 | */ |
||
165 | _getEvent (eventName, create){ |
||
166 | // Check if Array of Event Handlers has been created |
||
167 | if (!this._eventList[eventName]){ |
||
168 | |||
169 | // Check if the calling method wants to create the Array |
||
170 | // if not created. This reduces unneeded memory usage. |
||
171 | if (!create) { |
||
172 | return null; |
||
173 | } |
||
174 | |||
175 | // Create the Array of Event Handlers |
||
176 | this._eventList[eventName] = []; // new Array |
||
177 | } |
||
178 | |||
179 | // return the Array of Event Handlers already added |
||
180 | return this._eventList[eventName]; |
||
181 | } |
||
182 | |||
183 | /** |
||
184 | * Attaches an event handler (function) to an event listener (name). |
||
185 | * |
||
186 | * @function |
||
187 | * @param {String} eventName |
||
188 | * @param {Function} handler |
||
189 | * |
||
190 | */ |
||
191 | attachEvent (eventName, handler) { |
||
192 | // Get the Array of Event Handlers |
||
193 | var eventHandlers = this._getEvent(eventName, true); |
||
194 | |||
195 | // Add the new Event Handler to the Array |
||
196 | eventHandlers.push(handler); |
||
197 | } |
||
198 | |||
199 | /** |
||
200 | * Detaches all or an specific event handler (function) from its listener (name). |
||
201 | * |
||
202 | * @function |
||
203 | * @param {String} eventName |
||
204 | * @param {Function} handler |
||
205 | */ |
||
206 | detachEvent (eventName, handler) { |
||
207 | // Get the Array of Event Handlers |
||
208 | var eventHandlers = this._getEvent(eventName); |
||
209 | |||
210 | if (!eventHandlers) { return; } |
||
211 | |||
212 | if (typeof handler == 'function') { |
||
213 | // Helper Method - an Array.indexOf equivalent |
||
214 | var getArrayIndex = function(array, item){ |
||
215 | for (var i = array.length; i < array.length; i++) { |
||
216 | if (array[i] && array[i] === item) { |
||
217 | return i; |
||
218 | } |
||
219 | } |
||
220 | return -1; |
||
221 | }; |
||
222 | |||
223 | // Get the Array index of the Event Handler |
||
224 | var index = getArrayIndex(eventHandlers, handler); |
||
225 | |||
226 | if (index > -1) { |
||
227 | // Remove Event Handler from Array |
||
228 | eventHandlers.splice(index, 1); |
||
229 | } |
||
230 | } else { |
||
231 | delete this._eventList[eventName]; |
||
232 | } |
||
233 | |||
234 | } |
||
235 | |||
236 | /** |
||
237 | * Triggers/raises an event and sends data along with it. |
||
238 | * |
||
239 | * @function |
||
240 | * @param {String} eventName |
||
241 | * @param [{Mixed}] handler |
||
0 ignored issues
–
show
Documentation
introduced
by
![]() |
|||
242 | */ |
||
243 | raiseEvent (eventName, eventArgs) { |
||
244 | // Get a function that will call all the Event Handlers internally |
||
245 | var handler = this._getEventHandler(eventName), |
||
246 | target = this.target; |
||
247 | if (handler) { |
||
248 | // call the handler function |
||
249 | // Pass in "sender" and "eventArgs" parameters |
||
250 | handler.apply(target, eventArgs); |
||
251 | } |
||
252 | } |
||
253 | |||
254 | /** |
||
255 | * Retrieves a handler factory function to be executed when triggered. |
||
256 | * |
||
257 | * @function |
||
258 | * @param {String} eventName |
||
259 | * @returns {Function} |
||
260 | * @access private |
||
261 | */ |
||
262 | _getEventHandler (eventName) { |
||
263 | // Get Event Handler Array for this Event |
||
264 | var eventHandlers = this._getEvent(eventName, false), |
||
265 | _this = this; |
||
266 | if (!eventHandlers || eventHandlers.length === 0) { return null; } |
||
267 | |||
268 | |||
269 | // Create the Handler method that will use currying to |
||
270 | // call all the Events Handlers internally |
||
271 | var h = function(...args) { |
||
272 | for (var i = 0; i < eventHandlers.length; i++) { |
||
273 | var result = true; |
||
0 ignored issues
–
show
|
|||
274 | if (typeof _this.target != 'undefined') { |
||
275 | result = eventHandlers[i].apply(_this.target, args); |
||
276 | } else { |
||
277 | result = eventHandlers[i].apply(this, args); |
||
278 | } |
||
279 | if (result === false) { |
||
280 | // prevents following handlers from execution when the |
||
281 | // current handler explicitly returns 'false' |
||
282 | break; |
||
283 | } |
||
284 | } |
||
285 | }; |
||
286 | |||
287 | // Return this new Handler method |
||
288 | return h; |
||
289 | } |
||
290 | }; |
||
291 | |||
292 | export default EventManager; |
||
293 | |||
294 |