openlayers
Version:
Build tools and sources for developing OpenLayers based mapping applications
241 lines (218 loc) • 7.69 kB
JavaScript
goog.provide('ol.events');
goog.require('ol.obj');
/**
* @param {ol.EventsKey} listenerObj Listener object.
* @return {ol.EventsListenerFunctionType} Bound listener.
*/
ol.events.bindListener_ = function(listenerObj) {
var boundListener = function(evt) {
var listener = listenerObj.listener;
var bindTo = listenerObj.bindTo || listenerObj.target;
if (listenerObj.callOnce) {
ol.events.unlistenByKey(listenerObj);
}
return listener.call(bindTo, evt);
};
listenerObj.boundListener = boundListener;
return boundListener;
};
/**
* Finds the matching {@link ol.EventsKey} in the given listener
* array.
*
* @param {!Array<!ol.EventsKey>} listeners Array of listeners.
* @param {!Function} listener The listener function.
* @param {Object=} opt_this The `this` value inside the listener.
* @param {boolean=} opt_setDeleteIndex Set the deleteIndex on the matching
* listener, for {@link ol.events.unlistenByKey}.
* @return {ol.EventsKey|undefined} The matching listener object.
* @private
*/
ol.events.findListener_ = function(listeners, listener, opt_this,
opt_setDeleteIndex) {
var listenerObj;
for (var i = 0, ii = listeners.length; i < ii; ++i) {
listenerObj = listeners[i];
if (listenerObj.listener === listener &&
listenerObj.bindTo === opt_this) {
if (opt_setDeleteIndex) {
listenerObj.deleteIndex = i;
}
return listenerObj;
}
}
return undefined;
};
/**
* @param {ol.EventTargetLike} target Target.
* @param {string} type Type.
* @return {Array.<ol.EventsKey>|undefined} Listeners.
*/
ol.events.getListeners = function(target, type) {
var listenerMap = target.ol_lm;
return listenerMap ? listenerMap[type] : undefined;
};
/**
* Get the lookup of listeners. If one does not exist on the target, it is
* created.
* @param {ol.EventTargetLike} target Target.
* @return {!Object.<string, Array.<ol.EventsKey>>} Map of
* listeners by event type.
* @private
*/
ol.events.getListenerMap_ = function(target) {
var listenerMap = target.ol_lm;
if (!listenerMap) {
listenerMap = target.ol_lm = {};
}
return listenerMap;
};
/**
* Clean up all listener objects of the given type. All properties on the
* listener objects will be removed, and if no listeners remain in the listener
* map, it will be removed from the target.
* @param {ol.EventTargetLike} target Target.
* @param {string} type Type.
* @private
*/
ol.events.removeListeners_ = function(target, type) {
var listeners = ol.events.getListeners(target, type);
if (listeners) {
for (var i = 0, ii = listeners.length; i < ii; ++i) {
target.removeEventListener(type, listeners[i].boundListener);
ol.obj.clear(listeners[i]);
}
listeners.length = 0;
var listenerMap = target.ol_lm;
if (listenerMap) {
delete listenerMap[type];
if (Object.keys(listenerMap).length === 0) {
delete target.ol_lm;
}
}
}
};
/**
* Registers an event listener on an event target. Inspired by
* {@link https://google.github.io/closure-library/api/source/closure/goog/events/events.js.src.html}
*
* This function efficiently binds a `listener` to a `this` object, and returns
* a key for use with {@link ol.events.unlistenByKey}.
*
* @param {ol.EventTargetLike} target Event target.
* @param {string} type Event type.
* @param {ol.EventsListenerFunctionType} listener Listener.
* @param {Object=} opt_this Object referenced by the `this` keyword in the
* listener. Default is the `target`.
* @param {boolean=} opt_once If true, add the listener as one-off listener.
* @return {ol.EventsKey} Unique key for the listener.
*/
ol.events.listen = function(target, type, listener, opt_this, opt_once) {
var listenerMap = ol.events.getListenerMap_(target);
var listeners = listenerMap[type];
if (!listeners) {
listeners = listenerMap[type] = [];
}
var listenerObj = ol.events.findListener_(listeners, listener, opt_this,
false);
if (listenerObj) {
if (!opt_once) {
// Turn one-off listener into a permanent one.
listenerObj.callOnce = false;
}
} else {
listenerObj = /** @type {ol.EventsKey} */ ({
bindTo: opt_this,
callOnce: !!opt_once,
listener: listener,
target: target,
type: type
});
target.addEventListener(type, ol.events.bindListener_(listenerObj));
listeners.push(listenerObj);
}
return listenerObj;
};
/**
* Registers a one-off event listener on an event target. Inspired by
* {@link https://google.github.io/closure-library/api/source/closure/goog/events/events.js.src.html}
*
* This function efficiently binds a `listener` as self-unregistering listener
* to a `this` object, and returns a key for use with
* {@link ol.events.unlistenByKey} in case the listener needs to be unregistered
* before it is called.
*
* When {@link ol.events.listen} is called with the same arguments after this
* function, the self-unregistering listener will be turned into a permanent
* listener.
*
* @param {ol.EventTargetLike} target Event target.
* @param {string} type Event type.
* @param {ol.EventsListenerFunctionType} listener Listener.
* @param {Object=} opt_this Object referenced by the `this` keyword in the
* listener. Default is the `target`.
* @return {ol.EventsKey} Key for unlistenByKey.
*/
ol.events.listenOnce = function(target, type, listener, opt_this) {
return ol.events.listen(target, type, listener, opt_this, true);
};
/**
* Unregisters an event listener on an event target. Inspired by
* {@link https://google.github.io/closure-library/api/source/closure/goog/events/events.js.src.html}
*
* To return a listener, this function needs to be called with the exact same
* arguments that were used for a previous {@link ol.events.listen} call.
*
* @param {ol.EventTargetLike} target Event target.
* @param {string} type Event type.
* @param {ol.EventsListenerFunctionType} listener Listener.
* @param {Object=} opt_this Object referenced by the `this` keyword in the
* listener. Default is the `target`.
*/
ol.events.unlisten = function(target, type, listener, opt_this) {
var listeners = ol.events.getListeners(target, type);
if (listeners) {
var listenerObj = ol.events.findListener_(listeners, listener, opt_this,
true);
if (listenerObj) {
ol.events.unlistenByKey(listenerObj);
}
}
};
/**
* Unregisters event listeners on an event target. Inspired by
* {@link https://google.github.io/closure-library/api/source/closure/goog/events/events.js.src.html}
*
* The argument passed to this function is the key returned from
* {@link ol.events.listen} or {@link ol.events.listenOnce}.
*
* @param {ol.EventsKey} key The key.
*/
ol.events.unlistenByKey = function(key) {
if (key && key.target) {
key.target.removeEventListener(key.type, key.boundListener);
var listeners = ol.events.getListeners(key.target, key.type);
if (listeners) {
var i = 'deleteIndex' in key ? key.deleteIndex : listeners.indexOf(key);
if (i !== -1) {
listeners.splice(i, 1);
}
if (listeners.length === 0) {
ol.events.removeListeners_(key.target, key.type);
}
}
ol.obj.clear(key);
}
};
/**
* Unregisters all event listeners on an event target. Inspired by
* {@link https://google.github.io/closure-library/api/source/closure/goog/events/events.js.src.html}
*
* @param {ol.EventTargetLike} target Target.
*/
ol.events.unlistenAll = function(target) {
var listenerMap = ol.events.getListenerMap_(target);
for (var type in listenerMap) {
ol.events.removeListeners_(target, type);
}
};