UNPKG

10.9 kBJavaScriptView Raw
1"use strict";
2Object.defineProperty(exports, "__esModule", { value: true });
3var object_1 = require("./object");
4/** An instance of EventGroup allows anything with a handle to it to trigger events on it.
5 * If the target is an HTMLElement, the event will be attached to the element and can be
6 * triggered as usual (like clicking for onClick).
7 * The event can be triggered by calling EventGroup.raise() here. If the target is an
8 * HTMLElement, the event gets raised and is handled by the browser. Otherwise, it gets
9 * handled here in EventGroup, and the handler is called in the context of the parent
10 * (which is passed in in the constructor).
11 *
12 * @public
13 * {@docCategory EventGroup}
14 */
15var EventGroup = /** @class */ (function () {
16 /** parent: the context in which events attached to non-HTMLElements are called */
17 function EventGroup(parent) {
18 this._id = EventGroup._uniqueId++;
19 this._parent = parent;
20 this._eventRecords = [];
21 }
22 /** For IE8, bubbleEvent is ignored here and must be dealt with by the handler.
23 * Events raised here by default have bubbling set to false and cancelable set to true.
24 * This applies also to built-in events being raised manually here on HTMLElements,
25 * which may lead to unexpected behavior if it differs from the defaults.
26 *
27 */
28 EventGroup.raise = function (target, eventName, eventArgs, bubbleEvent) {
29 var retVal;
30 if (EventGroup._isElement(target)) {
31 if (typeof document !== 'undefined' && document.createEvent) {
32 var ev = document.createEvent('HTMLEvents');
33 ev.initEvent(eventName, bubbleEvent || false, true);
34 object_1.assign(ev, eventArgs);
35 retVal = target.dispatchEvent(ev);
36 }
37 else if (typeof document !== 'undefined' && document.createEventObject) {
38 // IE8
39 var evObj = document.createEventObject(eventArgs);
40 // cannot set cancelBubble on evObj, fireEvent will overwrite it
41 target.fireEvent('on' + eventName, evObj);
42 }
43 }
44 else {
45 while (target && retVal !== false) {
46 var events = target.__events__;
47 var eventRecords = events ? events[eventName] : null;
48 if (eventRecords) {
49 for (var id in eventRecords) {
50 if (eventRecords.hasOwnProperty(id)) {
51 var eventRecordList = eventRecords[id];
52 for (var listIndex = 0; retVal !== false && listIndex < eventRecordList.length; listIndex++) {
53 var record = eventRecordList[listIndex];
54 if (record.objectCallback) {
55 retVal = record.objectCallback.call(record.parent, eventArgs);
56 }
57 }
58 }
59 }
60 }
61 // If the target has a parent, bubble the event up.
62 target = bubbleEvent ? target.parent : null;
63 }
64 }
65 return retVal;
66 };
67 EventGroup.isObserved = function (target, eventName) {
68 var events = target && target.__events__;
69 return !!events && !!events[eventName];
70 };
71 /** Check to see if the target has declared support of the given event. */
72 EventGroup.isDeclared = function (target, eventName) {
73 var declaredEvents = target && target.__declaredEvents;
74 return !!declaredEvents && !!declaredEvents[eventName];
75 };
76 EventGroup.stopPropagation = function (event) {
77 if (event.stopPropagation) {
78 event.stopPropagation();
79 }
80 else {
81 // IE8
82 event.cancelBubble = true;
83 }
84 };
85 EventGroup._isElement = function (target) {
86 return (!!target && (!!target.addEventListener || (typeof HTMLElement !== 'undefined' && target instanceof HTMLElement)));
87 };
88 EventGroup.prototype.dispose = function () {
89 if (!this._isDisposed) {
90 this._isDisposed = true;
91 this.off();
92 this._parent = null;
93 }
94 };
95 /** On the target, attach a set of events, where the events object is a name to function mapping. */
96 EventGroup.prototype.onAll = function (target, events, useCapture) {
97 for (var eventName in events) {
98 if (events.hasOwnProperty(eventName)) {
99 this.on(target, eventName, events[eventName], useCapture);
100 }
101 }
102 };
103 /**
104 * On the target, attach an event whose handler will be called in the context of the parent
105 * of this instance of EventGroup.
106 */
107 EventGroup.prototype.on = function (target, eventName, callback, options) {
108 var _this = this;
109 if (eventName.indexOf(',') > -1) {
110 var events = eventName.split(/[ ,]+/);
111 for (var i = 0; i < events.length; i++) {
112 this.on(target, events[i], callback, options);
113 }
114 }
115 else {
116 var parent_1 = this._parent;
117 var eventRecord = {
118 target: target,
119 eventName: eventName,
120 parent: parent_1,
121 callback: callback,
122 options: options,
123 };
124 // Initialize and wire up the record on the target, so that it can call the callback if the event fires.
125 var events = (target.__events__ = target.__events__ || {});
126 events[eventName] =
127 events[eventName] ||
128 {
129 count: 0,
130 };
131 events[eventName][this._id] = events[eventName][this._id] || [];
132 events[eventName][this._id].push(eventRecord);
133 events[eventName].count++;
134 if (EventGroup._isElement(target)) {
135 var processElementEvent = function () {
136 var args = [];
137 for (var _i = 0; _i < arguments.length; _i++) {
138 args[_i] = arguments[_i];
139 }
140 if (_this._isDisposed) {
141 return;
142 }
143 var result;
144 try {
145 result = callback.apply(parent_1, args);
146 if (result === false && args[0]) {
147 var e = args[0];
148 if (e.preventDefault) {
149 e.preventDefault();
150 }
151 if (e.stopPropagation) {
152 e.stopPropagation();
153 }
154 e.cancelBubble = true;
155 }
156 }
157 catch (e) {
158 // ignore
159 }
160 return result;
161 };
162 eventRecord.elementCallback = processElementEvent;
163 if (target.addEventListener) {
164 target.addEventListener(eventName, processElementEvent, options);
165 }
166 else if (target.attachEvent) {
167 // IE8
168 target.attachEvent('on' + eventName, processElementEvent);
169 }
170 }
171 else {
172 var processObjectEvent = function () {
173 var args = [];
174 for (var _i = 0; _i < arguments.length; _i++) {
175 args[_i] = arguments[_i];
176 }
177 if (_this._isDisposed) {
178 return;
179 }
180 return callback.apply(parent_1, args);
181 };
182 eventRecord.objectCallback = processObjectEvent;
183 }
184 // Remember the record locally, so that it can be removed.
185 this._eventRecords.push(eventRecord);
186 }
187 };
188 EventGroup.prototype.off = function (target, eventName, callback, options) {
189 for (var i = 0; i < this._eventRecords.length; i++) {
190 var eventRecord = this._eventRecords[i];
191 if ((!target || target === eventRecord.target) &&
192 (!eventName || eventName === eventRecord.eventName) &&
193 (!callback || callback === eventRecord.callback) &&
194 (typeof options !== 'boolean' || options === eventRecord.options)) {
195 var events = eventRecord.target.__events__;
196 var targetArrayLookup = events[eventRecord.eventName];
197 var targetArray = targetArrayLookup ? targetArrayLookup[this._id] : null;
198 // We may have already target's entries, so check for null.
199 if (targetArray) {
200 if (targetArray.length === 1 || !callback) {
201 targetArrayLookup.count -= targetArray.length;
202 delete events[eventRecord.eventName][this._id];
203 }
204 else {
205 targetArrayLookup.count--;
206 targetArray.splice(targetArray.indexOf(eventRecord), 1);
207 }
208 if (!targetArrayLookup.count) {
209 delete events[eventRecord.eventName];
210 }
211 }
212 if (eventRecord.elementCallback) {
213 if (eventRecord.target.removeEventListener) {
214 eventRecord.target.removeEventListener(eventRecord.eventName, eventRecord.elementCallback, eventRecord.options);
215 }
216 else if (eventRecord.target.detachEvent) {
217 // IE8
218 eventRecord.target.detachEvent('on' + eventRecord.eventName, eventRecord.elementCallback);
219 }
220 }
221 this._eventRecords.splice(i--, 1);
222 }
223 }
224 };
225 /** Trigger the given event in the context of this instance of EventGroup. */
226 EventGroup.prototype.raise = function (eventName, eventArgs, bubbleEvent) {
227 return EventGroup.raise(this._parent, eventName, eventArgs, bubbleEvent);
228 };
229 /** Declare an event as being supported by this instance of EventGroup. */
230 EventGroup.prototype.declare = function (event) {
231 var declaredEvents = (this._parent.__declaredEvents = this._parent.__declaredEvents || {});
232 if (typeof event === 'string') {
233 declaredEvents[event] = true;
234 }
235 else {
236 for (var i = 0; i < event.length; i++) {
237 declaredEvents[event[i]] = true;
238 }
239 }
240 };
241 EventGroup._uniqueId = 0;
242 return EventGroup;
243}());
244exports.EventGroup = EventGroup;
245//# sourceMappingURL=EventGroup.js.map
\No newline at end of file