You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
132 lines
2.9 KiB
132 lines
2.9 KiB
'use strict'; |
|
|
|
var d = require('d') |
|
, callable = require('es5-ext/object/valid-callable') |
|
|
|
, apply = Function.prototype.apply, call = Function.prototype.call |
|
, create = Object.create, defineProperty = Object.defineProperty |
|
, defineProperties = Object.defineProperties |
|
, hasOwnProperty = Object.prototype.hasOwnProperty |
|
, descriptor = { configurable: true, enumerable: false, writable: true } |
|
|
|
, on, once, off, emit, methods, descriptors, base; |
|
|
|
on = function (type, listener) { |
|
var data; |
|
|
|
callable(listener); |
|
|
|
if (!hasOwnProperty.call(this, '__ee__')) { |
|
data = descriptor.value = create(null); |
|
defineProperty(this, '__ee__', descriptor); |
|
descriptor.value = null; |
|
} else { |
|
data = this.__ee__; |
|
} |
|
if (!data[type]) data[type] = listener; |
|
else if (typeof data[type] === 'object') data[type].push(listener); |
|
else data[type] = [data[type], listener]; |
|
|
|
return this; |
|
}; |
|
|
|
once = function (type, listener) { |
|
var once, self; |
|
|
|
callable(listener); |
|
self = this; |
|
on.call(this, type, once = function () { |
|
off.call(self, type, once); |
|
apply.call(listener, this, arguments); |
|
}); |
|
|
|
once.__eeOnceListener__ = listener; |
|
return this; |
|
}; |
|
|
|
off = function (type, listener) { |
|
var data, listeners, candidate, i; |
|
|
|
callable(listener); |
|
|
|
if (!hasOwnProperty.call(this, '__ee__')) return this; |
|
data = this.__ee__; |
|
if (!data[type]) return this; |
|
listeners = data[type]; |
|
|
|
if (typeof listeners === 'object') { |
|
for (i = 0; (candidate = listeners[i]); ++i) { |
|
if ((candidate === listener) || |
|
(candidate.__eeOnceListener__ === listener)) { |
|
if (listeners.length === 2) data[type] = listeners[i ? 0 : 1]; |
|
else listeners.splice(i, 1); |
|
} |
|
} |
|
} else { |
|
if ((listeners === listener) || |
|
(listeners.__eeOnceListener__ === listener)) { |
|
delete data[type]; |
|
} |
|
} |
|
|
|
return this; |
|
}; |
|
|
|
emit = function (type) { |
|
var i, l, listener, listeners, args; |
|
|
|
if (!hasOwnProperty.call(this, '__ee__')) return; |
|
listeners = this.__ee__[type]; |
|
if (!listeners) return; |
|
|
|
if (typeof listeners === 'object') { |
|
l = arguments.length; |
|
args = new Array(l - 1); |
|
for (i = 1; i < l; ++i) args[i - 1] = arguments[i]; |
|
|
|
listeners = listeners.slice(); |
|
for (i = 0; (listener = listeners[i]); ++i) { |
|
apply.call(listener, this, args); |
|
} |
|
} else { |
|
switch (arguments.length) { |
|
case 1: |
|
call.call(listeners, this); |
|
break; |
|
case 2: |
|
call.call(listeners, this, arguments[1]); |
|
break; |
|
case 3: |
|
call.call(listeners, this, arguments[1], arguments[2]); |
|
break; |
|
default: |
|
l = arguments.length; |
|
args = new Array(l - 1); |
|
for (i = 1; i < l; ++i) { |
|
args[i - 1] = arguments[i]; |
|
} |
|
apply.call(listeners, this, args); |
|
} |
|
} |
|
}; |
|
|
|
methods = { |
|
on: on, |
|
once: once, |
|
off: off, |
|
emit: emit |
|
}; |
|
|
|
descriptors = { |
|
on: d(on), |
|
once: d(once), |
|
off: d(off), |
|
emit: d(emit) |
|
}; |
|
|
|
base = defineProperties({}, descriptors); |
|
|
|
module.exports = exports = function (o) { |
|
return (o == null) ? create(base) : defineProperties(Object(o), descriptors); |
|
}; |
|
exports.methods = methods;
|
|
|