123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164 |
- import Check from "./Check.js";
- import defined from "./defined.js";
- /**
- * A generic utility class for managing subscribers for a particular event.
- * This class is usually instantiated inside of a container class and
- * exposed as a property for others to subscribe to.
- *
- * @alias Event
- * @template Listener extends (...args: any[]) => void = (...args: any[]) => void
- * @constructor
- * @example
- * MyObject.prototype.myListener = function(arg1, arg2) {
- * this.myArg1Copy = arg1;
- * this.myArg2Copy = arg2;
- * }
- *
- * const myObjectInstance = new MyObject();
- * const evt = new Cesium.Event();
- * evt.addEventListener(MyObject.prototype.myListener, myObjectInstance);
- * evt.raiseEvent('1', '2');
- * evt.removeEventListener(MyObject.prototype.myListener);
- */
- function Event() {
- this._listeners = [];
- this._scopes = [];
- this._toRemove = [];
- this._insideRaiseEvent = false;
- }
- Object.defineProperties(Event.prototype, {
- /**
- * The number of listeners currently subscribed to the event.
- * @memberof Event.prototype
- * @type {number}
- * @readonly
- */
- numberOfListeners: {
- get: function () {
- return this._listeners.length - this._toRemove.length;
- },
- },
- });
- /**
- * Registers a callback function to be executed whenever the event is raised.
- * An optional scope can be provided to serve as the <code>this</code> pointer
- * in which the function will execute.
- *
- * @param {Listener} listener The function to be executed when the event is raised.
- * @param {object} [scope] An optional object scope to serve as the <code>this</code>
- * pointer in which the listener function will execute.
- * @returns {Event.RemoveCallback} A function that will remove this event listener when invoked.
- *
- * @see Event#raiseEvent
- * @see Event#removeEventListener
- */
- Event.prototype.addEventListener = function (listener, scope) {
- //>>includeStart('debug', pragmas.debug);
- Check.typeOf.func("listener", listener);
- //>>includeEnd('debug');
- this._listeners.push(listener);
- this._scopes.push(scope);
- const event = this;
- return function () {
- event.removeEventListener(listener, scope);
- };
- };
- /**
- * Unregisters a previously registered callback.
- *
- * @param {Listener} listener The function to be unregistered.
- * @param {object} [scope] The scope that was originally passed to addEventListener.
- * @returns {boolean} <code>true</code> if the listener was removed; <code>false</code> if the listener and scope are not registered with the event.
- *
- * @see Event#addEventListener
- * @see Event#raiseEvent
- */
- Event.prototype.removeEventListener = function (listener, scope) {
- //>>includeStart('debug', pragmas.debug);
- Check.typeOf.func("listener", listener);
- //>>includeEnd('debug');
- const listeners = this._listeners;
- const scopes = this._scopes;
- let index = -1;
- for (let i = 0; i < listeners.length; i++) {
- if (listeners[i] === listener && scopes[i] === scope) {
- index = i;
- break;
- }
- }
- if (index !== -1) {
- if (this._insideRaiseEvent) {
- //In order to allow removing an event subscription from within
- //a callback, we don't actually remove the items here. Instead
- //remember the index they are at and undefined their value.
- this._toRemove.push(index);
- listeners[index] = undefined;
- scopes[index] = undefined;
- } else {
- listeners.splice(index, 1);
- scopes.splice(index, 1);
- }
- return true;
- }
- return false;
- };
- function compareNumber(a, b) {
- return b - a;
- }
- /**
- * Raises the event by calling each registered listener with all supplied arguments.
- *
- * @param {...Parameters<Listener>} arguments This method takes any number of parameters and passes them through to the listener functions.
- *
- * @see Event#addEventListener
- * @see Event#removeEventListener
- */
- Event.prototype.raiseEvent = function () {
- this._insideRaiseEvent = true;
- let i;
- const listeners = this._listeners;
- const scopes = this._scopes;
- let length = listeners.length;
- for (i = 0; i < length; i++) {
- const listener = listeners[i];
- if (defined(listener)) {
- listeners[i].apply(scopes[i], arguments);
- }
- }
- //Actually remove items removed in removeEventListener.
- const toRemove = this._toRemove;
- length = toRemove.length;
- if (length > 0) {
- toRemove.sort(compareNumber);
- for (i = 0; i < length; i++) {
- const index = toRemove[i];
- listeners.splice(index, 1);
- scopes.splice(index, 1);
- }
- toRemove.length = 0;
- }
- this._insideRaiseEvent = false;
- };
- /**
- * A function that removes a listener.
- * @callback Event.RemoveCallback
- */
- export default Event;
|