UNPKG

4.26 kBJavaScriptView Raw
1function WildEmitter() { }
2
3WildEmitter.mixin = function (constructor) {
4 var prototype = constructor.prototype || constructor;
5
6 prototype.isWildEmitter= true;
7
8 // Listen on the given `event` with `fn`. Store a group name if present.
9 prototype.on = function (event, groupName, fn) {
10 this.callbacks = this.callbacks || {};
11 var hasGroup = (arguments.length === 3),
12 group = hasGroup ? arguments[1] : undefined,
13 func = hasGroup ? arguments[2] : arguments[1];
14 func._groupName = group;
15 (this.callbacks[event] = this.callbacks[event] || []).push(func);
16 return this;
17 };
18
19 // Adds an `event` listener that will be invoked a single
20 // time then automatically removed.
21 prototype.once = function (event, groupName, fn) {
22 var self = this,
23 hasGroup = (arguments.length === 3),
24 group = hasGroup ? arguments[1] : undefined,
25 func = hasGroup ? arguments[2] : arguments[1];
26 function on() {
27 self.off(event, on);
28 func.apply(this, arguments);
29 }
30 this.on(event, group, on);
31 return this;
32 };
33
34 // Unbinds an entire group
35 prototype.releaseGroup = function (groupName) {
36 this.callbacks = this.callbacks || {};
37 var item, i, len, handlers;
38 for (item in this.callbacks) {
39 handlers = this.callbacks[item];
40 for (i = 0, len = handlers.length; i < len; i++) {
41 if (handlers[i]._groupName === groupName) {
42 //console.log('removing');
43 // remove it and shorten the array we're looping through
44 handlers.splice(i, 1);
45 i--;
46 len--;
47 }
48 }
49 }
50 return this;
51 };
52
53 // Remove the given callback for `event` or all
54 // registered callbacks.
55 prototype.off = function (event, fn) {
56 this.callbacks = this.callbacks || {};
57 var callbacks = this.callbacks[event],
58 i;
59
60 if (!callbacks) return this;
61
62 // remove all handlers
63 if (arguments.length === 1) {
64 delete this.callbacks[event];
65 return this;
66 }
67
68 // remove specific handler
69 i = callbacks.indexOf(fn);
70 callbacks.splice(i, 1);
71 if (callbacks.length === 0) {
72 delete this.callbacks[event];
73 }
74 return this;
75 };
76
77 /// Emit `event` with the given args.
78 // also calls any `*` handlers
79 prototype.emit = function (event) {
80 this.callbacks = this.callbacks || {};
81 var args = [].slice.call(arguments, 1),
82 callbacks = this.callbacks[event],
83 specialCallbacks = this.getWildcardCallbacks(event),
84 i,
85 len,
86 item,
87 listeners;
88
89 if (callbacks) {
90 listeners = callbacks.slice();
91 for (i = 0, len = listeners.length; i < len; ++i) {
92 if (!listeners[i]) {
93 break;
94 }
95 listeners[i].apply(this, args);
96 }
97 }
98
99 if (specialCallbacks) {
100 len = specialCallbacks.length;
101 listeners = specialCallbacks.slice();
102 for (i = 0, len = listeners.length; i < len; ++i) {
103 if (!listeners[i]) {
104 break;
105 }
106 listeners[i].apply(this, [event].concat(args));
107 }
108 }
109
110 return this;
111 };
112
113 // Helper for for finding special wildcard event handlers that match the event
114 prototype.getWildcardCallbacks = function (eventName) {
115 this.callbacks = this.callbacks || {};
116 var item,
117 split,
118 result = [];
119
120 for (item in this.callbacks) {
121 split = item.split('*');
122 if (item === '*' || (split.length === 2 && eventName.slice(0, split[0].length) === split[0])) {
123 result = result.concat(this.callbacks[item]);
124 }
125 }
126 return result;
127 };
128
129};
130
131WildEmitter.mixin(WildEmitter);