UNPKG

3.48 kBJavaScriptView Raw
1
2/**
3 * Module dependencies.
4 */
5
6var events = require('event');
7var delegate = require('delegate');
8
9/**
10 * Expose `Events`.
11 */
12
13module.exports = Events;
14
15/**
16 * Initialize an `Events` with the given
17 * `el` object which events will be bound to,
18 * and the `obj` which will receive method calls.
19 *
20 * @param {Object} el
21 * @param {Object} obj
22 * @api public
23 */
24
25function Events(el, obj) {
26 if (!(this instanceof Events)) return new Events(el, obj);
27 if (!el) throw new Error('element required');
28 if (!obj) throw new Error('object required');
29 this.el = el;
30 this.obj = obj;
31 this._events = {};
32}
33
34/**
35 * Subscription helper.
36 */
37
38Events.prototype.sub = function(event, method, cb){
39 this._events[event] = this._events[event] || {};
40 this._events[event][method] = cb;
41};
42
43/**
44 * Bind to `event` with optional `method` name.
45 * When `method` is undefined it becomes `event`
46 * with the "on" prefix.
47 *
48 * Examples:
49 *
50 * Direct event handling:
51 *
52 * events.bind('click') // implies "onclick"
53 * events.bind('click', 'remove')
54 * events.bind('click', 'sort', 'asc')
55 *
56 * Delegated event handling:
57 *
58 * events.bind('click li > a')
59 * events.bind('click li > a', 'remove')
60 * events.bind('click a.sort-ascending', 'sort', 'asc')
61 * events.bind('click a.sort-descending', 'sort', 'desc')
62 *
63 * @param {String} event
64 * @param {String|function} [method]
65 * @return {Function} callback
66 * @api public
67 */
68
69Events.prototype.bind = function(event, method){
70 var e = parse(event);
71 var el = this.el;
72 var obj = this.obj;
73 var name = e.name;
74 var method = method || 'on' + name;
75 var args = [].slice.call(arguments, 2);
76
77 // callback
78 function cb(){
79 var a = [].slice.call(arguments).concat(args);
80 obj[method].apply(obj, a);
81 }
82
83 // bind
84 if (e.selector) {
85 cb = delegate.bind(el, e.selector, name, cb);
86 } else {
87 events.bind(el, name, cb);
88 }
89
90 // subscription for unbinding
91 this.sub(name, method, cb);
92
93 return cb;
94};
95
96/**
97 * Unbind a single binding, all bindings for `event`,
98 * or all bindings within the manager.
99 *
100 * Examples:
101 *
102 * Unbind direct handlers:
103 *
104 * events.unbind('click', 'remove')
105 * events.unbind('click')
106 * events.unbind()
107 *
108 * Unbind delegate handlers:
109 *
110 * events.unbind('click', 'remove')
111 * events.unbind('click')
112 * events.unbind()
113 *
114 * @param {String|Function} [event]
115 * @param {String|Function} [method]
116 * @api public
117 */
118
119Events.prototype.unbind = function(event, method){
120 if (0 == arguments.length) return this.unbindAll();
121 if (1 == arguments.length) return this.unbindAllOf(event);
122
123 // no bindings for this event
124 var bindings = this._events[event];
125 if (!bindings) return;
126
127 // no bindings for this method
128 var cb = bindings[method];
129 if (!cb) return;
130
131 events.unbind(this.el, event, cb);
132};
133
134/**
135 * Unbind all events.
136 *
137 * @api private
138 */
139
140Events.prototype.unbindAll = function(){
141 for (var event in this._events) {
142 this.unbindAllOf(event);
143 }
144};
145
146/**
147 * Unbind all events for `event`.
148 *
149 * @param {String} event
150 * @api private
151 */
152
153Events.prototype.unbindAllOf = function(event){
154 var bindings = this._events[event];
155 if (!bindings) return;
156
157 for (var method in bindings) {
158 this.unbind(event, method);
159 }
160};
161
162/**
163 * Parse `event`.
164 *
165 * @param {String} event
166 * @return {Object}
167 * @api private
168 */
169
170function parse(event) {
171 var parts = event.split(/ +/);
172 return {
173 name: parts.shift(),
174 selector: parts.join(' ')
175 }
176}