|
|
@@ -1,310 +0,0 @@
|
|
|
-/**
|
|
|
- * @license Copyright (c) 2003-2016, CKSource - Frederico Knabben. All rights reserved.
|
|
|
- * For licensing, see LICENSE.md.
|
|
|
- */
|
|
|
-
|
|
|
-'use strict';
|
|
|
-
|
|
|
-import EventInfo from './eventinfo.js';
|
|
|
-import utils from './utils.js';
|
|
|
-
|
|
|
-// Saves how many callbacks has been already added. Does not decrement when callback is removed.
|
|
|
-// Used internally as a unique id for a callback.
|
|
|
-let eventsCounter = 0;
|
|
|
-
|
|
|
-/**
|
|
|
- * Mixin that injects the events API into its host.
|
|
|
- *
|
|
|
- * @mixin core.EmitterMixin
|
|
|
- * @implements core.Emitter
|
|
|
- */
|
|
|
-const EmitterMixin = {
|
|
|
- /**
|
|
|
- * Registers a callback function to be executed when an event is fired.
|
|
|
- *
|
|
|
- * @param {String} event The name of the event.
|
|
|
- * @param {Function} callback The function to be called on event.
|
|
|
- * @param {Object} [ctx] The object that represents `this` in the callback. Defaults to the object firing the
|
|
|
- * event.
|
|
|
- * @param {Number} [priority=10] The priority of this callback in relation to other callbacks to that same event.
|
|
|
- * Lower values are called first.
|
|
|
- * @method core.EmitterMixin#on
|
|
|
- */
|
|
|
- on( event, callback, ctx, priority ) {
|
|
|
- const callbacks = getCallbacks( this, event );
|
|
|
-
|
|
|
- // Set the priority defaults.
|
|
|
- if ( typeof priority != 'number' ) {
|
|
|
- priority = 10;
|
|
|
- }
|
|
|
-
|
|
|
- callback = {
|
|
|
- callback: callback,
|
|
|
- ctx: ctx || this,
|
|
|
- priority: priority,
|
|
|
- // Save counter value as unique id.
|
|
|
- counter: ++eventsCounter
|
|
|
- };
|
|
|
-
|
|
|
- // Add the callback to the list in the right priority position.
|
|
|
- for ( let i = callbacks.length - 1; i >= 0; i-- ) {
|
|
|
- if ( callbacks[ i ].priority <= priority ) {
|
|
|
- callbacks.splice( i + 1, 0, callback );
|
|
|
-
|
|
|
- return;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- callbacks.unshift( callback );
|
|
|
- },
|
|
|
-
|
|
|
- /**
|
|
|
- * Registers a callback function to be executed on the next time the event is fired only. This is similar to
|
|
|
- * calling {@link #on} followed by {@link #off} in the callback.
|
|
|
- *
|
|
|
- * @param {String} event The name of the event.
|
|
|
- * @param {Function} callback The function to be called on event.
|
|
|
- * @param {Object} [ctx] The object that represents `this` in the callback. Defaults to the object firing the
|
|
|
- * event.
|
|
|
- * @param {Number} [priority=10] The priority of this callback in relation to other callbacks to that same event.
|
|
|
- * Lower values are called first.
|
|
|
- * @method core.EmitterMixin#once
|
|
|
- */
|
|
|
- once( event, callback, ctx, priority ) {
|
|
|
- const onceCallback = function( event ) {
|
|
|
- // Go off() at the first call.
|
|
|
- event.off();
|
|
|
-
|
|
|
- // Go with the original callback.
|
|
|
- callback.apply( this, arguments );
|
|
|
- };
|
|
|
-
|
|
|
- // Make the a similar on() call, simply replacing the callback.
|
|
|
- this.on( event, onceCallback, ctx, priority );
|
|
|
- },
|
|
|
-
|
|
|
- /**
|
|
|
- * Stops executing the callback on the given event.
|
|
|
- *
|
|
|
- * @param {String} event The name of the event.
|
|
|
- * @param {Function} callback The function to stop being called.
|
|
|
- * @param {Object} [ctx] The context object to be removed, pared with the given callback. To handle cases where
|
|
|
- * the same callback is used several times with different contexts.
|
|
|
- * @method core.EmitterMixin#off
|
|
|
- */
|
|
|
- off( event, callback, ctx ) {
|
|
|
- const callbacks = getCallbacksIfAny( this, event );
|
|
|
-
|
|
|
- if ( !callbacks ) {
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- for ( let i = 0; i < callbacks.length; i++ ) {
|
|
|
- if ( callbacks[ i ].callback == callback ) {
|
|
|
- if ( !ctx || ctx == callbacks[ i ].ctx ) {
|
|
|
- // Remove the callback from the list (fixing the next index).
|
|
|
- callbacks.splice( i, 1 );
|
|
|
- i--;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- },
|
|
|
-
|
|
|
- /**
|
|
|
- * Registers a callback function to be executed when an event is fired in a specific (emitter) object.
|
|
|
- *
|
|
|
- * @param {core.Emitter} emitter The object that fires the event.
|
|
|
- * @param {String} event The name of the event.
|
|
|
- * @param {Function} callback The function to be called on event.
|
|
|
- * @param {Object} [ctx] The object that represents `this` in the callback. Defaults to `emitter`.
|
|
|
- * @param {Number} [priority=10] The priority of this callback in relation to other callbacks to that same event.
|
|
|
- * Lower values are called first.
|
|
|
- * @method core.EmitterMixin#listenTo
|
|
|
- */
|
|
|
- listenTo( emitter, event, callback, ctx, priority ) {
|
|
|
- let emitters, emitterId, emitterInfo, eventCallbacks;
|
|
|
-
|
|
|
- // _listeningTo contains a list of emitters that this object is listening to.
|
|
|
- // This list has the following format:
|
|
|
- //
|
|
|
- // _listeningTo: {
|
|
|
- // emitterId: {
|
|
|
- // emitter: emitter,
|
|
|
- // callbacks: {
|
|
|
- // event1: [ callback1, callback2, ... ]
|
|
|
- // ....
|
|
|
- // }
|
|
|
- // },
|
|
|
- // ...
|
|
|
- // }
|
|
|
-
|
|
|
- if ( !( emitters = this._listeningTo ) ) {
|
|
|
- emitters = this._listeningTo = {};
|
|
|
- }
|
|
|
-
|
|
|
- if ( !( emitterId = emitter._emitterId ) ) {
|
|
|
- emitterId = emitter._emitterId = utils.uid();
|
|
|
- }
|
|
|
-
|
|
|
- if ( !( emitterInfo = emitters[ emitterId ] ) ) {
|
|
|
- emitterInfo = emitters[ emitterId ] = {
|
|
|
- emitter: emitter,
|
|
|
- callbacks: {}
|
|
|
- };
|
|
|
- }
|
|
|
-
|
|
|
- if ( !( eventCallbacks = emitterInfo.callbacks[ event ] ) ) {
|
|
|
- eventCallbacks = emitterInfo.callbacks[ event ] = [];
|
|
|
- }
|
|
|
-
|
|
|
- eventCallbacks.push( callback );
|
|
|
-
|
|
|
- // Finally register the callback to the event.
|
|
|
- emitter.on( event, callback, ctx, priority );
|
|
|
- },
|
|
|
-
|
|
|
- /**
|
|
|
- * Stops listening for events. It can be used at different levels:
|
|
|
- *
|
|
|
- * * To stop listening to a specific callback.
|
|
|
- * * To stop listening to a specific event.
|
|
|
- * * To stop listening to all events fired by a specific object.
|
|
|
- * * To stop listening to all events fired by all object.
|
|
|
- *
|
|
|
- * @param {core.Emitter} [emitter] The object to stop listening to. If omitted, stops it for all objects.
|
|
|
- * @param {String} [event] (Requires the `emitter`) The name of the event to stop listening to. If omitted, stops it
|
|
|
- * for all events from `emitter`.
|
|
|
- * @param {Function} [callback] (Requires the `event`) The function to be removed from the call list for the given
|
|
|
- * `event`.
|
|
|
- * @method core.EmitterMixin#stopListening
|
|
|
- */
|
|
|
- stopListening( emitter, event, callback ) {
|
|
|
- let emitters = this._listeningTo;
|
|
|
- let emitterId = emitter && emitter._emitterId;
|
|
|
- let emitterInfo = emitters && emitterId && emitters[ emitterId ];
|
|
|
- let eventCallbacks = emitterInfo && event && emitterInfo.callbacks[ event ];
|
|
|
-
|
|
|
- // Stop if nothing has been listened.
|
|
|
- if ( !emitters || ( emitter && !emitterInfo ) || ( event && !eventCallbacks ) ) {
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- // All params provided. off() that single callback.
|
|
|
- if ( callback ) {
|
|
|
- emitter.off( event, callback );
|
|
|
- }
|
|
|
- // Only `emitter` and `event` provided. off() all callbacks for that event.
|
|
|
- else if ( eventCallbacks ) {
|
|
|
- while ( ( callback = eventCallbacks.pop() ) ) {
|
|
|
- emitter.off( event, callback );
|
|
|
- }
|
|
|
- delete emitterInfo.callbacks[ event ];
|
|
|
- }
|
|
|
- // Only `emitter` provided. off() all events for that emitter.
|
|
|
- else if ( emitterInfo ) {
|
|
|
- for ( event in emitterInfo.callbacks ) {
|
|
|
- this.stopListening( emitter, event );
|
|
|
- }
|
|
|
- delete emitters[ emitterId ];
|
|
|
- }
|
|
|
- // No params provided. off() all emitters.
|
|
|
- else {
|
|
|
- for ( emitterId in emitters ) {
|
|
|
- this.stopListening( emitters[ emitterId ].emitter );
|
|
|
- }
|
|
|
- delete this._listeningTo;
|
|
|
- }
|
|
|
- },
|
|
|
-
|
|
|
- /**
|
|
|
- * Fires an event, executing all callbacks registered for it.
|
|
|
- *
|
|
|
- * The first parameter passed to callbacks is an {@link EventInfo} object, followed by the optional `args` provided in
|
|
|
- * the `fire()` method call.
|
|
|
- *
|
|
|
- * @param {String} event The name of the event.
|
|
|
- * @param {...*} [args] Additional arguments to be passed to the callbacks.
|
|
|
- * @method core.EmitterMixin#fire
|
|
|
- */
|
|
|
- fire( event, args ) {
|
|
|
- const callbacks = getCallbacksIfAny( this, event );
|
|
|
-
|
|
|
- if ( !callbacks ) {
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- let eventInfo = new EventInfo( this, event );
|
|
|
-
|
|
|
- // Take the list of arguments to pass to the callbacks.
|
|
|
- args = Array.prototype.slice.call( arguments, 1 );
|
|
|
- args.unshift( eventInfo );
|
|
|
-
|
|
|
- // Save how many callbacks were added at the moment when the event has been fired.
|
|
|
- const counter = eventsCounter;
|
|
|
-
|
|
|
- for ( let i = 0; i < callbacks.length; i++ ) {
|
|
|
- // Filter out callbacks that have been added after event has been fired.
|
|
|
- if ( callbacks[ i ].counter > counter ) {
|
|
|
- continue;
|
|
|
- }
|
|
|
-
|
|
|
- callbacks[ i ].callback.apply( callbacks[ i ].ctx, args );
|
|
|
-
|
|
|
- // Remove the callback from future requests if off() has been called.
|
|
|
- if ( eventInfo.off.called ) {
|
|
|
- // Remove the called mark for the next calls.
|
|
|
- delete eventInfo.off.called;
|
|
|
-
|
|
|
- // Remove the callback from the list (fixing the next index).
|
|
|
- callbacks.splice( i, 1 );
|
|
|
- i--;
|
|
|
- }
|
|
|
-
|
|
|
- // Do not execute next callbacks if stop() was called.
|
|
|
- if ( eventInfo.stop.called ) {
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-};
|
|
|
-
|
|
|
-export default EmitterMixin;
|
|
|
-
|
|
|
-// Gets the internal events hash of a give object.
|
|
|
-function getEvents( source ) {
|
|
|
- if ( !source._events ) {
|
|
|
- Object.defineProperty( source, '_events', {
|
|
|
- value: {}
|
|
|
- } );
|
|
|
- }
|
|
|
-
|
|
|
- return source._events;
|
|
|
-}
|
|
|
-
|
|
|
-// Gets the list of callbacks for a given event.
|
|
|
-function getCallbacks( source, eventName ) {
|
|
|
- const events = getEvents( source );
|
|
|
-
|
|
|
- if ( !events[ eventName ] ) {
|
|
|
- events[ eventName ] = [];
|
|
|
- }
|
|
|
-
|
|
|
- return events[ eventName ];
|
|
|
-}
|
|
|
-
|
|
|
-// Get the list of callbacks for a given event only if there is any available.
|
|
|
-function getCallbacksIfAny( source, event ) {
|
|
|
- let callbacks;
|
|
|
-
|
|
|
- if ( !source._events || !( callbacks = source._events[ event ] ) || !callbacks.length ) {
|
|
|
- return null;
|
|
|
- }
|
|
|
-
|
|
|
- return callbacks;
|
|
|
-}
|
|
|
-
|
|
|
-/**
|
|
|
- * Interface representing classes which mix in {@link core.EmitterMixin}.
|
|
|
- *
|
|
|
- * @interface core.Emitter
|
|
|
- */
|