Example pub/sub - similar to jQuery.Callbacks()
(function(a){function b(a,b,c){this.signal=a,this.ctx=c,this.cb=b,this.active=!0}function c(a){this.slots=[],this.strict=a===!0?!0:!1}b.prototype={execute:function(){var a=this.cb.apply(this.ctx,arguments);return this.once===!0&&this.destroy(),a},destroy:function(){this.signal.remove(this.cb)}},c.prototype={add:function(a){var c,d;if(this.strict===!0){d=this.findCon(a);if(d>-1)throw new Error("Duplicate Slot added to strict Signal")}return c=new b(this,a,arguments.length>1?arguments[1]:this),this.slots.push(c),c},addOnce:function(a){var b=this.add.apply(this,arguments);return b.once=!0,b},dispatch:function(){var a=this.slots.slice(),b=a.length,c,d,e;for(c=0;c<b;c++){e=a[c],e.active===!0&&(d=e.execute.apply(e,arguments));if(d===!1)break}},remove:function(a){var b=this.findCon(a);return b>-1?(this.slots.splice(b,1),!0):!1},removeAll:function(){this.slots.length=0},findCon:function(a){var c,d,e;if(a instanceof b)d=this.slots.indexOf(a.cb);else for(c=0;c<this.slots.length;c++){e=this.slots[c];if(e.cb===a){d=c;break}}return d}},a.Signal=c})(typeof exports!="undefined"?exports:typeof window!="undefined"?window:{})
/*jslint laxbreak:true */
(function(root){
function Con(signal, cb, ctx){
this.signal = signal;
this.ctx = ctx;
this.cb = cb;
this.active = true;
}
Con.prototype = {
execute: function(){
var ret = this.cb.apply(this.ctx, arguments);
if(this.once === true){
this.destroy();
}
return ret;
}
,destroy: function(){
this.signal.remove(this.cb);
}
};
function Signal(strict){
this.slots = [];
this.strict = strict === true
? true
: false;
}
Signal.prototype = {
add: function(f){
var con, index;
if(this.strict === true){
index = this.findCon(f);
if(index > -1){
throw new Error('Duplicate Slot added to strict Signal');
}
}
con = new Con(this, f,
arguments.length > 1
? arguments[1]
: this); // default ctx is signal
this.slots.push(con);
return con;
}
,addOnce: function(f){
var con = this.add.apply(this, arguments);
con.once = true;
return con;
}
,dispatch: function(){
var slots = this.slots.slice()
,len = slots.length
,i
,ret
,slot;
for (i = 0; i < len; i++){
slot = slots[i];
if(slot.active === true){
ret = slot.execute.apply(slot, arguments);
}
if(ret === false){
break;
}
}
}
,remove: function(f){
var index = this.findCon(f);
if(index > -1){
this.slots.splice(index, 1);
return true;
} else {
return false;
}
}
,removeAll: function(){
this.slots.length = 0;
}
,findCon: function(f){
var i, index, slot;
if(f instanceof Con){
index = this.slots.indexOf(f.cb);
} else {
// manually search for passed in func
for(i = 0; i < this.slots.length; i++){
slot = this.slots[i];
if(slot.cb === f){
index = i;
break;
}
}
}
return index;
}
};
root.Signal = Signal;
})(
typeof exports !== 'undefined'
? exports
: typeof window !== 'undefined'
? window
: {}
);
var s = new Signal(), cb = function(a, b){ console.log('callback', arguments, this); };
s.add(cb);
s.add(cb);
s.dispatch('for', 'science', '!', 1);
s.remove(cb);
s.dispatch('for', 'science', '!', 2);
s.remove(cb);
s.dispatch('for', 'science', '!', 3);
var con = s.add(cb);
s.dispatch('for', 'science', '!', 4);
con.destroy();
s.dispatch('for', 'science', '!', 5);
s.addOnce(cb);
s.dispatch('for', 'science', '!', 6);
s.dispatch('for', 'science', '!', 7);
s.addOnce(cb, this); // set context to this (window)
s.dispatch('for', 'science', '!', 8);
var con = s.add(cb);
s.add(cb);
s.dispatch('for', 'science', '!', 9);
con.active = false;
s.dispatch('for', 'science', '!', 10);
s.strict = true;
s.add(cb);
s.add(cb); // throws error
// should output dispatches: 1, 1, 2, 4, 6, 8, 9, 9, 10