Code coverage report for lib/module/events.js

Statements: 100% (45 / 45)      Branches: 100% (24 / 24)      Functions: 100% (7 / 7)      Lines: 100% (42 / 42)      Ignored: none     

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          1           1                   1 41       41 35 35             41 6 6     6 5       6   35     41                     1       249 247 247     249 3       5 1         4 4       249 247     249                 1 17 17     1     17                 17 16     17     1 47   30 30 30     1  
 
/**
 * Module Dependencies
 */
 
var events = require('event');
 
/**
 * 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;