159 lines
4.3 KiB
JavaScript
159 lines
4.3 KiB
JavaScript
goog.provide('ol.events.EventTarget');
|
|
|
|
goog.require('ol.Disposable');
|
|
goog.require('ol.events');
|
|
goog.require('ol.events.Event');
|
|
|
|
|
|
/**
|
|
* @classdesc
|
|
* A simplified implementation of the W3C DOM Level 2 EventTarget interface.
|
|
* @see {@link https://www.w3.org/TR/2000/REC-DOM-Level-2-Events-20001113/events.html#Events-EventTarget}
|
|
*
|
|
* There are two important simplifications compared to the specification:
|
|
*
|
|
* 1. The handling of `useCapture` in `addEventListener` and
|
|
* `removeEventListener`. There is no real capture model.
|
|
* 2. The handling of `stopPropagation` and `preventDefault` on `dispatchEvent`.
|
|
* There is no event target hierarchy. When a listener calls
|
|
* `stopPropagation` or `preventDefault` on an event object, it means that no
|
|
* more listeners after this one will be called. Same as when the listener
|
|
* returns false.
|
|
*
|
|
* @constructor
|
|
* @extends {ol.Disposable}
|
|
*/
|
|
ol.events.EventTarget = function() {
|
|
|
|
ol.Disposable.call(this);
|
|
|
|
/**
|
|
* @private
|
|
* @type {!Object.<string, number>}
|
|
*/
|
|
this.pendingRemovals_ = {};
|
|
|
|
/**
|
|
* @private
|
|
* @type {!Object.<string, number>}
|
|
*/
|
|
this.dispatching_ = {};
|
|
|
|
/**
|
|
* @private
|
|
* @type {!Object.<string, Array.<ol.EventsListenerFunctionType>>}
|
|
*/
|
|
this.listeners_ = {};
|
|
|
|
};
|
|
ol.inherits(ol.events.EventTarget, ol.Disposable);
|
|
|
|
|
|
/**
|
|
* @param {string} type Type.
|
|
* @param {ol.EventsListenerFunctionType} listener Listener.
|
|
*/
|
|
ol.events.EventTarget.prototype.addEventListener = function(type, listener) {
|
|
var listeners = this.listeners_[type];
|
|
if (!listeners) {
|
|
listeners = this.listeners_[type] = [];
|
|
}
|
|
if (listeners.indexOf(listener) === -1) {
|
|
listeners.push(listener);
|
|
}
|
|
};
|
|
|
|
|
|
/**
|
|
* @param {{type: string,
|
|
* target: (EventTarget|ol.events.EventTarget|undefined)}|ol.events.Event|
|
|
* string} event Event or event type.
|
|
* @return {boolean|undefined} `false` if anyone called preventDefault on the
|
|
* event object or if any of the listeners returned false.
|
|
*/
|
|
ol.events.EventTarget.prototype.dispatchEvent = function(event) {
|
|
var evt = typeof event === 'string' ? new ol.events.Event(event) : event;
|
|
var type = evt.type;
|
|
evt.target = this;
|
|
var listeners = this.listeners_[type];
|
|
var propagate;
|
|
if (listeners) {
|
|
if (!(type in this.dispatching_)) {
|
|
this.dispatching_[type] = 0;
|
|
this.pendingRemovals_[type] = 0;
|
|
}
|
|
++this.dispatching_[type];
|
|
for (var i = 0, ii = listeners.length; i < ii; ++i) {
|
|
if (listeners[i].call(this, evt) === false || evt.propagationStopped) {
|
|
propagate = false;
|
|
break;
|
|
}
|
|
}
|
|
--this.dispatching_[type];
|
|
if (this.dispatching_[type] === 0) {
|
|
var pendingRemovals = this.pendingRemovals_[type];
|
|
delete this.pendingRemovals_[type];
|
|
while (pendingRemovals--) {
|
|
this.removeEventListener(type, ol.nullFunction);
|
|
}
|
|
delete this.dispatching_[type];
|
|
}
|
|
return propagate;
|
|
}
|
|
};
|
|
|
|
|
|
/**
|
|
* @inheritDoc
|
|
*/
|
|
ol.events.EventTarget.prototype.disposeInternal = function() {
|
|
ol.events.unlistenAll(this);
|
|
};
|
|
|
|
|
|
/**
|
|
* Get the listeners for a specified event type. Listeners are returned in the
|
|
* order that they will be called in.
|
|
*
|
|
* @param {string} type Type.
|
|
* @return {Array.<ol.EventsListenerFunctionType>} Listeners.
|
|
*/
|
|
ol.events.EventTarget.prototype.getListeners = function(type) {
|
|
return this.listeners_[type];
|
|
};
|
|
|
|
|
|
/**
|
|
* @param {string=} opt_type Type. If not provided,
|
|
* `true` will be returned if this EventTarget has any listeners.
|
|
* @return {boolean} Has listeners.
|
|
*/
|
|
ol.events.EventTarget.prototype.hasListener = function(opt_type) {
|
|
return opt_type ?
|
|
opt_type in this.listeners_ :
|
|
Object.keys(this.listeners_).length > 0;
|
|
};
|
|
|
|
|
|
/**
|
|
* @param {string} type Type.
|
|
* @param {ol.EventsListenerFunctionType} listener Listener.
|
|
*/
|
|
ol.events.EventTarget.prototype.removeEventListener = function(type, listener) {
|
|
var listeners = this.listeners_[type];
|
|
if (listeners) {
|
|
var index = listeners.indexOf(listener);
|
|
goog.DEBUG && console.assert(index != -1, 'listener not found');
|
|
if (type in this.pendingRemovals_) {
|
|
// make listener a no-op, and remove later in #dispatchEvent()
|
|
listeners[index] = ol.nullFunction;
|
|
++this.pendingRemovals_[type];
|
|
} else {
|
|
listeners.splice(index, 1);
|
|
if (listeners.length === 0) {
|
|
delete this.listeners_[type];
|
|
}
|
|
}
|
|
}
|
|
};
|