What I'm looking for here is a method to refer to a bound method from within that method for the purpose of removing an eventlistener from within the event listener.
I'd like to create a single method to handle the same action over a few different events.
I've got a function that handles rotating the elements called rotateActiveItem
. It looks at a list of list items and activates one at a time.
In my constructor I'd like to set up a few, potentially many, events that trigger rotateLoadingCopy
.
this.oneQuarter = genericDurationEvent.bind(this, animationDuration * .25);
this.half = genericDurationEvent.bind(this, animationDuration * .5);
this.threeQuarters = genericDurationEvent.bind(this, animationDuration * .75);
Each of these are added to the animation's events:
this.animation_.addEventListener('enterFrame', this.oneQuarter);
this.animation_.addEventListener('enterFrame', this.half);
this.animation_.addEventListener('enterFrame', this.threeQuarters);
And then the event checks for duration, executes the rotation, and then should remove itself from the eventListeners.
genericDurationEvent(duration, event) {
if (event.currentTime >= duration) {
// Activate the next loading text element.
this.rotateActiveItem();
// Stop listening for this event.
this.animation_.removeEventListener('enterFrame', /*What goes here?*/);
}
}
At first I thought maybe I could bind the bound method onto another method, but that's a rabbit hole of bound functions.
Then I thought arguments.callee
would do this, but I'm in strict mode it its deprecated in strict mode.
I would recommend going for a closure pattern, and generating the handlers dynamically, so you can keep a reference to the function.
genericDurationEvent(context, duration) {
var handler = function (event) {
if (event.currentTime >= duration) {
// Activate the next loading text element.
this.rotateActiveItem();
// Stop listening for this event.
this.animation_.removeEventListener('enterFrame', handler);
}
}.bind(context);
return handler;
}
this.oneQuarter = genericDurationEvent(this, animationDuration * .25);
this.half = genericDurationEvent(this, animationDuration * .5);
this.threeQuarters = genericDurationEvent(this, animationDuration * .75);
If you wanna go the extra mile, you could isolate the logic in a way that the generator makes any function behave like "once" ala jQuery#one():
// definition
function once (what, eventName, originalHandler) {
function onceHandler (...args) {
what.removeEventListener(eventName, onceHandler);
return originalHandler.apply(this, args);
};
what.addEventListener(eventName, onceHandler);
}
// usage
once(this.animation_, 'enterFrame', event => {
if (event.currentTime >= animationDuration * .25) {
// Activate the next loading text element.
this.rotateActiveItem();
}
});