code: function (ctx, obj, type, callback) {
          if (arguments.length === 3) {
              callback = type;
              type = obj;
              obj = window.document;
          }
  
          //save anonymous function to be able to remove
          var afn = function (e) { 
                  var e = e || window.event; 
  
                  if (typeof callback === 'function') {
                      callback.call(ctx, e);
                  }
              },
              id = ctx[0] || "";
  
          if (!this._events[id + obj + type + callback]) this._events[id + obj + type + callback] = afn;
          else return;
  
          if (obj.attachEvent) { //IE
              obj.attachEvent('on' + type, afn);
          } else { //Everyone else
              obj.addEventListener(type, afn, false);
          }
      }
docs: @
  #Crafty.addEvent
  @category Events, Misc
  @sign public this Crafty.addEvent(Object ctx, HTMLElement obj, String event, Function callback)
  @param ctx - Context of the callback or the value of `this`
  @param obj - Element to add the DOM event to
  @param event - Event name to bind to
  @param callback - Method to execute when triggered
  
  Adds DOM level 3 events to elements. The arguments it accepts are the call
  context (the value of `this`), the DOM element to attach the event to,
  the event name (without `on` (`click` rather than `onclick`)) and
  finally the callback method.
  
  If no element is passed, the default element will be `window.document`.
  
  Callbacks are passed with event data.
  
  @example
  Will add a stage-wide MouseDown event listener to the player. Will log which button was pressed
  & the (x,y) coordinates in viewport/world/game space.
  ~~~
  var player = Crafty.e("2D");
  player.onMouseDown = function(e) {
  console.log(e.mouseButton, e.realX, e.realY);
  };
  Crafty.addEvent(player, Crafty.stage.elem, "mousedown", player.onMouseDown);
  ~~~
  @see Crafty.removeEvent