简体   繁体   中英

jQuery Plugin Namespacing Functions

I'm creating a jQuery plugin that that is rather large in scope. In fact, the plugin technically consists of a few plugins that all work together.

(function($){
    $.fn.foo = function(){
        //plugin part A
    }
    $.fn.bar = function(){
        //plugin part B
    }
    $.fn.baz = function(){
        //plugin part C
    }
}(jQuery))

Is it possible to namespace jQuery plugins such that the minor plugins could be functions of the larger plugin

$.fn.foo.bar = function(){}
$.fn.foo.baz = funciton(){}

This would keep from polluting the jQuery function namespace. You could then call the plugins like

$('#example').foo()
$('#other_example').foo.bar()

The issue I have run into when trying this out myself is that the functions declared as properties of the foo() plugin function don't have their references to 'this' set properly. 'this' ends up referring to the parent object and not the jQuery object.

Any ideas or opinions would be appreciated.

-Matt

As soon as you use $.fn.foo.bar() -- this points to $.fn.foo , which is what you would expect in JavaScript ( this being the object that the function is called on.)

I have noticed in plugins from jQuery UI (like sortable) where you call functions like:

$(...).sortable("serialize");
$(...).sortable({options});

If you were doing something like this - you could extend jQuery itself:

$.foo_plugin = {
  bar: function() {},
  baz: function() {}
}

$.fn.foo = function(opts) {
  if (opts == 'bar') return $.foo_plugin.bar.call(this);
  if (opts == 'baz') return $.foo_plugin.baz.call(this);
}

I know this has already been answered but I have created a plugin that does exactly what you want:

http://code.google.com/p/jquery-plugin-dev/source/browse/trunk/jquery.plugin.js

I've included a small example below, but check out this jQuery Dev Group post for a more in-depth example: http://groups.google.com/group/jquery-dev/browse_thread/thread/664cb89b43ccb92c/72cf730045d4333a?hl=en&q=structure+plugin+authoring#72cf730045d4333a

It allows you to create an object with as many methods as you want:

var _myPlugin = function() {
    // return the plugin namespace
    return this;
}

_myPlugin.prototype.alertHtml = function() {
    // use this the same way you would with jQuery
    alert($(this).html());
}

$.fn.plugin.add('myPlugin', _myPlugin);

now you can go:

$(someElement).myPlugin().alertHtml();

There are, of course, many, many other possibilities with this as explained in the dev group post.

Well, I'm sure there are many ways to skin this cat. The jQuery UI library uses a pattern like this:

// initialize a dialog window from an element:
$('#selector').dialog({});

// call the show method of a dialog:
$('#selector').dialog('show');

I'm a fan of the pattern I've seen on Eric Martin's SimpleModal . This works well for when I'm NOT acting on DOM elements -- in this case a wrapper to utilize localStorage.

This way I can easily refer to the constructor:

$.totalStorage('robo', 'cop');

...or a public method:

$.totalStorage.getItem('robo'); //returns 'cop'

Here's the internals:

;(function($){

/* Variables I'll need throghout */

var ls;
var supported = true;
if (typeof localStorage == 'undefined' || typeof JSON == 'undefined') {
    supported = false;
} else {
    ls = localStorage;
}

/* Make the methods public */

$.totalStorage = function(key, value, options){
    return $.totalStorage.impl.init(key, value);
}

$.totalStorage.setItem = function(key, value){
    return $.totalStorage.impl.setItem(key, value);
}

$.totalStorage.getItem = function(key){
    return $.totalStorage.impl.getItem(key);
}

/* Object to hold all methods: public and private */

$.totalStorage.impl = {

    init: function(key, value){
        if (typeof value != 'undefined') {
            return this.setItem(name, value);   
        } else {
            return this.getItem(name);
        }
    },

    setItem: function(key, value){
        if (!supported){
            $.cookie(key, value);
            return true;
        }
        ls.setItem(key, JSON.stringify(value));
        return true;
    },

    getItem: function(key){
        if (!supported){
            return this.parseResult($.cookie(key));
        }
        return this.parseResult(ls.getItem(key));
    },  

    parseResult: function(res){
        var ret;
        try {
            ret = JSON.parse(res);
            if (ret == 'true'){
                ret = true;
            }
            if (ret == 'false'){
                ret = false;
            }
            if (parseFloat(ret) == ret){
                ret = parseFloat(ret);
            }
        } catch(e){}
        return ret;
    }
}})(jQuery);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM