UNPKG

3 kBJavaScriptView Raw
1'use strict';
2
3var d = require('d')
4 , callable = require('es5-ext/object/valid-callable')
5
6 , apply = Function.prototype.apply, call = Function.prototype.call
7 , create = Object.create, defineProperty = Object.defineProperty
8 , defineProperties = Object.defineProperties
9 , hasOwnProperty = Object.prototype.hasOwnProperty
10 , descriptor = { configurable: true, enumerable: false, writable: true }
11
12 , on, once, off, emit, methods, descriptors, base;
13
14on = function (type, listener) {
15 var data;
16
17 callable(listener);
18
19 if (!hasOwnProperty.call(this, '__ee__')) {
20 data = descriptor.value = create(null);
21 defineProperty(this, '__ee__', descriptor);
22 descriptor.value = null;
23 } else {
24 data = this.__ee__;
25 }
26 if (!data[type]) data[type] = listener;
27 else if (typeof data[type] === 'object') data[type].push(listener);
28 else data[type] = [data[type], listener];
29
30 return this;
31};
32
33once = function (type, listener) {
34 var once, self;
35
36 callable(listener);
37 self = this;
38 on.call(this, type, once = function () {
39 off.call(self, type, once);
40 apply.call(listener, this, arguments);
41 });
42
43 once.__eeOnceListener__ = listener;
44 return this;
45};
46
47off = function (type, listener) {
48 var data, listeners, candidate, i;
49
50 callable(listener);
51
52 if (!hasOwnProperty.call(this, '__ee__')) return this;
53 data = this.__ee__;
54 if (!data[type]) return this;
55 listeners = data[type];
56
57 if (typeof listeners === 'object') {
58 for (i = 0; (candidate = listeners[i]); ++i) {
59 if ((candidate === listener) ||
60 (candidate.__eeOnceListener__ === listener)) {
61 if (listeners.length === 2) data[type] = listeners[i ? 0 : 1];
62 else listeners.splice(i, 1);
63 }
64 }
65 } else {
66 if ((listeners === listener) ||
67 (listeners.__eeOnceListener__ === listener)) {
68 delete data[type];
69 }
70 }
71
72 return this;
73};
74
75emit = function (type) {
76 var i, l, listener, listeners, args;
77
78 if (!hasOwnProperty.call(this, '__ee__')) return;
79 listeners = this.__ee__[type];
80 if (!listeners) return;
81
82 if (typeof listeners === 'object') {
83 l = arguments.length;
84 args = new Array(l - 1);
85 for (i = 1; i < l; ++i) args[i - 1] = arguments[i];
86
87 listeners = listeners.slice();
88 for (i = 0; (listener = listeners[i]); ++i) {
89 apply.call(listener, this, args);
90 }
91 } else {
92 switch (arguments.length) {
93 case 1:
94 call.call(listeners, this);
95 break;
96 case 2:
97 call.call(listeners, this, arguments[1]);
98 break;
99 case 3:
100 call.call(listeners, this, arguments[1], arguments[2]);
101 break;
102 default:
103 l = arguments.length;
104 args = new Array(l - 1);
105 for (i = 1; i < l; ++i) {
106 args[i - 1] = arguments[i];
107 }
108 apply.call(listeners, this, args);
109 }
110 }
111};
112
113methods = {
114 on: on,
115 once: once,
116 off: off,
117 emit: emit
118};
119
120descriptors = {
121 on: d(on),
122 once: d(once),
123 off: d(off),
124 emit: d(emit)
125};
126
127base = defineProperties({}, descriptors);
128
129module.exports = exports = function (o) {
130 return (o == null) ? create(base) : defineProperties(Object(o), descriptors);
131};
132exports.methods = methods;