Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
SeleniumHQ
GitHub Repository: SeleniumHQ/Selenium
Path: blob/trunk/third_party/closure/goog/events/eventhandler.js
4063 views
1
/**
2
* @license
3
* Copyright The Closure Library Authors.
4
* SPDX-License-Identifier: Apache-2.0
5
*/
6
7
/**
8
* @fileoverview Class to create objects which want to handle multiple events
9
* and have their listeners easily cleaned up via a dispose method.
10
*
11
* Example:
12
* <pre>
13
* function Something() {
14
* Something.base(this);
15
*
16
* ... set up object ...
17
*
18
* // Add event listeners
19
* this.listen(this.starEl, goog.events.EventType.CLICK, this.handleStar);
20
* this.listen(this.headerEl, goog.events.EventType.CLICK, this.expand);
21
* this.listen(this.collapseEl, goog.events.EventType.CLICK, this.collapse);
22
* this.listen(this.infoEl, goog.events.EventType.MOUSEOVER, this.showHover);
23
* this.listen(this.infoEl, goog.events.EventType.MOUSEOUT, this.hideHover);
24
* }
25
* goog.inherits(Something, goog.events.EventHandler);
26
*
27
* Something.prototype.disposeInternal = function() {
28
* Something.base(this, 'disposeInternal');
29
* goog.dom.removeNode(this.container);
30
* };
31
*
32
*
33
* // Then elsewhere:
34
*
35
* var activeSomething = null;
36
* function openSomething() {
37
* activeSomething = new Something();
38
* }
39
*
40
* function closeSomething() {
41
* if (activeSomething) {
42
* activeSomething.dispose(); // Remove event listeners
43
* activeSomething = null;
44
* }
45
* }
46
* </pre>
47
*/
48
49
goog.provide('goog.events.EventHandler');
50
51
goog.require('goog.Disposable');
52
goog.require('goog.events');
53
goog.require('goog.object');
54
goog.requireType('goog.events.Event');
55
goog.requireType('goog.events.EventId');
56
goog.requireType('goog.events.EventTarget');
57
goog.requireType('goog.events.EventWrapper');
58
59
60
61
/**
62
* Super class for objects that want to easily manage a number of event
63
* listeners. It allows a short cut to listen and also provides a quick way
64
* to remove all events listeners belonging to this object.
65
* @param {SCOPE=} opt_scope Object in whose scope to call the listeners.
66
* @constructor
67
* @extends {goog.Disposable}
68
* @template SCOPE
69
*/
70
goog.events.EventHandler = function(opt_scope) {
71
'use strict';
72
goog.Disposable.call(this);
73
// TODO(mknichel): Rename this to this.scope_ and fix the classes in google3
74
// that access this private variable. :(
75
this.handler_ = opt_scope;
76
77
/**
78
* Keys for events that are being listened to.
79
* @type {!Object<!goog.events.Key>}
80
* @private
81
*/
82
this.keys_ = {};
83
};
84
goog.inherits(goog.events.EventHandler, goog.Disposable);
85
86
87
/**
88
* Utility array used to unify the cases of listening for an array of types
89
* and listening for a single event, without using recursion or allocating
90
* an array each time.
91
* @type {!Array<string>}
92
* @const
93
* @private
94
*/
95
goog.events.EventHandler.typeArray_ = [];
96
97
98
/**
99
* Listen to an event on a Listenable. If the function is omitted then the
100
* EventHandler's handleEvent method will be used.
101
* @param {goog.events.ListenableType} src Event source.
102
* @param {string|Array<string>|
103
* !goog.events.EventId<EVENTOBJ>|!Array<!goog.events.EventId<EVENTOBJ>>}
104
* type Event type to listen for or array of event types.
105
* @param {function(this:SCOPE, EVENTOBJ):?|{handleEvent:function(?):?}|null=}
106
* opt_fn Optional callback function to be used as the listener or an object
107
* with handleEvent function.
108
* @param {(boolean|!AddEventListenerOptions)=} opt_options
109
* @return {THIS} This object, allowing for chaining of calls.
110
* @this {THIS}
111
* @template EVENTOBJ, THIS
112
*/
113
goog.events.EventHandler.prototype.listen = function(
114
src, type, opt_fn, opt_options) {
115
'use strict';
116
var self = /** @type {!goog.events.EventHandler} */ (this);
117
return self.listen_(src, type, opt_fn, opt_options);
118
};
119
120
121
/**
122
* Listen to an event on a Listenable. If the function is omitted then the
123
* EventHandler's handleEvent method will be used.
124
* @param {goog.events.ListenableType} src Event source.
125
* @param {string|Array<string>|
126
* !goog.events.EventId<EVENTOBJ>|!Array<!goog.events.EventId<EVENTOBJ>>}
127
* type Event type to listen for or array of event types.
128
* @param {function(this:T, EVENTOBJ):?|{handleEvent:function(this:T, ?):?}|
129
* null|undefined} fn Optional callback function to be used as the
130
* listener or an object with handleEvent function.
131
* @param {boolean|!AddEventListenerOptions|undefined} options
132
* @param {T} scope Object in whose scope to call the listener.
133
* @return {THIS} This object, allowing for chaining of calls.
134
* @this {THIS}
135
* @template T, EVENTOBJ, THIS
136
*/
137
goog.events.EventHandler.prototype.listenWithScope = function(
138
src, type, fn, options, scope) {
139
'use strict';
140
var self = /** @type {!goog.events.EventHandler} */ (this);
141
// TODO(mknichel): Deprecate this function.
142
return self.listen_(src, type, fn, options, scope);
143
};
144
145
146
/**
147
* Listen to an event on a Listenable. If the function is omitted then the
148
* EventHandler's handleEvent method will be used.
149
* @param {goog.events.ListenableType} src Event source.
150
* @param {string|Array<string>|
151
* !goog.events.EventId<EVENTOBJ>|!Array<!goog.events.EventId<EVENTOBJ>>}
152
* type Event type to listen for or array of event types.
153
* @param {function(EVENTOBJ):?|{handleEvent:function(?):?}|null=} opt_fn
154
* Optional callback function to be used as the listener or an object with
155
* handleEvent function.
156
* @param {(boolean|!AddEventListenerOptions)=} opt_options
157
* @param {Object=} opt_scope Object in whose scope to call the listener.
158
* @return {THIS} This object, allowing for chaining of calls.
159
* @this {THIS}
160
* @template EVENTOBJ, THIS
161
* @private
162
*/
163
goog.events.EventHandler.prototype.listen_ = function(
164
src, type, opt_fn, opt_options, opt_scope) {
165
'use strict';
166
var self = /** @type {!goog.events.EventHandler} */ (this);
167
if (!Array.isArray(type)) {
168
if (type) {
169
goog.events.EventHandler.typeArray_[0] = type.toString();
170
}
171
type = goog.events.EventHandler.typeArray_;
172
}
173
for (var i = 0; i < type.length; i++) {
174
var listenerObj = goog.events.listen(
175
src, type[i], opt_fn || self.handleEvent, opt_options || false,
176
opt_scope || self.handler_ || self);
177
178
if (!listenerObj) {
179
// When goog.events.listen run on OFF_AND_FAIL or OFF_AND_SILENT
180
// (goog.events.CaptureSimulationMode) in IE8-, it will return null
181
// value.
182
return self;
183
}
184
185
/** @suppress {strictMissingProperties} Added to tighten compiler checks */
186
var key = listenerObj.key;
187
self.keys_[key] = listenerObj;
188
}
189
190
return self;
191
};
192
193
194
/**
195
* Listen to an event on a Listenable. If the function is omitted, then the
196
* EventHandler's handleEvent method will be used. After the event has fired the
197
* event listener is removed from the target. If an array of event types is
198
* provided, each event type will be listened to once.
199
* @param {goog.events.ListenableType} src Event source.
200
* @param {string|Array<string>|
201
* !goog.events.EventId<EVENTOBJ>|!Array<!goog.events.EventId<EVENTOBJ>>}
202
* type Event type to listen for or array of event types.
203
* @param {function(this:SCOPE, EVENTOBJ):?|{handleEvent:function(?):?}|null=}
204
* opt_fn
205
* Optional callback function to be used as the listener or an object with
206
* handleEvent function.
207
* @param {(boolean|!AddEventListenerOptions)=} opt_options
208
* @return {THIS} This object, allowing for chaining of calls.
209
* @this {THIS}
210
* @template EVENTOBJ, THIS
211
*/
212
goog.events.EventHandler.prototype.listenOnce = function(
213
src, type, opt_fn, opt_options) {
214
'use strict';
215
var self = /** @type {!goog.events.EventHandler} */ (this);
216
return self.listenOnce_(src, type, opt_fn, opt_options);
217
};
218
219
220
/**
221
* Listen to an event on a Listenable. If the function is omitted, then the
222
* EventHandler's handleEvent method will be used. After the event has fired the
223
* event listener is removed from the target. If an array of event types is
224
* provided, each event type will be listened to once.
225
* @param {goog.events.ListenableType} src Event source.
226
* @param {string|Array<string>|
227
* !goog.events.EventId<EVENTOBJ>|!Array<!goog.events.EventId<EVENTOBJ>>}
228
* type Event type to listen for or array of event types.
229
* @param {function(this:T, EVENTOBJ):?|{handleEvent:function(this:T, ?):?}|
230
* null|undefined} fn Optional callback function to be used as the
231
* listener or an object with handleEvent function.
232
* @param {boolean|undefined} capture Optional whether to use capture phase.
233
* @param {T} scope Object in whose scope to call the listener.
234
* @return {THIS} This object, allowing for chaining of calls.
235
* @this {THIS}
236
* @template T, EVENTOBJ, THIS
237
*/
238
goog.events.EventHandler.prototype.listenOnceWithScope = function(
239
src, type, fn, capture, scope) {
240
'use strict';
241
var self = /** @type {!goog.events.EventHandler} */ (this);
242
// TODO(mknichel): Deprecate this function.
243
return self.listenOnce_(src, type, fn, capture, scope);
244
};
245
246
247
/**
248
* Listen to an event on a Listenable. If the function is omitted, then the
249
* EventHandler's handleEvent method will be used. After the event has fired
250
* the event listener is removed from the target. If an array of event types is
251
* provided, each event type will be listened to once.
252
* @param {goog.events.ListenableType} src Event source.
253
* @param {string|Array<string>|
254
* !goog.events.EventId<EVENTOBJ>|!Array<!goog.events.EventId<EVENTOBJ>>}
255
* type Event type to listen for or array of event types.
256
* @param {function(EVENTOBJ):?|{handleEvent:function(?):?}|null=} opt_fn
257
* Optional callback function to be used as the listener or an object with
258
* handleEvent function.
259
* @param {(boolean|!AddEventListenerOptions)=} opt_options
260
* @param {Object=} opt_scope Object in whose scope to call the listener.
261
* @return {THIS} This object, allowing for chaining of calls.
262
* @this {THIS}
263
* @template EVENTOBJ, THIS
264
* @private
265
*/
266
goog.events.EventHandler.prototype.listenOnce_ = function(
267
src, type, opt_fn, opt_options, opt_scope) {
268
'use strict';
269
var self = /** @type {!goog.events.EventHandler} */ (this);
270
if (Array.isArray(type)) {
271
for (var i = 0; i < type.length; i++) {
272
self.listenOnce_(src, type[i], opt_fn, opt_options, opt_scope);
273
}
274
} else {
275
var listenerObj = goog.events.listenOnce(
276
src, type, opt_fn || self.handleEvent, opt_options,
277
opt_scope || self.handler_ || self);
278
if (!listenerObj) {
279
// When goog.events.listen run on OFF_AND_FAIL or OFF_AND_SILENT
280
// (goog.events.CaptureSimulationMode) in IE8-, it will return null
281
// value.
282
return self;
283
}
284
285
/** @suppress {strictMissingProperties} Added to tighten compiler checks */
286
var key = listenerObj.key;
287
self.keys_[key] = listenerObj;
288
}
289
290
return self;
291
};
292
293
294
/**
295
* Adds an event listener with a specific event wrapper on a DOM Node or an
296
* object that has implemented {@link goog.events.EventTarget}. A listener can
297
* only be added once to an object.
298
*
299
* @param {EventTarget|goog.events.EventTarget} src The node to listen to
300
* events on.
301
* @param {goog.events.EventWrapper} wrapper Event wrapper to use.
302
* @param {function(this:SCOPE, ?):?|{handleEvent:function(?):?}|null} listener
303
* Callback method, or an object with a handleEvent function.
304
* @param {boolean=} opt_capt Whether to fire in capture phase (defaults to
305
* false).
306
* @return {THIS} This object, allowing for chaining of calls.
307
* @this {THIS}
308
* @template THIS
309
*/
310
goog.events.EventHandler.prototype.listenWithWrapper = function(
311
src, wrapper, listener, opt_capt) {
312
'use strict';
313
var self = /** @type {!goog.events.EventHandler} */ (this);
314
// TODO(mknichel): Remove the opt_scope from this function and then
315
// templatize it.
316
return self.listenWithWrapper_(src, wrapper, listener, opt_capt);
317
};
318
319
320
/**
321
* Adds an event listener with a specific event wrapper on a DOM Node or an
322
* object that has implemented {@link goog.events.EventTarget}. A listener can
323
* only be added once to an object.
324
*
325
* @param {EventTarget|goog.events.EventTarget} src The node to listen to
326
* events on.
327
* @param {goog.events.EventWrapper} wrapper Event wrapper to use.
328
* @param {function(this:T, ?):?|{handleEvent:function(this:T, ?):?}|null}
329
* listener Optional callback function to be used as the
330
* listener or an object with handleEvent function.
331
* @param {boolean|undefined} capture Optional whether to use capture phase.
332
* @param {T} scope Object in whose scope to call the listener.
333
* @return {THIS} This object, allowing for chaining of calls.
334
* @this {THIS}
335
* @template T, THIS
336
*/
337
goog.events.EventHandler.prototype.listenWithWrapperAndScope = function(
338
src, wrapper, listener, capture, scope) {
339
'use strict';
340
var self = /** @type {!goog.events.EventHandler} */ (this);
341
// TODO(mknichel): Deprecate this function.
342
return self.listenWithWrapper_(src, wrapper, listener, capture, scope);
343
};
344
345
346
/**
347
* Adds an event listener with a specific event wrapper on a DOM Node or an
348
* object that has implemented {@link goog.events.EventTarget}. A listener can
349
* only be added once to an object.
350
*
351
* @param {EventTarget|goog.events.EventTarget} src The node to listen to
352
* events on.
353
* @param {goog.events.EventWrapper} wrapper Event wrapper to use.
354
* @param {function(?):?|{handleEvent:function(?):?}|null} listener Callback
355
* method, or an object with a handleEvent function.
356
* @param {boolean=} opt_capt Whether to fire in capture phase (defaults to
357
* false).
358
* @param {Object=} opt_scope Element in whose scope to call the listener.
359
* @return {THIS} This object, allowing for chaining of calls.
360
* @this {THIS}
361
* @template THIS
362
* @private
363
*/
364
goog.events.EventHandler.prototype.listenWithWrapper_ = function(
365
src, wrapper, listener, opt_capt, opt_scope) {
366
'use strict';
367
var self = /** @type {!goog.events.EventHandler} */ (this);
368
wrapper.listen(
369
src, listener, opt_capt, opt_scope || self.handler_ || self, self);
370
return self;
371
};
372
373
374
/**
375
* @return {number} Number of listeners registered by this handler.
376
*/
377
goog.events.EventHandler.prototype.getListenerCount = function() {
378
'use strict';
379
var count = 0;
380
for (var key in this.keys_) {
381
if (Object.prototype.hasOwnProperty.call(this.keys_, key)) {
382
count++;
383
}
384
}
385
return count;
386
};
387
388
389
/**
390
* Unlistens on an event.
391
* @param {goog.events.ListenableType} src Event source.
392
* @param {string|Array<string>|
393
* !goog.events.EventId<EVENTOBJ>|!Array<!goog.events.EventId<EVENTOBJ>>}
394
* type Event type or array of event types to unlisten to.
395
* @param {function(this:?, EVENTOBJ):?|{handleEvent:function(?):?}|null=}
396
* opt_fn Optional callback function to be used as the listener or an object
397
* with handleEvent function.
398
* @param {(boolean|!EventListenerOptions)=} opt_options
399
* @param {Object=} opt_scope Object in whose scope to call the listener.
400
* @return {THIS} This object, allowing for chaining of calls.
401
* @this {THIS}
402
* @template EVENTOBJ, THIS
403
*/
404
goog.events.EventHandler.prototype.unlisten = function(
405
src, type, opt_fn, opt_options, opt_scope) {
406
'use strict';
407
var self = /** @type {!goog.events.EventHandler} */ (this);
408
if (Array.isArray(type)) {
409
for (var i = 0; i < type.length; i++) {
410
self.unlisten(src, type[i], opt_fn, opt_options, opt_scope);
411
}
412
} else {
413
var capture =
414
goog.isObject(opt_options) ? !!opt_options.capture : !!opt_options;
415
var listener = goog.events.getListener(
416
src, type, opt_fn || self.handleEvent, capture,
417
opt_scope || self.handler_ || self);
418
419
if (listener) {
420
goog.events.unlistenByKey(listener);
421
delete self.keys_[listener.key];
422
}
423
}
424
425
return self;
426
};
427
428
429
/**
430
* Removes an event listener which was added with listenWithWrapper().
431
*
432
* @param {EventTarget|goog.events.EventTarget} src The target to stop
433
* listening to events on.
434
* @param {goog.events.EventWrapper} wrapper Event wrapper to use.
435
* @param {function(?):?|{handleEvent:function(?):?}|null} listener The
436
* listener function to remove.
437
* @param {boolean=} opt_capt In DOM-compliant browsers, this determines
438
* whether the listener is fired during the capture or bubble phase of the
439
* event.
440
* @param {Object=} opt_scope Element in whose scope to call the listener.
441
* @return {THIS} This object, allowing for chaining of calls.
442
* @this {THIS}
443
* @template THIS
444
*/
445
goog.events.EventHandler.prototype.unlistenWithWrapper = function(
446
src, wrapper, listener, opt_capt, opt_scope) {
447
'use strict';
448
var self = /** @type {!goog.events.EventHandler} */ (this);
449
wrapper.unlisten(
450
src, listener, opt_capt, opt_scope || self.handler_ || self, self);
451
return self;
452
};
453
454
455
/**
456
* Unlistens to all events.
457
*/
458
goog.events.EventHandler.prototype.removeAll = function() {
459
'use strict';
460
goog.object.forEach(this.keys_, function(listenerObj, key) {
461
'use strict';
462
if (this.keys_.hasOwnProperty(key)) {
463
goog.events.unlistenByKey(listenerObj);
464
}
465
}, this);
466
467
this.keys_ = {};
468
};
469
470
471
/**
472
* Disposes of this EventHandler and removes all listeners that it registered.
473
* @override
474
* @protected
475
*/
476
goog.events.EventHandler.prototype.disposeInternal = function() {
477
'use strict';
478
goog.events.EventHandler.superClass_.disposeInternal.call(this);
479
this.removeAll();
480
};
481
482
483
/**
484
* Default event handler
485
* @param {goog.events.Event} e Event object.
486
*/
487
goog.events.EventHandler.prototype.handleEvent = function(e) {
488
'use strict';
489
throw new Error('EventHandler.handleEvent not implemented');
490
};
491
492