From 897bbf6851692ae75e37a5df176d325c05817649 Mon Sep 17 00:00:00 2001 From: David Yu Date: Fri, 23 Jan 2015 23:26:40 -0800 Subject: [PATCH 1/4] update js-signals: - declare a constructor - wrap Signals object in signals namespace --- js-signals/js-signals.d.ts | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/js-signals/js-signals.d.ts b/js-signals/js-signals.d.ts index c64c6db2a..9ab097583 100644 --- a/js-signals/js-signals.d.ts +++ b/js-signals/js-signals.d.ts @@ -3,6 +3,12 @@ // Definitions by: Diullei Gomes // Definitions: https://github.com/borisyankov/DefinitelyTyped +declare var signals: SignalWrapper; + +interface SignalWrapper { + Signal: Signal +} + interface SignalBinding { active: boolean; context: any; @@ -16,6 +22,15 @@ interface SignalBinding { } interface Signal { + /** + * Custom event broadcaster + *
- inspired by Robert Penner's AS3 Signals. + * @name Signal + * @author Miller Medeiros + * @constructor + */ + new(); + /** * If Signal is active and should broadcast events. */ From 0dbb64a8dd5b4acf0a178f8c9c7506415557538d Mon Sep 17 00:00:00 2001 From: David Yu Date: Fri, 23 Jan 2015 23:48:43 -0800 Subject: [PATCH 2/4] add tests based on js-signals examples - make some parameters in d.ts optional according to examples --- js-signals/js-signals-tests.ts | 221 +++++++++++++++++++++++++++++++++ js-signals/js-signals.d.ts | 4 +- 2 files changed, 223 insertions(+), 2 deletions(-) create mode 100644 js-signals/js-signals-tests.ts diff --git a/js-signals/js-signals-tests.ts b/js-signals/js-signals-tests.ts new file mode 100644 index 000000000..6da3f358d --- /dev/null +++ b/js-signals/js-signals-tests.ts @@ -0,0 +1,221 @@ +/// + +// lifted from https://github.com/millermedeiros/js-signals/wiki/Examples +interface TestObject { + started: Signal; + stopped: Signal; +} + +module Signals.Tests { + //store local reference for brevity + var Signal = signals.Signal; + + //custom object that dispatch signals + var myObject: TestObject = { + started : new Signal(), //past tense is the recommended signal naming convention + stopped : new Signal() + }; + + //single listener + function onStarted(param1, param2){ + alert(param1 + param2); + } + + myObject.started.add(onStarted); //add listener + myObject.started.dispatch('foo', 'bar'); //dispatch signal passing custom parameters + myObject.started.remove(onStarted); //remove a single listener + + //multiple listeners + function onStopped(){ + alert('stopped'); + } + function onStopped2(){ + alert('stopped listener 2'); + } + myObject.stopped.add(onStopped); + myObject.stopped.add(onStopped2); + myObject.stopped.dispatch(); + myObject.stopped.removeAll(); //remove all listeners of the `stopped` signal + + //multiple dispatches + var i = 0; + myObject.started.add(function(){ + i += 1; + alert(i); + }); + myObject.started.dispatch(); //will alert 1 + myObject.started.dispatch(); //will alert 2 + + //multiple dispatches + addOnce() + var i = 0; + myObject.started.addOnce(function(){ + i += 1; + alert(i); + }); + myObject.started.dispatch(); //will alert 1 + myObject.started.dispatch(); //nothing happens + + //enable/disable signal + var i = 0; + myObject.started.add(function(){ + i += 1; + alert(i); + }); + myObject.started.dispatch(); //will alert 1 + myObject.started.active = false; + myObject.started.dispatch(); //nothing happens + myObject.started.active = true; + myObject.started.dispatch(); //will alert 2 + + //Stop/Halt Propagation (method 1) + myObject.started.add(function(){ + myObject.started.halt(); //prevent next listeners on the queue from being executed + }); + myObject.started.add(function(){ + alert('second listener'); //won't be called since first listener stops propagation + }); + myObject.started.dispatch(); + + //Stop/Halt Propagation (method 2) + myObject.started.add(function(){ + return false; //if handler returns `false` will also stop propagation + }); + myObject.started.add(function(){ + alert('second listener'); //won't be called since first listener stops propagation + }); + myObject.started.dispatch(); + + //Set execution context of the listener handler + var foo = 'bar'; + var obj = { + foo : 10 + }; + + function handler1(){ + alert(this.foo); + } + + function handler2(){ + alert(this.foo); + } + + //note that you cannot add the same handler twice to the same signal without removing it first + myObject.started.add(handler1); //default execution context + myObject.started.add(handler2, obj); //set a different execution context + myObject.started.dispatch(); //first handler will alert "bar", second will alert "10". +} + +module Signals.AdvancedTests { + //store local reference for brevity + var Signal = signals.Signal; + + //custom object that dispatch signals + var myObject: TestObject = { + started : new Signal(), //past tense is the recommended signal naming convention + stopped : new Signal() + }; + + //Set listener priority/order (v0.5.3+) + var handler1 = function(){ + alert('foo'); + }; + var handler2 = function(){ + alert('bar'); + }; + myObject.started.add(handler1); //default priority is 0 + myObject.started.add(handler2, null, 2); //setting priority to 2 will make `handler2` execute before `handler1` + myObject.started.dispatch(); //will alert "bar" than "foo" + + //Enable/Disable a single SignalBinding + var handler1 = function(){ + alert('foo bar'); + }; + var handler2 = function(){ + alert('lorem ipsum'); + }; + var binding1 = myObject.started.add(handler1); //methods `add()` and `addOnce()` returns a SignalBinding object + myObject.started.add(handler2); + myObject.started.dispatch(); //will alert "foo bar" than "lorem ipsum" + binding1.active = false; //disable a single binding + myObject.started.dispatch(); //will alert "lorem ipsum" + binding1.active = true; + myObject.started.dispatch(); //will alert "foo bar" than "lorem ipsum" + + //Manually execute a signal handler + var handler = function(){ + alert('foo bar'); + }; + var binding:SignalBinding = myObject.started.add(handler); //methods `add()` and `addOnce()` returns a SignalBinding object + binding.execute(); //will alert "foo bar" + + //Retrieve anonymous listener + var binding:SignalBinding = myObject.started.add(function(){ + alert('foo bar'); + }); + + // note: in the original docs, this is handler, but that collides with handler above because these are in one giant scope + // perhaps these are best split into functions for readability + var anonymousHandler = binding.getListener(); //reference to the anonymous function + + //Remove / Detach anonymous listener + var binding:SignalBinding = myObject.started.add(function(){ + alert('foo bar'); + }); + myObject.started.dispatch(); //will alert "foo bar" + binding.detach(); + alert(binding.isBound()); //will alert `false` + myObject.started.dispatch(); //nothing happens + + //Check if binding will execute only once + var binding1:SignalBinding = myObject.started.add(function(){ + alert('foo bar'); + }); + var binding2:SignalBinding = myObject.started.addOnce(function(){ + alert('foo bar'); + }); + alert(binding1.isOnce()); //alert "false" + alert(binding2.isOnce()); //alert "true" + + //Change listener execution context on-the-fly + var foo = 'bar'; + var obj = { + foo : "it's over 9000!" + }; + var binding:SignalBinding = myObject.started.add(function(){ + alert(this.foo); + }); + myObject.started.dispatch(); //will alert "bar" + binding.context = obj; + myObject.started.dispatch(); //will alert "it's over 9000!" + + //Add default parameters to Signal dispatch (v0.6.3+) + var binding:SignalBinding = myObject.started.add(function(a, b, c){ + alert(a +' '+ b +' '+ c); + }); + binding.params = ['lorem', 'ipsum']; //set default parameters of the binding + myObject.started.dispatch('dolor'); //will alert "lorem ipsum dolor" + + //Check if Signal has specific listener (v0.7.0+) + function onStart(a){ + console.log(a); + } + myObject.started.add(onStart); + myObject.started.has(onStart); // true + + //Memorize previously dispatched values / forget values (v0.7.0+) + myObject.started.memorize = true; // default is false + myObject.started.dispatch('foo'); + + // add()/addOnce() will automatically fire listener if signal was dispatched before + // will log "foo" since it keeps record of previously dispatched values + myObject.started.addOnce(console.log, console); + + // dispatching a new value will overwrite the "memory" + myObject.started.dispatch('lorem'); + // will log "lorem" + myObject.started.addOnce(console.log, console); + + myObject.started.forget(); // forget previously dispatched values (reset signal state) + myObject.started.addOnce(console.log, console); // won't log till next dispatch (since it "forgot") + myObject.started.dispatch('bar'); // log "bar" +} diff --git a/js-signals/js-signals.d.ts b/js-signals/js-signals.d.ts index 9ab097583..5072d7b95 100644 --- a/js-signals/js-signals.d.ts +++ b/js-signals/js-signals.d.ts @@ -14,7 +14,7 @@ interface SignalBinding { context: any; params: any; detach(); - execute(paramsArr); + execute(paramsArr?); getListener(): Function; getSignal(): Signal; isBound(): boolean; @@ -63,7 +63,7 @@ interface Signal { * @param listenercontext Context on which listener will be executed (object that should represent the `this` variable inside listener function). * @param priority The priority level of the event listener. Listeners with higher priority will be executed before listeners with lower priority. Listeners with same priority level will be executed at the same order as they were added. (default = 0) */ - addOnce(listener: Function, listenerContext, priority): SignalBinding; + addOnce(listener: Function, listenerContext?, priority?): SignalBinding; /** * Dispatch/Broadcast Signal to all listeners added to the queue. From 7dcc4fd448d62ac3a2fc5ab5f02f252c0f8818ef Mon Sep 17 00:00:00 2001 From: David Yu Date: Sat, 24 Jan 2015 00:01:44 -0800 Subject: [PATCH 3/4] fix test; explicitly type parameters --- js-signals/js-signals-tests.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/js-signals/js-signals-tests.ts b/js-signals/js-signals-tests.ts index 6da3f358d..eae9d7521 100644 --- a/js-signals/js-signals-tests.ts +++ b/js-signals/js-signals-tests.ts @@ -17,7 +17,7 @@ module Signals.Tests { }; //single listener - function onStarted(param1, param2){ + function onStarted(param1:string, param2:string){ alert(param1 + param2); } @@ -189,14 +189,14 @@ module Signals.AdvancedTests { myObject.started.dispatch(); //will alert "it's over 9000!" //Add default parameters to Signal dispatch (v0.6.3+) - var binding:SignalBinding = myObject.started.add(function(a, b, c){ + var binding:SignalBinding = myObject.started.add(function(a:string, b:string, c:string){ alert(a +' '+ b +' '+ c); }); binding.params = ['lorem', 'ipsum']; //set default parameters of the binding myObject.started.dispatch('dolor'); //will alert "lorem ipsum dolor" //Check if Signal has specific listener (v0.7.0+) - function onStart(a){ + function onStart(a:string){ console.log(a); } myObject.started.add(onStart); From 83e26f88258026884fac86667818dd078758e3d3 Mon Sep 17 00:00:00 2001 From: David Yu Date: Sat, 24 Jan 2015 00:10:20 -0800 Subject: [PATCH 4/4] fix d.ts; add return and parameter types --- js-signals/js-signals.d.ts | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/js-signals/js-signals.d.ts b/js-signals/js-signals.d.ts index 5072d7b95..ebc8f72ae 100644 --- a/js-signals/js-signals.d.ts +++ b/js-signals/js-signals.d.ts @@ -13,8 +13,8 @@ interface SignalBinding { active: boolean; context: any; params: any; - detach(); - execute(paramsArr?); + detach(): Function; + execute(paramsArr?:any[]): any; getListener(): Function; getSignal(): Signal; isBound(): boolean; @@ -29,7 +29,7 @@ interface Signal { * @author Miller Medeiros * @constructor */ - new(); + new(): Signal; /** * If Signal is active and should broadcast events. @@ -63,24 +63,24 @@ interface Signal { * @param listenercontext Context on which listener will be executed (object that should represent the `this` variable inside listener function). * @param priority The priority level of the event listener. Listeners with higher priority will be executed before listeners with lower priority. Listeners with same priority level will be executed at the same order as they were added. (default = 0) */ - addOnce(listener: Function, listenerContext?, priority?): SignalBinding; + addOnce(listener: Function, listenerContext?: any, priority?: Number): SignalBinding; /** * Dispatch/Broadcast Signal to all listeners added to the queue. * * @param params Parameters that should be passed to each handler. */ - dispatch(...params: any[]); + dispatch(...params: any[]): void; /** * Remove all bindings from signal and destroy any reference to external objects (destroy Signal object). */ - dispose(); + dispose(): void; /** * Forget memorized arguments. */ - forget(); + forget(): void; /** * Returns a number of listeners attached to the Signal. @@ -90,7 +90,7 @@ interface Signal { /** * Stop propagation of the event, blocking the dispatch to next listeners on the queue. */ - halt(); + halt(): void; /** * Check if listener was attached to Signal. @@ -102,5 +102,5 @@ interface Signal { */ remove(listener: Function, context?: any): Function; - removeAll(); + removeAll(): void; }