[6a3a178] | 1 |
|
---|
| 2 | /**
|
---|
| 3 | * Expose `Emitter`.
|
---|
| 4 | */
|
---|
| 5 |
|
---|
| 6 | if (typeof module !== 'undefined') {
|
---|
| 7 | module.exports = Emitter;
|
---|
| 8 | }
|
---|
| 9 |
|
---|
| 10 | /**
|
---|
| 11 | * Initialize a new `Emitter`.
|
---|
| 12 | *
|
---|
| 13 | * @api public
|
---|
| 14 | */
|
---|
| 15 |
|
---|
| 16 | function Emitter(obj) {
|
---|
| 17 | if (obj) return mixin(obj);
|
---|
| 18 | };
|
---|
| 19 |
|
---|
| 20 | /**
|
---|
| 21 | * Mixin the emitter properties.
|
---|
| 22 | *
|
---|
| 23 | * @param {Object} obj
|
---|
| 24 | * @return {Object}
|
---|
| 25 | * @api private
|
---|
| 26 | */
|
---|
| 27 |
|
---|
| 28 | function mixin(obj) {
|
---|
| 29 | for (var key in Emitter.prototype) {
|
---|
| 30 | obj[key] = Emitter.prototype[key];
|
---|
| 31 | }
|
---|
| 32 | return obj;
|
---|
| 33 | }
|
---|
| 34 |
|
---|
| 35 | /**
|
---|
| 36 | * Listen on the given `event` with `fn`.
|
---|
| 37 | *
|
---|
| 38 | * @param {String} event
|
---|
| 39 | * @param {Function} fn
|
---|
| 40 | * @return {Emitter}
|
---|
| 41 | * @api public
|
---|
| 42 | */
|
---|
| 43 |
|
---|
| 44 | Emitter.prototype.on =
|
---|
| 45 | Emitter.prototype.addEventListener = function(event, fn){
|
---|
| 46 | this._callbacks = this._callbacks || {};
|
---|
| 47 | (this._callbacks['$' + event] = this._callbacks['$' + event] || [])
|
---|
| 48 | .push(fn);
|
---|
| 49 | return this;
|
---|
| 50 | };
|
---|
| 51 |
|
---|
| 52 | /**
|
---|
| 53 | * Adds an `event` listener that will be invoked a single
|
---|
| 54 | * time then automatically removed.
|
---|
| 55 | *
|
---|
| 56 | * @param {String} event
|
---|
| 57 | * @param {Function} fn
|
---|
| 58 | * @return {Emitter}
|
---|
| 59 | * @api public
|
---|
| 60 | */
|
---|
| 61 |
|
---|
| 62 | Emitter.prototype.once = function(event, fn){
|
---|
| 63 | function on() {
|
---|
| 64 | this.off(event, on);
|
---|
| 65 | fn.apply(this, arguments);
|
---|
| 66 | }
|
---|
| 67 |
|
---|
| 68 | on.fn = fn;
|
---|
| 69 | this.on(event, on);
|
---|
| 70 | return this;
|
---|
| 71 | };
|
---|
| 72 |
|
---|
| 73 | /**
|
---|
| 74 | * Remove the given callback for `event` or all
|
---|
| 75 | * registered callbacks.
|
---|
| 76 | *
|
---|
| 77 | * @param {String} event
|
---|
| 78 | * @param {Function} fn
|
---|
| 79 | * @return {Emitter}
|
---|
| 80 | * @api public
|
---|
| 81 | */
|
---|
| 82 |
|
---|
| 83 | Emitter.prototype.off =
|
---|
| 84 | Emitter.prototype.removeListener =
|
---|
| 85 | Emitter.prototype.removeAllListeners =
|
---|
| 86 | Emitter.prototype.removeEventListener = function(event, fn){
|
---|
| 87 | this._callbacks = this._callbacks || {};
|
---|
| 88 |
|
---|
| 89 | // all
|
---|
| 90 | if (0 == arguments.length) {
|
---|
| 91 | this._callbacks = {};
|
---|
| 92 | return this;
|
---|
| 93 | }
|
---|
| 94 |
|
---|
| 95 | // specific event
|
---|
| 96 | var callbacks = this._callbacks['$' + event];
|
---|
| 97 | if (!callbacks) return this;
|
---|
| 98 |
|
---|
| 99 | // remove all handlers
|
---|
| 100 | if (1 == arguments.length) {
|
---|
| 101 | delete this._callbacks['$' + event];
|
---|
| 102 | return this;
|
---|
| 103 | }
|
---|
| 104 |
|
---|
| 105 | // remove specific handler
|
---|
| 106 | var cb;
|
---|
| 107 | for (var i = 0; i < callbacks.length; i++) {
|
---|
| 108 | cb = callbacks[i];
|
---|
| 109 | if (cb === fn || cb.fn === fn) {
|
---|
| 110 | callbacks.splice(i, 1);
|
---|
| 111 | break;
|
---|
| 112 | }
|
---|
| 113 | }
|
---|
| 114 |
|
---|
| 115 | // Remove event specific arrays for event types that no
|
---|
| 116 | // one is subscribed for to avoid memory leak.
|
---|
| 117 | if (callbacks.length === 0) {
|
---|
| 118 | delete this._callbacks['$' + event];
|
---|
| 119 | }
|
---|
| 120 |
|
---|
| 121 | return this;
|
---|
| 122 | };
|
---|
| 123 |
|
---|
| 124 | /**
|
---|
| 125 | * Emit `event` with the given args.
|
---|
| 126 | *
|
---|
| 127 | * @param {String} event
|
---|
| 128 | * @param {Mixed} ...
|
---|
| 129 | * @return {Emitter}
|
---|
| 130 | */
|
---|
| 131 |
|
---|
| 132 | Emitter.prototype.emit = function(event){
|
---|
| 133 | this._callbacks = this._callbacks || {};
|
---|
| 134 |
|
---|
| 135 | var args = new Array(arguments.length - 1)
|
---|
| 136 | , callbacks = this._callbacks['$' + event];
|
---|
| 137 |
|
---|
| 138 | for (var i = 1; i < arguments.length; i++) {
|
---|
| 139 | args[i - 1] = arguments[i];
|
---|
| 140 | }
|
---|
| 141 |
|
---|
| 142 | if (callbacks) {
|
---|
| 143 | callbacks = callbacks.slice(0);
|
---|
| 144 | for (var i = 0, len = callbacks.length; i < len; ++i) {
|
---|
| 145 | callbacks[i].apply(this, args);
|
---|
| 146 | }
|
---|
| 147 | }
|
---|
| 148 |
|
---|
| 149 | return this;
|
---|
| 150 | };
|
---|
| 151 |
|
---|
| 152 | /**
|
---|
| 153 | * Return array of callbacks for `event`.
|
---|
| 154 | *
|
---|
| 155 | * @param {String} event
|
---|
| 156 | * @return {Array}
|
---|
| 157 | * @api public
|
---|
| 158 | */
|
---|
| 159 |
|
---|
| 160 | Emitter.prototype.listeners = function(event){
|
---|
| 161 | this._callbacks = this._callbacks || {};
|
---|
| 162 | return this._callbacks['$' + event] || [];
|
---|
| 163 | };
|
---|
| 164 |
|
---|
| 165 | /**
|
---|
| 166 | * Check if this emitter has `event` handlers.
|
---|
| 167 | *
|
---|
| 168 | * @param {String} event
|
---|
| 169 | * @return {Boolean}
|
---|
| 170 | * @api public
|
---|
| 171 | */
|
---|
| 172 |
|
---|
| 173 | Emitter.prototype.hasListeners = function(event){
|
---|
| 174 | return !! this.listeners(event).length;
|
---|
| 175 | };
|
---|