Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Issue with creating an jQuery plugin without selector

I'm working on a jQuery plugin which does not require a selector so I'm just adding it to the global jQuery namespace.

I'm having issues with sharing internal instance variables between my plugin's public methods. For example, I would like to be able to access $.MyPlugin.settings from the .init method.

Here's the plugin code:

(function($) {
    $.MyPlugin = function(options) {

        var defaults = {
            username: '',
            password: ''
        }

        var plugin = this;

        plugin.settings = {};

        plugin.init = function() {
          plugin.settings = $.extend({}, defaults, options);
        }

        plugin.init();
  }

  $.MyPlugin.init = function(callback) {
    console.log(this.settings); // undefined
    callback();
  }


}(jQuery));

In main.js, I have:

$(document).ready(function() {
  $.MyPlugin({
      username: 'myuser',
      password: 'mypass'
  });

  $.MyPlugin.init(function() {
      console.log('hi');
  });

This returns:

undefined
hi
like image 741
doremi Avatar asked Sep 09 '13 00:09

doremi


2 Answers

The issue you're coming across is that the data isn't persistent across every instance of your plugin. This is default behaviour but you can get around it using .data():

(function ($) {
    $.MyPlugin = function (options) {

        var defaults = {
                username: '',
                password: ''
            },
            plugin = this,
            options = options || {};


        plugin.init = function () {
            var settings = $.extend({}, defaults, options);
            $.data(document, 'MyPlugin', settings);
        }

        plugin.init();

    }

    $.MyPlugin.init = function (callback) {
        console.log($.data(document, 'MyPlugin'));
        callback();
    }

}(jQuery));

This stores your plugin's settings on the document element using jQuery's .data() function. This doesn't allow for multiple instances of your plugin with separate options though as every re-declaration of $.MyPlugin's options will overwrite the previous ones.

I'm basing my answer on the presumption that you want to use different public methods throughout your script and have them all share the original options. If you're only wanting to call the plugin once then Robert's is probably more in the right direction.

Here it is working: http://jsfiddle.net/pPJYx/

like image 170
Joe Avatar answered Nov 07 '22 14:11

Joe


In this case I would pass the init function along with the options, so you would end up initializing the plugin like this:

$(document).ready(function() {
  $.MyPlugin({
      username: 'myuser',
      password: 'mypass',
      init: function() {
          console.log('hi');
      }
  });

And in the plug in, you can call the init function like this:

//set the 'this' to the plugin inside init
if (options.init) options.init.call(plugin)
like image 42
Robert Byrne Avatar answered Nov 07 '22 15:11

Robert Byrne