11

I've been using the jQuery Boilerplate for developing plugins and one thing I can't figure out is how to call methods from outside the plugin.

For reference, here is the boilerplate code I'm talking about: http://jqueryboilerplate.com/

In my fiddle,

http://jsfiddle.net/D9JSQ/2/

Here is the code:

;(function ( $, window, document, undefined ) {

    var pluginName = 'test';
    var defaults;

    function Plugin(element, options) {
        this.element = element;

        this.options = $.extend( {}, defaults, options) ;

        this._name = pluginName;

        this.init();
    }

    Plugin.prototype = {
        init: function() {
            this.hello();
        },
        hello : function() {
            document.write('hello');
        },
        goodbye : function() {
            document.write('goodbye');
        }
    }


    $.fn[pluginName] = function ( options ) {
            return this.each(function () {
                if (!$.data(this, 'plugin_' + pluginName)) {
                    $.data(this, 'plugin_' + pluginName, 
                    new Plugin( this, options ));
                }
            });
    }


})( jQuery, window, document );

$(document).ready(function() {
    $("#foo").test();
    $("#foo").test('goodbye');
});

I am trying to call the goodbye method using the following syntax:

$("#foo").test('goodbye')

How do I achieve this? Thanks in advance

Andrew H
  • 225
  • 3
  • 9
  • You can see [my answer on this question](http://stackoverflow.com/a/13778012/417685). It has a jQuery plugin template with accessible methods which actually resemble very much this one, but it is not the same – Alexander Jan 02 '13 at 20:20
  • From the jquery boilerplate wiki: https://github.com/jquery-boilerplate/jquery-boilerplate/wiki/Extending-jQuery-Boilerplate – jackocnr Sep 23 '13 at 00:21

1 Answers1

19

You'll have to get a reference to the class to call it's method with that plugin structure.

http://jsfiddle.net/D9JSQ/3/

$(document).ready(function() {
    var test = $("#foo").test().data("plugin_test");
    test.goodbye();
});

To do what you want, you must get rid of document.write to test it.

http://jsfiddle.net/D9JSQ/8/

;
(function($, window, document, undefined) {

    var pluginName = 'test';
    var defaults;

    function Plugin(element, options) {
        this.element = element;

        this.options = $.extend({}, defaults, options);

        this._name = pluginName;

        this.init();
    }

    Plugin.prototype = {
        init: function(name) {
            this.hello();
        },
        hello: function(name) {
            console.log('hello');
        },
        goodbye: function(name) {
            console.log('goodbye');
        }
    }


    $.fn[pluginName] = function(options) {
        return this.each(function() {
            if (!$.data(this, 'plugin_' + pluginName)) {
                $.data(this, 'plugin_' + pluginName, new Plugin(this, options));
            }
            else if ($.isFunction(Plugin.prototype[options])) {
                $.data(this, 'plugin_' + pluginName)[options]();
            }
        });
    }


})(jQuery, window, document);

$(document).ready(function() {
    $("#foo").test();
    $("#foo").test('goodbye');
});​

Look to the console for information.

Kevin B
  • 94,570
  • 16
  • 163
  • 180
  • I have seen a pattern somewhere where it stores all the methods into a an array and checks if the options when the plugin is called, is a string and if it is, then it calls that method. Is this possible with this structure? – Andrew H Jan 02 '13 at 20:15
  • 1
    Yes, you would just add an elseif to your structure that checks the prototype for an existing method. If it exists, it gets executed. Here's a good example, no point in re-inventing the wheel: http://keith-wood.name/pluginFramework.html – Kevin B Jan 02 '13 at 20:17
  • @AndrewH I answered a similar question to the if/else here: http://stackoverflow.com/questions/14078481/not-able-to-call-a-function-within-a-simple-jquery-plugin/14078885#14078885 I recently noticed this new pattern for developing jQuery plugins, I'll check out that boilerplate link you posted. – Syon Jan 02 '13 at 20:22
  • Thanks Syon, you answered my question :) – Andrew H Jan 02 '13 at 22:24
  • 2
    Could parameters be passed in using this method? – Fisu Mar 02 '14 at 12:21
  • @KevinB Great example. How can we do this other way around? Access function that is outside boilerplate inside boilerplate method? – Benn Mar 04 '14 at 05:26
  • You would have to give me an example, i don't know what you mean. – Kevin B Mar 04 '14 at 16:07
  • Hi, how to retrieve methods arguments such as $("#foo").test('goodbye', {foo: bar}); ? – Syl Apr 28 '14 at 16:48
  • @sylouuu In my code sample, the `name` argument would contain `{foo: bar}` – Kevin B Apr 28 '14 at 16:50
  • @KevinB ... next question. What is the best way to return data from the method call? var c = $("#foo").test('goodbye'); – nokturnal Mar 02 '15 at 15:30
  • you would simply return what you want instead of returning `return this.each...` – Kevin B Mar 02 '15 at 16:04