Skip to content

Instantly share code, notes, and snippets.

@raglan-road
Created September 21, 2012 16:23
Show Gist options
  • Save raglan-road/3762458 to your computer and use it in GitHub Desktop.
Save raglan-road/3762458 to your computer and use it in GitHub Desktop.
Patterns for building jQuery plugins!
// Why plugins? Think about using a plugin when you need a piece of reusable functionality that will be applied to
// an element - and potentially many elements - in a given UI.
// Resource: http://docs.jquery.com/Plugins/Authoring
// The basic plugin boilerplate
;(function($){
$.fn.plugin = function(){
// If your plugin needs to be chainable, return this!
return this; // this -> reference to calling jQuery Object e.g. $('.foo').plugin() => $('.foo')
}
}(jQuery));
// $('.foo').plugin();
// $('li').plugin().removeClass('no-plugins-here');
// What about processing multiple items in a selector, like $('li') or $('.foo')?
;(function($){
$.fn.plugin = function(){
return this.each(function(){
// Process each item in your jQuery collection
});
}
}(jQuery));
// $('body, .foo, li').plugin().addClass('pluginified');
// More robust: passing in configuration options! This is meant to run exactly *once*; running multiple times will basically rerun everything.
;(function($){
$.fn.plugin = function(opts){
// Always set defaults so callers do not need to pass in an options object
var options = {
foo: 1,
bar: 2,
onBeforeInit: null
};
$.extend(options, opts); // jQuery magic: Merge default options and user-supplied opts; farthest-right argument takes precendence in the merge.
return this.each(function(){
// Maybe we use onBeforeInit to notify subscribers that something's happening...
if(typeof options.onBeforeInit === "function"){
options.onBeforeInit();
}
// Process each item in your jQuery collection
$(this).data('foobar', options.foo + options.bar);
console.log(options)
});
}
}(jQuery));
// $('div').plugin()
// $('div').plugin({ foo: 1, bar: 2, newOpt: "hello!"})
// Let's get super-fancy: methods! This is the jQuery UI-ish way of doing things, like $('.some-el').dialog('open') or $('.some-el').dialog('close')
;(function($){
"use strict";
// Always set defaults so callers do not need to pass in an options object
var options = {
foo: 1,
bar: 2,
onBeforeInit: null
},
methods = {
// Allow the user to get or set options
options: function(key, value){
if(typeof value !== "undefined"){
options[key] = value;
}
return options[key];
},
// Our default case: initialize the plugin
init: function(opts){
// Maybe we use onBeforeInit to notify subscribers that something's happening...
if(typeof options.onBeforeInit === "function"){
options.onBeforeInit();
}
$.extend(options, opts);
return this.each(function(){
// Always bind info to .data()!
$(this).data('plugin', $('<div class="plugin">Hi!</div>').appendTo(this).hide())
.bind('click.plugin', function(){ alert('plugin!') });
});
},
// Just an example
show: function(){
$(this).data('plugin').show();
console.log('we just showed a fake div!')
},
destroy : function(){
// Unbind any events we bound
// Clean up any data() we stored
// Remove any elements added to page
}
};
// Note the change! Everything else is "private" due to a closure.
$.fn.plugin = function(method){ // User can pass in optional arguments, so the signature is really something like (method,[option, option, ...])
// Did the user pass in a configuration object or a method name?
if(method in methods){
// If the user supplied a method, execute it for them. We'll slice off the first argument (method name) in case the user supplied additional parameters.
return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
}
else if(typeof method === "object" || typeof method === "undefined"){
return methods['init'].apply(this, arguments); // Our default case: initialize the plugin
}
else{
$.error("Method " + method + " does not exist");
}
}
}(jQuery));
// $('.some-selector').plugin();
// $('.some-selector').plugin({ foo: 42, baz: "hello!", onBeforeInit: function(){ console.log('before!') } });
// $('.some-selector').plugin('options','foo',11);
// $('.some-selector').plugin('show');
;(function($){
$.fn.navItemThing = function(){
var show = function(el){
$(el).addClass('visible');
$('#' + $(el).data('flyoutid').show();
}
var hide = function(el){
$(el).removeClass('visible');
$('#' + $(el).data('flyoutid').hide();
}
return this.each(function(){
// $('.action-button').navItemThing();
$(this).bind('click.navItemThing', function(e){
e.preventDefault(); // ALWAYS!!!
// <a href="#" data-flyoutid="foo">^</a> ... <ol id="foo"><li>one</li><li>two</li><li>three</li></ol>
if($(this).hasClass('visible'){ show(this); }
else{ hide(this); }
}
});
}
}(jQuery));
// $('.action-buttons').navItemThing();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment