Skip to content

Instantly share code, notes, and snippets.

@lokothodida
Last active August 29, 2015 14:24
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save lokothodida/d688afcf894ddb61209f to your computer and use it in GitHub Desktop.
Save lokothodida/d688afcf894ddb61209f to your computer and use it in GitHub Desktop.
jQuery Nested Plugins
// This piece of code illustrates how you can build a series of jQuery plugins
// nested on your own desired namespace. So if you have a plugin named 'plugin',
// it can have the signature:
// $(selector).plugin(opts)
// and there can exist jQuery plugins 'module1', 'module2', 'module3', ... which
// have the signatures:
// $(selector).plugin().module1(opts)
// $(selector).plugin().module2(opts)
// $(selector).plugin().module3(opts)
// These modules are written almost exactly like normal jQuery plugins bound
// directly to $.fn, but they only live within the 'plugin' namespace.
;(function($, window, document, undefined) {
// Your main plugin, as it would be defined on $.fn
// We alias $.fn.plugin with just @plugin to shorten our references to
// $.fn.plugin later on
var plugin = $.fn.plugin = function(opts) {
// If no arguments are passed, we will return the sub plugins
// using the @getModules singleton method which we will later define
if (!arguments.length) {
return plugin.getModules(this, plugin.modules);
}
// Now you can define your plugin as usual...
// E.g:
var init = function(i, elem) {
var $elem = $(elem);
// ...
};
// ...
return this.each(init);
};
// This is the method that does the heavy lifting
// It will take a @context (a jQuery Element), and @modules -- which will be an
// object literal of jQuery plugins -- and return a new object literal wherein
// the references to @this in those plugins has been fixed to the @context
plugin.getModules = function(context, modules) {
var api = {}; // where the altered methods will be stored
$.each(modules, function(name, module) {
// Module name is the same, but the function will instead call @body with
// the context shifted to @context (and take the same arguments)
api[name] = function() {
return module.apply(context, arguments);
};
});
return api;
};
// Initialize the @modules object
plugin.modules = {};
// Now each of your modules are defined on the @modules literal as though they
// were normal jQuery plugins; their references to @this will be fixed by the
// @getModules method (called when your main plugin is initialized)
// Module 1
// Accessed with: $(selector).plugin().module1(opts)
plugin.modules.module1 = function(opts) {
// Code for this plugin ...
var init = function(i, elem) {
// ...
};
// By returning this.each, module1 is chainable with the plugins on the $.fn
// namespace
// E.g. you can call $(selector).plugin().module1(opts1).css(opts2);
return this.each(init);
};
// Module 2
// Accessed with: $(selector).plugin().module2(params)
plugin.modules.module2 = function(opts) {
// Code for this plugin ...
var init = function(i, elem) {
// ...
};
// By returning this.each(...).plugin, module2 is chainable with the plugins
// on the $(...).plugin() namespace
// E.g. you can call $(selector).plugin().module2(opts1).module1(opts2);
return this.each(init).plugin();
};
// Module 3
// Accessed with: $(selector).plugin().module3(params)
plugin.modules.module3 = function(opts) {
// Code for this plugin ...
// You can have as many modules as you need
};
})(jQuery, window, document);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment