Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ui: Expands create-listeners API to allow recursive addition and plain function addition #5616

Merged
merged 1 commit into from
May 15, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 36 additions & 28 deletions ui-v2/app/utils/dom/create-listeners.js
Original file line number Diff line number Diff line change
@@ -1,32 +1,40 @@
export default function(listeners = []) {
const add = function(target, event, handler) {
let addEventListener = 'addEventListener';
let removeEventListener = 'removeEventListener';
if (typeof target[addEventListener] === 'undefined') {
addEventListener = 'on';
removeEventListener = 'off';
class Listeners {
constructor(listeners = []) {
this.listeners = listeners;
}
add(target, event, handler) {
let remove;
if (typeof target === 'function') {
remove = target;
} else if (target instanceof Listeners) {
remove = target.remove.bind(target);
} else {
let addEventListener = 'addEventListener';
let removeEventListener = 'removeEventListener';
if (typeof target[addEventListener] === 'undefined') {
addEventListener = 'on';
removeEventListener = 'off';
}
target[addEventListener](event, handler);
remove = function() {
target[removeEventListener](event, handler);
return handler;
};
}
target[addEventListener](event, handler);
const remove = function() {
target[removeEventListener](event, handler);
return handler;
this.listeners.push(remove);
return () => {
const pos = this.listeners.findIndex(function(item) {
return item === remove;
});
return this.listeners.splice(pos, 1)[0]();
};
listeners.push(remove);
return remove;
};
// TODO: Allow passing of a 'listener remove' in here
// call it, find in the array and remove
// Post-thoughts, pretty sure this is covered now by returning the remove
// function above, use-case for wanting to use this method to remove individual
// listeners is probably pretty limited, this method itself could be easily implemented
// from the outside also, but I suppose its handy to keep here
const remove = function() {
const handlers = listeners.map(item => item());
listeners.splice(0, listeners.length);
}
remove() {
const handlers = this.listeners.map(item => item());
this.listeners.splice(0, this.listeners.length);
return handlers;
};
return {
add: add,
remove: remove,
};
}
}
export default function(listeners = []) {
return new Listeners(listeners);
}
26 changes: 25 additions & 1 deletion ui-v2/tests/unit/utils/dom/create-listeners-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ test('it has add and remove methods', function(assert) {
assert.ok(typeof listeners.add === 'function');
assert.ok(typeof listeners.remove === 'function');
});
test('add returns an remove function', function(assert) {
test('add returns a remove function', function(assert) {
const listeners = createListeners();
const remove = listeners.add({
addEventListener: function() {},
Expand Down Expand Up @@ -64,6 +64,30 @@ test('listeners are removed on remove', function(assert) {
assert.ok(stub.calledOnce);
assert.ok(stub.calledWith(name, handler));
});
test('listeners as functions are removed on remove', function(assert) {
const listeners = createListeners();
const stub = this.stub();
const remove = listeners.add(stub);
remove();
assert.ok(stub.calledOnce);
});
test('listeners as other listeners are removed on remove', function(assert) {
const listeners = createListeners();
const listeners2 = createListeners();
const stub = this.stub();
listeners2.add(stub);
const remove = listeners.add(listeners2);
remove();
assert.ok(stub.calledOnce);
});
test('listeners as functions of other listeners are removed on remove', function(assert) {
const listeners = createListeners();
const listeners2 = createListeners();
const stub = this.stub();
const remove = listeners.add(listeners2.add(stub));
remove();
assert.ok(stub.calledOnce);
});
test('remove returns the original handler', function(assert) {
const listeners = createListeners();
const target = {
Expand Down