1 |
|
2 | /**
|
3 | * Module dependencies.
|
4 | */
|
5 |
|
6 | var events = require('event');
|
7 | var delegate = require('delegate');
|
8 |
|
9 | /**
|
10 | * Expose `Events`.
|
11 | */
|
12 |
|
13 | module.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 |
|
25 | function 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 |
|
38 | Events.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 |
|
69 | Events.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 |
|
119 | Events.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 |
|
140 | Events.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 |
|
153 | Events.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 |
|
170 | function parse(event) {
|
171 | var parts = event.split(/ +/);
|
172 | return {
|
173 | name: parts.shift(),
|
174 | selector: parts.join(' ')
|
175 | }
|
176 | }
|