c36d3e49a2d562445fa542019b0c11e9afb6dde6
[platform/framework/web/crosswalk-tizen.git] /
1 'use strict';
2
3 var 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
14 on = 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
33 once = 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
47 off = 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
75 emit = 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
113 methods = {
114         on: on,
115         once: once,
116         off: off,
117         emit: emit
118 };
119
120 descriptors = {
121         on: d(on),
122         once: d(once),
123         off: d(off),
124         emit: d(emit)
125 };
126
127 base = defineProperties({}, descriptors);
128
129 module.exports = exports = function (o) {
130         return (o == null) ? create(base) : defineProperties(Object(o), descriptors);
131 };
132 exports.methods = methods;