--- /dev/null
+\r
+/**\r
+ * Expose `Emitter`.\r
+ */\r
+\r
+if (typeof module !== 'undefined') {\r
+ module.exports = Emitter;\r
+}\r
+\r
+/**\r
+ * Initialize a new `Emitter`.\r
+ *\r
+ * @api public\r
+ */\r
+\r
+function Emitter(obj) {\r
+ if (obj) return mixin(obj);\r
+};\r
+\r
+/**\r
+ * Mixin the emitter properties.\r
+ *\r
+ * @param {Object} obj\r
+ * @return {Object}\r
+ * @api private\r
+ */\r
+\r
+function mixin(obj) {\r
+ for (var key in Emitter.prototype) {\r
+ obj[key] = Emitter.prototype[key];\r
+ }\r
+ return obj;\r
+}\r
+\r
+/**\r
+ * Listen on the given `event` with `fn`.\r
+ *\r
+ * @param {String} event\r
+ * @param {Function} fn\r
+ * @return {Emitter}\r
+ * @api public\r
+ */\r
+\r
+Emitter.prototype.on =\r
+Emitter.prototype.addEventListener = function(event, fn){\r
+ this._callbacks = this._callbacks || {};\r
+ (this._callbacks['$' + event] = this._callbacks['$' + event] || [])\r
+ .push(fn);\r
+ return this;\r
+};\r
+\r
+/**\r
+ * Adds an `event` listener that will be invoked a single\r
+ * time then automatically removed.\r
+ *\r
+ * @param {String} event\r
+ * @param {Function} fn\r
+ * @return {Emitter}\r
+ * @api public\r
+ */\r
+\r
+Emitter.prototype.once = function(event, fn){\r
+ function on() {\r
+ this.off(event, on);\r
+ fn.apply(this, arguments);\r
+ }\r
+\r
+ on.fn = fn;\r
+ this.on(event, on);\r
+ return this;\r
+};\r
+\r
+/**\r
+ * Remove the given callback for `event` or all\r
+ * registered callbacks.\r
+ *\r
+ * @param {String} event\r
+ * @param {Function} fn\r
+ * @return {Emitter}\r
+ * @api public\r
+ */\r
+\r
+Emitter.prototype.off =\r
+Emitter.prototype.removeListener =\r
+Emitter.prototype.removeAllListeners =\r
+Emitter.prototype.removeEventListener = function(event, fn){\r
+ this._callbacks = this._callbacks || {};\r
+\r
+ // all\r
+ if (0 == arguments.length) {\r
+ this._callbacks = {};\r
+ return this;\r
+ }\r
+\r
+ // specific event\r
+ var callbacks = this._callbacks['$' + event];\r
+ if (!callbacks) return this;\r
+\r
+ // remove all handlers\r
+ if (1 == arguments.length) {\r
+ delete this._callbacks['$' + event];\r
+ return this;\r
+ }\r
+\r
+ // remove specific handler\r
+ var cb;\r
+ for (var i = 0; i < callbacks.length; i++) {\r
+ cb = callbacks[i];\r
+ if (cb === fn || cb.fn === fn) {\r
+ callbacks.splice(i, 1);\r
+ break;\r
+ }\r
+ }\r
+\r
+ // Remove event specific arrays for event types that no\r
+ // one is subscribed for to avoid memory leak.\r
+ if (callbacks.length === 0) {\r
+ delete this._callbacks['$' + event];\r
+ }\r
+\r
+ return this;\r
+};\r
+\r
+/**\r
+ * Emit `event` with the given args.\r
+ *\r
+ * @param {String} event\r
+ * @param {Mixed} ...\r
+ * @return {Emitter}\r
+ */\r
+\r
+Emitter.prototype.emit = function(event){\r
+ this._callbacks = this._callbacks || {};\r
+\r
+ var args = new Array(arguments.length - 1)\r
+ , callbacks = this._callbacks['$' + event];\r
+\r
+ for (var i = 1; i < arguments.length; i++) {\r
+ args[i - 1] = arguments[i];\r
+ }\r
+\r
+ if (callbacks) {\r
+ callbacks = callbacks.slice(0);\r
+ for (var i = 0, len = callbacks.length; i < len; ++i) {\r
+ callbacks[i].apply(this, args);\r
+ }\r
+ }\r
+\r
+ return this;\r
+};\r
+\r
+/**\r
+ * Return array of callbacks for `event`.\r
+ *\r
+ * @param {String} event\r
+ * @return {Array}\r
+ * @api public\r
+ */\r
+\r
+Emitter.prototype.listeners = function(event){\r
+ this._callbacks = this._callbacks || {};\r
+ return this._callbacks['$' + event] || [];\r
+};\r
+\r
+/**\r
+ * Check if this emitter has `event` handlers.\r
+ *\r
+ * @param {String} event\r
+ * @return {Boolean}\r
+ * @api public\r
+ */\r
+\r
+Emitter.prototype.hasListeners = function(event){\r
+ return !! this.listeners(event).length;\r
+};\r