From 36df9eae2f8fcc56e0e8c2f970aba450174e7b6a Mon Sep 17 00:00:00 2001 From: Miller Medeiros Date: Wed, 1 Dec 2010 22:23:21 -0500 Subject: [PATCH 01/10] removed unnecessary function names --- dev/build/build.number | 4 ++-- dev/src/Signal.js | 28 ++++++++++++------------ dev/src/SignalBinding.js | 16 +++++++------- dist/js-signals.js | 46 ++++++++++++++++++++-------------------- dist/js-signals.min.js | 4 ++-- 5 files changed, 49 insertions(+), 49 deletions(-) diff --git a/dev/build/build.number b/dev/build/build.number index 2c686c2..725705b 100644 --- a/dev/build/build.number +++ b/dev/build/build.number @@ -1,3 +1,3 @@ #Build Number for ANT. Do not edit! -#Sat Nov 27 16:19:16 EST 2010 -build.number=65 +#Wed Dec 01 22:22:08 EST 2010 +build.number=66 diff --git a/dev/src/Signal.js b/dev/src/Signal.js index 481b413..ade358f 100644 --- a/dev/src/Signal.js +++ b/dev/src/Signal.js @@ -34,7 +34,7 @@ * @return {signals.SignalBinding} * @private */ - _registerListener : function _registerListener(listener, isOnce, scope){ + _registerListener : function(listener, isOnce, scope){ var prevIndex = this._indexOfListener(listener), binding; @@ -55,7 +55,7 @@ * @param {signals.SignalBinding} binding * @private */ - _addBinding : function _addBinding(binding){ + _addBinding : function(binding){ this._bindings.push(binding); }, @@ -64,7 +64,7 @@ * @return {int} * @private */ - _indexOfListener : function _indexOfListener(listener){ + _indexOfListener : function(listener){ var n = this._bindings.length; while(n--){ if(this._bindings[n].listener === listener) return n; @@ -78,7 +78,7 @@ * @param {Object} scope Context on which listener will be executed (object that should represent the `this` variable inside listener function). * @return {signals.SignalBinding} An Object representing the binding between the Signal and listener. */ - add : function add(listener, scope){ + add : function(listener, scope){ return this._registerListener(listener, false, scope); }, @@ -88,7 +88,7 @@ * @param {Object} scope Context on which listener will be executed (object that should represent the `this` variable inside listener function). * @return {signals.SignalBinding} An Object representing the binding between the Signal and listener. */ - addOnce : function addOnce(listener, scope){ + addOnce : function(listener, scope){ return this._registerListener(listener, true, scope); }, @@ -97,7 +97,7 @@ * @param {Function} listener Handler function that should be removed. * @return {Function} Listener handler function. */ - remove : function remove(listener){ + remove : function(listener){ var i = this._indexOfListener(listener); if(i !== -1){ this._bindings.splice(i, 1); @@ -108,14 +108,14 @@ /** * Remove all listeners from the Signal. */ - removeAll : function removeAll(){ + removeAll : function(){ this._bindings.length = 0; }, /** * @return {uint} Number of listeners attached to the Signal. */ - getNumListeners : function getNumListeners(){ + getNumListeners : function(){ return this._bindings.length; }, @@ -123,7 +123,7 @@ * Disable Signal, will block dispatch to listeners until `enable()` is called. * @see signals.Signal.prototype.enable */ - disable : function disable(){ + disable : function(){ this._isEnabled = false; }, @@ -131,14 +131,14 @@ * Enable broadcast to listeners. * @see signals.Signal.prototype.disable */ - enable : function enable(){ + enable : function(){ this._isEnabled = true; }, /** * @return {boolean} If Signal is currently enabled and will broadcast message to listeners. */ - isEnabled : function isEnabled(){ + isEnabled : function(){ return this._isEnabled; }, @@ -146,7 +146,7 @@ * Stop propagation of the event, blocking the dispatch to next listeners on the queue. * - should be called only during signal dispatch, calling it before/after dispatch won't affect signal broadcast. */ - halt : function halt(){ + halt : function(){ this._shouldPropagate = false; }, @@ -154,7 +154,7 @@ * Dispatch/Broadcast Signal to all listeners added to the queue. * @param {...*} params Parameters that should be passed to each handler. */ - dispatch : function dispatch(params){ + dispatch : function(params){ if(! this._isEnabled) return; var paramsArr = Array.prototype.slice.call(arguments), @@ -172,7 +172,7 @@ /** * @return {string} String representation of the object. */ - toString : function toString(){ + toString : function(){ return '[Signal isEnabled: '+ this._isEnabled +' numListeners: '+ this.getNumListeners() +']'; } diff --git a/dev/src/SignalBinding.js b/dev/src/SignalBinding.js index cf36b53..e41f7c7 100644 --- a/dev/src/SignalBinding.js +++ b/dev/src/SignalBinding.js @@ -54,7 +54,7 @@ * @param {Array} paramsArr Array of parameters that should be passed to the listener * @return {*} Value returned by the listener. */ - execute : function execute(paramsArr){ + execute : function(paramsArr){ if(this._isEnabled){ if(this._isOnce) this.detach(); return this.listener.apply(this.listenerScope, paramsArr); @@ -66,14 +66,14 @@ * - alias to: mySignal.remove(myBinding.listener); * @return {Function} Handler function binded to the signal. */ - detach : function detach(){ + detach : function(){ return this._signal.remove(this.listener); }, /** * Remove binding from signal and destroy any reference to external Objects (destroy SignalBinding object). */ - dispose : function dispose(){ + dispose : function(){ this.detach(); //remove reference to all objects delete this._signal; @@ -85,7 +85,7 @@ * Disable SignalBinding, block listener execution. Listener will only be executed after calling `enable()`. * @see signals.SignalBinding.enable() */ - disable : function disable(){ + disable : function(){ this._isEnabled = false; }, @@ -93,28 +93,28 @@ * Enable SignalBinding. Enable listener execution. * @see signals.SignalBinding.disable() */ - enable : function enable(){ + enable : function(){ this._isEnabled = true; }, /** * @return {boolean} If SignalBinding is currently paused and won't execute listener during dispatch. */ - isEnabled : function isEnabled(){ + isEnabled : function(){ return this._isEnabled; }, /** * @return {boolean} If SignalBinding will only be executed once. */ - isOnce : function isOnce(){ + isOnce : function(){ return this._isOnce; }, /** * @return {string} String representation of the object. */ - toString : function toString(){ + toString : function(){ return '[SignalBinding listener: '+ this.listener +', isOnce: '+ this._isOnce +', isEnabled: '+ this._isEnabled +', listenerScope: '+ this.listenerScope +']'; } diff --git a/dist/js-signals.js b/dist/js-signals.js index 7757652..5270253 100644 --- a/dist/js-signals.js +++ b/dist/js-signals.js @@ -3,7 +3,7 @@ * Released under the MIT license (http://www.opensource.org/licenses/mit-license.php) * @author Miller Medeiros * @version 0.4 - * @build 64 11/27/2010 04:19 PM + * @build 65 12/01/2010 10:22 PM */ (function(){ @@ -48,7 +48,7 @@ * @return {signals.SignalBinding} * @private */ - _registerListener : function _registerListener(listener, isOnce, scope){ + _registerListener : function(listener, isOnce, scope){ var prevIndex = this._indexOfListener(listener), binding; @@ -69,7 +69,7 @@ * @param {signals.SignalBinding} binding * @private */ - _addBinding : function _addBinding(binding){ + _addBinding : function(binding){ this._bindings.push(binding); }, @@ -78,7 +78,7 @@ * @return {int} * @private */ - _indexOfListener : function _indexOfListener(listener){ + _indexOfListener : function(listener){ var n = this._bindings.length; while(n--){ if(this._bindings[n].listener === listener) return n; @@ -92,7 +92,7 @@ * @param {Object} scope Context on which listener will be executed (object that should represent the `this` variable inside listener function). * @return {signals.SignalBinding} An Object representing the binding between the Signal and listener. */ - add : function add(listener, scope){ + add : function(listener, scope){ return this._registerListener(listener, false, scope); }, @@ -102,7 +102,7 @@ * @param {Object} scope Context on which listener will be executed (object that should represent the `this` variable inside listener function). * @return {signals.SignalBinding} An Object representing the binding between the Signal and listener. */ - addOnce : function addOnce(listener, scope){ + addOnce : function(listener, scope){ return this._registerListener(listener, true, scope); }, @@ -111,7 +111,7 @@ * @param {Function} listener Handler function that should be removed. * @return {Function} Listener handler function. */ - remove : function remove(listener){ + remove : function(listener){ var i = this._indexOfListener(listener); if(i !== -1){ this._bindings.splice(i, 1); @@ -122,14 +122,14 @@ /** * Remove all listeners from the Signal. */ - removeAll : function removeAll(){ + removeAll : function(){ this._bindings.length = 0; }, /** * @return {uint} Number of listeners attached to the Signal. */ - getNumListeners : function getNumListeners(){ + getNumListeners : function(){ return this._bindings.length; }, @@ -137,7 +137,7 @@ * Disable Signal, will block dispatch to listeners until `enable()` is called. * @see signals.Signal.prototype.enable */ - disable : function disable(){ + disable : function(){ this._isEnabled = false; }, @@ -145,14 +145,14 @@ * Enable broadcast to listeners. * @see signals.Signal.prototype.disable */ - enable : function enable(){ + enable : function(){ this._isEnabled = true; }, /** * @return {boolean} If Signal is currently enabled and will broadcast message to listeners. */ - isEnabled : function isEnabled(){ + isEnabled : function(){ return this._isEnabled; }, @@ -160,7 +160,7 @@ * Stop propagation of the event, blocking the dispatch to next listeners on the queue. * - should be called only during signal dispatch, calling it before/after dispatch won't affect signal broadcast. */ - halt : function halt(){ + halt : function(){ this._shouldPropagate = false; }, @@ -168,7 +168,7 @@ * Dispatch/Broadcast Signal to all listeners added to the queue. * @param {...*} params Parameters that should be passed to each handler. */ - dispatch : function dispatch(params){ + dispatch : function(params){ if(! this._isEnabled) return; var paramsArr = Array.prototype.slice.call(arguments), @@ -186,7 +186,7 @@ /** * @return {string} String representation of the object. */ - toString : function toString(){ + toString : function(){ return '[Signal isEnabled: '+ this._isEnabled +' numListeners: '+ this.getNumListeners() +']'; } @@ -247,7 +247,7 @@ * @param {Array} paramsArr Array of parameters that should be passed to the listener * @return {*} Value returned by the listener. */ - execute : function execute(paramsArr){ + execute : function(paramsArr){ if(this._isEnabled){ if(this._isOnce) this.detach(); return this.listener.apply(this.listenerScope, paramsArr); @@ -259,14 +259,14 @@ * - alias to: mySignal.remove(myBinding.listener); * @return {Function} Handler function binded to the signal. */ - detach : function detach(){ + detach : function(){ return this._signal.remove(this.listener); }, /** * Remove binding from signal and destroy any reference to external Objects (destroy SignalBinding object). */ - dispose : function dispose(){ + dispose : function(){ this.detach(); //remove reference to all objects delete this._signal; @@ -278,7 +278,7 @@ * Disable SignalBinding, block listener execution. Listener will only be executed after calling `enable()`. * @see signals.SignalBinding.enable() */ - disable : function disable(){ + disable : function(){ this._isEnabled = false; }, @@ -286,28 +286,28 @@ * Enable SignalBinding. Enable listener execution. * @see signals.SignalBinding.disable() */ - enable : function enable(){ + enable : function(){ this._isEnabled = true; }, /** * @return {boolean} If SignalBinding is currently paused and won't execute listener during dispatch. */ - isEnabled : function isEnabled(){ + isEnabled : function(){ return this._isEnabled; }, /** * @return {boolean} If SignalBinding will only be executed once. */ - isOnce : function isOnce(){ + isOnce : function(){ return this._isOnce; }, /** * @return {string} String representation of the object. */ - toString : function toString(){ + toString : function(){ return '[SignalBinding listener: '+ this.listener +', isOnce: '+ this._isOnce +', isEnabled: '+ this._isEnabled +', listenerScope: '+ this.listenerScope +']'; } diff --git a/dist/js-signals.min.js b/dist/js-signals.min.js index 0f4b14f..9035039 100644 --- a/dist/js-signals.min.js +++ b/dist/js-signals.min.js @@ -3,6 +3,6 @@ * Released under the MIT license (http://www.opensource.org/licenses/mit-license.php) * @author Miller Medeiros * @version 0.4 - * @build 64 11/27/2010 04:19 PM + * @build 65 12/01/2010 10:22 PM */ -(function(){var n=window.signals={};n.Signal=function(){this._bindings=[]};n.Signal.prototype={_shouldPropagate:true,_isEnabled:true,_registerListener:function f(x,w,v){var u=this._indexOfListener(x),y;if(u!==-1){y=this._bindings[u];if(y.isOnce()!==w){throw new Error("You cannot "+(w?"add()":"addOnce()")+" then "+(!w?"add()":"addOnce()")+" the same listener without removing the relationship first.")}}else{y=new n.SignalBinding(x,w,v,this);this._addBinding(y)}return y},_addBinding:function c(u){this._bindings.push(u)},_indexOfListener:function i(u){var v=this._bindings.length;while(v--){if(this._bindings[v].listener===u){return v}}return -1},add:function j(v,u){return this._registerListener(v,false,u)},addOnce:function m(v,u){return this._registerListener(v,true,u)},remove:function t(v){var u=this._indexOfListener(v);if(u!==-1){this._bindings.splice(u,1)}return v},removeAll:function a(){this._bindings.length=0},getNumListeners:function k(){return this._bindings.length},disable:function b(){this._isEnabled=false},enable:function h(){this._isEnabled=true},isEnabled:function o(){return this._isEnabled},halt:function g(){this._shouldPropagate=false},dispatch:function s(x){if(!this._isEnabled){return}var u=Array.prototype.slice.call(arguments),y=this._bindings.slice(),v=0,w;this._shouldPropagate=true;while(w=y[v++]){if(w.execute(u)===false||!this._shouldPropagate){break}}},toString:function l(){return"[Signal isEnabled: "+this._isEnabled+" numListeners: "+this.getNumListeners()+"]"}};n.SignalBinding=function e(x,v,u,w){this.listener=x;this._isOnce=v;this.listenerScope=u;this._signal=w};n.SignalBinding.prototype={_isEnabled:true,execute:function d(u){if(this._isEnabled){if(this._isOnce){this.detach()}return this.listener.apply(this.listenerScope,u)}},detach:function q(){return this._signal.remove(this.listener)},dispose:function p(){this.detach();delete this._signal;delete this.listener;delete this.listenerScope},disable:function b(){this._isEnabled=false},enable:function h(){this._isEnabled=true},isEnabled:function o(){return this._isEnabled},isOnce:function r(){return this._isOnce},toString:function l(){return"[SignalBinding listener: "+this.listener+", isOnce: "+this._isOnce+", isEnabled: "+this._isEnabled+", listenerScope: "+this.listenerScope+"]"}}}()); \ No newline at end of file +(function(){var a=window.signals={};a.Signal=function(){this._bindings=[]};a.Signal.prototype={_shouldPropagate:true,_isEnabled:true,_registerListener:function(f,e,d){var c=this._indexOfListener(f),g;if(c!==-1){g=this._bindings[c];if(g.isOnce()!==e){throw new Error("You cannot "+(e?"add()":"addOnce()")+" then "+(!e?"add()":"addOnce()")+" the same listener without removing the relationship first.")}}else{g=new a.SignalBinding(f,e,d,this);this._addBinding(g)}return g},_addBinding:function(c){this._bindings.push(c)},_indexOfListener:function(c){var d=this._bindings.length;while(d--){if(this._bindings[d].listener===c){return d}}return -1},add:function(d,c){return this._registerListener(d,false,c)},addOnce:function(d,c){return this._registerListener(d,true,c)},remove:function(d){var c=this._indexOfListener(d);if(c!==-1){this._bindings.splice(c,1)}return d},removeAll:function(){this._bindings.length=0},getNumListeners:function(){return this._bindings.length},disable:function(){this._isEnabled=false},enable:function(){this._isEnabled=true},isEnabled:function(){return this._isEnabled},halt:function(){this._shouldPropagate=false},dispatch:function(f){if(!this._isEnabled){return}var c=Array.prototype.slice.call(arguments),g=this._bindings.slice(),d=0,e;this._shouldPropagate=true;while(e=g[d++]){if(e.execute(c)===false||!this._shouldPropagate){break}}},toString:function(){return"[Signal isEnabled: "+this._isEnabled+" numListeners: "+this.getNumListeners()+"]"}};a.SignalBinding=function b(f,d,c,e){this.listener=f;this._isOnce=d;this.listenerScope=c;this._signal=e};a.SignalBinding.prototype={_isEnabled:true,execute:function(c){if(this._isEnabled){if(this._isOnce){this.detach()}return this.listener.apply(this.listenerScope,c)}},detach:function(){return this._signal.remove(this.listener)},dispose:function(){this.detach();delete this._signal;delete this.listener;delete this.listenerScope},disable:function(){this._isEnabled=false},enable:function(){this._isEnabled=true},isEnabled:function(){return this._isEnabled},isOnce:function(){return this._isOnce},toString:function(){return"[SignalBinding listener: "+this.listener+", isOnce: "+this._isOnce+", isEnabled: "+this._isEnabled+", listenerScope: "+this.listenerScope+"]"}}}()); \ No newline at end of file From af477d9c0b29c9c0cb8da25590a0cf7852e51853 Mon Sep 17 00:00:00 2001 From: Miller Medeiros Date: Wed, 1 Dec 2010 22:32:47 -0500 Subject: [PATCH 02/10] changed SignalBinding.listener to private --- dev/build/build.number | 4 ++-- dev/src/Signal.js | 2 +- dev/src/SignalBinding.js | 26 +++++++++++++++++--------- dist/js-signals.js | 30 +++++++++++++++++++----------- dist/js-signals.min.js | 4 ++-- 5 files changed, 41 insertions(+), 25 deletions(-) diff --git a/dev/build/build.number b/dev/build/build.number index 725705b..574e944 100644 --- a/dev/build/build.number +++ b/dev/build/build.number @@ -1,3 +1,3 @@ #Build Number for ANT. Do not edit! -#Wed Dec 01 22:22:08 EST 2010 -build.number=66 +#Wed Dec 01 22:31:55 EST 2010 +build.number=69 diff --git a/dev/src/Signal.js b/dev/src/Signal.js index ade358f..f65a89a 100644 --- a/dev/src/Signal.js +++ b/dev/src/Signal.js @@ -67,7 +67,7 @@ _indexOfListener : function(listener){ var n = this._bindings.length; while(n--){ - if(this._bindings[n].listener === listener) return n; + if(this._bindings[n]._listener === listener) return n; } return -1; }, diff --git a/dev/src/SignalBinding.js b/dev/src/SignalBinding.js index e41f7c7..9db858b 100644 --- a/dev/src/SignalBinding.js +++ b/dev/src/SignalBinding.js @@ -5,18 +5,19 @@ *
- inspired by Joa Ebert AS3 SignalBinding and Robert Penner's Slot classes. * @author Miller Medeiros * @constructor - * @param {Function} listener Handler function binded to the signal. + * @param {Function} listener Handler function bound to the signal. * @param {boolean} isOnce If binding should be executed just once. * @param {Object} listenerScope Context on which listener will be executed (object that should represent the `this` variable inside listener function). - * @param {signals.Signal} signal Reference to Signal object that listener is currently binded to. + * @param {signals.Signal} signal Reference to Signal object that listener is currently bound to. */ signals.SignalBinding = function SignalBinding(listener, isOnce, listenerScope, signal){ /** - * Handler function binded to the signal. + * Handler function bound to the signal. * @type Function + * @private */ - this.listener = listener; + this._listener = listener; /** * If binding should be executed just once. @@ -32,7 +33,7 @@ this.listenerScope = listenerScope; /** - * Reference to Signal object that listener is currently binded to. + * Reference to Signal object that listener is currently bound to. * @type signals.Signal * @private */ @@ -57,17 +58,24 @@ execute : function(paramsArr){ if(this._isEnabled){ if(this._isOnce) this.detach(); - return this.listener.apply(this.listenerScope, paramsArr); + return this._listener.apply(this.listenerScope, paramsArr); } }, /** * Detach binding from signal. - * - alias to: mySignal.remove(myBinding.listener); - * @return {Function} Handler function binded to the signal. + * - alias to: mySignal.remove(myBinding.getListener()); + * @return {Function} Handler function bound to the signal. */ detach : function(){ - return this._signal.remove(this.listener); + return this._signal.remove(this._listener); + }, + + /** + * @return {Function} Handler function bound to the signal. + */ + getListener : function(){ + return this._listener; }, /** diff --git a/dist/js-signals.js b/dist/js-signals.js index 5270253..5c145ed 100644 --- a/dist/js-signals.js +++ b/dist/js-signals.js @@ -3,7 +3,7 @@ * Released under the MIT license (http://www.opensource.org/licenses/mit-license.php) * @author Miller Medeiros * @version 0.4 - * @build 65 12/01/2010 10:22 PM + * @build 68 12/01/2010 10:31 PM */ (function(){ @@ -81,7 +81,7 @@ _indexOfListener : function(listener){ var n = this._bindings.length; while(n--){ - if(this._bindings[n].listener === listener) return n; + if(this._bindings[n]._listener === listener) return n; } return -1; }, @@ -198,18 +198,19 @@ *
- inspired by Joa Ebert AS3 SignalBinding and Robert Penner's Slot classes. * @author Miller Medeiros * @constructor - * @param {Function} listener Handler function binded to the signal. + * @param {Function} listener Handler function bound to the signal. * @param {boolean} isOnce If binding should be executed just once. * @param {Object} listenerScope Context on which listener will be executed (object that should represent the `this` variable inside listener function). - * @param {signals.Signal} signal Reference to Signal object that listener is currently binded to. + * @param {signals.Signal} signal Reference to Signal object that listener is currently bound to. */ signals.SignalBinding = function SignalBinding(listener, isOnce, listenerScope, signal){ /** - * Handler function binded to the signal. + * Handler function bound to the signal. * @type Function + * @private */ - this.listener = listener; + this._listener = listener; /** * If binding should be executed just once. @@ -225,7 +226,7 @@ this.listenerScope = listenerScope; /** - * Reference to Signal object that listener is currently binded to. + * Reference to Signal object that listener is currently bound to. * @type signals.Signal * @private */ @@ -250,17 +251,24 @@ execute : function(paramsArr){ if(this._isEnabled){ if(this._isOnce) this.detach(); - return this.listener.apply(this.listenerScope, paramsArr); + return this._listener.apply(this.listenerScope, paramsArr); } }, /** * Detach binding from signal. - * - alias to: mySignal.remove(myBinding.listener); - * @return {Function} Handler function binded to the signal. + * - alias to: mySignal.remove(myBinding.getListener()); + * @return {Function} Handler function bound to the signal. */ detach : function(){ - return this._signal.remove(this.listener); + return this._signal.remove(this._listener); + }, + + /** + * @return {Function} Handler function bound to the signal. + */ + getListener : function(){ + return this._listener; }, /** diff --git a/dist/js-signals.min.js b/dist/js-signals.min.js index 9035039..e8b1c24 100644 --- a/dist/js-signals.min.js +++ b/dist/js-signals.min.js @@ -3,6 +3,6 @@ * Released under the MIT license (http://www.opensource.org/licenses/mit-license.php) * @author Miller Medeiros * @version 0.4 - * @build 65 12/01/2010 10:22 PM + * @build 68 12/01/2010 10:31 PM */ -(function(){var a=window.signals={};a.Signal=function(){this._bindings=[]};a.Signal.prototype={_shouldPropagate:true,_isEnabled:true,_registerListener:function(f,e,d){var c=this._indexOfListener(f),g;if(c!==-1){g=this._bindings[c];if(g.isOnce()!==e){throw new Error("You cannot "+(e?"add()":"addOnce()")+" then "+(!e?"add()":"addOnce()")+" the same listener without removing the relationship first.")}}else{g=new a.SignalBinding(f,e,d,this);this._addBinding(g)}return g},_addBinding:function(c){this._bindings.push(c)},_indexOfListener:function(c){var d=this._bindings.length;while(d--){if(this._bindings[d].listener===c){return d}}return -1},add:function(d,c){return this._registerListener(d,false,c)},addOnce:function(d,c){return this._registerListener(d,true,c)},remove:function(d){var c=this._indexOfListener(d);if(c!==-1){this._bindings.splice(c,1)}return d},removeAll:function(){this._bindings.length=0},getNumListeners:function(){return this._bindings.length},disable:function(){this._isEnabled=false},enable:function(){this._isEnabled=true},isEnabled:function(){return this._isEnabled},halt:function(){this._shouldPropagate=false},dispatch:function(f){if(!this._isEnabled){return}var c=Array.prototype.slice.call(arguments),g=this._bindings.slice(),d=0,e;this._shouldPropagate=true;while(e=g[d++]){if(e.execute(c)===false||!this._shouldPropagate){break}}},toString:function(){return"[Signal isEnabled: "+this._isEnabled+" numListeners: "+this.getNumListeners()+"]"}};a.SignalBinding=function b(f,d,c,e){this.listener=f;this._isOnce=d;this.listenerScope=c;this._signal=e};a.SignalBinding.prototype={_isEnabled:true,execute:function(c){if(this._isEnabled){if(this._isOnce){this.detach()}return this.listener.apply(this.listenerScope,c)}},detach:function(){return this._signal.remove(this.listener)},dispose:function(){this.detach();delete this._signal;delete this.listener;delete this.listenerScope},disable:function(){this._isEnabled=false},enable:function(){this._isEnabled=true},isEnabled:function(){return this._isEnabled},isOnce:function(){return this._isOnce},toString:function(){return"[SignalBinding listener: "+this.listener+", isOnce: "+this._isOnce+", isEnabled: "+this._isEnabled+", listenerScope: "+this.listenerScope+"]"}}}()); \ No newline at end of file +(function(){var a=window.signals={};a.Signal=function(){this._bindings=[]};a.Signal.prototype={_shouldPropagate:true,_isEnabled:true,_registerListener:function(f,e,d){var c=this._indexOfListener(f),g;if(c!==-1){g=this._bindings[c];if(g.isOnce()!==e){throw new Error("You cannot "+(e?"add()":"addOnce()")+" then "+(!e?"add()":"addOnce()")+" the same listener without removing the relationship first.")}}else{g=new a.SignalBinding(f,e,d,this);this._addBinding(g)}return g},_addBinding:function(c){this._bindings.push(c)},_indexOfListener:function(c){var d=this._bindings.length;while(d--){if(this._bindings[d]._listener===c){return d}}return -1},add:function(d,c){return this._registerListener(d,false,c)},addOnce:function(d,c){return this._registerListener(d,true,c)},remove:function(d){var c=this._indexOfListener(d);if(c!==-1){this._bindings.splice(c,1)}return d},removeAll:function(){this._bindings.length=0},getNumListeners:function(){return this._bindings.length},disable:function(){this._isEnabled=false},enable:function(){this._isEnabled=true},isEnabled:function(){return this._isEnabled},halt:function(){this._shouldPropagate=false},dispatch:function(f){if(!this._isEnabled){return}var c=Array.prototype.slice.call(arguments),g=this._bindings.slice(),d=0,e;this._shouldPropagate=true;while(e=g[d++]){if(e.execute(c)===false||!this._shouldPropagate){break}}},toString:function(){return"[Signal isEnabled: "+this._isEnabled+" numListeners: "+this.getNumListeners()+"]"}};a.SignalBinding=function b(f,d,c,e){this._listener=f;this._isOnce=d;this.listenerScope=c;this._signal=e};a.SignalBinding.prototype={_isEnabled:true,execute:function(c){if(this._isEnabled){if(this._isOnce){this.detach()}return this._listener.apply(this.listenerScope,c)}},detach:function(){return this._signal.remove(this._listener)},getListener:function(){return this._listener},dispose:function(){this.detach();delete this._signal;delete this.listener;delete this.listenerScope},disable:function(){this._isEnabled=false},enable:function(){this._isEnabled=true},isEnabled:function(){return this._isEnabled},isOnce:function(){return this._isOnce},toString:function(){return"[SignalBinding listener: "+this.listener+", isOnce: "+this._isOnce+", isEnabled: "+this._isEnabled+", listenerScope: "+this.listenerScope+"]"}}}()); \ No newline at end of file From 5bde61e229280d029fbaf5e81e37acab2efda1de Mon Sep 17 00:00:00 2001 From: Miller Medeiros Date: Wed, 1 Dec 2010 22:52:58 -0500 Subject: [PATCH 03/10] changed listenerScope to context and added unit test for it --- dev/build/build.number | 4 ++-- dev/src/SignalBinding.js | 4 ++-- dev/tests/src/01.js | 45 +++++++++++++++++++++++++++++++++++++++- dist/js-signals.js | 6 +++--- dist/js-signals.min.js | 4 ++-- 5 files changed, 53 insertions(+), 10 deletions(-) diff --git a/dev/build/build.number b/dev/build/build.number index 574e944..1cd2b05 100644 --- a/dev/build/build.number +++ b/dev/build/build.number @@ -1,3 +1,3 @@ #Build Number for ANT. Do not edit! -#Wed Dec 01 22:31:55 EST 2010 -build.number=69 +#Wed Dec 01 22:41:26 EST 2010 +build.number=70 diff --git a/dev/src/SignalBinding.js b/dev/src/SignalBinding.js index 9db858b..5227b95 100644 --- a/dev/src/SignalBinding.js +++ b/dev/src/SignalBinding.js @@ -30,7 +30,7 @@ * Context on which listener will be executed (object that should represent the `this` variable inside listener function). * @type Object */ - this.listenerScope = listenerScope; + this.context = listenerScope; /** * Reference to Signal object that listener is currently bound to. @@ -58,7 +58,7 @@ execute : function(paramsArr){ if(this._isEnabled){ if(this._isOnce) this.detach(); - return this._listener.apply(this.listenerScope, paramsArr); + return this._listener.apply(this.context, paramsArr); } }, diff --git a/dev/tests/src/01.js b/dev/tests/src/01.js index d0bb623..32ea7e7 100644 --- a/dev/tests/src/01.js +++ b/dev/tests/src/01.js @@ -827,6 +827,49 @@ YUI().use('node', 'console', 'test', function (Y){ s.dispatch(); }, + testBindingGetListener : function(){ + var s = this.signal; + var l1 = function(){}; + var b1 = s.add(l1); + Y.Assert.isUndefined(b1.listener); //make sure it's private + Y.Assert.areSame(1, s.getNumListeners()); + Y.Assert.areSame(l1, b1.getListener()); + }, + + testBindingContext : function(){ + var s = this.signal; + + var scope1 = { + n : 0, + sum : function(){ + this.n++; + } + }; + + var scope2 = { + n : 0, + sum : function(){ + this.n++; + } + }; + + var l1 = function(){this.sum()}; + var l2 = function(){this.sum()}; + + var b1 = s.add(l1, scope1); + var b2 = s.add(l2, scope2); + s.dispatch(); + + Y.Assert.areSame(1, scope1.n); + Y.Assert.areSame(1, scope2.n); + + b1.context = scope2; + s.dispatch(); + + Y.Assert.areSame(1, scope1.n); + Y.Assert.areSame(3, scope2.n); + }, + testBindingDispose : function(){ var s = this.signal; var b1 = s.add(function(){}); @@ -834,7 +877,7 @@ YUI().use('node', 'console', 'test', function (Y){ b1.dispose(); Y.Assert.areSame(0, s.getNumListeners()); Y.Assert.isUndefined(b1.listener); - Y.Assert.isUndefined(b1.listenerScope); + Y.Assert.isUndefined(b1.context); }, diff --git a/dist/js-signals.js b/dist/js-signals.js index 5c145ed..da49e02 100644 --- a/dist/js-signals.js +++ b/dist/js-signals.js @@ -3,7 +3,7 @@ * Released under the MIT license (http://www.opensource.org/licenses/mit-license.php) * @author Miller Medeiros * @version 0.4 - * @build 68 12/01/2010 10:31 PM + * @build 69 12/01/2010 10:41 PM */ (function(){ @@ -223,7 +223,7 @@ * Context on which listener will be executed (object that should represent the `this` variable inside listener function). * @type Object */ - this.listenerScope = listenerScope; + this.context = listenerScope; /** * Reference to Signal object that listener is currently bound to. @@ -251,7 +251,7 @@ execute : function(paramsArr){ if(this._isEnabled){ if(this._isOnce) this.detach(); - return this._listener.apply(this.listenerScope, paramsArr); + return this._listener.apply(this.context, paramsArr); } }, diff --git a/dist/js-signals.min.js b/dist/js-signals.min.js index e8b1c24..e966a6e 100644 --- a/dist/js-signals.min.js +++ b/dist/js-signals.min.js @@ -3,6 +3,6 @@ * Released under the MIT license (http://www.opensource.org/licenses/mit-license.php) * @author Miller Medeiros * @version 0.4 - * @build 68 12/01/2010 10:31 PM + * @build 69 12/01/2010 10:41 PM */ -(function(){var a=window.signals={};a.Signal=function(){this._bindings=[]};a.Signal.prototype={_shouldPropagate:true,_isEnabled:true,_registerListener:function(f,e,d){var c=this._indexOfListener(f),g;if(c!==-1){g=this._bindings[c];if(g.isOnce()!==e){throw new Error("You cannot "+(e?"add()":"addOnce()")+" then "+(!e?"add()":"addOnce()")+" the same listener without removing the relationship first.")}}else{g=new a.SignalBinding(f,e,d,this);this._addBinding(g)}return g},_addBinding:function(c){this._bindings.push(c)},_indexOfListener:function(c){var d=this._bindings.length;while(d--){if(this._bindings[d]._listener===c){return d}}return -1},add:function(d,c){return this._registerListener(d,false,c)},addOnce:function(d,c){return this._registerListener(d,true,c)},remove:function(d){var c=this._indexOfListener(d);if(c!==-1){this._bindings.splice(c,1)}return d},removeAll:function(){this._bindings.length=0},getNumListeners:function(){return this._bindings.length},disable:function(){this._isEnabled=false},enable:function(){this._isEnabled=true},isEnabled:function(){return this._isEnabled},halt:function(){this._shouldPropagate=false},dispatch:function(f){if(!this._isEnabled){return}var c=Array.prototype.slice.call(arguments),g=this._bindings.slice(),d=0,e;this._shouldPropagate=true;while(e=g[d++]){if(e.execute(c)===false||!this._shouldPropagate){break}}},toString:function(){return"[Signal isEnabled: "+this._isEnabled+" numListeners: "+this.getNumListeners()+"]"}};a.SignalBinding=function b(f,d,c,e){this._listener=f;this._isOnce=d;this.listenerScope=c;this._signal=e};a.SignalBinding.prototype={_isEnabled:true,execute:function(c){if(this._isEnabled){if(this._isOnce){this.detach()}return this._listener.apply(this.listenerScope,c)}},detach:function(){return this._signal.remove(this._listener)},getListener:function(){return this._listener},dispose:function(){this.detach();delete this._signal;delete this.listener;delete this.listenerScope},disable:function(){this._isEnabled=false},enable:function(){this._isEnabled=true},isEnabled:function(){return this._isEnabled},isOnce:function(){return this._isOnce},toString:function(){return"[SignalBinding listener: "+this.listener+", isOnce: "+this._isOnce+", isEnabled: "+this._isEnabled+", listenerScope: "+this.listenerScope+"]"}}}()); \ No newline at end of file +(function(){var a=window.signals={};a.Signal=function(){this._bindings=[]};a.Signal.prototype={_shouldPropagate:true,_isEnabled:true,_registerListener:function(f,e,d){var c=this._indexOfListener(f),g;if(c!==-1){g=this._bindings[c];if(g.isOnce()!==e){throw new Error("You cannot "+(e?"add()":"addOnce()")+" then "+(!e?"add()":"addOnce()")+" the same listener without removing the relationship first.")}}else{g=new a.SignalBinding(f,e,d,this);this._addBinding(g)}return g},_addBinding:function(c){this._bindings.push(c)},_indexOfListener:function(c){var d=this._bindings.length;while(d--){if(this._bindings[d]._listener===c){return d}}return -1},add:function(d,c){return this._registerListener(d,false,c)},addOnce:function(d,c){return this._registerListener(d,true,c)},remove:function(d){var c=this._indexOfListener(d);if(c!==-1){this._bindings.splice(c,1)}return d},removeAll:function(){this._bindings.length=0},getNumListeners:function(){return this._bindings.length},disable:function(){this._isEnabled=false},enable:function(){this._isEnabled=true},isEnabled:function(){return this._isEnabled},halt:function(){this._shouldPropagate=false},dispatch:function(f){if(!this._isEnabled){return}var c=Array.prototype.slice.call(arguments),g=this._bindings.slice(),d=0,e;this._shouldPropagate=true;while(e=g[d++]){if(e.execute(c)===false||!this._shouldPropagate){break}}},toString:function(){return"[Signal isEnabled: "+this._isEnabled+" numListeners: "+this.getNumListeners()+"]"}};a.SignalBinding=function b(f,d,c,e){this._listener=f;this._isOnce=d;this.context=c;this._signal=e};a.SignalBinding.prototype={_isEnabled:true,execute:function(c){if(this._isEnabled){if(this._isOnce){this.detach()}return this._listener.apply(this.context,c)}},detach:function(){return this._signal.remove(this._listener)},getListener:function(){return this._listener},dispose:function(){this.detach();delete this._signal;delete this.listener;delete this.listenerScope},disable:function(){this._isEnabled=false},enable:function(){this._isEnabled=true},isEnabled:function(){return this._isEnabled},isOnce:function(){return this._isOnce},toString:function(){return"[SignalBinding listener: "+this.listener+", isOnce: "+this._isOnce+", isEnabled: "+this._isEnabled+", listenerScope: "+this.listenerScope+"]"}}}()); \ No newline at end of file From 6f1f17004d17b4f3ca0fac5da55e88f7e5e876b3 Mon Sep 17 00:00:00 2001 From: Miller Medeiros Date: Wed, 1 Dec 2010 23:53:54 -0500 Subject: [PATCH 04/10] fixed/improved SignalBinding.dispose --- dev/build/build.number | 4 ++-- dev/src/SignalBinding.js | 14 +++++++++++--- dev/tests/src/01.js | 4 +++- dist/js-signals.js | 16 ++++++++++++---- dist/js-signals.min.js | 4 ++-- 5 files changed, 30 insertions(+), 12 deletions(-) diff --git a/dev/build/build.number b/dev/build/build.number index 1cd2b05..11114ec 100644 --- a/dev/build/build.number +++ b/dev/build/build.number @@ -1,3 +1,3 @@ #Build Number for ANT. Do not edit! -#Wed Dec 01 22:41:26 EST 2010 -build.number=70 +#Wed Dec 01 23:53:23 EST 2010 +build.number=74 diff --git a/dev/src/SignalBinding.js b/dev/src/SignalBinding.js index 5227b95..1bebeb4 100644 --- a/dev/src/SignalBinding.js +++ b/dev/src/SignalBinding.js @@ -83,10 +83,18 @@ */ dispose : function(){ this.detach(); - //remove reference to all objects + this._destroy(); + }, + + /** + * Delete all instance properties + * @private + */ + _destroy : function(){ delete this._signal; - delete this.listener; - delete this.listenerScope; + delete this._isOnce; + delete this._listener; + delete this.context; }, /** diff --git a/dev/tests/src/01.js b/dev/tests/src/01.js index 32ea7e7..3cff7f5 100644 --- a/dev/tests/src/01.js +++ b/dev/tests/src/01.js @@ -872,11 +872,13 @@ YUI().use('node', 'console', 'test', function (Y){ testBindingDispose : function(){ var s = this.signal; - var b1 = s.add(function(){}); + var b1 = s.add(function(){}, {}); Y.Assert.areSame(1, s.getNumListeners()); b1.dispose(); Y.Assert.areSame(0, s.getNumListeners()); Y.Assert.isUndefined(b1.listener); + Y.Assert.isUndefined(b1.getListener()); + //Y.Assert.isUndefined(b1.isEnabled()); Y.Assert.isUndefined(b1.context); }, diff --git a/dist/js-signals.js b/dist/js-signals.js index da49e02..c98d1f7 100644 --- a/dist/js-signals.js +++ b/dist/js-signals.js @@ -3,7 +3,7 @@ * Released under the MIT license (http://www.opensource.org/licenses/mit-license.php) * @author Miller Medeiros * @version 0.4 - * @build 69 12/01/2010 10:41 PM + * @build 73 12/01/2010 11:53 PM */ (function(){ @@ -276,10 +276,18 @@ */ dispose : function(){ this.detach(); - //remove reference to all objects + this._destroy(); + }, + + /** + * Delete all instance properties + * @private + */ + _destroy : function(){ delete this._signal; - delete this.listener; - delete this.listenerScope; + delete this._isOnce; + delete this._listener; + delete this.context; }, /** diff --git a/dist/js-signals.min.js b/dist/js-signals.min.js index e966a6e..978d502 100644 --- a/dist/js-signals.min.js +++ b/dist/js-signals.min.js @@ -3,6 +3,6 @@ * Released under the MIT license (http://www.opensource.org/licenses/mit-license.php) * @author Miller Medeiros * @version 0.4 - * @build 69 12/01/2010 10:41 PM + * @build 73 12/01/2010 11:53 PM */ -(function(){var a=window.signals={};a.Signal=function(){this._bindings=[]};a.Signal.prototype={_shouldPropagate:true,_isEnabled:true,_registerListener:function(f,e,d){var c=this._indexOfListener(f),g;if(c!==-1){g=this._bindings[c];if(g.isOnce()!==e){throw new Error("You cannot "+(e?"add()":"addOnce()")+" then "+(!e?"add()":"addOnce()")+" the same listener without removing the relationship first.")}}else{g=new a.SignalBinding(f,e,d,this);this._addBinding(g)}return g},_addBinding:function(c){this._bindings.push(c)},_indexOfListener:function(c){var d=this._bindings.length;while(d--){if(this._bindings[d]._listener===c){return d}}return -1},add:function(d,c){return this._registerListener(d,false,c)},addOnce:function(d,c){return this._registerListener(d,true,c)},remove:function(d){var c=this._indexOfListener(d);if(c!==-1){this._bindings.splice(c,1)}return d},removeAll:function(){this._bindings.length=0},getNumListeners:function(){return this._bindings.length},disable:function(){this._isEnabled=false},enable:function(){this._isEnabled=true},isEnabled:function(){return this._isEnabled},halt:function(){this._shouldPropagate=false},dispatch:function(f){if(!this._isEnabled){return}var c=Array.prototype.slice.call(arguments),g=this._bindings.slice(),d=0,e;this._shouldPropagate=true;while(e=g[d++]){if(e.execute(c)===false||!this._shouldPropagate){break}}},toString:function(){return"[Signal isEnabled: "+this._isEnabled+" numListeners: "+this.getNumListeners()+"]"}};a.SignalBinding=function b(f,d,c,e){this._listener=f;this._isOnce=d;this.context=c;this._signal=e};a.SignalBinding.prototype={_isEnabled:true,execute:function(c){if(this._isEnabled){if(this._isOnce){this.detach()}return this._listener.apply(this.context,c)}},detach:function(){return this._signal.remove(this._listener)},getListener:function(){return this._listener},dispose:function(){this.detach();delete this._signal;delete this.listener;delete this.listenerScope},disable:function(){this._isEnabled=false},enable:function(){this._isEnabled=true},isEnabled:function(){return this._isEnabled},isOnce:function(){return this._isOnce},toString:function(){return"[SignalBinding listener: "+this.listener+", isOnce: "+this._isOnce+", isEnabled: "+this._isEnabled+", listenerScope: "+this.listenerScope+"]"}}}()); \ No newline at end of file +(function(){var a=window.signals={};a.Signal=function(){this._bindings=[]};a.Signal.prototype={_shouldPropagate:true,_isEnabled:true,_registerListener:function(f,e,d){var c=this._indexOfListener(f),g;if(c!==-1){g=this._bindings[c];if(g.isOnce()!==e){throw new Error("You cannot "+(e?"add()":"addOnce()")+" then "+(!e?"add()":"addOnce()")+" the same listener without removing the relationship first.")}}else{g=new a.SignalBinding(f,e,d,this);this._addBinding(g)}return g},_addBinding:function(c){this._bindings.push(c)},_indexOfListener:function(c){var d=this._bindings.length;while(d--){if(this._bindings[d]._listener===c){return d}}return -1},add:function(d,c){return this._registerListener(d,false,c)},addOnce:function(d,c){return this._registerListener(d,true,c)},remove:function(d){var c=this._indexOfListener(d);if(c!==-1){this._bindings.splice(c,1)}return d},removeAll:function(){this._bindings.length=0},getNumListeners:function(){return this._bindings.length},disable:function(){this._isEnabled=false},enable:function(){this._isEnabled=true},isEnabled:function(){return this._isEnabled},halt:function(){this._shouldPropagate=false},dispatch:function(f){if(!this._isEnabled){return}var c=Array.prototype.slice.call(arguments),g=this._bindings.slice(),d=0,e;this._shouldPropagate=true;while(e=g[d++]){if(e.execute(c)===false||!this._shouldPropagate){break}}},toString:function(){return"[Signal isEnabled: "+this._isEnabled+" numListeners: "+this.getNumListeners()+"]"}};a.SignalBinding=function b(f,d,c,e){this._listener=f;this._isOnce=d;this.context=c;this._signal=e};a.SignalBinding.prototype={_isEnabled:true,execute:function(c){if(this._isEnabled){if(this._isOnce){this.detach()}return this._listener.apply(this.context,c)}},detach:function(){return this._signal.remove(this._listener)},getListener:function(){return this._listener},dispose:function(){this.detach();this._destroy()},_destroy:function(){delete this._signal;delete this._isOnce;delete this._listener;delete this.context},disable:function(){this._isEnabled=false},enable:function(){this._isEnabled=true},isEnabled:function(){return this._isEnabled},isOnce:function(){return this._isOnce},toString:function(){return"[SignalBinding listener: "+this.listener+", isOnce: "+this._isOnce+", isEnabled: "+this._isEnabled+", listenerScope: "+this.listenerScope+"]"}}}()); \ No newline at end of file From 8eece1fa709f2bdd82e68c9079b826702d5c7f54 Mon Sep 17 00:00:00 2001 From: Miller Medeiros Date: Thu, 2 Dec 2010 00:40:33 -0500 Subject: [PATCH 05/10] destroying bindings during remove --- dev/build/build.number | 4 +-- dev/src/Signal.js | 17 +++++++++--- dev/src/SignalBinding.js | 3 ++- dev/tests/src/01.js | 57 +++++++++++++++++++++++++++++++++++++--- dist/js-signals.js | 22 +++++++++++----- dist/js-signals.min.js | 4 +-- 6 files changed, 88 insertions(+), 19 deletions(-) diff --git a/dev/build/build.number b/dev/build/build.number index 11114ec..c875868 100644 --- a/dev/build/build.number +++ b/dev/build/build.number @@ -1,3 +1,3 @@ #Build Number for ANT. Do not edit! -#Wed Dec 01 23:53:23 EST 2010 -build.number=74 +#Thu Dec 02 00:39:44 EST 2010 +build.number=78 diff --git a/dev/src/Signal.js b/dev/src/Signal.js index f65a89a..d4eff9d 100644 --- a/dev/src/Signal.js +++ b/dev/src/Signal.js @@ -92,6 +92,14 @@ return this._registerListener(listener, true, scope); }, + /** + * @private + */ + _removeByIndex : function(i){ + this._bindings[i]._destroy(); //no reason to a SignalBinding exist if it isn't attached to a signal + this._bindings.splice(i, 1); + }, + /** * Remove a single listener from the dispatch queue. * @param {Function} listener Handler function that should be removed. @@ -99,9 +107,7 @@ */ remove : function(listener){ var i = this._indexOfListener(listener); - if(i !== -1){ - this._bindings.splice(i, 1); - } + if(i !== -1) this._removeByIndex(i); return listener; }, @@ -109,7 +115,10 @@ * Remove all listeners from the Signal. */ removeAll : function(){ - this._bindings.length = 0; + var n = this._bindings.length; + while(n--){ + this._removeByIndex(n); + } }, /** diff --git a/dev/src/SignalBinding.js b/dev/src/SignalBinding.js index 1bebeb4..f709930 100644 --- a/dev/src/SignalBinding.js +++ b/dev/src/SignalBinding.js @@ -57,8 +57,9 @@ */ execute : function(paramsArr){ if(this._isEnabled){ + var r = this._listener.apply(this.context, paramsArr); if(this._isOnce) this.detach(); - return this._listener.apply(this.context, paramsArr); + return r; } }, diff --git a/dev/tests/src/01.js b/dev/tests/src/01.js index 3cff7f5..ee060b2 100644 --- a/dev/tests/src/01.js +++ b/dev/tests/src/01.js @@ -878,7 +878,6 @@ YUI().use('node', 'console', 'test', function (Y){ Y.Assert.areSame(0, s.getNumListeners()); Y.Assert.isUndefined(b1.listener); Y.Assert.isUndefined(b1.getListener()); - //Y.Assert.isUndefined(b1.isEnabled()); Y.Assert.isUndefined(b1.context); }, @@ -888,14 +887,28 @@ YUI().use('node', 'console', 'test', function (Y){ testRemoveSingle : function(){ var s = this.signal; - var l = function(){Y.Assert.fail();}; + var l1 = function(){Y.Assert.fail();}; - s.add(l); - s.remove(l); + var b1 = s.add(l1); + s.remove(l1); Y.Assert.areSame(0, s.getNumListeners()); s.dispatch(); }, + testRemoveSingle2 : function(){ + var s = this.signal; + + var l1 = function(){Y.Assert.fail();}; + + var b1 = s.add(l1); + s.remove(l1); + Y.Assert.areSame(0, s.getNumListeners()); + Y.Assert.isUndefined(b1.listener); + Y.Assert.isUndefined(b1.getListener()); + Y.Assert.isUndefined(b1.context); + s.dispatch(); + }, + testRemoveSingleTwice : function(){ var s = this.signal; @@ -991,6 +1004,42 @@ YUI().use('node', 'console', 'test', function (Y){ s.dispatch(); }, + testRemoveAll2 : function(){ + var s = this.signal; + + var b1 = s.add(function(){Y.Assert.fail();}); + var b2 = s.add(function(){Y.Assert.fail();}); + var b3 = s.addOnce(function(){Y.Assert.fail();}); + var b4 = s.add(function(){Y.Assert.fail();}); + var b5 = s.addOnce(function(){Y.Assert.fail();}); + + Y.Assert.areSame(5, s.getNumListeners()); + s.removeAll(); + Y.Assert.areSame(0, s.getNumListeners()); + + Y.Assert.isUndefined(b1.listener); + Y.Assert.isUndefined(b1.getListener()); + Y.Assert.isUndefined(b1.context); + + Y.Assert.isUndefined(b2.listener); + Y.Assert.isUndefined(b2.getListener()); + Y.Assert.isUndefined(b2.context); + + Y.Assert.isUndefined(b3.listener); + Y.Assert.isUndefined(b3.getListener()); + Y.Assert.isUndefined(b3.context); + + Y.Assert.isUndefined(b4.listener); + Y.Assert.isUndefined(b4.getListener()); + Y.Assert.isUndefined(b4.context); + + Y.Assert.isUndefined(b5.listener); + Y.Assert.isUndefined(b5.getListener()); + Y.Assert.isUndefined(b5.context); + + s.dispatch(); + }, + testRemoveAllTwice : function(){ var s = this.signal; diff --git a/dist/js-signals.js b/dist/js-signals.js index c98d1f7..0c0bc63 100644 --- a/dist/js-signals.js +++ b/dist/js-signals.js @@ -3,7 +3,7 @@ * Released under the MIT license (http://www.opensource.org/licenses/mit-license.php) * @author Miller Medeiros * @version 0.4 - * @build 73 12/01/2010 11:53 PM + * @build 77 12/02/2010 12:39 AM */ (function(){ @@ -106,6 +106,14 @@ return this._registerListener(listener, true, scope); }, + /** + * @private + */ + _removeByIndex : function(i){ + this._bindings[i]._destroy(); //no reason to a SignalBinding exist if it isn't attached to a signal + this._bindings.splice(i, 1); + }, + /** * Remove a single listener from the dispatch queue. * @param {Function} listener Handler function that should be removed. @@ -113,9 +121,7 @@ */ remove : function(listener){ var i = this._indexOfListener(listener); - if(i !== -1){ - this._bindings.splice(i, 1); - } + if(i !== -1) this._removeByIndex(i); return listener; }, @@ -123,7 +129,10 @@ * Remove all listeners from the Signal. */ removeAll : function(){ - this._bindings.length = 0; + var n = this._bindings.length; + while(n--){ + this._removeByIndex(n); + } }, /** @@ -250,8 +259,9 @@ */ execute : function(paramsArr){ if(this._isEnabled){ + var r = this._listener.apply(this.context, paramsArr); if(this._isOnce) this.detach(); - return this._listener.apply(this.context, paramsArr); + return r; } }, diff --git a/dist/js-signals.min.js b/dist/js-signals.min.js index 978d502..1dc8266 100644 --- a/dist/js-signals.min.js +++ b/dist/js-signals.min.js @@ -3,6 +3,6 @@ * Released under the MIT license (http://www.opensource.org/licenses/mit-license.php) * @author Miller Medeiros * @version 0.4 - * @build 73 12/01/2010 11:53 PM + * @build 77 12/02/2010 12:39 AM */ -(function(){var a=window.signals={};a.Signal=function(){this._bindings=[]};a.Signal.prototype={_shouldPropagate:true,_isEnabled:true,_registerListener:function(f,e,d){var c=this._indexOfListener(f),g;if(c!==-1){g=this._bindings[c];if(g.isOnce()!==e){throw new Error("You cannot "+(e?"add()":"addOnce()")+" then "+(!e?"add()":"addOnce()")+" the same listener without removing the relationship first.")}}else{g=new a.SignalBinding(f,e,d,this);this._addBinding(g)}return g},_addBinding:function(c){this._bindings.push(c)},_indexOfListener:function(c){var d=this._bindings.length;while(d--){if(this._bindings[d]._listener===c){return d}}return -1},add:function(d,c){return this._registerListener(d,false,c)},addOnce:function(d,c){return this._registerListener(d,true,c)},remove:function(d){var c=this._indexOfListener(d);if(c!==-1){this._bindings.splice(c,1)}return d},removeAll:function(){this._bindings.length=0},getNumListeners:function(){return this._bindings.length},disable:function(){this._isEnabled=false},enable:function(){this._isEnabled=true},isEnabled:function(){return this._isEnabled},halt:function(){this._shouldPropagate=false},dispatch:function(f){if(!this._isEnabled){return}var c=Array.prototype.slice.call(arguments),g=this._bindings.slice(),d=0,e;this._shouldPropagate=true;while(e=g[d++]){if(e.execute(c)===false||!this._shouldPropagate){break}}},toString:function(){return"[Signal isEnabled: "+this._isEnabled+" numListeners: "+this.getNumListeners()+"]"}};a.SignalBinding=function b(f,d,c,e){this._listener=f;this._isOnce=d;this.context=c;this._signal=e};a.SignalBinding.prototype={_isEnabled:true,execute:function(c){if(this._isEnabled){if(this._isOnce){this.detach()}return this._listener.apply(this.context,c)}},detach:function(){return this._signal.remove(this._listener)},getListener:function(){return this._listener},dispose:function(){this.detach();this._destroy()},_destroy:function(){delete this._signal;delete this._isOnce;delete this._listener;delete this.context},disable:function(){this._isEnabled=false},enable:function(){this._isEnabled=true},isEnabled:function(){return this._isEnabled},isOnce:function(){return this._isOnce},toString:function(){return"[SignalBinding listener: "+this.listener+", isOnce: "+this._isOnce+", isEnabled: "+this._isEnabled+", listenerScope: "+this.listenerScope+"]"}}}()); \ No newline at end of file +(function(){var a=window.signals={};a.Signal=function(){this._bindings=[]};a.Signal.prototype={_shouldPropagate:true,_isEnabled:true,_registerListener:function(f,e,d){var c=this._indexOfListener(f),g;if(c!==-1){g=this._bindings[c];if(g.isOnce()!==e){throw new Error("You cannot "+(e?"add()":"addOnce()")+" then "+(!e?"add()":"addOnce()")+" the same listener without removing the relationship first.")}}else{g=new a.SignalBinding(f,e,d,this);this._addBinding(g)}return g},_addBinding:function(c){this._bindings.push(c)},_indexOfListener:function(c){var d=this._bindings.length;while(d--){if(this._bindings[d]._listener===c){return d}}return -1},add:function(d,c){return this._registerListener(d,false,c)},addOnce:function(d,c){return this._registerListener(d,true,c)},_removeByIndex:function(c){this._bindings[c]._destroy();this._bindings.splice(c,1)},remove:function(d){var c=this._indexOfListener(d);if(c!==-1){this._removeByIndex(c)}return d},removeAll:function(){var c=this._bindings.length;while(c--){this._removeByIndex(c)}},getNumListeners:function(){return this._bindings.length},disable:function(){this._isEnabled=false},enable:function(){this._isEnabled=true},isEnabled:function(){return this._isEnabled},halt:function(){this._shouldPropagate=false},dispatch:function(f){if(!this._isEnabled){return}var c=Array.prototype.slice.call(arguments),g=this._bindings.slice(),d=0,e;this._shouldPropagate=true;while(e=g[d++]){if(e.execute(c)===false||!this._shouldPropagate){break}}},toString:function(){return"[Signal isEnabled: "+this._isEnabled+" numListeners: "+this.getNumListeners()+"]"}};a.SignalBinding=function b(f,d,c,e){this._listener=f;this._isOnce=d;this.context=c;this._signal=e};a.SignalBinding.prototype={_isEnabled:true,execute:function(c){if(this._isEnabled){var d=this._listener.apply(this.context,c);if(this._isOnce){this.detach()}return d}},detach:function(){return this._signal.remove(this._listener)},getListener:function(){return this._listener},dispose:function(){this.detach();this._destroy()},_destroy:function(){delete this._signal;delete this._isOnce;delete this._listener;delete this.context},disable:function(){this._isEnabled=false},enable:function(){this._isEnabled=true},isEnabled:function(){return this._isEnabled},isOnce:function(){return this._isOnce},toString:function(){return"[SignalBinding listener: "+this.listener+", isOnce: "+this._isOnce+", isEnabled: "+this._isEnabled+", listenerScope: "+this.listenerScope+"]"}}}()); \ No newline at end of file From 635641375c40c0cb5049c5f8910bcf208bf71a9b Mon Sep 17 00:00:00 2001 From: Miller Medeiros Date: Thu, 2 Dec 2010 01:05:30 -0500 Subject: [PATCH 06/10] added Signal.dispose --- dev/build/build.number | 4 ++-- dev/src/Signal.js | 9 ++++++++ dev/src/SignalBinding.js | 1 + dev/tests/src/01.js | 50 +++++++++++++++++++++++++++++++++++++++- dist/js-signals.js | 12 +++++++++- dist/js-signals.min.js | 4 ++-- 6 files changed, 74 insertions(+), 6 deletions(-) diff --git a/dev/build/build.number b/dev/build/build.number index c875868..de77265 100644 --- a/dev/build/build.number +++ b/dev/build/build.number @@ -1,3 +1,3 @@ #Build Number for ANT. Do not edit! -#Thu Dec 02 00:39:44 EST 2010 -build.number=78 +#Thu Dec 02 01:05:14 EST 2010 +build.number=80 diff --git a/dev/src/Signal.js b/dev/src/Signal.js index d4eff9d..21d1214 100644 --- a/dev/src/Signal.js +++ b/dev/src/Signal.js @@ -178,6 +178,15 @@ } }, + /** + * Remove binding from signal and destroy any reference to external Objects (destroy Signal object). + *
- calling methods on the signal instance after calling dispose will throw errors. + */ + dispose : function(){ + this.removeAll(); + delete this._bindings; + }, + /** * @return {string} String representation of the object. */ diff --git a/dev/src/SignalBinding.js b/dev/src/SignalBinding.js index f709930..08c4573 100644 --- a/dev/src/SignalBinding.js +++ b/dev/src/SignalBinding.js @@ -81,6 +81,7 @@ /** * Remove binding from signal and destroy any reference to external Objects (destroy SignalBinding object). + *
- calling methods on the binding instance after calling dispose will throw errors. */ dispose : function(){ this.detach(); diff --git a/dev/tests/src/01.js b/dev/tests/src/01.js index ee060b2..c984fa8 100644 --- a/dev/tests/src/01.js +++ b/dev/tests/src/01.js @@ -16,7 +16,11 @@ YUI().use('node', 'console', 'test', function (Y){ ignore: {}, error : { testAddSameListenerMixed1 : true, - testAddSameListenerMixed2 : true + testAddSameListenerMixed2 : true, + testDispose1 : true, + testDispose2 : true, + testDispose3 : true, + testDispose4 : true } }, @@ -1054,6 +1058,50 @@ YUI().use('node', 'console', 'test', function (Y){ s.removeAll(); Y.Assert.areSame(0, s.getNumListeners()); s.dispatch(); + }, + + testDispose1 : function(){ + var s = this.signal; + + s.addOnce(function(){}); + s.add(function(){}); + Y.Assert.areSame(2, s.getNumListeners()); + + s.dispose(); + s.dispatch(); //will throw error + }, + + testDispose2 : function(){ + var s = this.signal; + + s.addOnce(function(){}); + s.add(function(){}); + Y.Assert.areSame(2, s.getNumListeners()); + + s.dispose(); + s.add(function(){}); //will throw error + }, + + testDispose3 : function(){ + var s = this.signal; + + s.addOnce(function(){}); + s.add(function(){}); + Y.Assert.areSame(2, s.getNumListeners()); + + s.dispose(); + s.remove(function(){}); //will throw error + }, + + testDispose4 : function(){ + var s = this.signal; + + s.addOnce(function(){}); + s.add(function(){}); + Y.Assert.areSame(2, s.getNumListeners()); + + s.dispose(); + s.getNumListeners(); //will throw error } }); diff --git a/dist/js-signals.js b/dist/js-signals.js index 0c0bc63..17c559a 100644 --- a/dist/js-signals.js +++ b/dist/js-signals.js @@ -3,7 +3,7 @@ * Released under the MIT license (http://www.opensource.org/licenses/mit-license.php) * @author Miller Medeiros * @version 0.4 - * @build 77 12/02/2010 12:39 AM + * @build 79 12/02/2010 01:05 AM */ (function(){ @@ -192,6 +192,15 @@ } }, + /** + * Remove binding from signal and destroy any reference to external Objects (destroy Signal object). + *
- calling methods on the signal instance after calling dispose will throw errors. + */ + dispose : function(){ + this.removeAll(); + delete this._bindings; + }, + /** * @return {string} String representation of the object. */ @@ -283,6 +292,7 @@ /** * Remove binding from signal and destroy any reference to external Objects (destroy SignalBinding object). + *
- calling methods on the binding instance after calling dispose will throw errors. */ dispose : function(){ this.detach(); diff --git a/dist/js-signals.min.js b/dist/js-signals.min.js index 1dc8266..f966434 100644 --- a/dist/js-signals.min.js +++ b/dist/js-signals.min.js @@ -3,6 +3,6 @@ * Released under the MIT license (http://www.opensource.org/licenses/mit-license.php) * @author Miller Medeiros * @version 0.4 - * @build 77 12/02/2010 12:39 AM + * @build 79 12/02/2010 01:05 AM */ -(function(){var a=window.signals={};a.Signal=function(){this._bindings=[]};a.Signal.prototype={_shouldPropagate:true,_isEnabled:true,_registerListener:function(f,e,d){var c=this._indexOfListener(f),g;if(c!==-1){g=this._bindings[c];if(g.isOnce()!==e){throw new Error("You cannot "+(e?"add()":"addOnce()")+" then "+(!e?"add()":"addOnce()")+" the same listener without removing the relationship first.")}}else{g=new a.SignalBinding(f,e,d,this);this._addBinding(g)}return g},_addBinding:function(c){this._bindings.push(c)},_indexOfListener:function(c){var d=this._bindings.length;while(d--){if(this._bindings[d]._listener===c){return d}}return -1},add:function(d,c){return this._registerListener(d,false,c)},addOnce:function(d,c){return this._registerListener(d,true,c)},_removeByIndex:function(c){this._bindings[c]._destroy();this._bindings.splice(c,1)},remove:function(d){var c=this._indexOfListener(d);if(c!==-1){this._removeByIndex(c)}return d},removeAll:function(){var c=this._bindings.length;while(c--){this._removeByIndex(c)}},getNumListeners:function(){return this._bindings.length},disable:function(){this._isEnabled=false},enable:function(){this._isEnabled=true},isEnabled:function(){return this._isEnabled},halt:function(){this._shouldPropagate=false},dispatch:function(f){if(!this._isEnabled){return}var c=Array.prototype.slice.call(arguments),g=this._bindings.slice(),d=0,e;this._shouldPropagate=true;while(e=g[d++]){if(e.execute(c)===false||!this._shouldPropagate){break}}},toString:function(){return"[Signal isEnabled: "+this._isEnabled+" numListeners: "+this.getNumListeners()+"]"}};a.SignalBinding=function b(f,d,c,e){this._listener=f;this._isOnce=d;this.context=c;this._signal=e};a.SignalBinding.prototype={_isEnabled:true,execute:function(c){if(this._isEnabled){var d=this._listener.apply(this.context,c);if(this._isOnce){this.detach()}return d}},detach:function(){return this._signal.remove(this._listener)},getListener:function(){return this._listener},dispose:function(){this.detach();this._destroy()},_destroy:function(){delete this._signal;delete this._isOnce;delete this._listener;delete this.context},disable:function(){this._isEnabled=false},enable:function(){this._isEnabled=true},isEnabled:function(){return this._isEnabled},isOnce:function(){return this._isOnce},toString:function(){return"[SignalBinding listener: "+this.listener+", isOnce: "+this._isOnce+", isEnabled: "+this._isEnabled+", listenerScope: "+this.listenerScope+"]"}}}()); \ No newline at end of file +(function(){var a=window.signals={};a.Signal=function(){this._bindings=[]};a.Signal.prototype={_shouldPropagate:true,_isEnabled:true,_registerListener:function(f,e,d){var c=this._indexOfListener(f),g;if(c!==-1){g=this._bindings[c];if(g.isOnce()!==e){throw new Error("You cannot "+(e?"add()":"addOnce()")+" then "+(!e?"add()":"addOnce()")+" the same listener without removing the relationship first.")}}else{g=new a.SignalBinding(f,e,d,this);this._addBinding(g)}return g},_addBinding:function(c){this._bindings.push(c)},_indexOfListener:function(c){var d=this._bindings.length;while(d--){if(this._bindings[d]._listener===c){return d}}return -1},add:function(d,c){return this._registerListener(d,false,c)},addOnce:function(d,c){return this._registerListener(d,true,c)},_removeByIndex:function(c){this._bindings[c]._destroy();this._bindings.splice(c,1)},remove:function(d){var c=this._indexOfListener(d);if(c!==-1){this._removeByIndex(c)}return d},removeAll:function(){var c=this._bindings.length;while(c--){this._removeByIndex(c)}},getNumListeners:function(){return this._bindings.length},disable:function(){this._isEnabled=false},enable:function(){this._isEnabled=true},isEnabled:function(){return this._isEnabled},halt:function(){this._shouldPropagate=false},dispatch:function(f){if(!this._isEnabled){return}var c=Array.prototype.slice.call(arguments),g=this._bindings.slice(),d=0,e;this._shouldPropagate=true;while(e=g[d++]){if(e.execute(c)===false||!this._shouldPropagate){break}}},dispose:function(){this.removeAll();delete this._bindings},toString:function(){return"[Signal isEnabled: "+this._isEnabled+" numListeners: "+this.getNumListeners()+"]"}};a.SignalBinding=function b(f,d,c,e){this._listener=f;this._isOnce=d;this.context=c;this._signal=e};a.SignalBinding.prototype={_isEnabled:true,execute:function(c){if(this._isEnabled){var d=this._listener.apply(this.context,c);if(this._isOnce){this.detach()}return d}},detach:function(){return this._signal.remove(this._listener)},getListener:function(){return this._listener},dispose:function(){this.detach();this._destroy()},_destroy:function(){delete this._signal;delete this._isOnce;delete this._listener;delete this.context},disable:function(){this._isEnabled=false},enable:function(){this._isEnabled=true},isEnabled:function(){return this._isEnabled},isOnce:function(){return this._isOnce},toString:function(){return"[SignalBinding listener: "+this.listener+", isOnce: "+this._isOnce+", isEnabled: "+this._isEnabled+", listenerScope: "+this.listenerScope+"]"}}}()); \ No newline at end of file From 5f5137ae293a960b7ecf435705fa93984cb1120a Mon Sep 17 00:00:00 2001 From: Miller Medeiros Date: Fri, 3 Dec 2010 14:35:33 -0500 Subject: [PATCH 07/10] fixed SignalBinding.toString() and some minor refactoring on SignalBinding. also created different HTMLs to unit test dev/dist/min and separated signals namespace into a new file. --- build.xml | 1 + dev/build/build.number | 4 ++-- dev/src/SignalBinding.js | 13 +++++++------ dev/src/intro.js | 8 +------- dev/src/signals.js | 6 ++++++ dev/tests/dev.html | 19 +++++++++++++++++++ dev/tests/{01.html => dist.html} | 2 +- dev/tests/dist_min.html | 17 +++++++++++++++++ dist/js-signals.js | 17 +++++++++-------- dist/js-signals.min.js | 4 ++-- 10 files changed, 65 insertions(+), 26 deletions(-) create mode 100644 dev/src/signals.js create mode 100644 dev/tests/dev.html rename dev/tests/{01.html => dist.html} (93%) create mode 100644 dev/tests/dist_min.html diff --git a/build.xml b/build.xml index 63bff4c..7de5f6b 100644 --- a/build.xml +++ b/build.xml @@ -33,6 +33,7 @@ + diff --git a/dev/build/build.number b/dev/build/build.number index de77265..0cdf3b7 100644 --- a/dev/build/build.number +++ b/dev/build/build.number @@ -1,3 +1,3 @@ #Build Number for ANT. Do not edit! -#Thu Dec 02 01:05:14 EST 2010 -build.number=80 +#Fri Dec 03 14:26:46 EST 2010 +build.number=82 diff --git a/dev/src/SignalBinding.js b/dev/src/SignalBinding.js index 08c4573..2b2b57e 100644 --- a/dev/src/SignalBinding.js +++ b/dev/src/SignalBinding.js @@ -7,10 +7,10 @@ * @constructor * @param {Function} listener Handler function bound to the signal. * @param {boolean} isOnce If binding should be executed just once. - * @param {Object} listenerScope Context on which listener will be executed (object that should represent the `this` variable inside listener function). + * @param {Object} listenerContext Context on which listener will be executed (object that should represent the `this` variable inside listener function). * @param {signals.Signal} signal Reference to Signal object that listener is currently bound to. */ - signals.SignalBinding = function SignalBinding(listener, isOnce, listenerScope, signal){ + signals.SignalBinding = function SignalBinding(listener, isOnce, listenerContext, signal){ /** * Handler function bound to the signal. @@ -30,7 +30,7 @@ * Context on which listener will be executed (object that should represent the `this` variable inside listener function). * @type Object */ - this.context = listenerScope; + this.context = listenerContext; /** * Reference to Signal object that listener is currently bound to. @@ -56,11 +56,12 @@ * @return {*} Value returned by the listener. */ execute : function(paramsArr){ + var r; if(this._isEnabled){ - var r = this._listener.apply(this.context, paramsArr); + r = this._listener.apply(this.context, paramsArr); if(this._isOnce) this.detach(); - return r; } + return r; //avoid warnings on some editors }, /** @@ -133,7 +134,7 @@ * @return {string} String representation of the object. */ toString : function(){ - return '[SignalBinding listener: '+ this.listener +', isOnce: '+ this._isOnce +', isEnabled: '+ this._isEnabled +', listenerScope: '+ this.listenerScope +']'; + return '[SignalBinding listener: '+ this._listener +', isOnce: '+ this._isOnce +', isEnabled: '+ this._isEnabled +', context: '+ this.context +']'; } }; diff --git a/dev/src/intro.js b/dev/src/intro.js index 165870c..bf7ab29 100644 --- a/dev/src/intro.js +++ b/dev/src/intro.js @@ -5,10 +5,4 @@ * @version ::VERSION_NUMBER:: * @build ::BUILD_NUMBER:: ::BUILD_DATE:: */ -(function(){ - - /** - * @namespace Signals Namespace - Custom event/messaging system based on AS3 Signals - * @name signals - */ - var signals = window.signals = {}; \ No newline at end of file +(function(){ \ No newline at end of file diff --git a/dev/src/signals.js b/dev/src/signals.js new file mode 100644 index 0000000..420baff --- /dev/null +++ b/dev/src/signals.js @@ -0,0 +1,6 @@ + + /** + * @namespace Signals Namespace - Custom event/messaging system based on AS3 Signals + * @name signals + */ + var signals = window.signals = {}; \ No newline at end of file diff --git a/dev/tests/dev.html b/dev/tests/dev.html new file mode 100644 index 0000000..c5c6757 --- /dev/null +++ b/dev/tests/dev.html @@ -0,0 +1,19 @@ + + + + + + DEV | js-signals unit test + + + +
+
+
+ + + + + + + \ No newline at end of file diff --git a/dev/tests/01.html b/dev/tests/dist.html similarity index 93% rename from dev/tests/01.html rename to dev/tests/dist.html index 217295c..2bb28e6 100644 --- a/dev/tests/01.html +++ b/dev/tests/dist.html @@ -3,7 +3,7 @@ - js-signals unit test + DIST | js-signals unit test diff --git a/dev/tests/dist_min.html b/dev/tests/dist_min.html new file mode 100644 index 0000000..9b6f4d1 --- /dev/null +++ b/dev/tests/dist_min.html @@ -0,0 +1,17 @@ + + + + + + DIST.MIN | js-signals unit test + + + +
+
+
+ + + + + \ No newline at end of file diff --git a/dist/js-signals.js b/dist/js-signals.js index 17c559a..b7e84bc 100644 --- a/dist/js-signals.js +++ b/dist/js-signals.js @@ -3,10 +3,10 @@ * Released under the MIT license (http://www.opensource.org/licenses/mit-license.php) * @author Miller Medeiros * @version 0.4 - * @build 79 12/02/2010 01:05 AM + * @build 81 12/03/2010 02:26 PM */ (function(){ - + /** * @namespace Signals Namespace - Custom event/messaging system based on AS3 Signals * @name signals @@ -218,10 +218,10 @@ * @constructor * @param {Function} listener Handler function bound to the signal. * @param {boolean} isOnce If binding should be executed just once. - * @param {Object} listenerScope Context on which listener will be executed (object that should represent the `this` variable inside listener function). + * @param {Object} listenerContext Context on which listener will be executed (object that should represent the `this` variable inside listener function). * @param {signals.Signal} signal Reference to Signal object that listener is currently bound to. */ - signals.SignalBinding = function SignalBinding(listener, isOnce, listenerScope, signal){ + signals.SignalBinding = function SignalBinding(listener, isOnce, listenerContext, signal){ /** * Handler function bound to the signal. @@ -241,7 +241,7 @@ * Context on which listener will be executed (object that should represent the `this` variable inside listener function). * @type Object */ - this.context = listenerScope; + this.context = listenerContext; /** * Reference to Signal object that listener is currently bound to. @@ -267,11 +267,12 @@ * @return {*} Value returned by the listener. */ execute : function(paramsArr){ + var r; if(this._isEnabled){ - var r = this._listener.apply(this.context, paramsArr); + r = this._listener.apply(this.context, paramsArr); if(this._isOnce) this.detach(); - return r; } + return r; }, /** @@ -344,7 +345,7 @@ * @return {string} String representation of the object. */ toString : function(){ - return '[SignalBinding listener: '+ this.listener +', isOnce: '+ this._isOnce +', isEnabled: '+ this._isEnabled +', listenerScope: '+ this.listenerScope +']'; + return '[SignalBinding listener: '+ this._listener +', isOnce: '+ this._isOnce +', isEnabled: '+ this._isEnabled +', context: '+ this.context +']'; } }; diff --git a/dist/js-signals.min.js b/dist/js-signals.min.js index f966434..f3274af 100644 --- a/dist/js-signals.min.js +++ b/dist/js-signals.min.js @@ -3,6 +3,6 @@ * Released under the MIT license (http://www.opensource.org/licenses/mit-license.php) * @author Miller Medeiros * @version 0.4 - * @build 79 12/02/2010 01:05 AM + * @build 81 12/03/2010 02:26 PM */ -(function(){var a=window.signals={};a.Signal=function(){this._bindings=[]};a.Signal.prototype={_shouldPropagate:true,_isEnabled:true,_registerListener:function(f,e,d){var c=this._indexOfListener(f),g;if(c!==-1){g=this._bindings[c];if(g.isOnce()!==e){throw new Error("You cannot "+(e?"add()":"addOnce()")+" then "+(!e?"add()":"addOnce()")+" the same listener without removing the relationship first.")}}else{g=new a.SignalBinding(f,e,d,this);this._addBinding(g)}return g},_addBinding:function(c){this._bindings.push(c)},_indexOfListener:function(c){var d=this._bindings.length;while(d--){if(this._bindings[d]._listener===c){return d}}return -1},add:function(d,c){return this._registerListener(d,false,c)},addOnce:function(d,c){return this._registerListener(d,true,c)},_removeByIndex:function(c){this._bindings[c]._destroy();this._bindings.splice(c,1)},remove:function(d){var c=this._indexOfListener(d);if(c!==-1){this._removeByIndex(c)}return d},removeAll:function(){var c=this._bindings.length;while(c--){this._removeByIndex(c)}},getNumListeners:function(){return this._bindings.length},disable:function(){this._isEnabled=false},enable:function(){this._isEnabled=true},isEnabled:function(){return this._isEnabled},halt:function(){this._shouldPropagate=false},dispatch:function(f){if(!this._isEnabled){return}var c=Array.prototype.slice.call(arguments),g=this._bindings.slice(),d=0,e;this._shouldPropagate=true;while(e=g[d++]){if(e.execute(c)===false||!this._shouldPropagate){break}}},dispose:function(){this.removeAll();delete this._bindings},toString:function(){return"[Signal isEnabled: "+this._isEnabled+" numListeners: "+this.getNumListeners()+"]"}};a.SignalBinding=function b(f,d,c,e){this._listener=f;this._isOnce=d;this.context=c;this._signal=e};a.SignalBinding.prototype={_isEnabled:true,execute:function(c){if(this._isEnabled){var d=this._listener.apply(this.context,c);if(this._isOnce){this.detach()}return d}},detach:function(){return this._signal.remove(this._listener)},getListener:function(){return this._listener},dispose:function(){this.detach();this._destroy()},_destroy:function(){delete this._signal;delete this._isOnce;delete this._listener;delete this.context},disable:function(){this._isEnabled=false},enable:function(){this._isEnabled=true},isEnabled:function(){return this._isEnabled},isOnce:function(){return this._isOnce},toString:function(){return"[SignalBinding listener: "+this.listener+", isOnce: "+this._isOnce+", isEnabled: "+this._isEnabled+", listenerScope: "+this.listenerScope+"]"}}}()); \ No newline at end of file +(function(){var a=window.signals={};a.Signal=function(){this._bindings=[]};a.Signal.prototype={_shouldPropagate:true,_isEnabled:true,_registerListener:function(f,e,d){var c=this._indexOfListener(f),g;if(c!==-1){g=this._bindings[c];if(g.isOnce()!==e){throw new Error("You cannot "+(e?"add()":"addOnce()")+" then "+(!e?"add()":"addOnce()")+" the same listener without removing the relationship first.")}}else{g=new a.SignalBinding(f,e,d,this);this._addBinding(g)}return g},_addBinding:function(c){this._bindings.push(c)},_indexOfListener:function(c){var d=this._bindings.length;while(d--){if(this._bindings[d]._listener===c){return d}}return -1},add:function(d,c){return this._registerListener(d,false,c)},addOnce:function(d,c){return this._registerListener(d,true,c)},_removeByIndex:function(c){this._bindings[c]._destroy();this._bindings.splice(c,1)},remove:function(d){var c=this._indexOfListener(d);if(c!==-1){this._removeByIndex(c)}return d},removeAll:function(){var c=this._bindings.length;while(c--){this._removeByIndex(c)}},getNumListeners:function(){return this._bindings.length},disable:function(){this._isEnabled=false},enable:function(){this._isEnabled=true},isEnabled:function(){return this._isEnabled},halt:function(){this._shouldPropagate=false},dispatch:function(f){if(!this._isEnabled){return}var c=Array.prototype.slice.call(arguments),g=this._bindings.slice(),d=0,e;this._shouldPropagate=true;while(e=g[d++]){if(e.execute(c)===false||!this._shouldPropagate){break}}},dispose:function(){this.removeAll();delete this._bindings},toString:function(){return"[Signal isEnabled: "+this._isEnabled+" numListeners: "+this.getNumListeners()+"]"}};a.SignalBinding=function b(f,c,e,d){this._listener=f;this._isOnce=c;this.context=e;this._signal=d};a.SignalBinding.prototype={_isEnabled:true,execute:function(c){var d;if(this._isEnabled){d=this._listener.apply(this.context,c);if(this._isOnce){this.detach()}}return d},detach:function(){return this._signal.remove(this._listener)},getListener:function(){return this._listener},dispose:function(){this.detach();this._destroy()},_destroy:function(){delete this._signal;delete this._isOnce;delete this._listener;delete this.context},disable:function(){this._isEnabled=false},enable:function(){this._isEnabled=true},isEnabled:function(){return this._isEnabled},isOnce:function(){return this._isOnce},toString:function(){return"[SignalBinding listener: "+this._listener+", isOnce: "+this._isOnce+", isEnabled: "+this._isEnabled+", context: "+this.context+"]"}}}()); \ No newline at end of file From 86f1ca8d6953cf67656b496f495fc5bd9188d66b Mon Sep 17 00:00:00 2001 From: Miller Medeiros Date: Fri, 3 Dec 2010 15:43:04 -0500 Subject: [PATCH 08/10] added error messages for required params and unit tests for it, also improved some comments/docs. --- dev/build/build.number | 4 ++-- dev/src/Signal.js | 17 +++++++++++------ dev/src/SignalBinding.js | 6 +++--- dev/src/signals.js | 12 +++++++++++- dev/tests/src/01.js | 36 +++++++++++++++++++++++++++++++++--- dist/js-signals.js | 39 +++++++++++++++++++++++++++------------ dist/js-signals.min.js | 4 ++-- 7 files changed, 89 insertions(+), 29 deletions(-) diff --git a/dev/build/build.number b/dev/build/build.number index 0cdf3b7..e2de90e 100644 --- a/dev/build/build.number +++ b/dev/build/build.number @@ -1,3 +1,3 @@ #Build Number for ANT. Do not edit! -#Fri Dec 03 14:26:46 EST 2010 -build.number=82 +#Fri Dec 03 15:42:22 EST 2010 +build.number=90 diff --git a/dev/src/Signal.js b/dev/src/Signal.js index 21d1214..03b69bc 100644 --- a/dev/src/Signal.js +++ b/dev/src/Signal.js @@ -6,7 +6,7 @@ */ signals.Signal = function(){ /** - * @type Array. + * @type Array. * @private */ this._bindings = []; @@ -30,18 +30,21 @@ /** * @param {Function} listener * @param {boolean} isOnce - * @param {Object} scope + * @param {Object} [scope] * @return {signals.SignalBinding} * @private */ _registerListener : function(listener, isOnce, scope){ + + if(!signals.isDef(listener)) throw new Error('listener is a required param of add() and addOnce().'); + var prevIndex = this._indexOfListener(listener), binding; if(prevIndex !== -1){ //avoid creating a new Binding for same listener if already added to list binding = this._bindings[prevIndex]; if(binding.isOnce() !== isOnce){ - throw new Error('You cannot '+ (isOnce? 'add()' : 'addOnce()') +' then '+ (!isOnce? 'add()' : 'addOnce()') +' the same listener without removing the relationship first.'); + throw new Error('You cannot add'+ (isOnce? '' : 'Once') +'() then add'+ (!isOnce? '' : 'Once') +'() the same listener without removing the relationship first.'); } } else { binding = new signals.SignalBinding(listener, isOnce, scope, this); @@ -75,7 +78,7 @@ /** * Add a listener to the signal. * @param {Function} listener Signal handler function. - * @param {Object} scope Context on which listener will be executed (object that should represent the `this` variable inside listener function). + * @param {Object} [scope] Context on which listener will be executed (object that should represent the `this` variable inside listener function). * @return {signals.SignalBinding} An Object representing the binding between the Signal and listener. */ add : function(listener, scope){ @@ -85,7 +88,7 @@ /** * Add listener to the signal that should be removed after first execution (will be executed only once). * @param {Function} listener Signal handler function. - * @param {Object} scope Context on which listener will be executed (object that should represent the `this` variable inside listener function). + * @param {Object} [scope] Context on which listener will be executed (object that should represent the `this` variable inside listener function). * @return {signals.SignalBinding} An Object representing the binding between the Signal and listener. */ addOnce : function(listener, scope){ @@ -106,6 +109,8 @@ * @return {Function} Listener handler function. */ remove : function(listener){ + if(!signals.isDef(listener)) throw new Error('listener is a required param of remove().'); + var i = this._indexOfListener(listener); if(i !== -1) this._removeByIndex(i); return listener; @@ -161,7 +166,7 @@ /** * Dispatch/Broadcast Signal to all listeners added to the queue. - * @param {...*} params Parameters that should be passed to each handler. + * @param {...*} [params] Parameters that should be passed to each handler. */ dispatch : function(params){ if(! this._isEnabled) return; diff --git a/dev/src/SignalBinding.js b/dev/src/SignalBinding.js index 2b2b57e..9159b08 100644 --- a/dev/src/SignalBinding.js +++ b/dev/src/SignalBinding.js @@ -7,7 +7,7 @@ * @constructor * @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 {?Object} listenerContext Context on which listener will be executed (object that should represent the `this` variable inside listener function). * @param {signals.Signal} signal Reference to Signal object that listener is currently bound to. */ signals.SignalBinding = function SignalBinding(listener, isOnce, listenerContext, signal){ @@ -52,7 +52,7 @@ /** * 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 + * @param {Array} [paramsArr] Array of parameters that should be passed to the listener * @return {*} Value returned by the listener. */ execute : function(paramsArr){ @@ -134,7 +134,7 @@ * @return {string} String representation of the object. */ toString : function(){ - return '[SignalBinding listener: '+ this._listener +', isOnce: '+ this._isOnce +', isEnabled: '+ this._isEnabled +', context: '+ this.context +']'; + return '[SignalBinding isOnce: '+ this._isOnce +', isEnabled: '+ this._isEnabled +']'; } }; diff --git a/dev/src/signals.js b/dev/src/signals.js index 420baff..79c2f95 100644 --- a/dev/src/signals.js +++ b/dev/src/signals.js @@ -3,4 +3,14 @@ * @namespace Signals Namespace - Custom event/messaging system based on AS3 Signals * @name signals */ - var signals = window.signals = {}; \ No newline at end of file + var signals = window.signals = { + + /** + * @param {*} param Parameter to check. + * @return {boolean} `true` if parameter is different than `undefined`. + */ + isDef : function(param){ + return typeof param !== 'undefined'; + } + + }; \ No newline at end of file diff --git a/dev/tests/src/01.js b/dev/tests/src/01.js index c984fa8..91e6b2d 100644 --- a/dev/tests/src/01.js +++ b/dev/tests/src/01.js @@ -15,8 +15,11 @@ YUI().use('node', 'console', 'test', function (Y){ _should: { ignore: {}, error : { - testAddSameListenerMixed1 : true, - testAddSameListenerMixed2 : true, + testAddNull : 'listener is a required param of add() and addOnce().', + testAddOnceNull : 'listener is a required param of add() and addOnce().', + testAddSameListenerMixed1 : 'You cannot add() then addOnce() the same listener without removing the relationship first.', + testAddSameListenerMixed2 : 'You cannot addOnce() then add() the same listener without removing the relationship first.', + testRemoveNull : 'listener is a required param of remove().', testDispose1 : true, testDispose2 : true, testDispose3 : true, @@ -65,7 +68,7 @@ YUI().use('node', 'console', 'test', function (Y){ var s = this.signal; s.add(function(){}); - + Y.Assert.areSame(1, s.getNumListeners()); }, @@ -89,6 +92,13 @@ YUI().use('node', 'console', 'test', function (Y){ Y.Assert.areSame(1, s.getNumListeners()); }, + testAddNull : function(){ + var s = this.signal; + + s.add(); //should throw error + Y.Assert.areSame(0, s.getNumListeners()); + }, + //--------------------------- Add Once ---------------------------------// testAddOnce : function(){ @@ -115,6 +125,13 @@ YUI().use('node', 'console', 'test', function (Y){ Y.Assert.areSame(1, s.getNumListeners()); }, + testAddOnceNull : function(){ + var s = this.signal; + + s.addOnce(); //should throw error + Y.Assert.areSame(0, s.getNumListeners()); + }, + //--------------------------- Add Mixed ---------------------------------// testAddSameListenerMixed1 : function(){ @@ -1060,6 +1077,19 @@ YUI().use('node', 'console', 'test', function (Y){ s.dispatch(); }, + testRemoveNull : function(){ + var s = this.signal; + + var l1 = function(){Y.Assert.fail();}; + + var b1 = s.add(l1); + s.remove(); //should throw error + Y.Assert.areSame(0, s.getNumListeners()); + s.dispatch(); + }, + + //--------------------- Dispose --------------------------// + testDispose1 : function(){ var s = this.signal; diff --git a/dist/js-signals.js b/dist/js-signals.js index b7e84bc..93ced03 100644 --- a/dist/js-signals.js +++ b/dist/js-signals.js @@ -3,7 +3,7 @@ * Released under the MIT license (http://www.opensource.org/licenses/mit-license.php) * @author Miller Medeiros * @version 0.4 - * @build 81 12/03/2010 02:26 PM + * @build 89 12/03/2010 03:42 PM */ (function(){ @@ -11,7 +11,17 @@ * @namespace Signals Namespace - Custom event/messaging system based on AS3 Signals * @name signals */ - var signals = window.signals = {}; + var signals = window.signals = { + + /** + * @param {*} param Parameter to check. + * @return {boolean} `true` if parameter is different than `undefined`. + */ + isDef : function(param){ + return typeof param !== 'undefined'; + } + + }; /** * Signal - custom event broadcaster inpired by Robert Penner's AS3Signals @@ -20,7 +30,7 @@ */ signals.Signal = function(){ /** - * @type Array. + * @type Array. * @private */ this._bindings = []; @@ -44,18 +54,21 @@ /** * @param {Function} listener * @param {boolean} isOnce - * @param {Object} scope + * @param {Object} [scope] * @return {signals.SignalBinding} * @private */ _registerListener : function(listener, isOnce, scope){ + + if(!signals.isDef(listener)) throw new Error('listener is a required param of add() and addOnce().'); + var prevIndex = this._indexOfListener(listener), binding; if(prevIndex !== -1){ //avoid creating a new Binding for same listener if already added to list binding = this._bindings[prevIndex]; if(binding.isOnce() !== isOnce){ - throw new Error('You cannot '+ (isOnce? 'add()' : 'addOnce()') +' then '+ (!isOnce? 'add()' : 'addOnce()') +' the same listener without removing the relationship first.'); + throw new Error('You cannot add'+ (isOnce? '' : 'Once') +'() then add'+ (!isOnce? '' : 'Once') +'() the same listener without removing the relationship first.'); } } else { binding = new signals.SignalBinding(listener, isOnce, scope, this); @@ -89,7 +102,7 @@ /** * Add a listener to the signal. * @param {Function} listener Signal handler function. - * @param {Object} scope Context on which listener will be executed (object that should represent the `this` variable inside listener function). + * @param {Object} [scope] Context on which listener will be executed (object that should represent the `this` variable inside listener function). * @return {signals.SignalBinding} An Object representing the binding between the Signal and listener. */ add : function(listener, scope){ @@ -99,7 +112,7 @@ /** * Add listener to the signal that should be removed after first execution (will be executed only once). * @param {Function} listener Signal handler function. - * @param {Object} scope Context on which listener will be executed (object that should represent the `this` variable inside listener function). + * @param {Object} [scope] Context on which listener will be executed (object that should represent the `this` variable inside listener function). * @return {signals.SignalBinding} An Object representing the binding between the Signal and listener. */ addOnce : function(listener, scope){ @@ -120,6 +133,8 @@ * @return {Function} Listener handler function. */ remove : function(listener){ + if(!signals.isDef(listener)) throw new Error('listener is a required param of remove().'); + var i = this._indexOfListener(listener); if(i !== -1) this._removeByIndex(i); return listener; @@ -175,7 +190,7 @@ /** * Dispatch/Broadcast Signal to all listeners added to the queue. - * @param {...*} params Parameters that should be passed to each handler. + * @param {...*} [params] Parameters that should be passed to each handler. */ dispatch : function(params){ if(! this._isEnabled) return; @@ -218,7 +233,7 @@ * @constructor * @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 {?Object} listenerContext Context on which listener will be executed (object that should represent the `this` variable inside listener function). * @param {signals.Signal} signal Reference to Signal object that listener is currently bound to. */ signals.SignalBinding = function SignalBinding(listener, isOnce, listenerContext, signal){ @@ -263,7 +278,7 @@ /** * 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 + * @param {Array} [paramsArr] Array of parameters that should be passed to the listener * @return {*} Value returned by the listener. */ execute : function(paramsArr){ @@ -272,7 +287,7 @@ r = this._listener.apply(this.context, paramsArr); if(this._isOnce) this.detach(); } - return r; + return r; //avoid warnings on some editors }, /** @@ -345,7 +360,7 @@ * @return {string} String representation of the object. */ toString : function(){ - return '[SignalBinding listener: '+ this._listener +', isOnce: '+ this._isOnce +', isEnabled: '+ this._isEnabled +', context: '+ this.context +']'; + return '[SignalBinding isOnce: '+ this._isOnce +', isEnabled: '+ this._isEnabled +']'; } }; diff --git a/dist/js-signals.min.js b/dist/js-signals.min.js index f3274af..97ebc57 100644 --- a/dist/js-signals.min.js +++ b/dist/js-signals.min.js @@ -3,6 +3,6 @@ * Released under the MIT license (http://www.opensource.org/licenses/mit-license.php) * @author Miller Medeiros * @version 0.4 - * @build 81 12/03/2010 02:26 PM + * @build 89 12/03/2010 03:42 PM */ -(function(){var a=window.signals={};a.Signal=function(){this._bindings=[]};a.Signal.prototype={_shouldPropagate:true,_isEnabled:true,_registerListener:function(f,e,d){var c=this._indexOfListener(f),g;if(c!==-1){g=this._bindings[c];if(g.isOnce()!==e){throw new Error("You cannot "+(e?"add()":"addOnce()")+" then "+(!e?"add()":"addOnce()")+" the same listener without removing the relationship first.")}}else{g=new a.SignalBinding(f,e,d,this);this._addBinding(g)}return g},_addBinding:function(c){this._bindings.push(c)},_indexOfListener:function(c){var d=this._bindings.length;while(d--){if(this._bindings[d]._listener===c){return d}}return -1},add:function(d,c){return this._registerListener(d,false,c)},addOnce:function(d,c){return this._registerListener(d,true,c)},_removeByIndex:function(c){this._bindings[c]._destroy();this._bindings.splice(c,1)},remove:function(d){var c=this._indexOfListener(d);if(c!==-1){this._removeByIndex(c)}return d},removeAll:function(){var c=this._bindings.length;while(c--){this._removeByIndex(c)}},getNumListeners:function(){return this._bindings.length},disable:function(){this._isEnabled=false},enable:function(){this._isEnabled=true},isEnabled:function(){return this._isEnabled},halt:function(){this._shouldPropagate=false},dispatch:function(f){if(!this._isEnabled){return}var c=Array.prototype.slice.call(arguments),g=this._bindings.slice(),d=0,e;this._shouldPropagate=true;while(e=g[d++]){if(e.execute(c)===false||!this._shouldPropagate){break}}},dispose:function(){this.removeAll();delete this._bindings},toString:function(){return"[Signal isEnabled: "+this._isEnabled+" numListeners: "+this.getNumListeners()+"]"}};a.SignalBinding=function b(f,c,e,d){this._listener=f;this._isOnce=c;this.context=e;this._signal=d};a.SignalBinding.prototype={_isEnabled:true,execute:function(c){var d;if(this._isEnabled){d=this._listener.apply(this.context,c);if(this._isOnce){this.detach()}}return d},detach:function(){return this._signal.remove(this._listener)},getListener:function(){return this._listener},dispose:function(){this.detach();this._destroy()},_destroy:function(){delete this._signal;delete this._isOnce;delete this._listener;delete this.context},disable:function(){this._isEnabled=false},enable:function(){this._isEnabled=true},isEnabled:function(){return this._isEnabled},isOnce:function(){return this._isOnce},toString:function(){return"[SignalBinding listener: "+this._listener+", isOnce: "+this._isOnce+", isEnabled: "+this._isEnabled+", context: "+this.context+"]"}}}()); \ No newline at end of file +(function(){var a=window.signals={isDef:function(c){return typeof c!=="undefined"}};a.Signal=function(){this._bindings=[]};a.Signal.prototype={_shouldPropagate:true,_isEnabled:true,_registerListener:function(f,e,d){if(!a.isDef(f)){throw new Error("listener is a required param of add() and addOnce().")}var c=this._indexOfListener(f),g;if(c!==-1){g=this._bindings[c];if(g.isOnce()!==e){throw new Error("You cannot add"+(e?"":"Once")+"() then add"+(!e?"":"Once")+"() the same listener without removing the relationship first.")}}else{g=new a.SignalBinding(f,e,d,this);this._addBinding(g)}return g},_addBinding:function(c){this._bindings.push(c)},_indexOfListener:function(c){var d=this._bindings.length;while(d--){if(this._bindings[d]._listener===c){return d}}return -1},add:function(d,c){return this._registerListener(d,false,c)},addOnce:function(d,c){return this._registerListener(d,true,c)},_removeByIndex:function(c){this._bindings[c]._destroy();this._bindings.splice(c,1)},remove:function(d){if(!a.isDef(d)){throw new Error("listener is a required param of remove().")}var c=this._indexOfListener(d);if(c!==-1){this._removeByIndex(c)}return d},removeAll:function(){var c=this._bindings.length;while(c--){this._removeByIndex(c)}},getNumListeners:function(){return this._bindings.length},disable:function(){this._isEnabled=false},enable:function(){this._isEnabled=true},isEnabled:function(){return this._isEnabled},halt:function(){this._shouldPropagate=false},dispatch:function(f){if(!this._isEnabled){return}var c=Array.prototype.slice.call(arguments),g=this._bindings.slice(),d=0,e;this._shouldPropagate=true;while(e=g[d++]){if(e.execute(c)===false||!this._shouldPropagate){break}}},dispose:function(){this.removeAll();delete this._bindings},toString:function(){return"[Signal isEnabled: "+this._isEnabled+" numListeners: "+this.getNumListeners()+"]"}};a.SignalBinding=function b(f,c,e,d){this._listener=f;this._isOnce=c;this.context=e;this._signal=d};a.SignalBinding.prototype={_isEnabled:true,execute:function(c){var d;if(this._isEnabled){d=this._listener.apply(this.context,c);if(this._isOnce){this.detach()}}return d},detach:function(){return this._signal.remove(this._listener)},getListener:function(){return this._listener},dispose:function(){this.detach();this._destroy()},_destroy:function(){delete this._signal;delete this._isOnce;delete this._listener;delete this.context},disable:function(){this._isEnabled=false},enable:function(){this._isEnabled=true},isEnabled:function(){return this._isEnabled},isOnce:function(){return this._isOnce},toString:function(){return"[SignalBinding isOnce: "+this._isOnce+", isEnabled: "+this._isEnabled+"]"}}}()); \ No newline at end of file From 0f98772c29df21ecbbce9f0e95dea21dabd7ff66 Mon Sep 17 00:00:00 2001 From: Miller Medeiros Date: Fri, 3 Dec 2010 17:09:14 -0500 Subject: [PATCH 09/10] bumped version number to 0.5; updated changelog, documentation and build.xml --- CHANGELOG.markdown | 35 +- build.xml | 1 + dev/build/build.number | 4 +- dev/build/build.properties | 2 +- dev/src/Signal.js | 3 +- dev/src/SignalBinding.js | 2 +- dev/src/intro.js | 2 +- dist/docs/files.html | 4 +- dist/docs/index.html | 2 +- dist/docs/symbolindex.html | 40 +- dist/docs/symbols/_global_.html | 2 +- dist/docs/symbols/signals.Signal.html | 45 ++- dist/docs/symbols/signals.SignalBinding.html | 95 +++-- dist/docs/symbols/signals.html | 4 +- ...rojects_js-signals_dist_js-signals.js.html | 376 ++++++++++++++++++ ...edeiros_js-signals_dist_js-signals.js.html | 323 --------------- dist/js-signals.js | 11 +- dist/js-signals.min.js | 6 +- 18 files changed, 546 insertions(+), 411 deletions(-) create mode 100644 dist/docs/symbols/src/C__Miller_Personal_open_source_projects_js-signals_dist_js-signals.js.html delete mode 100644 dist/docs/symbols/src/D__Projetos_millermedeiros_js-signals_dist_js-signals.js.html diff --git a/CHANGELOG.markdown b/CHANGELOG.markdown index dbf12a0..160cc7a 100644 --- a/CHANGELOG.markdown +++ b/CHANGELOG.markdown @@ -2,6 +2,39 @@ +## v0.5 (2010/12/03) ## + +### API changes ### + + - Added: + - `SignalBinding.prototype.getListener()` (issue #3) + - `Signal.dispose()` (issue #6) + + - Removed: + - `SignalBinding.listener` (issue #3) + + - Renamed: + - `SignalBinding.listenerScope` -> `SignalBinding.context` (issue #4) + +### Fixes ### + + - Removed unnecessary function names (issue #5) + - Improved `remove()`, `removeAll()` to dispose binding (issue #10) + +### Test Changes ### + + - Added different HTML files to test dev/dist/min files. + - Updated test cases to match new API. + +### Other ### + + - Improved source code comments and documentation. + - Small refactoring for better organization and DRY. + - Added error messages for required params. + - Removed unnecessary info from `SignalBinding.toString()`. + + + ## v0.4 (2010/11/27) ## ### API changes ### @@ -45,7 +78,7 @@ ### Other ### -Added inline documentation to source codeand included an HTML version of the documentation together with distribution files. +Added inline documentation to source code and included an HTML version of the documentation together with distribution files. diff --git a/build.xml b/build.xml index 7de5f6b..a6a8596 100644 --- a/build.xml +++ b/build.xml @@ -60,6 +60,7 @@ + diff --git a/dev/build/build.number b/dev/build/build.number index e2de90e..ac900cb 100644 --- a/dev/build/build.number +++ b/dev/build/build.number @@ -1,3 +1,3 @@ #Build Number for ANT. Do not edit! -#Fri Dec 03 15:42:22 EST 2010 -build.number=90 +#Fri Dec 03 17:03:45 EST 2010 +build.number=95 diff --git a/dev/build/build.properties b/dev/build/build.properties index 6c9c7cb..edeef56 100644 --- a/dev/build/build.properties +++ b/dev/build/build.properties @@ -6,6 +6,6 @@ docs.dir = ${dist.dir}/docs jsdoc-toolkit.dir = ${build.dir}/jsdoc-toolkit yuicompressor.jar = ${build.dir}/yuicompressor/yuicompressor-2.4.2.jar product.name = js-signals -version.number = 0.4 +version.number = 0.5 dist.name = ${product.name}.js dist.min.name = ${product.name}.min.js \ No newline at end of file diff --git a/dev/src/Signal.js b/dev/src/Signal.js index 03b69bc..32d0420 100644 --- a/dev/src/Signal.js +++ b/dev/src/Signal.js @@ -1,6 +1,7 @@ /** - * Signal - custom event broadcaster inpired by Robert Penner's AS3Signals + * Signal - custom event broadcaster + *
- inspired by Robert Penner's AS3 Signals. * @author Miller Medeiros * @constructor */ diff --git a/dev/src/SignalBinding.js b/dev/src/SignalBinding.js index 9159b08..786ba6c 100644 --- a/dev/src/SignalBinding.js +++ b/dev/src/SignalBinding.js @@ -1,7 +1,7 @@ /** * Object that represents a binding between a Signal and a listener function. - *
- Constructor shouldn't be called by regular user, no point on creating a new binding without a Signal. + *
- Constructor shouldn't be called by regular user, used internally. *
- inspired by Joa Ebert AS3 SignalBinding and Robert Penner's Slot classes. * @author Miller Medeiros * @constructor diff --git a/dev/src/intro.js b/dev/src/intro.js index bf7ab29..eab413e 100644 --- a/dev/src/intro.js +++ b/dev/src/intro.js @@ -1,4 +1,4 @@ -/*! +/*!! * JS Signals * Released under the MIT license (http://www.opensource.org/licenses/mit-license.php) * @author Miller Medeiros diff --git a/dist/docs/files.html b/dist/docs/files.html index f3d88aa..3e6303b 100644 --- a/dist/docs/files.html +++ b/dist/docs/files.html @@ -46,7 +46,7 @@

File Index

-

D:\Projetos\millermedeiros\js-signals\dist\js-signals.js

+

C:\Miller\Personal\open_source_projects\js-signals\dist\js-signals.js

@@ -61,7 +61,7 @@

- Documentation generated by JsDoc Toolkit 2.4.0 on Sat Nov 27 2010 16:19:19 GMT-0500 (EST) + Documentation generated by JsDoc Toolkit 2.4.0 on Fri Dec 03 2010 16:44:57 GMT-0500 (EST) | template based on Steffen Siering jsdoc-simple.

diff --git a/dist/docs/index.html b/dist/docs/index.html index 90ca99b..19f6649 100644 --- a/dist/docs/index.html +++ b/dist/docs/index.html @@ -85,7 +85,7 @@

signals.SignalBinding

- Documentation generated by JsDoc Toolkit 2.4.0 on Sat Nov 27 2010 16:19:19 GMT-0500 (EST) + Documentation generated by JsDoc Toolkit 2.4.0 on Fri Dec 03 2010 16:44:57 GMT-0500 (EST) | template based on Steffen Siering jsdoc-simple.
diff --git a/dist/docs/symbolindex.html b/dist/docs/symbolindex.html index a1936b9..72c566f 100644 --- a/dist/docs/symbolindex.html +++ b/dist/docs/symbolindex.html @@ -106,6 +106,15 @@

Symbol Index

+ + context + + + signals.SignalBinding#context + + + + detach @@ -139,6 +148,8 @@

Symbol Index

dispose + signals.Signal#dispose + signals.SignalBinding#dispose @@ -164,6 +175,15 @@

Symbol Index

+ + getListener + + + signals.SignalBinding#getListener + + + + getNumListeners @@ -202,24 +222,6 @@

Symbol Index

- - listener - - - signals.SignalBinding#listener - - - - - - listenerScope - - - signals.SignalBinding#listenerScope - - - - remove @@ -282,7 +284,7 @@

Symbol Index

- Documentation generated by JsDoc Toolkit 2.4.0 on Sat Nov 27 2010 16:19:19 GMT-0500 (EST) + Documentation generated by JsDoc Toolkit 2.4.0 on Fri Dec 03 2010 16:44:57 GMT-0500 (EST) | template based on Steffen Siering jsdoc-simple.
diff --git a/dist/docs/symbols/_global_.html b/dist/docs/symbols/_global_.html index f7c234f..dbed7b1 100644 --- a/dist/docs/symbols/_global_.html +++ b/dist/docs/symbols/_global_.html @@ -101,7 +101,7 @@

- Documentation generated by JsDoc Toolkit 2.4.0 on Sat Nov 27 2010 16:19:19 GMT-0500 (EST) + Documentation generated by JsDoc Toolkit 2.4.0 on Fri Dec 03 2010 16:44:56 GMT-0500 (EST) | template based on Steffen Siering jsdoc-simple.
diff --git a/dist/docs/symbols/signals.Signal.html b/dist/docs/symbols/signals.Signal.html index cd250de..d80faa8 100644 --- a/dist/docs/symbols/signals.Signal.html +++ b/dist/docs/symbols/signals.Signal.html @@ -87,6 +87,10 @@

Methods

dispatch +
  • + dispose +
  • +
  • enable
  • @@ -139,7 +143,7 @@

    -
    Defined in: js-signals.js. +
    Defined in: js-signals.js.

    @@ -155,7 +159,8 @@

    -

    Signal - custom event broadcaster inpired by Robert Penner's AS3Signals https://github.com/robertpenner/as3-signals/

    +

    Signal - custom event broadcaster +
    - inspired by Robert Penner's AS3 Signals.


    Author: Miller Medeiros.
    @@ -212,7 +217,7 @@

    {Object} scope - + Optional
    Context on which listener will be executed (object that should represent the `this` variable inside listener function).
    @@ -263,7 +268,7 @@

    {Object} scope - + Optional
    Context on which listener will be executed (object that should represent the `this` variable inside listener function).
    @@ -342,7 +347,7 @@

    {...*} params - + Optional
    Parameters that should be passed to each handler.
    @@ -355,6 +360,34 @@

    + + +
    + +
    +
    +
    + + dispose() + +
    +
    +

    Remove binding from signal and destroy any reference to external Objects (destroy Signal object). +
    - calling methods on the signal instance after calling dispose will throw errors.

    + + +
    + + + + + + + + + + +
    @@ -605,7 +638,7 @@

    - Documentation generated by JsDoc Toolkit 2.4.0 on Sat Nov 27 2010 16:19:19 GMT-0500 (EST) + Documentation generated by JsDoc Toolkit 2.4.0 on Fri Dec 03 2010 16:44:56 GMT-0500 (EST) | template based on Steffen Siering jsdoc-simple.
    diff --git a/dist/docs/symbols/signals.SignalBinding.html b/dist/docs/symbols/signals.SignalBinding.html index 02076cd..cc0c554 100644 --- a/dist/docs/symbols/signals.SignalBinding.html +++ b/dist/docs/symbols/signals.SignalBinding.html @@ -67,11 +67,7 @@

    Fields

    @@ -104,6 +100,10 @@

    Methods

    execute +
  • + getListener +
  • +
  • isEnabled
  • @@ -140,7 +140,7 @@

    -
    Defined in: js-signals.js. +
    Defined in: js-signals.js.

    @@ -152,12 +152,12 @@

    - signals.SignalBinding(listener, isOnce, listenerScope, signal) + signals.SignalBinding(listener, isOnce, listenerContext, signal)

    Object that represents a binding between a Signal and a listener function. -
    - Constructor shouldn't be called by regular user, no point on creating a new binding without a Signal. +
    - Constructor shouldn't be called by regular user, used internally.
    - inspired by Joa Ebert AS3 SignalBinding and Robert Penner's Slot classes.


    Author: Miller Medeiros.
    @@ -173,7 +173,7 @@

    {Function} listener -
    Handler function binded to the signal.
    +
    Handler function bound to the signal.
    {boolean} isOnce @@ -182,7 +182,7 @@

    If binding should be executed just once.
    - {Object} listenerScope + {?Object} listenerContext
    Context on which listener will be executed (object that should represent the `this` variable inside listener function).
    @@ -191,7 +191,7 @@

    {signals.Signal} signal

    -
    Reference to Signal object that listener is currently binded to.
    +
    Reference to Signal object that listener is currently bound to.
    @@ -213,37 +213,13 @@

    - -
    -
    -
    - - {Function} - listener - -
    -
    -

    Handler function binded to the signal.

    - - -
    - - - - - - - -
    - -
    - +
    {Object} - listenerScope + context
    @@ -281,7 +257,7 @@

    Detach binding from signal. -- alias to: mySignal.remove(myBinding.listener);

    +- alias to: mySignal.remove(myBinding.getListener());

    @@ -296,7 +272,7 @@

    Returns:
    -
    {Function} Handler function binded to the signal.
    +
    {Function} Handler function bound to the signal.
    @@ -349,7 +325,8 @@

    -

    Remove binding from signal and destroy any reference to external Objects (destroy SignalBinding object).

    +

    Remove binding from signal and destroy any reference to external Objects (destroy SignalBinding object). +
    - calling methods on the binding instance after calling dispose will throw errors.

    @@ -425,7 +402,7 @@

    {Array} paramsArr - + Optional
    Array of parameters that should be passed to the listener
    @@ -445,6 +422,40 @@

    + + +
    + +
    +
    +
    + {Function} + getListener() + +
    +
    + + + +
    + + + + + + + + +
    +
    Returns:
    + +
    {Function} Handler function bound to the signal.
    + +
    + + + +
    @@ -561,7 +572,7 @@

    - Documentation generated by JsDoc Toolkit 2.4.0 on Sat Nov 27 2010 16:19:19 GMT-0500 (EST) + Documentation generated by JsDoc Toolkit 2.4.0 on Fri Dec 03 2010 16:44:56 GMT-0500 (EST) | template based on Steffen Siering jsdoc-simple.
    diff --git a/dist/docs/symbols/signals.html b/dist/docs/symbols/signals.html index c5aa8ae..f52f904 100644 --- a/dist/docs/symbols/signals.html +++ b/dist/docs/symbols/signals.html @@ -90,7 +90,7 @@

    Signals Namespace - Custom event/messaging system based on AS3 Signals -
    Defined in: js-signals.js. +
    Defined in: js-signals.js.

    @@ -139,7 +139,7 @@

    - Documentation generated by JsDoc Toolkit 2.4.0 on Sat Nov 27 2010 16:19:19 GMT-0500 (EST) + Documentation generated by JsDoc Toolkit 2.4.0 on Fri Dec 03 2010 16:44:56 GMT-0500 (EST) | template based on Steffen Siering jsdoc-simple.
    diff --git a/dist/docs/symbols/src/C__Miller_Personal_open_source_projects_js-signals_dist_js-signals.js.html b/dist/docs/symbols/src/C__Miller_Personal_open_source_projects_js-signals_dist_js-signals.js.html new file mode 100644 index 0000000..d20e432 --- /dev/null +++ b/dist/docs/symbols/src/C__Miller_Personal_open_source_projects_js-signals_dist_js-signals.js.html @@ -0,0 +1,376 @@ +
      1 /*!
    +  2  * JS Signals <https://github.com/millermedeiros/js-signals>
    +  3  * Released under the MIT license (http://www.opensource.org/licenses/mit-license.php)
    +  4  * @author Miller Medeiros <http://millermedeiros.com>
    +  5  * @version 0.5
    +  6  * @build 92 12/03/2010 04:44 PM
    +  7  */
    +  8 (function(){
    +  9 
    + 10 	/**
    + 11 	 * @namespace Signals Namespace - Custom event/messaging system based on AS3 Signals
    + 12 	 * @name signals
    + 13 	 */
    + 14 	var signals = window.signals = {
    + 15 		
    + 16 		/**
    + 17 		 * @param {*} param	Parameter to check.
    + 18 		 * @return {boolean} `true` if parameter is different than `undefined`.
    + 19 		 */
    + 20 		isDef : function(param){
    + 21 			return typeof param !== 'undefined';
    + 22 		}
    + 23 		
    + 24 	};
    + 25 
    + 26 	/**
    + 27 	 * Signal - custom event broadcaster
    + 28 	 * <br />- inspired by Robert Penner's AS3 Signals.
    + 29 	 * @author Miller Medeiros
    + 30 	 * @constructor
    + 31 	 */
    + 32 	signals.Signal = function(){
    + 33 		/**
    + 34 		 * @type Array.<signals.SignalBinding>
    + 35 		 * @private
    + 36 		 */
    + 37 		this._bindings = [];
    + 38 	};
    + 39 	
    + 40 	
    + 41 	signals.Signal.prototype = {
    + 42 		
    + 43 		/**
    + 44 		 * @type boolean
    + 45 		 * @private
    + 46 		 */
    + 47 		_shouldPropagate : true,
    + 48 		
    + 49 		/**
    + 50 		 * @type boolean
    + 51 		 * @private
    + 52 		 */
    + 53 		_isEnabled : true,
    + 54 		
    + 55 		/**
    + 56 		 * @param {Function} listener
    + 57 		 * @param {boolean} isOnce
    + 58 		 * @param {Object} [scope]
    + 59 		 * @return {signals.SignalBinding}
    + 60 		 * @private
    + 61 		 */
    + 62 		_registerListener : function(listener, isOnce, scope){
    + 63 			
    + 64 			if(!signals.isDef(listener)) throw new Error('listener is a required param of add() and addOnce().');
    + 65 			
    + 66 			var prevIndex = this._indexOfListener(listener),
    + 67 				binding;
    + 68 			
    + 69 			if(prevIndex !== -1){ //avoid creating a new Binding for same listener if already added to list
    + 70 				binding = this._bindings[prevIndex];
    + 71 				if(binding.isOnce() !== isOnce){
    + 72 					throw new Error('You cannot add'+ (isOnce? '' : 'Once') +'() then add'+ (!isOnce? '' : 'Once') +'() the same listener without removing the relationship first.');
    + 73 				}
    + 74 			} else {
    + 75 				binding = new signals.SignalBinding(listener, isOnce, scope, this);
    + 76 				this._addBinding(binding);
    + 77 			}
    + 78 			
    + 79 			return binding;
    + 80 		},
    + 81 		
    + 82 		/**
    + 83 		 * @param {signals.SignalBinding} binding
    + 84 		 * @private
    + 85 		 */
    + 86 		_addBinding : function(binding){
    + 87 			this._bindings.push(binding);
    + 88 		},
    + 89 		
    + 90 		/**
    + 91 		 * @param {Function} listener
    + 92 		 * @return {int}
    + 93 		 * @private
    + 94 		 */
    + 95 		_indexOfListener : function(listener){
    + 96 			var n = this._bindings.length;
    + 97 			while(n--){
    + 98 				if(this._bindings[n]._listener === listener) return n;
    + 99 			}
    +100 			return -1;
    +101 		},
    +102 		
    +103 		/**
    +104 		 * Add a listener to the signal.
    +105 		 * @param {Function} listener	Signal handler function.
    +106 		 * @param {Object} [scope]	Context on which listener will be executed (object that should represent the `this` variable inside listener function).
    +107 		 * @return {signals.SignalBinding} An Object representing the binding between the Signal and listener.
    +108 		 */
    +109 		add : function(listener, scope){
    +110 			return this._registerListener(listener, false, scope);
    +111 		},
    +112 		
    +113 		/**
    +114 		 * Add listener to the signal that should be removed after first execution (will be executed only once).
    +115 		 * @param {Function} listener	Signal handler function.
    +116 		 * @param {Object} [scope]	Context on which listener will be executed (object that should represent the `this` variable inside listener function).
    +117 		 * @return {signals.SignalBinding} An Object representing the binding between the Signal and listener.
    +118 		 */
    +119 		addOnce : function(listener, scope){
    +120 			return this._registerListener(listener, true, scope);
    +121 		},
    +122 		
    +123 		/**
    +124 		 * @private
    +125 		 */
    +126 		_removeByIndex : function(i){
    +127 			this._bindings[i]._destroy(); //no reason to a SignalBinding exist if it isn't attached to a signal
    +128 			this._bindings.splice(i, 1);
    +129 		},
    +130 		
    +131 		/**
    +132 		 * Remove a single listener from the dispatch queue.
    +133 		 * @param {Function} listener	Handler function that should be removed.
    +134 		 * @return {Function} Listener handler function.
    +135 		 */
    +136 		remove : function(listener){
    +137 			if(!signals.isDef(listener)) throw new Error('listener is a required param of remove().');
    +138 			
    +139 			var i = this._indexOfListener(listener);
    +140 			if(i !== -1) this._removeByIndex(i);
    +141 			return listener;
    +142 		},
    +143 		
    +144 		/**
    +145 		 * Remove all listeners from the Signal.
    +146 		 */
    +147 		removeAll : function(){
    +148 			var n = this._bindings.length;
    +149 			while(n--){
    +150 				this._removeByIndex(n);
    +151 			}
    +152 		},
    +153 		
    +154 		/**
    +155 		 * @return {uint} Number of listeners attached to the Signal.
    +156 		 */
    +157 		getNumListeners : function(){
    +158 			return this._bindings.length;
    +159 		},
    +160 		
    +161 		/**
    +162 		 * Disable Signal, will block dispatch to listeners until `enable()` is called.
    +163 		 * @see signals.Signal.prototype.enable
    +164 		 */
    +165 		disable : function(){
    +166 			this._isEnabled = false;
    +167 		},
    +168 		
    +169 		/**
    +170 		 * Enable broadcast to listeners.
    +171 		 * @see signals.Signal.prototype.disable
    +172 		 */
    +173 		enable : function(){
    +174 			this._isEnabled = true;
    +175 		}, 
    +176 		
    +177 		/**
    +178 		 * @return {boolean} If Signal is currently enabled and will broadcast message to listeners.
    +179 		 */
    +180 		isEnabled : function(){
    +181 			return this._isEnabled;
    +182 		},
    +183 		
    +184 		/**
    +185 		 * Stop propagation of the event, blocking the dispatch to next listeners on the queue.
    +186 		 * - should be called only during signal dispatch, calling it before/after dispatch won't affect signal broadcast. 
    +187 		 */
    +188 		halt : function(){
    +189 			this._shouldPropagate = false;
    +190 		},
    +191 		
    +192 		/**
    +193 		 * Dispatch/Broadcast Signal to all listeners added to the queue. 
    +194 		 * @param {...*} [params]	Parameters that should be passed to each handler.
    +195 		 */
    +196 		dispatch : function(params){
    +197 			if(! this._isEnabled) return;
    +198 			
    +199 			var paramsArr = Array.prototype.slice.call(arguments),
    +200 				bindings = this._bindings.slice(), //clone array in case add/remove items during dispatch
    +201 				i = 0,
    +202 				cur;
    +203 			
    +204 			this._shouldPropagate = true; //in case `halt` was called before dispatch or during the previous dispatch.
    +205 						
    +206 			while(cur = bindings[i++]){
    +207 				if(cur.execute(paramsArr) === false || !this._shouldPropagate) break; //execute all callbacks until end of the list or until a callback returns `false` or stops propagation
    +208 			}
    +209 		},
    +210 		
    +211 		/**
    +212 		 * Remove binding from signal and destroy any reference to external Objects (destroy Signal object).
    +213 		 * <br /> - calling methods on the signal instance after calling dispose will throw errors.
    +214 		 */
    +215 		dispose : function(){
    +216 			this.removeAll();
    +217 			delete this._bindings;
    +218 		},
    +219 		
    +220 		/**
    +221 		 * @return {string} String representation of the object.
    +222 		 */
    +223 		toString : function(){
    +224 			return '[Signal isEnabled: '+ this._isEnabled +' numListeners: '+ this.getNumListeners() +']';
    +225 		}
    +226 		
    +227 	};
    +228 	
    +229 	/**
    +230 	 * Object that represents a binding between a Signal and a listener function.
    +231 	 * <br />- <strong>Constructor shouldn't be called by regular user, used internally.</strong>
    +232 	 * <br />- inspired by Joa Ebert AS3 SignalBinding and Robert Penner's Slot classes.
    +233 	 * @author Miller Medeiros
    +234 	 * @constructor
    +235 	 * @param {Function} listener	Handler function bound to the signal.
    +236 	 * @param {boolean} isOnce	If binding should be executed just once.
    +237 	 * @param {?Object} listenerContext	Context on which listener will be executed (object that should represent the `this` variable inside listener function).
    +238 	 * @param {signals.Signal} signal	Reference to Signal object that listener is currently bound to.
    +239 	 */
    +240 	signals.SignalBinding = function SignalBinding(listener, isOnce, listenerContext, signal){
    +241 		
    +242 		/**
    +243 		 * Handler function bound to the signal.
    +244 		 * @type Function
    +245 		 * @private
    +246 		 */
    +247 		this._listener = listener;
    +248 		
    +249 		/**
    +250 		 * If binding should be executed just once.
    +251 		 * @type boolean
    +252 		 * @private
    +253 		 */
    +254 		this._isOnce = isOnce;
    +255 		
    +256 		/**
    +257 		 * Context on which listener will be executed (object that should represent the `this` variable inside listener function).
    +258 		 * @type Object
    +259 		 */
    +260 		this.context = listenerContext;
    +261 		
    +262 		/**
    +263 		 * Reference to Signal object that listener is currently bound to.
    +264 		 * @type signals.Signal
    +265 		 * @private
    +266 		 */
    +267 		this._signal = signal;
    +268 	};
    +269 	
    +270 	
    +271 	signals.SignalBinding.prototype = {
    +272 		
    +273 		/**
    +274 		 * @type boolean
    +275 		 * @private
    +276 		 */
    +277 		_isEnabled : true,
    +278 		
    +279 		/**
    +280 		 * Call listener passing arbitrary parameters.
    +281 		 * <p>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.</p> 
    +282 		 * @param {Array} [paramsArr]	Array of parameters that should be passed to the listener
    +283 		 * @return {*} Value returned by the listener.
    +284 		 */
    +285 		execute : function(paramsArr){
    +286 			var r;
    +287 			if(this._isEnabled){
    +288 				r = this._listener.apply(this.context, paramsArr);
    +289 				if(this._isOnce) this.detach();
    +290 			}
    +291 			return r; //avoid warnings on some editors
    +292 		},
    +293 		
    +294 		/**
    +295 		 * Detach binding from signal.
    +296 		 * - alias to: mySignal.remove(myBinding.getListener());
    +297 		 * @return {Function} Handler function bound to the signal.
    +298 		 */
    +299 		detach : function(){
    +300 			return this._signal.remove(this._listener);
    +301 		},
    +302 		
    +303 		/**
    +304 		 * @return {Function} Handler function bound to the signal.
    +305 		 */
    +306 		getListener : function(){
    +307 			return this._listener;
    +308 		},
    +309 		
    +310 		/**
    +311 		 * Remove binding from signal and destroy any reference to external Objects (destroy SignalBinding object).
    +312 		 * <br /> - calling methods on the binding instance after calling dispose will throw errors.
    +313 		 */
    +314 		dispose : function(){
    +315 			this.detach();
    +316 			this._destroy();
    +317 		},
    +318 		
    +319 		/**
    +320 		 * Delete all instance properties
    +321 		 * @private
    +322 		 */
    +323 		_destroy : function(){
    +324 			delete this._signal;
    +325 			delete this._isOnce;
    +326 			delete this._listener;
    +327 			delete this.context;
    +328 		},
    +329 		
    +330 		/**
    +331 		 * Disable SignalBinding, block listener execution. Listener will only be executed after calling `enable()`.  
    +332 		 * @see signals.SignalBinding.enable()
    +333 		 */
    +334 		disable : function(){
    +335 			this._isEnabled = false;
    +336 		},
    +337 		
    +338 		/**
    +339 		 * Enable SignalBinding. Enable listener execution.
    +340 		 * @see signals.SignalBinding.disable()
    +341 		 */
    +342 		enable : function(){
    +343 			this._isEnabled = true;
    +344 		},
    +345 		
    +346 		/**
    +347 		 * @return {boolean} If SignalBinding is currently paused and won't execute listener during dispatch.
    +348 		 */
    +349 		isEnabled : function(){
    +350 			return this._isEnabled;
    +351 		},
    +352 		
    +353 		/**
    +354 		 * @return {boolean} If SignalBinding will only be executed once.
    +355 		 */
    +356 		isOnce : function(){
    +357 			return this._isOnce;
    +358 		},
    +359 		
    +360 		/**
    +361 		 * @return {string} String representation of the object.
    +362 		 */
    +363 		toString : function(){
    +364 			return '[SignalBinding isOnce: '+ this._isOnce +', isEnabled: '+ this._isEnabled +']';
    +365 		}
    +366 		
    +367 	};
    +368 }());
    +369 
    \ No newline at end of file diff --git a/dist/docs/symbols/src/D__Projetos_millermedeiros_js-signals_dist_js-signals.js.html b/dist/docs/symbols/src/D__Projetos_millermedeiros_js-signals_dist_js-signals.js.html deleted file mode 100644 index eda8c87..0000000 --- a/dist/docs/symbols/src/D__Projetos_millermedeiros_js-signals_dist_js-signals.js.html +++ /dev/null @@ -1,323 +0,0 @@ -
      1 /*!
    -  2  * JS Signals <https://github.com/millermedeiros/js-signals>
    -  3  * Released under the MIT license (http://www.opensource.org/licenses/mit-license.php)
    -  4  * @author Miller Medeiros <http://millermedeiros.com>
    -  5  * @version 0.4
    -  6  * @build 64 11/27/2010 04:19 PM
    -  7  */
    -  8 (function(){
    -  9 	
    - 10 	/**
    - 11 	 * @namespace Signals Namespace - Custom event/messaging system based on AS3 Signals
    - 12 	 * @name signals
    - 13 	 */
    - 14 	var signals = window.signals = {};
    - 15 
    - 16 	/**
    - 17 	 * Signal - custom event broadcaster inpired by Robert Penner's AS3Signals <https://github.com/robertpenner/as3-signals/>
    - 18 	 * @author Miller Medeiros
    - 19 	 * @constructor
    - 20 	 */
    - 21 	signals.Signal = function(){
    - 22 		/**
    - 23 		 * @type Array.<SignalBinding>
    - 24 		 * @private
    - 25 		 */
    - 26 		this._bindings = [];
    - 27 	};
    - 28 	
    - 29 	
    - 30 	signals.Signal.prototype = {
    - 31 		
    - 32 		/**
    - 33 		 * @type boolean
    - 34 		 * @private
    - 35 		 */
    - 36 		_shouldPropagate : true,
    - 37 		
    - 38 		/**
    - 39 		 * @type boolean
    - 40 		 * @private
    - 41 		 */
    - 42 		_isEnabled : true,
    - 43 		
    - 44 		/**
    - 45 		 * @param {Function} listener
    - 46 		 * @param {boolean} isOnce
    - 47 		 * @param {Object} scope
    - 48 		 * @return {signals.SignalBinding}
    - 49 		 * @private
    - 50 		 */
    - 51 		_registerListener : function _registerListener(listener, isOnce, scope){
    - 52 			var prevIndex = this._indexOfListener(listener),
    - 53 				binding;
    - 54 			
    - 55 			if(prevIndex !== -1){ //avoid creating a new Binding for same listener if already added to list
    - 56 				binding = this._bindings[prevIndex];
    - 57 				if(binding.isOnce() !== isOnce){
    - 58 					throw new Error('You cannot '+ (isOnce? 'add()' : 'addOnce()') +' then '+ (!isOnce? 'add()' : 'addOnce()') +' the same listener without removing the relationship first.');
    - 59 				}
    - 60 			} else {
    - 61 				binding = new signals.SignalBinding(listener, isOnce, scope, this);
    - 62 				this._addBinding(binding);
    - 63 			}
    - 64 			
    - 65 			return binding;
    - 66 		},
    - 67 		
    - 68 		/**
    - 69 		 * @param {signals.SignalBinding} binding
    - 70 		 * @private
    - 71 		 */
    - 72 		_addBinding : function _addBinding(binding){
    - 73 			this._bindings.push(binding);
    - 74 		},
    - 75 		
    - 76 		/**
    - 77 		 * @param {Function} listener
    - 78 		 * @return {int}
    - 79 		 * @private
    - 80 		 */
    - 81 		_indexOfListener : function _indexOfListener(listener){
    - 82 			var n = this._bindings.length;
    - 83 			while(n--){
    - 84 				if(this._bindings[n].listener === listener) return n;
    - 85 			}
    - 86 			return -1;
    - 87 		},
    - 88 		
    - 89 		/**
    - 90 		 * Add a listener to the signal.
    - 91 		 * @param {Function} listener	Signal handler function.
    - 92 		 * @param {Object} scope	Context on which listener will be executed (object that should represent the `this` variable inside listener function).
    - 93 		 * @return {signals.SignalBinding} An Object representing the binding between the Signal and listener.
    - 94 		 */
    - 95 		add : function add(listener, scope){
    - 96 			return this._registerListener(listener, false, scope);
    - 97 		},
    - 98 		
    - 99 		/**
    -100 		 * Add listener to the signal that should be removed after first execution (will be executed only once).
    -101 		 * @param {Function} listener	Signal handler function.
    -102 		 * @param {Object} scope	Context on which listener will be executed (object that should represent the `this` variable inside listener function).
    -103 		 * @return {signals.SignalBinding} An Object representing the binding between the Signal and listener.
    -104 		 */
    -105 		addOnce : function addOnce(listener, scope){
    -106 			return this._registerListener(listener, true, scope);
    -107 		},
    -108 		
    -109 		/**
    -110 		 * Remove a single listener from the dispatch queue.
    -111 		 * @param {Function} listener	Handler function that should be removed.
    -112 		 * @return {Function} Listener handler function.
    -113 		 */
    -114 		remove : function remove(listener){
    -115 			var i = this._indexOfListener(listener);
    -116 			if(i !== -1){
    -117 				this._bindings.splice(i, 1);
    -118 			}
    -119 			return listener;
    -120 		},
    -121 		
    -122 		/**
    -123 		 * Remove all listeners from the Signal.
    -124 		 */
    -125 		removeAll : function removeAll(){
    -126 			this._bindings.length = 0;
    -127 		},
    -128 		
    -129 		/**
    -130 		 * @return {uint} Number of listeners attached to the Signal.
    -131 		 */
    -132 		getNumListeners : function getNumListeners(){
    -133 			return this._bindings.length;
    -134 		},
    -135 		
    -136 		/**
    -137 		 * Disable Signal, will block dispatch to listeners until `enable()` is called.
    -138 		 * @see signals.Signal.prototype.enable
    -139 		 */
    -140 		disable : function disable(){
    -141 			this._isEnabled = false;
    -142 		},
    -143 		
    -144 		/**
    -145 		 * Enable broadcast to listeners.
    -146 		 * @see signals.Signal.prototype.disable
    -147 		 */
    -148 		enable : function enable(){
    -149 			this._isEnabled = true;
    -150 		}, 
    -151 		
    -152 		/**
    -153 		 * @return {boolean} If Signal is currently enabled and will broadcast message to listeners.
    -154 		 */
    -155 		isEnabled : function isEnabled(){
    -156 			return this._isEnabled;
    -157 		},
    -158 		
    -159 		/**
    -160 		 * Stop propagation of the event, blocking the dispatch to next listeners on the queue.
    -161 		 * - should be called only during signal dispatch, calling it before/after dispatch won't affect signal broadcast. 
    -162 		 */
    -163 		halt : function halt(){
    -164 			this._shouldPropagate = false;
    -165 		},
    -166 		
    -167 		/**
    -168 		 * Dispatch/Broadcast Signal to all listeners added to the queue. 
    -169 		 * @param {...*} params	Parameters that should be passed to each handler.
    -170 		 */
    -171 		dispatch : function dispatch(params){
    -172 			if(! this._isEnabled) return;
    -173 			
    -174 			var paramsArr = Array.prototype.slice.call(arguments),
    -175 				bindings = this._bindings.slice(), //clone array in case add/remove items during dispatch
    -176 				i = 0,
    -177 				cur;
    -178 			
    -179 			this._shouldPropagate = true; //in case `halt` was called before dispatch or during the previous dispatch.
    -180 						
    -181 			while(cur = bindings[i++]){
    -182 				if(cur.execute(paramsArr) === false || !this._shouldPropagate) break; //execute all callbacks until end of the list or until a callback returns `false` or stops propagation
    -183 			}
    -184 		},
    -185 		
    -186 		/**
    -187 		 * @return {string} String representation of the object.
    -188 		 */
    -189 		toString : function toString(){
    -190 			return '[Signal isEnabled: '+ this._isEnabled +' numListeners: '+ this.getNumListeners() +']';
    -191 		}
    -192 		
    -193 	};
    -194 	
    -195 	/**
    -196 	 * Object that represents a binding between a Signal and a listener function.
    -197 	 * <br />- Constructor shouldn't be called by regular user, no point on creating a new binding without a Signal.
    -198 	 * <br />- inspired by Joa Ebert AS3 SignalBinding and Robert Penner's Slot classes.
    -199 	 * @author Miller Medeiros
    -200 	 * @constructor
    -201 	 * @param {Function} listener	Handler function binded to the signal.
    -202 	 * @param {boolean} isOnce	If binding should be executed just once.
    -203 	 * @param {Object} listenerScope	Context on which listener will be executed (object that should represent the `this` variable inside listener function).
    -204 	 * @param {signals.Signal} signal	Reference to Signal object that listener is currently binded to.
    -205 	 */
    -206 	signals.SignalBinding = function SignalBinding(listener, isOnce, listenerScope, signal){
    -207 		
    -208 		/**
    -209 		 * Handler function binded to the signal.
    -210 		 * @type Function
    -211 		 */
    -212 		this.listener = listener;
    -213 		
    -214 		/**
    -215 		 * If binding should be executed just once.
    -216 		 * @type boolean
    -217 		 * @private
    -218 		 */
    -219 		this._isOnce = isOnce;
    -220 		
    -221 		/**
    -222 		 * Context on which listener will be executed (object that should represent the `this` variable inside listener function).
    -223 		 * @type Object
    -224 		 */
    -225 		this.listenerScope = listenerScope;
    -226 		
    -227 		/**
    -228 		 * Reference to Signal object that listener is currently binded to.
    -229 		 * @type signals.Signal
    -230 		 * @private
    -231 		 */
    -232 		this._signal = signal;
    -233 	};
    -234 	
    -235 	
    -236 	signals.SignalBinding.prototype = {
    -237 		
    -238 		/**
    -239 		 * @type boolean
    -240 		 * @private
    -241 		 */
    -242 		_isEnabled : true,
    -243 		
    -244 		/**
    -245 		 * Call listener passing arbitrary parameters.
    -246 		 * <p>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.</p> 
    -247 		 * @param {Array} paramsArr	Array of parameters that should be passed to the listener
    -248 		 * @return {*} Value returned by the listener.
    -249 		 */
    -250 		execute : function execute(paramsArr){
    -251 			if(this._isEnabled){
    -252 				if(this._isOnce) this.detach();
    -253 				return this.listener.apply(this.listenerScope, paramsArr);
    -254 			}
    -255 		},
    -256 		
    -257 		/**
    -258 		 * Detach binding from signal.
    -259 		 * - alias to: mySignal.remove(myBinding.listener);
    -260 		 * @return {Function} Handler function binded to the signal.
    -261 		 */
    -262 		detach : function detach(){
    -263 			return this._signal.remove(this.listener);
    -264 		},
    -265 		
    -266 		/**
    -267 		 * Remove binding from signal and destroy any reference to external Objects (destroy SignalBinding object).
    -268 		 */
    -269 		dispose : function dispose(){
    -270 			this.detach();
    -271 			//remove reference to all objects
    -272 			delete this._signal;
    -273 			delete this.listener;
    -274 			delete this.listenerScope;
    -275 		},
    -276 		
    -277 		/**
    -278 		 * Disable SignalBinding, block listener execution. Listener will only be executed after calling `enable()`.  
    -279 		 * @see signals.SignalBinding.enable()
    -280 		 */
    -281 		disable : function disable(){
    -282 			this._isEnabled = false;
    -283 		},
    -284 		
    -285 		/**
    -286 		 * Enable SignalBinding. Enable listener execution.
    -287 		 * @see signals.SignalBinding.disable()
    -288 		 */
    -289 		enable : function enable(){
    -290 			this._isEnabled = true;
    -291 		},
    -292 		
    -293 		/**
    -294 		 * @return {boolean} If SignalBinding is currently paused and won't execute listener during dispatch.
    -295 		 */
    -296 		isEnabled : function isEnabled(){
    -297 			return this._isEnabled;
    -298 		},
    -299 		
    -300 		/**
    -301 		 * @return {boolean} If SignalBinding will only be executed once.
    -302 		 */
    -303 		isOnce : function isOnce(){
    -304 			return this._isOnce;
    -305 		},
    -306 		
    -307 		/**
    -308 		 * @return {string} String representation of the object.
    -309 		 */
    -310 		toString : function toString(){
    -311 			return '[SignalBinding listener: '+ this.listener +', isOnce: '+ this._isOnce +', isEnabled: '+ this._isEnabled +', listenerScope: '+ this.listenerScope +']';
    -312 		}
    -313 		
    -314 	};
    -315 }());
    -316 
    \ No newline at end of file diff --git a/dist/js-signals.js b/dist/js-signals.js index 93ced03..2b30bf3 100644 --- a/dist/js-signals.js +++ b/dist/js-signals.js @@ -1,9 +1,9 @@ -/*! +/*!! * JS Signals * Released under the MIT license (http://www.opensource.org/licenses/mit-license.php) * @author Miller Medeiros - * @version 0.4 - * @build 89 12/03/2010 03:42 PM + * @version 0.5 + * @build 94 12/03/2010 05:03 PM */ (function(){ @@ -24,7 +24,8 @@ }; /** - * Signal - custom event broadcaster inpired by Robert Penner's AS3Signals + * Signal - custom event broadcaster + *
    - inspired by Robert Penner's AS3 Signals. * @author Miller Medeiros * @constructor */ @@ -227,7 +228,7 @@ /** * Object that represents a binding between a Signal and a listener function. - *
    - Constructor shouldn't be called by regular user, no point on creating a new binding without a Signal. + *
    - Constructor shouldn't be called by regular user, used internally. *
    - inspired by Joa Ebert AS3 SignalBinding and Robert Penner's Slot classes. * @author Miller Medeiros * @constructor diff --git a/dist/js-signals.min.js b/dist/js-signals.min.js index 97ebc57..ebb3c18 100644 --- a/dist/js-signals.min.js +++ b/dist/js-signals.min.js @@ -1,8 +1,8 @@ -/* +/*! * JS Signals * Released under the MIT license (http://www.opensource.org/licenses/mit-license.php) * @author Miller Medeiros - * @version 0.4 - * @build 89 12/03/2010 03:42 PM + * @version 0.5 + * @build 94 12/03/2010 05:03 PM */ (function(){var a=window.signals={isDef:function(c){return typeof c!=="undefined"}};a.Signal=function(){this._bindings=[]};a.Signal.prototype={_shouldPropagate:true,_isEnabled:true,_registerListener:function(f,e,d){if(!a.isDef(f)){throw new Error("listener is a required param of add() and addOnce().")}var c=this._indexOfListener(f),g;if(c!==-1){g=this._bindings[c];if(g.isOnce()!==e){throw new Error("You cannot add"+(e?"":"Once")+"() then add"+(!e?"":"Once")+"() the same listener without removing the relationship first.")}}else{g=new a.SignalBinding(f,e,d,this);this._addBinding(g)}return g},_addBinding:function(c){this._bindings.push(c)},_indexOfListener:function(c){var d=this._bindings.length;while(d--){if(this._bindings[d]._listener===c){return d}}return -1},add:function(d,c){return this._registerListener(d,false,c)},addOnce:function(d,c){return this._registerListener(d,true,c)},_removeByIndex:function(c){this._bindings[c]._destroy();this._bindings.splice(c,1)},remove:function(d){if(!a.isDef(d)){throw new Error("listener is a required param of remove().")}var c=this._indexOfListener(d);if(c!==-1){this._removeByIndex(c)}return d},removeAll:function(){var c=this._bindings.length;while(c--){this._removeByIndex(c)}},getNumListeners:function(){return this._bindings.length},disable:function(){this._isEnabled=false},enable:function(){this._isEnabled=true},isEnabled:function(){return this._isEnabled},halt:function(){this._shouldPropagate=false},dispatch:function(f){if(!this._isEnabled){return}var c=Array.prototype.slice.call(arguments),g=this._bindings.slice(),d=0,e;this._shouldPropagate=true;while(e=g[d++]){if(e.execute(c)===false||!this._shouldPropagate){break}}},dispose:function(){this.removeAll();delete this._bindings},toString:function(){return"[Signal isEnabled: "+this._isEnabled+" numListeners: "+this.getNumListeners()+"]"}};a.SignalBinding=function b(f,c,e,d){this._listener=f;this._isOnce=c;this.context=e;this._signal=d};a.SignalBinding.prototype={_isEnabled:true,execute:function(c){var d;if(this._isEnabled){d=this._listener.apply(this.context,c);if(this._isOnce){this.detach()}}return d},detach:function(){return this._signal.remove(this._listener)},getListener:function(){return this._listener},dispose:function(){this.detach();this._destroy()},_destroy:function(){delete this._signal;delete this._isOnce;delete this._listener;delete this.context},disable:function(){this._isEnabled=false},enable:function(){this._isEnabled=true},isEnabled:function(){return this._isEnabled},isOnce:function(){return this._isOnce},toString:function(){return"[SignalBinding isOnce: "+this._isOnce+", isEnabled: "+this._isEnabled+"]"}}}()); \ No newline at end of file From 6079634b57c418187c1ad82241315b43287c15f0 Mon Sep 17 00:00:00 2001 From: Miller Medeiros Date: Fri, 3 Dec 2010 17:35:40 -0500 Subject: [PATCH 10/10] added VERSION property, removed a named function, changed structure a little bit to improve docs, updated changelog --- CHANGELOG.markdown | 2 + dev/build/build.number | 4 +- dev/src/SignalBinding.js | 2 +- dev/src/signals.js | 27 +- dist/docs/files.html | 2 +- dist/docs/index.html | 2 +- dist/docs/symbolindex.html | 20 +- dist/docs/symbols/_global_.html | 2 +- dist/docs/symbols/signals.Signal.html | 2 +- dist/docs/symbols/signals.SignalBinding.html | 2 +- dist/docs/symbols/signals.html | 103 ++- ...rojects_js-signals_dist_js-signals.js.html | 719 +++++++++--------- dist/js-signals.js | 31 +- dist/js-signals.min.js | 4 +- 14 files changed, 529 insertions(+), 393 deletions(-) diff --git a/CHANGELOG.markdown b/CHANGELOG.markdown index 160cc7a..de16b29 100644 --- a/CHANGELOG.markdown +++ b/CHANGELOG.markdown @@ -9,6 +9,8 @@ - Added: - `SignalBinding.prototype.getListener()` (issue #3) - `Signal.dispose()` (issue #6) + - `signals.VERSION` + - `signals.isDef()` - Removed: - `SignalBinding.listener` (issue #3) diff --git a/dev/build/build.number b/dev/build/build.number index ac900cb..1ae3ba2 100644 --- a/dev/build/build.number +++ b/dev/build/build.number @@ -1,3 +1,3 @@ #Build Number for ANT. Do not edit! -#Fri Dec 03 17:03:45 EST 2010 -build.number=95 +#Fri Dec 03 17:27:32 EST 2010 +build.number=101 diff --git a/dev/src/SignalBinding.js b/dev/src/SignalBinding.js index 786ba6c..1d397f3 100644 --- a/dev/src/SignalBinding.js +++ b/dev/src/SignalBinding.js @@ -10,7 +10,7 @@ * @param {?Object} listenerContext Context on which listener will be executed (object that should represent the `this` variable inside listener function). * @param {signals.Signal} signal Reference to Signal object that listener is currently bound to. */ - signals.SignalBinding = function SignalBinding(listener, isOnce, listenerContext, signal){ + signals.SignalBinding = function(listener, isOnce, listenerContext, signal){ /** * Handler function bound to the signal. diff --git a/dev/src/signals.js b/dev/src/signals.js index 79c2f95..7bf465c 100644 --- a/dev/src/signals.js +++ b/dev/src/signals.js @@ -1,16 +1,21 @@ - + /** * @namespace Signals Namespace - Custom event/messaging system based on AS3 Signals * @name signals */ - var signals = window.signals = { - - /** - * @param {*} param Parameter to check. - * @return {boolean} `true` if parameter is different than `undefined`. - */ - isDef : function(param){ - return typeof param !== 'undefined'; - } - + var signals = window.signals = {}; + + /** + * Signals Version Number + * @type string + * @const + */ + signals.VERSION = '::VERSION_NUMBER::'; + + /** + * @param {*} param Parameter to check. + * @return {boolean} `true` if parameter is different than `undefined`. + */ + signals.isDef = function(param){ + return typeof param !== 'undefined'; }; \ No newline at end of file diff --git a/dist/docs/files.html b/dist/docs/files.html index 3e6303b..1eae9a3 100644 --- a/dist/docs/files.html +++ b/dist/docs/files.html @@ -61,7 +61,7 @@

    - Documentation generated by JsDoc Toolkit 2.4.0 on Fri Dec 03 2010 16:44:57 GMT-0500 (EST) + Documentation generated by JsDoc Toolkit 2.4.0 on Fri Dec 03 2010 17:27:36 GMT-0500 (EST) | template based on Steffen Siering jsdoc-simple.

    diff --git a/dist/docs/index.html b/dist/docs/index.html index 19f6649..4f4cba0 100644 --- a/dist/docs/index.html +++ b/dist/docs/index.html @@ -85,7 +85,7 @@

    signals.SignalBinding

    - Documentation generated by JsDoc Toolkit 2.4.0 on Fri Dec 03 2010 16:44:57 GMT-0500 (EST) + Documentation generated by JsDoc Toolkit 2.4.0 on Fri Dec 03 2010 17:27:36 GMT-0500 (EST) | template based on Steffen Siering jsdoc-simple.
    diff --git a/dist/docs/symbolindex.html b/dist/docs/symbolindex.html index 72c566f..1c0d66f 100644 --- a/dist/docs/symbolindex.html +++ b/dist/docs/symbolindex.html @@ -202,6 +202,15 @@

    Symbol Index

    + + isDef + + + signals.isDef + + + + isEnabled @@ -278,13 +287,22 @@

    Symbol Index

    + + VERSION + + + signals.VERSION + + + +
    - Documentation generated by JsDoc Toolkit 2.4.0 on Fri Dec 03 2010 16:44:57 GMT-0500 (EST) + Documentation generated by JsDoc Toolkit 2.4.0 on Fri Dec 03 2010 17:27:36 GMT-0500 (EST) | template based on Steffen Siering jsdoc-simple.
    diff --git a/dist/docs/symbols/_global_.html b/dist/docs/symbols/_global_.html index dbed7b1..4d6371e 100644 --- a/dist/docs/symbols/_global_.html +++ b/dist/docs/symbols/_global_.html @@ -101,7 +101,7 @@

    - Documentation generated by JsDoc Toolkit 2.4.0 on Fri Dec 03 2010 16:44:56 GMT-0500 (EST) + Documentation generated by JsDoc Toolkit 2.4.0 on Fri Dec 03 2010 17:27:36 GMT-0500 (EST) | template based on Steffen Siering jsdoc-simple.
    diff --git a/dist/docs/symbols/signals.Signal.html b/dist/docs/symbols/signals.Signal.html index d80faa8..4db473d 100644 --- a/dist/docs/symbols/signals.Signal.html +++ b/dist/docs/symbols/signals.Signal.html @@ -638,7 +638,7 @@

    - Documentation generated by JsDoc Toolkit 2.4.0 on Fri Dec 03 2010 16:44:56 GMT-0500 (EST) + Documentation generated by JsDoc Toolkit 2.4.0 on Fri Dec 03 2010 17:27:36 GMT-0500 (EST) | template based on Steffen Siering jsdoc-simple.
    diff --git a/dist/docs/symbols/signals.SignalBinding.html b/dist/docs/symbols/signals.SignalBinding.html index cc0c554..1ea20a3 100644 --- a/dist/docs/symbols/signals.SignalBinding.html +++ b/dist/docs/symbols/signals.SignalBinding.html @@ -572,7 +572,7 @@

    - Documentation generated by JsDoc Toolkit 2.4.0 on Fri Dec 03 2010 16:44:56 GMT-0500 (EST) + Documentation generated by JsDoc Toolkit 2.4.0 on Fri Dec 03 2010 17:27:36 GMT-0500 (EST) | template based on Steffen Siering jsdoc-simple.
    diff --git a/dist/docs/symbols/signals.html b/dist/docs/symbols/signals.html index f52f904..88fb4b2 100644 --- a/dist/docs/symbols/signals.html +++ b/dist/docs/symbols/signals.html @@ -63,11 +63,29 @@

    +

    Variables

    + + +

    Functions

    + + @@ -126,9 +144,92 @@

    +
    +
    + Field Detail +
    + +
    + +
    +
    <static> +
    + + {string} + signals.VERSION + +
    +
    +

    Signals Version Number

    + + +
    + + + + + + + +
    + +
    + +
    +
    + Method Detail +
    + +
    + +
    +
    <static> +
    + {boolean} + signals.isDef(param) + +
    +
    + + + +
    + + + + +
    +
    Parameters:
    + +
    + {*} param + +
    +
    Parameter to check.
    + +
    + + + + + +
    +
    Returns:
    + +
    {boolean} `true` if parameter is different than `undefined`.
    + +
    + + + + +
    + +
    + @@ -139,7 +240,7 @@

    - Documentation generated by JsDoc Toolkit 2.4.0 on Fri Dec 03 2010 16:44:56 GMT-0500 (EST) + Documentation generated by JsDoc Toolkit 2.4.0 on Fri Dec 03 2010 17:27:36 GMT-0500 (EST) | template based on Steffen Siering jsdoc-simple.
    diff --git a/dist/docs/symbols/src/C__Miller_Personal_open_source_projects_js-signals_dist_js-signals.js.html b/dist/docs/symbols/src/C__Miller_Personal_open_source_projects_js-signals_dist_js-signals.js.html index d20e432..cbbe385 100644 --- a/dist/docs/symbols/src/C__Miller_Personal_open_source_projects_js-signals_dist_js-signals.js.html +++ b/dist/docs/symbols/src/C__Miller_Personal_open_source_projects_js-signals_dist_js-signals.js.html @@ -5,372 +5,377 @@ .STRN {color: #393;} .REGX {color: #339;} .line {border-right: 1px dotted #666; color: #666; font-style: normal;} -
      1 /*!
    +	
      1 /*!!
       2  * JS Signals <https://github.com/millermedeiros/js-signals>
       3  * Released under the MIT license (http://www.opensource.org/licenses/mit-license.php)
       4  * @author Miller Medeiros <http://millermedeiros.com>
       5  * @version 0.5
    -  6  * @build 92 12/03/2010 04:44 PM
    +  6  * @build 100 12/03/2010 05:27 PM
       7  */
       8 (function(){
    -  9 
    +  9 	
      10 	/**
      11 	 * @namespace Signals Namespace - Custom event/messaging system based on AS3 Signals
      12 	 * @name signals
      13 	 */
    - 14 	var signals = window.signals = {
    - 15 		
    - 16 		/**
    - 17 		 * @param {*} param	Parameter to check.
    - 18 		 * @return {boolean} `true` if parameter is different than `undefined`.
    - 19 		 */
    - 20 		isDef : function(param){
    - 21 			return typeof param !== 'undefined';
    - 22 		}
    - 23 		
    - 24 	};
    - 25 
    - 26 	/**
    - 27 	 * Signal - custom event broadcaster
    - 28 	 * <br />- inspired by Robert Penner's AS3 Signals.
    - 29 	 * @author Miller Medeiros
    - 30 	 * @constructor
    - 31 	 */
    - 32 	signals.Signal = function(){
    - 33 		/**
    - 34 		 * @type Array.<signals.SignalBinding>
    - 35 		 * @private
    - 36 		 */
    - 37 		this._bindings = [];
    - 38 	};
    - 39 	
    - 40 	
    - 41 	signals.Signal.prototype = {
    - 42 		
    - 43 		/**
    - 44 		 * @type boolean
    - 45 		 * @private
    - 46 		 */
    - 47 		_shouldPropagate : true,
    - 48 		
    - 49 		/**
    - 50 		 * @type boolean
    - 51 		 * @private
    - 52 		 */
    - 53 		_isEnabled : true,
    - 54 		
    - 55 		/**
    - 56 		 * @param {Function} listener
    - 57 		 * @param {boolean} isOnce
    - 58 		 * @param {Object} [scope]
    - 59 		 * @return {signals.SignalBinding}
    - 60 		 * @private
    - 61 		 */
    - 62 		_registerListener : function(listener, isOnce, scope){
    - 63 			
    - 64 			if(!signals.isDef(listener)) throw new Error('listener is a required param of add() and addOnce().');
    - 65 			
    - 66 			var prevIndex = this._indexOfListener(listener),
    - 67 				binding;
    + 14 	var signals = window.signals = {};
    + 15 	
    + 16 	/**
    + 17 	 * Signals Version Number
    + 18 	 * @type string
    + 19 	 * @const
    + 20 	 */
    + 21 	signals.VERSION = '0.5';
    + 22 	
    + 23 	/**
    + 24 	 * @param {*} param	Parameter to check.
    + 25 	 * @return {boolean} `true` if parameter is different than `undefined`.
    + 26 	 */
    + 27 	signals.isDef = function(param){
    + 28 		return typeof param !== 'undefined';
    + 29 	};
    + 30 
    + 31 	/**
    + 32 	 * Signal - custom event broadcaster
    + 33 	 * <br />- inspired by Robert Penner's AS3 Signals.
    + 34 	 * @author Miller Medeiros
    + 35 	 * @constructor
    + 36 	 */
    + 37 	signals.Signal = function(){
    + 38 		/**
    + 39 		 * @type Array.<signals.SignalBinding>
    + 40 		 * @private
    + 41 		 */
    + 42 		this._bindings = [];
    + 43 	};
    + 44 	
    + 45 	
    + 46 	signals.Signal.prototype = {
    + 47 		
    + 48 		/**
    + 49 		 * @type boolean
    + 50 		 * @private
    + 51 		 */
    + 52 		_shouldPropagate : true,
    + 53 		
    + 54 		/**
    + 55 		 * @type boolean
    + 56 		 * @private
    + 57 		 */
    + 58 		_isEnabled : true,
    + 59 		
    + 60 		/**
    + 61 		 * @param {Function} listener
    + 62 		 * @param {boolean} isOnce
    + 63 		 * @param {Object} [scope]
    + 64 		 * @return {signals.SignalBinding}
    + 65 		 * @private
    + 66 		 */
    + 67 		_registerListener : function(listener, isOnce, scope){
      68 			
    - 69 			if(prevIndex !== -1){ //avoid creating a new Binding for same listener if already added to list
    - 70 				binding = this._bindings[prevIndex];
    - 71 				if(binding.isOnce() !== isOnce){
    - 72 					throw new Error('You cannot add'+ (isOnce? '' : 'Once') +'() then add'+ (!isOnce? '' : 'Once') +'() the same listener without removing the relationship first.');
    - 73 				}
    - 74 			} else {
    - 75 				binding = new signals.SignalBinding(listener, isOnce, scope, this);
    - 76 				this._addBinding(binding);
    - 77 			}
    - 78 			
    - 79 			return binding;
    - 80 		},
    - 81 		
    - 82 		/**
    - 83 		 * @param {signals.SignalBinding} binding
    - 84 		 * @private
    - 85 		 */
    - 86 		_addBinding : function(binding){
    - 87 			this._bindings.push(binding);
    - 88 		},
    - 89 		
    - 90 		/**
    - 91 		 * @param {Function} listener
    - 92 		 * @return {int}
    - 93 		 * @private
    - 94 		 */
    - 95 		_indexOfListener : function(listener){
    - 96 			var n = this._bindings.length;
    - 97 			while(n--){
    - 98 				if(this._bindings[n]._listener === listener) return n;
    - 99 			}
    -100 			return -1;
    -101 		},
    -102 		
    -103 		/**
    -104 		 * Add a listener to the signal.
    -105 		 * @param {Function} listener	Signal handler function.
    -106 		 * @param {Object} [scope]	Context on which listener will be executed (object that should represent the `this` variable inside listener function).
    -107 		 * @return {signals.SignalBinding} An Object representing the binding between the Signal and listener.
    -108 		 */
    -109 		add : function(listener, scope){
    -110 			return this._registerListener(listener, false, scope);
    -111 		},
    -112 		
    -113 		/**
    -114 		 * Add listener to the signal that should be removed after first execution (will be executed only once).
    -115 		 * @param {Function} listener	Signal handler function.
    -116 		 * @param {Object} [scope]	Context on which listener will be executed (object that should represent the `this` variable inside listener function).
    -117 		 * @return {signals.SignalBinding} An Object representing the binding between the Signal and listener.
    -118 		 */
    -119 		addOnce : function(listener, scope){
    -120 			return this._registerListener(listener, true, scope);
    -121 		},
    -122 		
    -123 		/**
    -124 		 * @private
    -125 		 */
    -126 		_removeByIndex : function(i){
    -127 			this._bindings[i]._destroy(); //no reason to a SignalBinding exist if it isn't attached to a signal
    -128 			this._bindings.splice(i, 1);
    -129 		},
    -130 		
    -131 		/**
    -132 		 * Remove a single listener from the dispatch queue.
    -133 		 * @param {Function} listener	Handler function that should be removed.
    -134 		 * @return {Function} Listener handler function.
    -135 		 */
    -136 		remove : function(listener){
    -137 			if(!signals.isDef(listener)) throw new Error('listener is a required param of remove().');
    -138 			
    -139 			var i = this._indexOfListener(listener);
    -140 			if(i !== -1) this._removeByIndex(i);
    -141 			return listener;
    -142 		},
    -143 		
    -144 		/**
    -145 		 * Remove all listeners from the Signal.
    -146 		 */
    -147 		removeAll : function(){
    -148 			var n = this._bindings.length;
    -149 			while(n--){
    -150 				this._removeByIndex(n);
    -151 			}
    -152 		},
    -153 		
    -154 		/**
    -155 		 * @return {uint} Number of listeners attached to the Signal.
    -156 		 */
    -157 		getNumListeners : function(){
    -158 			return this._bindings.length;
    -159 		},
    -160 		
    -161 		/**
    -162 		 * Disable Signal, will block dispatch to listeners until `enable()` is called.
    -163 		 * @see signals.Signal.prototype.enable
    -164 		 */
    -165 		disable : function(){
    -166 			this._isEnabled = false;
    -167 		},
    -168 		
    -169 		/**
    -170 		 * Enable broadcast to listeners.
    -171 		 * @see signals.Signal.prototype.disable
    -172 		 */
    -173 		enable : function(){
    -174 			this._isEnabled = true;
    -175 		}, 
    -176 		
    -177 		/**
    -178 		 * @return {boolean} If Signal is currently enabled and will broadcast message to listeners.
    -179 		 */
    -180 		isEnabled : function(){
    -181 			return this._isEnabled;
    -182 		},
    -183 		
    -184 		/**
    -185 		 * Stop propagation of the event, blocking the dispatch to next listeners on the queue.
    -186 		 * - should be called only during signal dispatch, calling it before/after dispatch won't affect signal broadcast. 
    -187 		 */
    -188 		halt : function(){
    -189 			this._shouldPropagate = false;
    -190 		},
    -191 		
    -192 		/**
    -193 		 * Dispatch/Broadcast Signal to all listeners added to the queue. 
    -194 		 * @param {...*} [params]	Parameters that should be passed to each handler.
    -195 		 */
    -196 		dispatch : function(params){
    -197 			if(! this._isEnabled) return;
    -198 			
    -199 			var paramsArr = Array.prototype.slice.call(arguments),
    -200 				bindings = this._bindings.slice(), //clone array in case add/remove items during dispatch
    -201 				i = 0,
    -202 				cur;
    + 69 			if(!signals.isDef(listener)) throw new Error('listener is a required param of add() and addOnce().');
    + 70 			
    + 71 			var prevIndex = this._indexOfListener(listener),
    + 72 				binding;
    + 73 			
    + 74 			if(prevIndex !== -1){ //avoid creating a new Binding for same listener if already added to list
    + 75 				binding = this._bindings[prevIndex];
    + 76 				if(binding.isOnce() !== isOnce){
    + 77 					throw new Error('You cannot add'+ (isOnce? '' : 'Once') +'() then add'+ (!isOnce? '' : 'Once') +'() the same listener without removing the relationship first.');
    + 78 				}
    + 79 			} else {
    + 80 				binding = new signals.SignalBinding(listener, isOnce, scope, this);
    + 81 				this._addBinding(binding);
    + 82 			}
    + 83 			
    + 84 			return binding;
    + 85 		},
    + 86 		
    + 87 		/**
    + 88 		 * @param {signals.SignalBinding} binding
    + 89 		 * @private
    + 90 		 */
    + 91 		_addBinding : function(binding){
    + 92 			this._bindings.push(binding);
    + 93 		},
    + 94 		
    + 95 		/**
    + 96 		 * @param {Function} listener
    + 97 		 * @return {int}
    + 98 		 * @private
    + 99 		 */
    +100 		_indexOfListener : function(listener){
    +101 			var n = this._bindings.length;
    +102 			while(n--){
    +103 				if(this._bindings[n]._listener === listener) return n;
    +104 			}
    +105 			return -1;
    +106 		},
    +107 		
    +108 		/**
    +109 		 * Add a listener to the signal.
    +110 		 * @param {Function} listener	Signal handler function.
    +111 		 * @param {Object} [scope]	Context on which listener will be executed (object that should represent the `this` variable inside listener function).
    +112 		 * @return {signals.SignalBinding} An Object representing the binding between the Signal and listener.
    +113 		 */
    +114 		add : function(listener, scope){
    +115 			return this._registerListener(listener, false, scope);
    +116 		},
    +117 		
    +118 		/**
    +119 		 * Add listener to the signal that should be removed after first execution (will be executed only once).
    +120 		 * @param {Function} listener	Signal handler function.
    +121 		 * @param {Object} [scope]	Context on which listener will be executed (object that should represent the `this` variable inside listener function).
    +122 		 * @return {signals.SignalBinding} An Object representing the binding between the Signal and listener.
    +123 		 */
    +124 		addOnce : function(listener, scope){
    +125 			return this._registerListener(listener, true, scope);
    +126 		},
    +127 		
    +128 		/**
    +129 		 * @private
    +130 		 */
    +131 		_removeByIndex : function(i){
    +132 			this._bindings[i]._destroy(); //no reason to a SignalBinding exist if it isn't attached to a signal
    +133 			this._bindings.splice(i, 1);
    +134 		},
    +135 		
    +136 		/**
    +137 		 * Remove a single listener from the dispatch queue.
    +138 		 * @param {Function} listener	Handler function that should be removed.
    +139 		 * @return {Function} Listener handler function.
    +140 		 */
    +141 		remove : function(listener){
    +142 			if(!signals.isDef(listener)) throw new Error('listener is a required param of remove().');
    +143 			
    +144 			var i = this._indexOfListener(listener);
    +145 			if(i !== -1) this._removeByIndex(i);
    +146 			return listener;
    +147 		},
    +148 		
    +149 		/**
    +150 		 * Remove all listeners from the Signal.
    +151 		 */
    +152 		removeAll : function(){
    +153 			var n = this._bindings.length;
    +154 			while(n--){
    +155 				this._removeByIndex(n);
    +156 			}
    +157 		},
    +158 		
    +159 		/**
    +160 		 * @return {uint} Number of listeners attached to the Signal.
    +161 		 */
    +162 		getNumListeners : function(){
    +163 			return this._bindings.length;
    +164 		},
    +165 		
    +166 		/**
    +167 		 * Disable Signal, will block dispatch to listeners until `enable()` is called.
    +168 		 * @see signals.Signal.prototype.enable
    +169 		 */
    +170 		disable : function(){
    +171 			this._isEnabled = false;
    +172 		},
    +173 		
    +174 		/**
    +175 		 * Enable broadcast to listeners.
    +176 		 * @see signals.Signal.prototype.disable
    +177 		 */
    +178 		enable : function(){
    +179 			this._isEnabled = true;
    +180 		}, 
    +181 		
    +182 		/**
    +183 		 * @return {boolean} If Signal is currently enabled and will broadcast message to listeners.
    +184 		 */
    +185 		isEnabled : function(){
    +186 			return this._isEnabled;
    +187 		},
    +188 		
    +189 		/**
    +190 		 * Stop propagation of the event, blocking the dispatch to next listeners on the queue.
    +191 		 * - should be called only during signal dispatch, calling it before/after dispatch won't affect signal broadcast. 
    +192 		 */
    +193 		halt : function(){
    +194 			this._shouldPropagate = false;
    +195 		},
    +196 		
    +197 		/**
    +198 		 * Dispatch/Broadcast Signal to all listeners added to the queue. 
    +199 		 * @param {...*} [params]	Parameters that should be passed to each handler.
    +200 		 */
    +201 		dispatch : function(params){
    +202 			if(! this._isEnabled) return;
     203 			
    -204 			this._shouldPropagate = true; //in case `halt` was called before dispatch or during the previous dispatch.
    -205 						
    -206 			while(cur = bindings[i++]){
    -207 				if(cur.execute(paramsArr) === false || !this._shouldPropagate) break; //execute all callbacks until end of the list or until a callback returns `false` or stops propagation
    -208 			}
    -209 		},
    -210 		
    -211 		/**
    -212 		 * Remove binding from signal and destroy any reference to external Objects (destroy Signal object).
    -213 		 * <br /> - calling methods on the signal instance after calling dispose will throw errors.
    -214 		 */
    -215 		dispose : function(){
    -216 			this.removeAll();
    -217 			delete this._bindings;
    -218 		},
    -219 		
    -220 		/**
    -221 		 * @return {string} String representation of the object.
    -222 		 */
    -223 		toString : function(){
    -224 			return '[Signal isEnabled: '+ this._isEnabled +' numListeners: '+ this.getNumListeners() +']';
    -225 		}
    -226 		
    -227 	};
    -228 	
    -229 	/**
    -230 	 * Object that represents a binding between a Signal and a listener function.
    -231 	 * <br />- <strong>Constructor shouldn't be called by regular user, used internally.</strong>
    -232 	 * <br />- inspired by Joa Ebert AS3 SignalBinding and Robert Penner's Slot classes.
    -233 	 * @author Miller Medeiros
    -234 	 * @constructor
    -235 	 * @param {Function} listener	Handler function bound to the signal.
    -236 	 * @param {boolean} isOnce	If binding should be executed just once.
    -237 	 * @param {?Object} listenerContext	Context on which listener will be executed (object that should represent the `this` variable inside listener function).
    -238 	 * @param {signals.Signal} signal	Reference to Signal object that listener is currently bound to.
    -239 	 */
    -240 	signals.SignalBinding = function SignalBinding(listener, isOnce, listenerContext, signal){
    -241 		
    -242 		/**
    -243 		 * Handler function bound to the signal.
    -244 		 * @type Function
    -245 		 * @private
    -246 		 */
    -247 		this._listener = listener;
    -248 		
    -249 		/**
    -250 		 * If binding should be executed just once.
    -251 		 * @type boolean
    -252 		 * @private
    -253 		 */
    -254 		this._isOnce = isOnce;
    -255 		
    -256 		/**
    -257 		 * Context on which listener will be executed (object that should represent the `this` variable inside listener function).
    -258 		 * @type Object
    -259 		 */
    -260 		this.context = listenerContext;
    -261 		
    -262 		/**
    -263 		 * Reference to Signal object that listener is currently bound to.
    -264 		 * @type signals.Signal
    -265 		 * @private
    -266 		 */
    -267 		this._signal = signal;
    -268 	};
    -269 	
    -270 	
    -271 	signals.SignalBinding.prototype = {
    -272 		
    -273 		/**
    -274 		 * @type boolean
    -275 		 * @private
    -276 		 */
    -277 		_isEnabled : true,
    -278 		
    -279 		/**
    -280 		 * Call listener passing arbitrary parameters.
    -281 		 * <p>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.</p> 
    -282 		 * @param {Array} [paramsArr]	Array of parameters that should be passed to the listener
    -283 		 * @return {*} Value returned by the listener.
    -284 		 */
    -285 		execute : function(paramsArr){
    -286 			var r;
    -287 			if(this._isEnabled){
    -288 				r = this._listener.apply(this.context, paramsArr);
    -289 				if(this._isOnce) this.detach();
    -290 			}
    -291 			return r; //avoid warnings on some editors
    -292 		},
    -293 		
    -294 		/**
    -295 		 * Detach binding from signal.
    -296 		 * - alias to: mySignal.remove(myBinding.getListener());
    -297 		 * @return {Function} Handler function bound to the signal.
    -298 		 */
    -299 		detach : function(){
    -300 			return this._signal.remove(this._listener);
    -301 		},
    -302 		
    -303 		/**
    -304 		 * @return {Function} Handler function bound to the signal.
    -305 		 */
    -306 		getListener : function(){
    -307 			return this._listener;
    -308 		},
    -309 		
    -310 		/**
    -311 		 * Remove binding from signal and destroy any reference to external Objects (destroy SignalBinding object).
    -312 		 * <br /> - calling methods on the binding instance after calling dispose will throw errors.
    -313 		 */
    -314 		dispose : function(){
    -315 			this.detach();
    -316 			this._destroy();
    -317 		},
    -318 		
    -319 		/**
    -320 		 * Delete all instance properties
    -321 		 * @private
    -322 		 */
    -323 		_destroy : function(){
    -324 			delete this._signal;
    -325 			delete this._isOnce;
    -326 			delete this._listener;
    -327 			delete this.context;
    -328 		},
    -329 		
    -330 		/**
    -331 		 * Disable SignalBinding, block listener execution. Listener will only be executed after calling `enable()`.  
    -332 		 * @see signals.SignalBinding.enable()
    -333 		 */
    -334 		disable : function(){
    -335 			this._isEnabled = false;
    -336 		},
    -337 		
    -338 		/**
    -339 		 * Enable SignalBinding. Enable listener execution.
    -340 		 * @see signals.SignalBinding.disable()
    -341 		 */
    -342 		enable : function(){
    -343 			this._isEnabled = true;
    -344 		},
    -345 		
    -346 		/**
    -347 		 * @return {boolean} If SignalBinding is currently paused and won't execute listener during dispatch.
    -348 		 */
    -349 		isEnabled : function(){
    -350 			return this._isEnabled;
    -351 		},
    -352 		
    -353 		/**
    -354 		 * @return {boolean} If SignalBinding will only be executed once.
    -355 		 */
    -356 		isOnce : function(){
    -357 			return this._isOnce;
    -358 		},
    -359 		
    -360 		/**
    -361 		 * @return {string} String representation of the object.
    -362 		 */
    -363 		toString : function(){
    -364 			return '[SignalBinding isOnce: '+ this._isOnce +', isEnabled: '+ this._isEnabled +']';
    -365 		}
    -366 		
    -367 	};
    -368 }());
    -369 
    \ No newline at end of file +204
    var paramsArr = Array.prototype.slice.call(arguments), +205 bindings = this._bindings.slice(), //clone array in case add/remove items during dispatch +206 i = 0, +207 cur; +208 +209 this._shouldPropagate = true; //in case `halt` was called before dispatch or during the previous dispatch. +210 +211 while(cur = bindings[i++]){ +212 if(cur.execute(paramsArr) === false || !this._shouldPropagate) break; //execute all callbacks until end of the list or until a callback returns `false` or stops propagation +213 } +214 }, +215 +216 /** +217 * Remove binding from signal and destroy any reference to external Objects (destroy Signal object). +218 * <br /> - calling methods on the signal instance after calling dispose will throw errors. +219 */ +220 dispose : function(){ +221 this.removeAll(); +222 delete this._bindings; +223 }, +224 +225 /** +226 * @return {string} String representation of the object. +227 */ +228 toString : function(){ +229 return '[Signal isEnabled: '+ this._isEnabled +' numListeners: '+ this.getNumListeners() +']'; +230 } +231 +232 }; +233 +234 /** +235 * Object that represents a binding between a Signal and a listener function. +236 * <br />- <strong>Constructor shouldn't be called by regular user, used internally.</strong> +237 * <br />- inspired by Joa Ebert AS3 SignalBinding and Robert Penner's Slot classes. +238 * @author Miller Medeiros +239 * @constructor +240 * @param {Function} listener Handler function bound to the signal. +241 * @param {boolean} isOnce If binding should be executed just once. +242 * @param {?Object} listenerContext Context on which listener will be executed (object that should represent the `this` variable inside listener function). +243 * @param {signals.Signal} signal Reference to Signal object that listener is currently bound to. +244 */ +245 signals.SignalBinding = function(listener, isOnce, listenerContext, signal){ +246 +247 /** +248 * Handler function bound to the signal. +249 * @type Function +250 * @private +251 */ +252 this._listener = listener; +253 +254 /** +255 * If binding should be executed just once. +256 * @type boolean +257 * @private +258 */ +259 this._isOnce = isOnce; +260 +261 /** +262 * Context on which listener will be executed (object that should represent the `this` variable inside listener function). +263 * @type Object +264 */ +265 this.context = listenerContext; +266 +267 /** +268 * Reference to Signal object that listener is currently bound to. +269 * @type signals.Signal +270 * @private +271 */ +272 this._signal = signal; +273 }; +274 +275 +276 signals.SignalBinding.prototype = { +277 +278 /** +279 * @type boolean +280 * @private +281 */ +282 _isEnabled : true, +283 +284 /** +285 * Call listener passing arbitrary parameters. +286 * <p>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.</p> +287 * @param {Array} [paramsArr] Array of parameters that should be passed to the listener +288 * @return {*} Value returned by the listener. +289 */ +290 execute : function(paramsArr){ +291 var r; +292 if(this._isEnabled){ +293 r = this._listener.apply(this.context, paramsArr); +294 if(this._isOnce) this.detach(); +295 } +296 return r; //avoid warnings on some editors +297 }, +298 +299 /** +300 * Detach binding from signal. +301 * - alias to: mySignal.remove(myBinding.getListener()); +302 * @return {Function} Handler function bound to the signal. +303 */ +304 detach : function(){ +305 return this._signal.remove(this._listener); +306 }, +307 +308 /** +309 * @return {Function} Handler function bound to the signal. +310 */ +311 getListener : function(){ +312 return this._listener; +313 }, +314 +315 /** +316 * Remove binding from signal and destroy any reference to external Objects (destroy SignalBinding object). +317 * <br /> - calling methods on the binding instance after calling dispose will throw errors. +318 */ +319 dispose : function(){ +320 this.detach(); +321 this._destroy(); +322 }, +323 +324 /** +325 * Delete all instance properties +326 * @private +327 */ +328 _destroy : function(){ +329 delete this._signal; +330 delete this._isOnce; +331 delete this._listener; +332 delete this.context; +333 }, +334 +335 /** +336 * Disable SignalBinding, block listener execution. Listener will only be executed after calling `enable()`. +337 * @see signals.SignalBinding.enable() +338 */ +339 disable : function(){ +340 this._isEnabled = false; +341 }, +342 +343 /** +344 * Enable SignalBinding. Enable listener execution. +345 * @see signals.SignalBinding.disable() +346 */ +347 enable : function(){ +348 this._isEnabled = true; +349 }, +350 +351 /** +352 * @return {boolean} If SignalBinding is currently paused and won't execute listener during dispatch. +353 */ +354 isEnabled : function(){ +355 return this._isEnabled; +356 }, +357 +358 /** +359 * @return {boolean} If SignalBinding will only be executed once. +360 */ +361 isOnce : function(){ +362 return this._isOnce; +363 }, +364 +365 /** +366 * @return {string} String representation of the object. +367 */ +368 toString : function(){ +369 return '[SignalBinding isOnce: '+ this._isOnce +', isEnabled: '+ this._isEnabled +']'; +370 } +371 +372 }; +373 }()); +374
    \ No newline at end of file diff --git a/dist/js-signals.js b/dist/js-signals.js index 2b30bf3..d5dc76f 100644 --- a/dist/js-signals.js +++ b/dist/js-signals.js @@ -3,24 +3,29 @@ * Released under the MIT license (http://www.opensource.org/licenses/mit-license.php) * @author Miller Medeiros * @version 0.5 - * @build 94 12/03/2010 05:03 PM + * @build 100 12/03/2010 05:27 PM */ (function(){ - + /** * @namespace Signals Namespace - Custom event/messaging system based on AS3 Signals * @name signals */ - var signals = window.signals = { - - /** - * @param {*} param Parameter to check. - * @return {boolean} `true` if parameter is different than `undefined`. - */ - isDef : function(param){ - return typeof param !== 'undefined'; - } - + var signals = window.signals = {}; + + /** + * Signals Version Number + * @type string + * @const + */ + signals.VERSION = '0.5'; + + /** + * @param {*} param Parameter to check. + * @return {boolean} `true` if parameter is different than `undefined`. + */ + signals.isDef = function(param){ + return typeof param !== 'undefined'; }; /** @@ -237,7 +242,7 @@ * @param {?Object} listenerContext Context on which listener will be executed (object that should represent the `this` variable inside listener function). * @param {signals.Signal} signal Reference to Signal object that listener is currently bound to. */ - signals.SignalBinding = function SignalBinding(listener, isOnce, listenerContext, signal){ + signals.SignalBinding = function(listener, isOnce, listenerContext, signal){ /** * Handler function bound to the signal. diff --git a/dist/js-signals.min.js b/dist/js-signals.min.js index ebb3c18..64a4dae 100644 --- a/dist/js-signals.min.js +++ b/dist/js-signals.min.js @@ -3,6 +3,6 @@ * Released under the MIT license (http://www.opensource.org/licenses/mit-license.php) * @author Miller Medeiros * @version 0.5 - * @build 94 12/03/2010 05:03 PM + * @build 100 12/03/2010 05:27 PM */ -(function(){var a=window.signals={isDef:function(c){return typeof c!=="undefined"}};a.Signal=function(){this._bindings=[]};a.Signal.prototype={_shouldPropagate:true,_isEnabled:true,_registerListener:function(f,e,d){if(!a.isDef(f)){throw new Error("listener is a required param of add() and addOnce().")}var c=this._indexOfListener(f),g;if(c!==-1){g=this._bindings[c];if(g.isOnce()!==e){throw new Error("You cannot add"+(e?"":"Once")+"() then add"+(!e?"":"Once")+"() the same listener without removing the relationship first.")}}else{g=new a.SignalBinding(f,e,d,this);this._addBinding(g)}return g},_addBinding:function(c){this._bindings.push(c)},_indexOfListener:function(c){var d=this._bindings.length;while(d--){if(this._bindings[d]._listener===c){return d}}return -1},add:function(d,c){return this._registerListener(d,false,c)},addOnce:function(d,c){return this._registerListener(d,true,c)},_removeByIndex:function(c){this._bindings[c]._destroy();this._bindings.splice(c,1)},remove:function(d){if(!a.isDef(d)){throw new Error("listener is a required param of remove().")}var c=this._indexOfListener(d);if(c!==-1){this._removeByIndex(c)}return d},removeAll:function(){var c=this._bindings.length;while(c--){this._removeByIndex(c)}},getNumListeners:function(){return this._bindings.length},disable:function(){this._isEnabled=false},enable:function(){this._isEnabled=true},isEnabled:function(){return this._isEnabled},halt:function(){this._shouldPropagate=false},dispatch:function(f){if(!this._isEnabled){return}var c=Array.prototype.slice.call(arguments),g=this._bindings.slice(),d=0,e;this._shouldPropagate=true;while(e=g[d++]){if(e.execute(c)===false||!this._shouldPropagate){break}}},dispose:function(){this.removeAll();delete this._bindings},toString:function(){return"[Signal isEnabled: "+this._isEnabled+" numListeners: "+this.getNumListeners()+"]"}};a.SignalBinding=function b(f,c,e,d){this._listener=f;this._isOnce=c;this.context=e;this._signal=d};a.SignalBinding.prototype={_isEnabled:true,execute:function(c){var d;if(this._isEnabled){d=this._listener.apply(this.context,c);if(this._isOnce){this.detach()}}return d},detach:function(){return this._signal.remove(this._listener)},getListener:function(){return this._listener},dispose:function(){this.detach();this._destroy()},_destroy:function(){delete this._signal;delete this._isOnce;delete this._listener;delete this.context},disable:function(){this._isEnabled=false},enable:function(){this._isEnabled=true},isEnabled:function(){return this._isEnabled},isOnce:function(){return this._isOnce},toString:function(){return"[SignalBinding isOnce: "+this._isOnce+", isEnabled: "+this._isEnabled+"]"}}}()); \ No newline at end of file +(function(){var a=window.signals={};a.VERSION="0.5";a.isDef=function(b){return typeof b!=="undefined"};a.Signal=function(){this._bindings=[]};a.Signal.prototype={_shouldPropagate:true,_isEnabled:true,_registerListener:function(e,d,c){if(!a.isDef(e)){throw new Error("listener is a required param of add() and addOnce().")}var b=this._indexOfListener(e),f;if(b!==-1){f=this._bindings[b];if(f.isOnce()!==d){throw new Error("You cannot add"+(d?"":"Once")+"() then add"+(!d?"":"Once")+"() the same listener without removing the relationship first.")}}else{f=new a.SignalBinding(e,d,c,this);this._addBinding(f)}return f},_addBinding:function(b){this._bindings.push(b)},_indexOfListener:function(b){var c=this._bindings.length;while(c--){if(this._bindings[c]._listener===b){return c}}return -1},add:function(c,b){return this._registerListener(c,false,b)},addOnce:function(c,b){return this._registerListener(c,true,b)},_removeByIndex:function(b){this._bindings[b]._destroy();this._bindings.splice(b,1)},remove:function(c){if(!a.isDef(c)){throw new Error("listener is a required param of remove().")}var b=this._indexOfListener(c);if(b!==-1){this._removeByIndex(b)}return c},removeAll:function(){var b=this._bindings.length;while(b--){this._removeByIndex(b)}},getNumListeners:function(){return this._bindings.length},disable:function(){this._isEnabled=false},enable:function(){this._isEnabled=true},isEnabled:function(){return this._isEnabled},halt:function(){this._shouldPropagate=false},dispatch:function(e){if(!this._isEnabled){return}var b=Array.prototype.slice.call(arguments),f=this._bindings.slice(),c=0,d;this._shouldPropagate=true;while(d=f[c++]){if(d.execute(b)===false||!this._shouldPropagate){break}}},dispose:function(){this.removeAll();delete this._bindings},toString:function(){return"[Signal isEnabled: "+this._isEnabled+" numListeners: "+this.getNumListeners()+"]"}};a.SignalBinding=function(e,b,d,c){this._listener=e;this._isOnce=b;this.context=d;this._signal=c};a.SignalBinding.prototype={_isEnabled:true,execute:function(b){var c;if(this._isEnabled){c=this._listener.apply(this.context,b);if(this._isOnce){this.detach()}}return c},detach:function(){return this._signal.remove(this._listener)},getListener:function(){return this._listener},dispose:function(){this.detach();this._destroy()},_destroy:function(){delete this._signal;delete this._isOnce;delete this._listener;delete this.context},disable:function(){this._isEnabled=false},enable:function(){this._isEnabled=true},isEnabled:function(){return this._isEnabled},isOnce:function(){return this._isOnce},toString:function(){return"[SignalBinding isOnce: "+this._isOnce+", isEnabled: "+this._isEnabled+"]"}}}()); \ No newline at end of file