1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305 | 2x
2x
2x
2x
2x
2x
2x
2x
2x
2x
2x
2x
2x
2x
2x
2x
2x
2x
2x
37x
37x
37x
37x
37x
37x
37x
37x
37x
37x
2x
2x
2x
2x
2x
2x
2x
| var __extends = (this && this.__extends) || function (d, b) {
for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
(function (factory) {
Eif (typeof module === 'object' && typeof module.exports === 'object') {
var v = factory(require, exports); Iif (v !== undefined) module.exports = v;
}
else if (typeof define === 'function' && define.amd) {
define(["require", "exports", '../ObjectManager', './BaseEvent', '../util/Util'], factory);
}
})(function (require, exports) {
"use strict";
var ObjectManager_1 = require('../ObjectManager');
var BaseEvent_1 = require('./BaseEvent');
var Util_1 = require('../util/Util');
/**
* EventDispatcher is the base class for all classes that dispatch events. It is the base class for the {{#crossLink "DisplayObjectContainer"}}{{/crossLink}} class.
* EventDispatcher provides methods for managing prioritized queues of event listeners and dispatching events.
*
* @class EventDispatcher
* @extends ObjectManager
* @module StructureJS
* @submodule event
* @requires Extend
* @requires ObjectManager
* @requires BaseEvent
* @constructor
* @author Robert S. (www.codeBelt.com)
* @example
* // Another way to use the EventDispatcher.
* let eventDispatcher = new EventDispatcher();
* eventDispatcher.addEventListener('change', this._handlerMethod, this);
* eventDispatcher.dispatchEvent('change');
*/
var EventDispatcher = (function (_super) {
__extends(EventDispatcher, _super);
function EventDispatcher() {
_super.call(this);
/**
* Holds a reference to added listeners.
*
* @property _listeners
* @type {any}
* @protected
*/
this._listeners = {};
/**
* Indicates the object that contains a child object. Uses the parent property
* to specify a relative path to display objects that are above the current display object in the display
* list hierarchy and helps facilitate event bubbling.
*
* @property parent
* @type {any}
* @public
*/
this.parent = null;
}
/**
* Registers an event listener object with an EventDispatcher object so the listener receives notification of an event.
*
* @method addEventListener
* @param type {String} The type of event.
* @param callback {Function} The listener function that processes the event. This function must accept an Event object as its only parameter and must return nothing, as this example shows. @example function(event:Event):void
* @param scope {any} Binds the scope to a particular object (scope is basically what "this" refers to in your function). This can be very useful in JavaScript because scope isn't generally maintained.
* @param [priority=0] {int} Influences the order in which the listeners are called. Listeners with lower priorities are called after ones with higher priorities.
* @public
* @chainable
* @example
* this.addEventListener(BaseEvent.CHANGE, this._handlerMethod, this);
*
* _handlerMethod(event) {
* console.log(event.target + " sent the event.");
* console.log(event.type, event.data);
* }
*/
EventDispatcher.prototype.addEventListener = function (type, callback, scope, priority) {
if (priority === void 0) { priority = 0; }
// Get the list of event listeners by the associated type value that is passed in.
var list = this._listeners[type];
if (list == null) {
// If a list of event listeners do not exist for the type value passed in then create a new empty array.
this._listeners[type] = list = [];
}
var index = 0;
var listener;
var i = list.length;
while (--i > -1) {
listener = list[i];
if (listener.callback === callback && listener.scope === scope) {
// If the same callback and scope are found then remove it and add the current one below.
list.splice(i, 1);
}
else if (index === 0 && listener.priority < priority) {
index = i + 1;
}
}
// Add the event listener to the list array at the index value.
list.splice(index, 0, { callback: callback, scope: scope, priority: priority, once: false });
return this;
};
/**
* Registers an event listener object once with an EventDispatcher object so the listener will receive the notification of an event.
*
* @method addEventListenerOnce
* @param type {String} The type of event.
* @param callback {Function} The listener function that processes the event. This function must accept an Event object as its only parameter and must return nothing, as this example shows. @example function(event:Event):void
* @param scope {any} Binds the scope to a particular object (scope is basically what "this" refers to in your function). This can be very useful in JavaScript because scope isn't generally maintained.
* @param [priority=0] {int} Influences the order in which the listeners are called. Listeners with lower priorities are called after ones with higher priorities.
* @public
* @chainable
* @example
* this.addEventListenerOnce(BaseEvent.CHANGE, this._handlerMethod, this);
*
* _handlerMethod(event) {
* console.log(event.target + " sent the event.");
* console.log(event.type, event.data);
* }
*/
EventDispatcher.prototype.addEventListenerOnce = function (type, callback, scope, priority) {
if (priority === void 0) { priority = 0; }
// Add the event listener the normal way.
this.addEventListener(type, callback, scope, priority);
// Get the event listeners we just added.
var list = this._listeners[type];
var listener = list[0];
// Change the value to true so it will be remove after dispatchEvent is called.
listener.once = true;
return this;
};
/**
* Removes a specified listener from the EventDispatcher object.
*
* @method removeEventListener
* @param type {String} The type of event.
* @param callback {Function} The listener object to remove.
* @param scope {any} The scope of the listener object to be removed.
* @hide This was added because it was needed for the {{#crossLink "EventBroker"}}{{/crossLink}} class. To keep things consistent this parameter is required.
* @public
* @chainable
* @example
* this.removeEventListener(BaseEvent.CHANGE, this._handlerMethod, this);
*/
EventDispatcher.prototype.removeEventListener = function (type, callback, scope) {
// Get the list of event listeners by the associated type value that is passed in.
var list = this._listeners[type];
if (list !== void 0) {
var i = list.length;
while (--i > -1) {
// If the callback and scope are the same then remove the event listener.
if (list[i].callback === callback && list[i].scope === scope) {
list.splice(i, 1);
break;
}
}
}
return this;
};
/**
* <p>Dispatches an event into the event flow. The event target is the EventDispatcher object upon which the dispatchEvent() method is called.</p>
*
* @method dispatchEvent
* @param event {string|BaseEvent} The Event object or event type string you want to dispatch. You can create custom events, the only requirement is all events must extend {{#crossLink "BaseEvent"}}{{/crossLink}}.
* @param [data=null] {any} The optional data you want to send with the event. Do not use this parameter if you are passing in a {{#crossLink "BaseEvent"}}{{/crossLink}}.
* @public
* @chainable
* @example
* this.dispatchEvent('change');
*
* // Example: Sending data with the event:
* this.dispatchEvent('change', {some: 'data'});
*
* // Example: With an event object
* // (event type, bubbling set to true, cancelable set to true and passing data) :
* let event = new BaseEvent(BaseEvent.CHANGE, true, true, {some: 'data'});
* this.dispatchEvent(event);
*
* // Here is a common inline event object being dispatched:
* this.dispatchEvent(new BaseEvent(BaseEvent.CHANGE));
*/
EventDispatcher.prototype.dispatchEvent = function (type, data) {
Eif (data === void 0) { data = null; }
var event = type;
Iif (typeof event === 'string') {
event = new BaseEvent_1.default(type, false, true, data);
}
// If target is null then set it to the object that dispatched the event.
Eif (event.target == null) {
event.target = this;
event.currentTarget = this;
}
// Get the list of event listener by the associated type value.
var list = this._listeners[event.type];
Iif (list !== void 0) {
// Cache to prevent the edge case were another listener is added during the dispatch loop.
var cachedList = list.slice();
var i = cachedList.length;
var listener = void 0;
while (--i > -1) {
// If cancelable and isImmediatePropagationStopped are true then break out of the while loop.
if (event.cancelable === true && event.isImmediatePropagationStopped === true) {
break;
}
listener = cachedList[i];
listener.callback.call(listener.scope, event);
// If the once value is true we want to remove the listener right after this callback was called.
if (listener.once === true) {
this.removeEventListener(event.type, listener.callback, listener.scope);
}
}
}
//Dispatches up the chain of classes that have a parent.
Iif (this.parent != null && event.bubbles === true) {
// If cancelable and isPropagationStopped are true then don't dispatch the event on the parent object.
if (event.cancelable === true && event.isPropagationStopped === true) {
return this;
}
// Assign the current object that is currently processing the event (i.e. event bubbling at).
event.currentTarget = this;
// Pass the event to the parent (event bubbling).
this.parent.dispatchEvent(event);
}
return this;
};
/**
* Check if an object has a specific event listener already added.
*
* @method hasEventListener
* @param type {String} The type of event.
* @param callback {Function} The listener method to call.
* @param scope {any} The scope of the listener object.
* @return {boolean}
* @public
* @example
* this.hasEventListener(BaseEvent.CHANGE, this._handlerMethod, this);
*/
EventDispatcher.prototype.hasEventListener = function (type, callback, scope) {
if (this._listeners[type] !== void 0) {
var listener = void 0;
var numOfCallbacks = this._listeners[type].length;
for (var i = 0; i < numOfCallbacks; i++) {
listener = this._listeners[type][i];
if (listener.callback === callback && listener.scope === scope) {
return true;
}
}
}
return false;
};
/**
* Returns and array of all current event types and there current listeners.
*
* @method getEventListeners
* @return {Array<any>}
* @public
* @example
* this.getEventListeners();
*/
EventDispatcher.prototype.getEventListeners = function () {
return this._listeners;
};
/**
* Prints out each event listener in the console.log
*
* @method print
* @return {string}
* @public
* @example
* this.printEventListeners();
*
* // [ClassName] is listening for the 'BaseEvent.change' event.
* // [AnotherClassName] is listening for the 'BaseEvent.refresh' event.
*/
EventDispatcher.prototype.printEventListeners = function () {
var numOfCallbacks;
var listener;
for (var type in this._listeners) {
numOfCallbacks = this._listeners[type].length;
for (var i = 0; i < numOfCallbacks; i++) {
listener = this._listeners[type][i];
var name_1 = void 0;
if (listener.scope) {
name_1 = '[' + Util_1.default.getName(listener.scope) + ']';
}
else {
name_1 = '[Unknown]';
}
console.log(name_1 + " is listen for \"" + type + "\" event.", listener.scope);
}
}
};
/**
* @overridden BaseObject.destroy
*/
EventDispatcher.prototype.destroy = function () {
this.disable();
_super.prototype.destroy.call(this);
};
return EventDispatcher;
}(ObjectManager_1.default));
Object.defineProperty(exports, "__esModule", { value: true });
exports.default = EventDispatcher;
});
|