@mezzy/signals
Version:
A luxurious user experience framework, developed by your friends at Mezzanine.
153 lines (115 loc) • 4.51 kB
text/typescript
import ISignal from './iSignal';
import ISignalBinding from './iSignalBinding';
/**
* @desc An object that represents a binding between a Signal and a listener function.
* Released under the MIT license
* http://millermedeiros.github.com/js-signals/
*
* @version 1.0 - 7th March 2013
*
* @author Richard Davey, TypeScript conversion
* @author Miller Medeiros, JS Signals
* @author Robert Penner, AS Signals
*
* @url http://www.kiwijs.org
*
*/
export class SignalBinding<T> implements ISignalBinding<T> {
/**
* Object that represents a binding between a Signal and a listener function.
* <br />- <strong>This is an internal constructor and shouldn't be called by regular users.</strong>
* <br />- inspired by Joa Ebert AS3 SignalBinding and Robert Penner's Slot classes.
* @author Miller Medeiros
* @constructor
* @internal
* @key SignalBinding
* @param Signal signal Reference to Signal object that listener is currently bound to.
* @param {(value:T) => void} 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:ISignal<T>, listener:(value:T) => void, isOnce:boolean, listenerContext:any, priority:number = 0) {
this._listener = listener;
this._isOnce = isOnce;
this._context = listenerContext;
this._signal = signal;
this.priority = priority;
}
/**
* @return {(value:T) => void} Handler function bound to the signal.
*/
get listener():(value:T) => void { return this._listener; }
private _listener:(value:T) => void; // Not readonly, so it can be deleted.
/**
* If binding should be executed just once.
*/
private readonly _isOnce:boolean;
/**
* Context on which listener will be executed (object that should represent the `this` variable inside listener function).
*/
get context():any { return this._context; }
set context(value:any) { this._context = value; }
private _context:any;
/**
* @return Signal Signal that listener is currently bound to.
*/
private _signal:ISignal<T>; // Not readonly, so it can be deleted.
/**
* Listener priority
*/
public priority:number;
/**
* If binding is active and should be executed.
*/
isActive:boolean = true;
/**
* Call listener passing arbitrary parameters.
* <p>If binding was added using `Signal.listenOnce()` it will be automatically deleted from signal dispatch queue,
* this method is used internally for the signal dispatch.</p>
* @param {T} [param] Parameter that should be passed to the listener
* @return {*} Value returned by the listener.
*/
execute(param:T):any {
let handlerReturn:any;
if (this.isActive && !!this._listener) {
handlerReturn = this._listener.apply(this._context, [param]);
if (this._isOnce) {
this.detach();
}
}
return handlerReturn;
}
/**
* Detach binding from signal.
* - alias to: mySignal.delete(myBinding.getListener());
* @return {(value:T) => void|null} Handler function bound to the signal or `null` if binding was previously detached.
*/
detach():(value:T) => void {
return this.isBound() ? this._signal.delete(this._listener, this._context) : null;
}
/**
* @return {boolean} Is the binding still bound to the signal with a listener?
*/
isBound():boolean { return (!!this._signal && !!this._listener); }
/**
* @return {boolean} Will SignalBinding be executed only once?
*/
isOnce():boolean { return this._isOnce; }
/**
* Delete instance properties
* @private
*/
destroy():void {
delete this._signal;
delete this._listener;
delete this._context;
}
/**
* @return {string} String representation of the object.
*/
toString():string {
return '[SignalBinding isOnce:' + this._isOnce + ', isBound:' + this.isBound() + ', isActive:' + this.isActive + ']';
}
} // End class
export default SignalBinding;