Skip to content

Instantly share code, notes, and snippets.

@jakearchibald
Created July 7, 2010 09:14
Show Gist options
  • Select an option

  • Save jakearchibald/466490 to your computer and use it in GitHub Desktop.

Select an option

Save jakearchibald/466490 to your computer and use it in GitHub Desktop.
// I dislike the pattern of using string action names instead
// of creating instances and having instance methods...
var videoPlayerElement = $('#playerContainer').videoPlayer({
loop: true
}).videoPlayer('setSrc', 'whatever.mp4').videoPlayer('play');
// and later...
videoPlayerElement.videoPlayer('stop');
// I see it a lot in jQuery plugins. I guess it's convention,
// but I much prefer getting an instance of the 'player'
var videoPlayer = $('#playerContainer').videoPlayer('whatever.mp4', {
loop: true
}).play();
// and later
videoPlayer.stop();
@allmarkedup

Copy link
Copy Markdown

I really dislike this pattern too - I think that the issue is that because of the chainable nature of all methods in the jQuery core there is an expectation that plugins will maintain this chainability and return the jQuery object. Returning a custom object breaks this.

The pattern that I have found most 'comfortable' is binding custom events to the jQuery object in question within the plugin, so that it can still return the jQuery object and maintain chainability, but then respond to the events called on it, which feels sensible to me.

So you could have:

var videoPlayer = $('#playerContainer').videoPlayer('whatever.mp4', {
loop: true
}).trigger('play');

// and later
videoPlayer.trigger('stop');

Personally I find this the best compromise because I find it natural to think of 'stop' and 'play' as events, and it still maintains the chainability of the plugin.

@jakearchibald

Copy link
Copy Markdown
Author

Yeah, that workaround works fine (although I'd use triggerHandler as trigger would also try and call the show method of #playerContainer, and that's a possibility).

Still much prefer returning an instance that can be stored and used later. It still chains (as in the example above), but you're dealing with a non-jQuery object.

@allmarkedup

Copy link
Copy Markdown

Indeed, trigger just used above for brevity :-) In reality I also namespace the events too ( i.e. elem.triggerHandler('stop.myplugin') ) to avoid collisions.

But I do agree with you - returning a non-jQuery object is a much more 'JavaScript' way of doing things, it's just that a lot of people use jQuery plugins who are not necessarily that good with plain ol' JS and who (in my experience) have the expectation that all the plugins are jQuery-chainable, and see them as 'broken' if that pattern is not adhered to.

@danielknell

Copy link
Copy Markdown

The jQuery tools guys would agree, they solved the chain problem by storing the api object in the data() attribute.

they appear to have taken a lot of heat in the past for breaking with the jQuery UI convention though, even though in my opinion the tools model makes far more sense.

using their model your example would become:

var videoPlayer = $('#playerContainer').videoPlayer('whatever.mp4', {
    loop: true,
    api: true
}).play();

// and later
videoPlayer.stop();

the player object is always accessible even if you fail to keep track of it

var videoPlayer = $('#playerContainer').data('videoPlayer');

and you still get the chaining

$('#playerContainer').videoPlayer('whatever.mp4', {
    loop: true
}).show();

@jakearchibald

Copy link
Copy Markdown
Author

Ahh well, glad to know I'm not alone when it comes to my opinion of that style.

I don't see why videoPlayer() shouldn't return an object, other jQuery methods like .offset() return objects... but then I guess those objects don't have methods.

@jakearchibald

Copy link
Copy Markdown
Author

Actually, this pattern causes API confusion in jQuery UI...

$("#dialog").dialog().hide();

Because dialog() creates elements outside $("#dialog"), hiding #dialog means parts of the dialog stay visible.

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