views:

48

answers:

2

I enjoy writing most of my functionality using object literal notation and wondered what other people thought of it in comparison to jQuery.fn plugin notation?

The issue I find with writing code as a jquery 'plugin' is that you then don't get a public 'API' to work with. Take this crude popup box example:

$.fn.popup = function() {

  // insert #popupContainer

  this.each(function() {

    $(this).click(function() {
      $('#popupContainer').show();
    });
  });

});

// DOM ready
$('a.showPopup').popup();

The popup will show when the a.showPopup anchor is clicked. There's no other interface to show the popup without querying the DOM for #popupContainer and manually showing it.

This is why I like object literals as they provide public methods that can be called whenever. Take this example:

var popup = {
   init: function() { 
        // insert #popupContainer
        // bind this.show to $(a.showPopup)
   }
   show: function() { $('#popupContainer').show(); }
}

This is nice because it allows me to call popup.show() whenever I want, I don't have to rely a binding I've made earlier.

This example is a bit rubbish but I hope you can see the idea I'm getting at and its impact when the functionality is more complex.

So what do you prefer? and is there anything I'm missing with jQuery plugins?

I'd be interested to hear any thoughts?

A: 

Can you not simply insert the "#popupContainer" element the first time you call popup() in your first example? That way you don't have to call init at all.

Also, in jQuery the standard way to add "global" API functions is to add them to the $ object directly:

(function($) {

    $.myPlugin = function() {
        alert("1");
    }

    $.fn.myPlugin = function() {
        alert(2);
    }

})(jQuery);

So now you can do the following:

$.myPlugin(); // pops up "1"

$("whatever").myPlugin(); // pops up "2"
Dean Harding
That looks like you'll end up polluting the jQuery namespace pretty quickly. Imagine having $.popupShow(), $.popupHide(), $.popupPosition(), $.popupInsert(). I think that would be a bad idea, maybe creating an object literal $.popup = {} in the jQuery namespace containing all it's related methods would be sensible but it would be no different to my initial object literal example...
Richard
@Richard: yes, if you've got lots of methods then it makes sense to add them to a object literal off the jQuery object: `$.popup.hideAll()` `$.popup.whatever()`. Whether you just go with a global literal or not at this point is largely a matter of choice... obviously if your goal is a jQuery plugin, then you've got no choice but if you're just doing for your own use, then do whatever is best for you.
Dean Harding
Yeah I guess that's the case, I'm sometimes unsure of when I should use an object literal over jQuery.fn. I guess the decision should be based on whether the functionality explicitly requires a jQuery object to iterate through, in which case jQuery.fn is probably better due to it's implicit iteration and chainability. Thanks for your thoughts.
Richard
A: 

Another under-utilized option is custom events, for example:

$.fn.popup = function() {    
  // insert #popupContainer    
  return this.each(function() {    
    $(this).bind({
      "open.popup": function() { $('#popupContainer').show(); },
      "click": function() { $(this).triggerHandler("open.popup"); }          
    });
  });    
});

This may not be a good example, but you could do for example:

$('a.showPopup').popup(); //initialize plugin
$('a.showPopup').trigger("open.popup"); //open the popup
$('a.showPopup').click(); //less explicit, but works...no need for the open bind
Nick Craver