All files / lib/module events.js

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133          25x           25x                   25x         55x 49x 49x             55x 6x 6x     6x 5x       6x   49x     55x                     25x       319x 317x 317x     319x 3x       9x 3x         6x 6x       319x 317x     319x                 25x 17x 17x     1x     17x                 17x 16x     17x       47x   30x 30x 30x     25x  
 
/**
 * Module Dependencies
 */
 
var events = require('evt');
 
/**
 * Local vars
 */
 
var listenerMap = {};
 
/**
 * Registers a event listener.
 *
 * @param  {String}   name
 * @param  {String}   module
 * @param  {Function} cb
 * @return {View}
 */
exports.on = function(name, module, cb) {
  var l;
 
  // cb can be passed as
  // the second or third argument
  if (typeof module !== 'string') {
    cb = module;
    module = null;
  }
 
  // if a module is provided
  // pass in a special callback
  // function that checks the
  // module
  if (module) {
    if (!listenerMap[name]) listenerMap[name] = [];
    l = listenerMap[name].push({
      orig: cb,
      cb: function() {
        if (this.event.target.module() === module) {
          cb.apply(this, arguments);
        }
      }
    });
    events.prototype.on.call(this, name, listenerMap[name][l-1].cb);
  } else {
    events.prototype.on.call(this, name, cb);
  }
 
  return this;
};
 
/**
 * Unregisters a event listener.
 *
 * @param  {String}   name
 * @param  {String}   module
 * @param  {Function} cb
 * @return {View}
 */
exports.off = function(name, module, cb) {
 
  // cb can be passed as
  // the second or third argument
  if (typeof module !== 'string') {
    cb = module;
    module = null;
  }
 
  if (listenerMap[name]) {
    listenerMap[name] = listenerMap[name].filter(function(map) {
 
      // If a callback provided, keep it
      // in the listener map if it doesn't match
      if (cb && map.orig !== cb) {
        return true;
 
      // Otherwise remove it from the listener
      // map and unbind the event listener
      } else {
        events.prototype.off.call(this, name, map.cb);
        return false;
      }
    }, this);
  }
  if (!module) {
    events.prototype.off.call(this, name, cb);
  }
 
  return this;
};
 
/**
 * Fires an event on a view.
 *
 * @param  {String} name
 * @return {View}
 */
exports.fire = function(name) {
  var _event = this.event;
  var event = {
    target: this,
    propagate: true,
    stopPropagation: function(){ this.propagate = false; }
  };
 
  propagate(this, arguments, event);
 
  // COMPLEX:
  // If an earlier event object was
  // cached, restore the the event
  // back onto the view. If there
  // wasn't an earlier event, make
  // sure the `event` key has been
  // deleted off the view.
  if (_event) this.event = _event;
  else delete this.event;
 
  // Allow chaining
  return this;
};
 
function propagate(view, args, event) {
  if (!view || !event.propagate) return;
 
  view.event = event;
  events.prototype.fire.apply(view, args);
  propagate(view.parent, args, event);
}
 
exports.fireStatic = events.prototype.fire;