/** @license
* JS Signals
- This is an internal constructor and shouldn't be called by regular users.
*
- inspired by Joa Ebert AS3 SignalBinding and Robert Penner's Slot classes.
* @author Miller Medeiros
* @constructor
* @internal
* @name SignalBinding
* @param {Signal} signal Reference to Signal object that listener is currently bound to.
* @param {Function} listener Handler function bound to the signal.
* @param {boolean} isOnce If binding should be executed just once.
* @param {Object} [listenerContext] Context on which listener will be executed (object that should represent the `this` variable inside listener function).
* @param {Number} [priority] The priority level of the event listener. (default = 0).
*/
constructor (signal, listener, isOnce, listenerContext, priority) {
/**
* If binding is active and should be executed.
* @type boolean
*/
this.active = true;
/**
* Default parameters passed to listener during `Signal.dispatch` and `SignalBinding.execute`. (curried parameters)
* @type Array|null
*/
this.params = null;
/**
* Handler function bound to the signal.
* @type Function
* @private
*/
this._listener = listener;
/**
* If binding should be executed just once.
* @type boolean
* @private
*/
this._isOnce = isOnce;
/**
* Context on which listener will be executed (object that should represent the `this` variable inside listener function).
* @memberOf SignalBinding.prototype
* @name context
* @type Object|undefined|null
*/
this.context = listenerContext;
/**
* Reference to Signal object that listener is currently bound to.
* @type Signal
* @private
*/
this._signal = signal;
/**
* Listener priority
* @type Number
* @private
*/
this._priority = priority || 0;
}
/**
* Call listener passing arbitrary parameters.
*
If binding was added using `Signal.addOnce()` it will be automatically removed from signal dispatch queue, this method is used internally for the signal dispatch.
* @param {Array} [paramsArr] Array of parameters that should be passed to the listener * @return {*} Value returned by the listener. */ execute (paramsArr) { var handlerReturn, params; if (this.active && !!this._listener) { params = this.params? this.params.concat(paramsArr) : paramsArr; handlerReturn = this._listener.apply(this.context, params); if (this._isOnce) { this.detach(); } } return handlerReturn; } /** * Detach binding from signal. * - alias to: mySignal.remove(myBinding.getListener()); * @return {Function|null} Handler function bound to the signal or `null` if binding was previously detached. */ detach () { return this.isBound()? this._signal.remove(this._listener, this.context) : null; } /** * @return {Boolean} `true` if binding is still bound to the signal and have a listener. */ isBound () { return (!!this._signal && !!this._listener); } /** * @return {boolean} If SignalBinding will only be executed once. */ isOnce () { return this._isOnce; } /** * @return {Function} Handler function bound to the signal. */ getListener () { return this._listener; } /** * @return {Signal} Signal that listener is currently bound to. */ getSignal () { return this._signal; } /** * Delete instance properties * @private */ _destroy () { delete this._signal; delete this._listener; delete this.context; } } // Signal -------------------------------------------------------- //================================================================ function validateListener(listener, fnName) { if (typeof listener !== 'function') { throw new Error( 'listener is a required param of {fn}() and should be a Function.'.replace('{fn}', fnName) ); } } class Signal { /** * Custom event broadcaster *IMPORTANT: Setting this property during a dispatch will only affect the next dispatch, if you want to stop the propagation of a signal use `halt()` instead.
* @type boolean */ this.active = true; /** * @type Array.IMPORTANT: calling any method on the signal instance after calling dispose will throw errors.
*/ dispose () { this.removeAll(); delete this._bindings; delete this._prevParams; } } // Namespace ----------------------------------------------------- //================================================================ var signals = Signal; /** * Custom event broadcaster * @see Signal */ // alias for backwards compatibility (see #gh-44) signals.Signal = Signal; global.signals = signals; })(this);