jQuery plugin + AMD = how to access functions?

365 views Asked by At

I am wrapping up my jQuery plugin in an AMD environment. This is my boilerplate,

!function(root, factory) {
    if (typeof define === 'function' && define.amd) {
        define(['jquery'], factory);
    } else {
        factory(root.jQuery);
    }
}(this, function($) {

    var defaults = {
       target: ''
    };

    var myPlugin = function(options) {
        options = $.extend(true, {}, defaults, options);

        return options;
    };

    myPlugin.prototype = {
        init: function(options) {
            return options;
        }
    };

    $.fn.myPlugin = myPlugin;

});

console.log($.fn.myPlugin.init());

error,

TypeError: $.fn.myPlugin.init is not a function

console.log($.fn.myPlugin.init());

Any ideas what I have done incorrectly? And how can I access the function inside myPlugin.prototype = {...}?

EDIT:

tested with this boilerplate,

console.log($('.test li').plugin({
        test: 'option1',
        test2: 'option2'
    }));

result,

Object[] // why is it empty?

And

console.log($.fn.plugin.someMethod());

result,

TypeError: $.fn.plugin.someMethod is not a function

console.log($.fn.plugin.someMethod());

And,

// Plugin methods and shared properties
    Plugin.prototype = {
        // Reset constructor - http://goo.gl/EcWdiy
        constructor: Plugin,

        someMethod: function(options) {
            return options;
        }
    };

console.log($.fn.plugin.Plugin.prototype.someMethod("hello world"));

result,

hello world

And,

var instance = $('.element').data('plugin');
    instance.someMethod("hello world");

result,

TypeError: instance is null // what does it mean? It should return 'hello world', isn't it?

instance.someMethod("hello world");

EDIT 2:

var plugin = $('.element').plugin();
    var instance = $('.element').data('plugin',plugin);
    console.log(instance); // returns - Object[]
    console.log(instance.someMethod("hello world"));

result,

TypeError: instance.someMethod is not a function

console.log(instance.someMethod("hello world"));

2

There are 2 answers

0
Run On BEST ANSWER
    var plugin = $('.element').plugin();
    var instance = $('.element').data('plugin');
    console.log(instance);
    console.log(instance.someMethod("hello world"));

result,

Object { element={...}, options={...}, constructor=function(), more...}

hello world
6
Simon Smith On

You don't seem to be actually creating an instance of myPlugin, instead you're trying to access the methods statically which may or may not be what you're after.

I find it better to create an instance of my Plugin object for each time the plugin is used. An example:

!function(root, factory) {
    if (typeof define === 'function' && define.amd) {
        define(['jquery'], factory);
    } else {
        factory(root.jQuery);
    }
}(this, function($) {
    'use strict';

    var defaults = {

    };

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

    Plugin.prototype = {
        constructor: Plugin,

        someMethod: function() {

        }
    }

    // Create the jQuery plugin
    $.fn.plugin = function(options) {
        options = $.extend(true, {}, defaults, options);

        return this.each(function() {
            var $this = $(this);
            $this.data('plugin', new Plugin($this, options));
        });
    };

    // Expose defaults and Constructor
    $.fn.plugin.defaults = defaults;
    $.fn.plugin.Plugin   = Plugin;
});

From here - https://gist.github.com/simonsmith/4353587

Now you could use the plugin like this:

require(['jquery', 'jquery.plugin'], function($) {
    $('.test li').plugin({
        test: 'option1',
        test2: 'option2'
    });
});

An instance of the object is saved in a data property, so it can always be accessed. Herotabs uses this technique:

var instance = $('.tabs').herotabs().data('herotabs');
instance.nextTab();