crazy4groovy
3/19/2013 - 1:33 PM

Example pub/sub - similar to jQuery.Callbacks()

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