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

Register multiple event listeners with the same callback in one call #1231

Closed
wants to merge 18 commits into from

Conversation

themicp
Copy link
Contributor

@themicp themicp commented May 22, 2014

There are cases where you want the same function to be called for many different events. For example take a look at the following code from the constructor of the Loading Spinner:

    player.on('canplay', vjs.bind(this, this.hide));
    player.on('canplaythrough', vjs.bind(this, this.hide));
    player.on('playing', vjs.bind(this, this.hide));
    player.on('seeking', vjs.bind(this, this.show));
    player.on('seeked', vjs.bind(this, this.hide));
    player.on('ended', vjs.bind(this, this.hide));
    player.on('waiting', vjs.bind(this, this.show));

We want to run the function vjs.bind(this, this.hide) for 5 different events and for that purpose we call player.on 5 times which makes the code very long and ugly.

From this, I came up with this feature/enhancement where you can call vjs.on with an array of events and attach the callback in all of them with a single call (passing an event as a string still works as before). With this feature the constructor of the Loading Spinner would look like this:

    player.on(['canplay', 'canplaythrough', 'playing', 'seeked', 'ended' ], vjs.bind(this, this.hide));
    player.on(['seeking', 'error', 'waiting'], vjs.bind(this, this.show));

The same goes with vjs.one and vjs.off, too.

For the implementation of this feature I needed a method to run a function for each element of an array but Array.prototype.forEach() was not a good idea due to performance issues (http://jsperf.com/fast-array-foreach) so I created vjs.arrayForEach which does the same thing but using the for() loop.
I have also included comments, unit tests for all of my changes (including .arrayForEach()) and updated the exports file to export vjs.on, vjs.off and vjs.one to be able to access them using bracket notation from vjs. forwardMultipleEvents.

themicp added 7 commits May 22, 2014 16:14
Passing an array of event types in vjs.on, vjs.one or vjs.off will create a listener for each one of the given events instead of calling vjs.on multiple times with the same callback.
….on, vjs.one or vjs.off and creates a call for each type in the array
…t array and write unit tests for vjs.arrayForEach to make sure that the fallback function works as expected
…otation and use for() loop instead forEach() for the arrays for better performance
@mmcc
Copy link
Member

mmcc commented May 22, 2014

Thank you for submitting this! I just did a quick once over, but from what I can see this is a really clean PR with tests to boot...Awesome.

@themicp
Copy link
Contributor Author

themicp commented May 22, 2014

Thank you! I will create soon another PR implementing this enhancement in cases like the one with the Loading Spinner.

@heff
Copy link
Member

heff commented May 22, 2014

Yeah, thanks @themicp! I'm going to make a few suggested updates inline.

Hold off on the loading spinner update specifically. In #1225 we're trying to moving away from binding to multiple events there.

* @param {Function} fn Event listener.
* @param {String} method Event method (on, off, one).
*/
vjs.forwardMultipleEvents = function( elem, type, fn, method ) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

By using the jsDoc comments and adding it to vjs it makes this a public function. I don't think it would get used outside of the core codebase so I think we could keep it private and allow closure compiler to mangle it. To make it public private you could change the name from vjs.forwardMultipleEvents to _forwardMultipleEvents and add the @private tag to the comment.

@heff
Copy link
Member

heff commented Jun 13, 2014

@themicp Are you still interested in making some of the updates listed here? Let me know if there's any outstanding questions I can answer.

@themicp
Copy link
Contributor Author

themicp commented Jun 16, 2014

@heff I am sorry for the delayed response. I am still interested in finishing this PR, I will fix those notes in the next couple of days.

@heff
Copy link
Member

heff commented Jun 16, 2014

No problem. Sounds good, thanks.

themicp added 3 commits June 17, 2014 07:48
moved vjs.arrayForEach in the vjs.arr object and rename it to vjs.arr.forEach,
update the vjs.arr.forEach unit tests.
renamed forwardMultipleEvents to _forwardMultipleEvents since it's a private function and also update the comments,
use vjs.arr.forEach instead of vjs.arrayForEach,
don't export vjs.one, vjs.on and vjs.off.
@themicp
Copy link
Contributor Author

themicp commented Jun 17, 2014

I updated the PR with the things mentioned in the comments. Let me know if there is anything left.

@heff heff added the confirmed label Jun 23, 2014
@heff
Copy link
Member

heff commented Jun 23, 2014

This looks ready to go to me. Will pull in soon.

@themicp
Copy link
Contributor Author

themicp commented Jun 23, 2014

That's great, thank you!

@heff
Copy link
Member

heff commented Jul 3, 2014

Awesome, thanks for pulling those changes in. I'll get this merged in after the holiday weekend.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants