1

From the jQuery boilerplate site, I've came up with a plugin that looks like this:

;(function($, window, document, undefined){
  "use strict"; 

  var defaults = {
        abc: 1,
        def: 'xyz'        
      };

  function Plugin(element, options){
    this.options = $.extend({}, defaults, options, element.dataset);
    this.element = element;
  }

  plugin.prototype = {
     goTo: function(where){
       // ...
     },

     close: function(){
       $(this.element).removeData('_myplug');   
     }
  };

  $.fn.myPlugin = function(options){
    return this.each(function(){
      if(!$.data(this, '_myplug'))
        $.data(this, '_myplug', new Plugin(this, options));

      if($.isPlainObject(options))
        return;

      // here how to check if 'options' matches one of the
      // functions, then call it with the rest of the variables
    });
  };

})(jQuery, window, document);

So it can be used like

$('.stuff').myPlugin({abc: 5});

How can I also allow calls to public methods, like this:

$('.stuff').myPlugin('goTo', 'top');
// should call instance.goTo('top');

Or:

$('.stuff').myPlugin('close');
// should call instance.close();

?

I know it's possible by adding more variables in the $.fn.myPlugin function declaration, then check with an if statement if options is a string, but I was wondering if there's a nicer way to do this


For example, in PHP it would look like this:

$args = func_get_args();
$arg1 = array_shift($args);
return call_user_func_array(array($this, $arg1), $args);

How can I do this in javascript?

Alex
  • 66,732
  • 177
  • 439
  • 641
  • Perhaps use the [`arguments`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions_and_function_scope/arguments) object? You're still going to have to have some way to distinguish how the function is called, and that's typically by checking argument types, and/or properties that may exist on some of the arguments. – ajp15243 Jun 10 '13 at 20:12
  • [I've been building a jQuery widget template for some time, which handles the function calling from line 52 to line 65](https://github.com/zzzzBov/jQuery-widget.tmpl.js/blob/master/jqwt/jquery-widget.tmpl.js). – zzzzBov Jun 10 '13 at 20:13

1 Answers1

1

Here is in short how you can do it:

var instance = $.data(this, '_myplug');
if (typeof options === "string" && typeof instance[options] === "function") {
    instance[options].apply(instance, arguments.slice(1));
}

Explaination

First, you check if options is a string and if your instance contains a method that has the name of options.

Then you use the arguments Array. You can access this array from inside any function and it contains all the arguments, that were passed when you called the function (whether those arguments are part of the function definition or not).

Finally you can use the function.apply() method, to pass a modified version of the arguments array (all arguments except the first) to the method of your instance.

basilikum
  • 10,378
  • 5
  • 45
  • 58