Skip to content

Instantly share code, notes, and snippets.

@hampusborgos
Created April 18, 2016 06:13
Show Gist options
  • Save hampusborgos/ee16e971f7bd83679f5d36e6e7ec94d3 to your computer and use it in GitHub Desktop.
Save hampusborgos/ee16e971f7bd83679f5d36e6e7ec94d3 to your computer and use it in GitHub Desktop.
addChangeListener / removeChangeListener that can find a bound function on it's own.
import Constants from '../Constants';
import {EventEmitter} from 'events';
let _listenerArguments = {};
let _listenerIds = 1;
export default _.assign({}, EventEmitter.prototype, {
// Allow Controller-View to register itself with store
addChangeListener(listener) {
if (typeof listener != 'function') {
throw new TypeError("'listener' argument must be a function");
}
if (arguments.length == 1) {
// Simple callback, just register it
this.on(Constants.CHANGE_EVENT, listener);
}
else {
// More complex, bind it, and keep a reference
let extraArguments = Array.prototype.slice.call(arguments, 1);
let boundListener = listener.bind.apply(listener, extraArguments);
// Remember the arguments we bound with
boundListener._listenerId = _listenerIds++;
_listenerArguments[boundListener._listenerId] = extraArguments;
// Register the listener
this.on(Constants.CHANGE_EVENT, boundListener);
}
},
removeChangeListener(listener) {
if (typeof listener != 'function') {
throw new TypeError("'listener' argument must be a function");
}
if (arguments.length == 1) {
// Just a callback, forward to the default method
this.removeListener(Constants.CHANGE_EVENT, listener);
}
else {
let extraArguments = Array.prototype.slice.call(arguments, 1);
// Find the listener with the same arguments
let boundListeners = this.listeners(Constants.CHANGE_EVENT);
for (var i = 0; i < boundListeners.length; ++i) {
let boundListener = boundListeners[i];
// What arguments was *this* listener bound with?
let argumentsForBoundListener = _listenerArguments[boundListener._listenerId];
// Check if the arguments are equal
if(extraArguments.length !== argumentsForBoundListener.length)
continue;
var equal = true;
for (var j = extraArguments.length; j--;) {
if(extraArguments[j] !== argumentsForBoundListener[j]) {
equal = false;
break;
}
}
// If they are, remove that listener
if (equal) {
this.removeListener(Constants.CHANGE_EVENT, boundListener);
return;
}
}
}
},
// Override the logic for removeListener to clean bound arguments
removeListener(type, listener) {
if (listener._listenerId) {
delete _listenerArguments[listener._listenerId];
}
EventEmitter.prototype.removeListener.apply(this, arguments);
},
// Override the logic for removeAllListeners to clean bound arguments
removeAllListeners(type) {
// Remove remembered arguments for all the listeners
if (type === Constants.CHANGE_EVENT || arguments.length === 0) {
let boundListeners = this.listeners(Constants.CHANGE_EVENT);
for (var i = boundListeners.length; i--;) {
let boundListener = boundListeners[i];
if (boundListener._listenerId) {
delete _listenerArguments[boundListener._listenerId];
}
}
}
EventEmitter.prototype.removeAllListeners.apply(this, arguments);
},
// triggers change listener above, firing controller-view callback
emitChange() {
this.emit(Constants.CHANGE_EVENT);
},
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment