Created
April 18, 2016 06:13
-
-
Save hampusborgos/ee16e971f7bd83679f5d36e6e7ec94d3 to your computer and use it in GitHub Desktop.
addChangeListener / removeChangeListener that can find a bound function on it's own.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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