Skip to content

Instantly share code, notes, and snippets.

@kflorence
Created November 17, 2010 01:43
Show Gist options
  • Select an option

  • Save kflorence/702866 to your computer and use it in GitHub Desktop.

Select an option

Save kflorence/702866 to your computer and use it in GitHub Desktop.
jQuery plugin pattern
(function($) {
// $.widget-lite
$.plugin = function(name, base, prototype) {
if (!prototype) {
prototype = base;
base = function(options, element) {
if (arguments.length) {
$.data(element, name, this);
this.element = $(element);
this._init(options);
}
};
base.prototype = {
_init: function() {}
};
}
$.extend(true, base.prototype, prototype);
$.fn[name] = function(options) {
var isMethodCall = (typeof options === "string"),
args = Array.prototype.slice.call(arguments, 1),
returnValue = this; // Chain by default
if (isMethodCall) {
if (options.charAt(0) === "_") { // Psuedo-private
return returnValue;
}
this.each(function() {
var instance = $.data(this, name) || new base({}, this);
if (instance && $.isFunction(instance[options])) {
var methodValue = instance[options].apply(instance, args);
if (methodValue !== undefined) {
returnValue = methodValue;
return false;
}
}
});
} else {
this.each(function() {
var instance = $.data(this, name);
if (instance) {
instance._init(options);
} else {
new base(options, this);
}
});
}
return returnValue;
};
};
})(jQuery);
// Set up like so:
jQuery(function($) {
$.plugin("pluginName", {
options: {
test: true
},
_init: function(options) {
$.extend(true, this.options, options || {});
},
somePublicFunc: function() {
console.log(this.options.test);
}
});
});
// Then use like so:
$("#element").pluginName({test: false}); // initialize first
$("#element").pluginName("somePublicFunc"); // => false
// Or use without initializing (danger!?)
$("#element").pluginName("somePublicFunc"); // => true
@kflorence

Copy link
Copy Markdown
Author

I wonder if there is anything inherently wrong with this...

@cowboy

cowboy commented Nov 17, 2010

Copy link
Copy Markdown

But then, every time you want to access that element's instance, you need to use $(elem).data("plugin"), which keeps you from being able to chain. A signature like $(elem).plugin() or $(elem).plugin( "submethod" ) (chainable) would probably feel more jQuery-like. This is the signature the jQuery UI Widget Factory provides (among other things).

@kflorence

Copy link
Copy Markdown
Author

Very true, apart from initialization chaining is impossible. I never really cared for the jQuery UI submethod style, but I suppose it's probably the best thing to use right now. Anyways, thanks for the insight, back to the drawing boards!

@kflorence

Copy link
Copy Markdown
Author

After reading up on $.widget a bit, it seems like that is basically what I want. I guess I was trying to avoid the overhead of having to incorporate jQuery.UI into my plugin, but there's no use in re-inventing the wheel.

@kflorence

Copy link
Copy Markdown
Author

I think my "$.widget-lite" should work for most of the things I want to use it for.

@cowboy

cowboy commented Nov 17, 2010

Copy link
Copy Markdown

I had been hacking around with a "lite" widget factory as well, but haven't gone too far with it yet.

@kflorence

Copy link
Copy Markdown
Author

Hah! And here I was thinking I was being original ;) I think yours is a bit more straightforward, I wonder which is faster.

@kflorence

Copy link
Copy Markdown
Author

http://jsfiddle.net/kflorence/bc8Kx/ -- Not sure how accurate that benchmark is, but it seems that prototypical inheritance is definitely the way to go. There are definitely other differences in the two plugins, but that one probably has the most bearing on speed ("new" vs. $.extend({}, {...}) is my guess).

@kflorence

Copy link
Copy Markdown
Author

Stuck what I've got now in a Repo: https://github.com/kflorence/jquery-plugin
Feel free to tweak

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment