Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Creating a jQuery plugin: best practices regarding functions' visibility?

I'm creating a jQuery plugin. So far it's working fine, but I'm having doubt about the way I'm doing things:

jQuery.fn.myMethod = function() {
  return this.each(function(){
    MyScope.doSomething(jQuery(this).attr("id"));
  });
};

var MyScope = {

  // The functions contained in MyScope are extremely linked to the logic 
  // of this plugin and it wouldn't make a lot of sense to extract them

  doSomething: function(id){
    // something
    doSomethingElse(23);
    // some more code
    doSomethingElse(55);
  },

  doSomethingElse: function(someInt){
    // some code 
  }
};

I use MyScope to store all my "private" functions. I don't want the user to be able to go $("p").doSomething(), but I do need to use them.

I could move everything in the myMethod function, but it would create a 100 lines long function and people would hate me for it.

What's the best practices in this situation? Are there any great tutorials out there regarding this?

like image 932
marcgg Avatar asked Jun 10 '10 13:06

marcgg


2 Answers

You can encapsulate your functions to do what you want, like this:

jQuery.fn.myMethod = function() {
  return this.each(function(){
    doSomething(jQuery(this).attr("id"));
  });        
  function doSomething(id){
    //do something
  }
  function doSomethingElse(){
    // some code
  }
};

You can view a quick demo here

"I could move everything in the myMethod function, but it would create a 100 lines long function and people would hate me for it." ....why?

The code has to be defined somewhere, if you don't want it to be externally accessible there are a few ways, but I don't see why anyone would dislike you doing exactly this. It's all about scope and where you want things, as long as you're not declaring it multiple times and exposing only what you want, I don't see any problem.

There are several styles to declaring it, some with the same effect, the option I gave is one of many, but placing things inside myMethod is a perfectly reasonable approach.


To be more complete, here's another alternative:

(function($) { 
    function doSomething(id){
      //do something, e.g:  doSomethingElse('bob');
    }
    function doSomethingElse(str){
      //some code
    }
    $.fn.myMethod = function() {
      return this.each(function(){
        doSomething(jQuery(this).attr("id"));
      });   
    };
})(jQuery);

Or another:

(function($) { 
    var me = {
        doSomething: function(id){
         //do something, e.g:  this.doSomethingElse('bob');
        },
        doSomethingElse: function(str){
          //some code
        }
    };
    $.fn.myMethod = function() {
      return this.each(function(){
        me.doSomething(jQuery(this).attr("id"));
      });   
    };
})(jQuery);

Related articles:

  • JavaScript Module Pattern: In-Depth
  • JavaScript Closures for Dummies
like image 144
Nick Craver Avatar answered Oct 14 '22 17:10

Nick Craver


There's nothing wrong with using a large function just to create a new scope. The following keeps doSomething and doSomethingElse private and avoids defining new doSomething and doSomethingElse functions for each invocation of myMethod, which is what would happen if you put doSomething and doSomethingElse inside myMethod's definition.

(function() {
  function doSomething(id) {
    // Something
  }

  function doSomethingElse() {
    // Something else
  }

  jQuery.fn.myMethod = function() {
    return this.each(function(){
      doSomething(this.id);
    });
  };
})();
like image 6
Tim Down Avatar answered Oct 14 '22 16:10

Tim Down