!function ($) {
  var b = require('bean'),
      integrate = function (method, type, method2) {
        var _args = type ? [type] : [];
        return function () {
          for (var args, i = 0, l = this.length; i < l; i++) {
            args = [this[i]].concat(_args, Array.prototype.slice.call(arguments, 0));
            args.length == 4 && args.push($);
            !arguments.length && method == 'add' && type && (method = 'fire');
            b[method].apply(this, args);
          }
          return this;
        };
      };

  var add = integrate('add'),
      remove = integrate('remove'),
      fire = integrate('fire');

  var methods = {

    on: add,
    addListener: add,
    bind: add,
    listen: add,
    delegate: add,

    unbind: remove,
    unlisten: remove,
    removeListener: remove,
    undelegate: remove,

    emit: fire,
    trigger: fire,

    cloneEvents: integrate('clone'),

    hover: function (enter, leave, i) { // i for internal
      for (i = this.length; i--;) {
        b.add.call(this, this[i], 'mouseenter', enter);
        b.add.call(this, this[i], 'mouseleave', leave);
      }
      return this;
    }
  };

  var i, shortcuts = [
    'blur', 'change', 'click', 'dblclick', 'error', 'focus', 'focusin',
    'focusout', 'keydown', 'keypress', 'keyup', 'load', 'mousedown',
    'mouseenter', 'mouseleave', 'mouseout', 'mouseover', 'mouseup', 'mousemove',
    'resize', 'scroll', 'select', 'submit', 'unload'
  ];

  for (i = shortcuts.length; i--;) {
    methods[shortcuts[i]] = integrate('add', shortcuts[i]);
  }

  $.ender(methods, true);
}(ender);