Conventional jquery plugin vs AMD jquery plugin

174 views Asked by At

I still can't get my head around with this AMD jquery plugin.

// UMD dance - https://github.com/umdjs/umd
!function(root, factory) {
    if (typeof define === 'function' && define.amd) {
        define(['jquery'], factory);
    } else {
        factory(root.jQuery);
    }
}(this, function($) {
    'use strict';

    // Default options
    var defaults = {

    };

    // Constructor, initialise everything you need here
    var Plugin = function(element, options) {
        this.element   = element;
        this.options   = options;
    };

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

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

    // Create the jQuery plugin
    $.fn.plugin = function(options) {
        // Do a deep copy of the options - http://goo.gl/gOSSrg
        options = $.extend(true, {}, defaults, options);

        return this.each(function() {
            var $this = $(this);
            // Create a new instance for each element in the matched jQuery set
            // Also save the instance so it can be accessed later to use methods/properties etc
            // e.g. 
            //    var instance = $('.element').data('plugin');
            //    instance.someMethod();
            $this.data('plugin', new Plugin($this, options));
        });
    };

    // Expose defaults and Constructor (allowing overriding of prototype methods for example)
    $.fn.plugin.defaults = defaults;
    $.fn.plugin.Plugin   = Plugin;
});

Some tests,

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

I always get this empty object,

Object[]

So how can I use this empty object?

And I want to access the method inside the plugin,

    var plugin = $('.element').plugin();
    var instance = $('.element').data('plugin',plugin);
    console.log(instance); // an empty object again!
    console.log(instance.someMethod("hello world"));

TypeError: instance.someMethod is not a function

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

So how should I do to run the method inside the plugin then?

It is so different from the conventional jquery plugin. AMD's is so difficult to understand. Any idea how I can get this AMD works like the conventional!??

EDIT:

Finally I got something,

    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

Why was it so difficult for the those who comment and answer to point this out! Sigh!

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
Louis On

In your test with .some-element you would get an empty jQuery object if .some-element matches nothing since $.fn.plugin returns what this.each(...) returns and the jQuery.each function returns exactly the same jQuery object as what it was called on.

As to how to get the instance, let's go through each step:

var plugin = $('.element').plugin();

The line above won't create a plugin if $('.element') matches nothing. One thing for sure, the value you assign to plugin is equal to $('.element').

var instance = $('.element').data('plugin',plugin);

In context, the line above is equivalent to var instance = $('.element').data('plugin', $('.element')); And the return value of jQuery.data(key, value) is the jQuery object itself, so that here instance will be equal to $('.element').

console.log(instance); // an empty object again!

That's what you'd get if $('.element') matches nothing.

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

This is definitely not going to work.

How to access the plugin instance is detailed in a comment in your code:

        //    var instance = $('.element').data('plugin');
        //    instance.someMethod();

Of course for this to work, $('.element') has to match a non-empty set of elements.

AMD is not a factor at all in your problems. All of the issues here have to do with how to use jQuery and how to write jQuery plugins.