Created
March 10, 2011 01:41
-
-
Save millermedeiros/863421 to your computer and use it in GitHub Desktop.
JS-Signals 0.5.3
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/*jslint onevar:true, undef:true, newcap:true, regexp:true, bitwise:true, maxerr:50, indent:4, white:false, nomen:false, plusplus:false */ | |
/*!! | |
* JS Signals <http://millermedeiros.github.com/js-signals/> | |
* Released under the MIT license <http://www.opensource.org/licenses/mit-license.php> | |
* @author Miller Medeiros <http://millermedeiros.com/> | |
* @version 0.5.3 | |
* @build 143 (02/21/2011 07:18 PM) | |
*/ | |
var signals = (function(){ | |
var signals = { | |
VERSION : '0.5.3' | |
}; | |
// SignalBinding ------------------------------------------------- | |
//================================================================ | |
function SignalBinding(signal, listener, isOnce, listenerContext, priority){ | |
this._listener = listener; | |
this._isOnce = isOnce; | |
this.context = listenerContext; | |
this._signal = signal; | |
this._priority = priority || 0; | |
} | |
SignalBinding.prototype = { | |
_isEnabled : true, | |
execute : function(paramsArr){ | |
var r; | |
if(this._isEnabled){ | |
r = this._listener.apply(this.context, paramsArr); | |
if(this._isOnce){ | |
this.detach(); | |
} | |
} | |
return r; | |
}, | |
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 +']'; | |
} | |
}; | |
// Signal -------------------------------------------------------- | |
//================================================================ | |
signals.Signal = function(){ | |
this._bindings = []; | |
}; | |
signals.Signal.prototype = { | |
_shouldPropagate : true, | |
_isEnabled : true, | |
_registerListener : function(listener, isOnce, scope, priority){ | |
if(typeof listener !== 'function'){ | |
throw new Error('listener is a required param of add() and addOnce() and should be a Function.'); | |
} | |
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 add'+ (isOnce? '' : 'Once') +'() then add'+ (!isOnce? '' : 'Once') +'() the same listener without removing the relationship first.'); | |
} | |
} else { | |
binding = new SignalBinding(this, listener, isOnce, scope, priority); | |
this._addBinding(binding); | |
} | |
return binding; | |
}, | |
_addBinding : function(binding){ | |
//simplified insertion sort | |
var n = this._bindings.length; | |
do { --n; } while (this._bindings[n] && binding._priority <= this._bindings[n]._priority); | |
this._bindings.splice(n+1, 0, binding); | |
}, | |
_indexOfListener : function(listener){ | |
var n = this._bindings.length; | |
while(n--){ | |
if(this._bindings[n]._listener === listener){ | |
return n; | |
} | |
} | |
return -1; | |
}, | |
add : function(listener, scope, priority){ | |
return this._registerListener(listener, false, scope, priority); | |
}, | |
addOnce : function(listener, scope, priority){ | |
return this._registerListener(listener, true, scope, priority); | |
}, | |
remove : function(listener){ | |
if(typeof listener !== 'function'){ | |
throw new Error('listener is a required param of remove() and should be a Function.'); | |
} | |
var i = this._indexOfListener(listener); | |
if(i !== -1){ | |
this._bindings[i]._destroy(); //no reason to a SignalBinding exist if it isn't attached to a signal | |
this._bindings.splice(i, 1); | |
} | |
return listener; | |
}, | |
removeAll : function(){ | |
var n = this._bindings.length; | |
while(n--){ | |
this._bindings[n]._destroy(); | |
} | |
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(params){ | |
if(! this._isEnabled){ | |
return; | |
} | |
var paramsArr = Array.prototype.slice.call(arguments), | |
bindings = this._bindings.slice(), //clone array in case add/remove items during dispatch | |
n = this._bindings.length; | |
this._shouldPropagate = true; //in case `halt` was called before dispatch or during the previous dispatch. | |
//execute all callbacks until end of the list or until a callback returns `false` or stops propagation | |
//reverse loop since listeners with higher priority will be added at the end of the list | |
do { n--; } while (bindings[n] && this._shouldPropagate && bindings[n].execute(paramsArr) !== false); | |
}, | |
dispose : function(){ | |
this.removeAll(); | |
delete this._bindings; | |
}, | |
toString : function(){ | |
return '[Signal isEnabled: '+ this._isEnabled +' numListeners: '+ this.getNumListeners() +']'; | |
} | |
}; | |
return signals; | |
}()); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
used as example on this post: http://blog.millermedeiros.com/2011/03/inline-documentation-why-im-ditching-it/