Skip to content

Commit 3748460

Browse files
committed
feat: off method added for removing events
1 parent b798256 commit 3748460

File tree

5 files changed

+94
-26
lines changed

5 files changed

+94
-26
lines changed

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,10 @@ To prevent multiple file uploads set singleFile to true.
140140
Note: avoid using `a` and `button` tags as file upload buttons, use span instead.
141141
* `.assignDrop(domNodes)` Assign one or more DOM nodes as a drop target.
142142
* `.on(event, callback)` Listen for event from Flow.js (see below)
143+
* `.off([event, [callback]])`:
144+
* `.off()` All events are removed.
145+
* `.off(event)` Remove all callbacks of specific event.
146+
* `.off(event, callback)` Remove specific callback of event. `callback` should be a `Function`.
143147
* `.upload()` Start or resume uploading.
144148
* `.pause()` Pause uploading.
145149
* `.resume()` Resume uploading.

src/flow.js

Lines changed: 49 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -92,11 +92,11 @@
9292

9393
/**
9494
* List of events:
95-
* even indexes stand for event names
96-
* odd indexes stands for event callbacks
97-
* @type {Array}
95+
* key stands for event name
96+
* value array list of callbacks
97+
* @type {}
9898
*/
99-
this.events = [];
99+
this.events = {};
100100

101101
var $ = this;
102102

@@ -145,7 +145,32 @@
145145
* @param {Function} callback
146146
*/
147147
on: function (event, callback) {
148-
this.events.push(event.toLowerCase(), callback);
148+
event = event.toLowerCase();
149+
if (!this.events.hasOwnProperty(event)) {
150+
this.events[event] = [];
151+
}
152+
this.events[event].push(callback);
153+
},
154+
155+
/**
156+
* Remove event callback
157+
* @function
158+
* @param {string} [event] removes all events if not specified
159+
* @param {Function} [fn] removes all callbacks of event if not specified
160+
*/
161+
off: function (event, fn) {
162+
if (event !== undefined) {
163+
event = event.toLowerCase();
164+
if (fn !== undefined) {
165+
if (this.events.hasOwnProperty(event)) {
166+
arrayRemove(this.events[event], fn);
167+
}
168+
} else {
169+
delete this.events[event];
170+
}
171+
} else {
172+
this.events = {};
173+
}
149174
},
150175

151176
/**
@@ -159,16 +184,16 @@
159184
fire: function (event, args) {
160185
// `arguments` is an object, not array, in FF, so:
161186
args = Array.prototype.slice.call(arguments);
162-
// Find event listeners, and support pseudo-event `catchAll`
163187
event = event.toLowerCase();
164188
var preventDefault = false;
165-
for (var i = 0; i <= this.events.length; i += 2) {
166-
if (this.events[i] === event) {
167-
preventDefault = this.events[i + 1].apply(this, args.slice(1)) === false || preventDefault;
168-
}
169-
if (this.events[i] === 'catchall') {
170-
preventDefault = this.events[i + 1].apply(null, args) === false || preventDefault;
171-
}
189+
if (this.events.hasOwnProperty(event)) {
190+
each(this.events[event], function (callback) {
191+
preventDefault = callback.apply(this, args.slice(1)) === false || preventDefault;
192+
});
193+
}
194+
if (event != 'catchall') {
195+
args.unshift('catchAll');
196+
preventDefault = this.fire.apply(this, args) === false || preventDefault;
172197
}
173198
return !preventDefault;
174199
},
@@ -1360,8 +1385,17 @@
13601385
}
13611386
};
13621387

1363-
1364-
1388+
/**
1389+
* Remove value from array
1390+
* @param array
1391+
* @param value
1392+
*/
1393+
function arrayRemove(array, value) {
1394+
var index = array.indexOf(value);
1395+
if (index > -1) {
1396+
array.splice(index, 1);
1397+
}
1398+
}
13651399

13661400
/**
13671401
* Extends the destination object `dst` by copying all of the properties from

test/eventsSpec.js

Lines changed: 40 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,6 @@ describe('events', function() {
88
flow = new Flow();
99
});
1010

11-
it('should catch all events', function() {
12-
var valid = false;
13-
flow.on('catchall', function (event) {
14-
expect(event).toBe('test');
15-
valid = true;
16-
});
17-
flow.fire('test');
18-
expect(valid).toBeTruthy();
19-
});
20-
2111
it('should catch an event', function() {
2212
var valid = false;
2313
flow.on('test', function () {
@@ -42,6 +32,23 @@ describe('events', function() {
4232
expect(valid).toBeTruthy();
4333
});
4434

35+
it('should throw catchall event last', function() {
36+
var executed = 0;
37+
flow.on('catchall', function (event, one) {
38+
expect(event).toBe('test');
39+
expect(one).toBe(1);
40+
expect(executed).toBe(1);
41+
executed++;
42+
});
43+
flow.on('test', function (one) {
44+
expect(one).toBe(1);
45+
expect(executed).toBe(0);
46+
executed++;
47+
});
48+
flow.fire('test', 1);
49+
expect(executed).toBe(2);
50+
});
51+
4552
it('should return event value', function() {
4653
flow.on('false', function () {
4754
return false;
@@ -71,4 +78,27 @@ describe('events', function() {
7178
});
7279
expect(flow.fire('maybe2')).toBeFalsy();
7380
});
81+
82+
describe('off', function () {
83+
var event;
84+
beforeEach(function () {
85+
event = jasmine.createSpy('event');
86+
flow.on('event', event);
87+
});
88+
it('should remove event', function () {
89+
flow.off('event');
90+
flow.fire('event');
91+
expect(event).not.toHaveBeenCalled();
92+
});
93+
it('should remove specific event', function () {
94+
flow.off('event', event);
95+
flow.fire('event');
96+
expect(event).not.toHaveBeenCalled();
97+
});
98+
it('should remove all events', function () {
99+
flow.off();
100+
flow.fire('event');
101+
expect(event).not.toHaveBeenCalled();
102+
});
103+
});
74104
});
File renamed without changes.

test/setupSpec.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ describe('setup', function() {
2323

2424
it('events should be empty', function() {
2525
expect(flow.events).toBeDefined();
26-
expect(flow.events.length).toBe(0);
26+
expect(Object.keys(flow.events).length).toBe(0);
2727
});
2828

2929
it('set opts', function() {

0 commit comments

Comments
 (0)