HiveBrain v1.2.0
Get Started
← Back to all entries
patternjavascriptMinor

A jQuery "utility" plugin template

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
pluginjqueryutilitytemplate

Problem

I need to write a jQuery plugin that doesn't take an element to work.

Example call:

$.funkyTown();


... not called like this:

$('#foo').funkyTown();


...in other words, I need this plugin to act more like a "utility" plugin (vs. apply itself directly to a matched element(s)).

Here's what I have written so far:

```
;(function($, window, document, undefined) {

var console = this.console || { log : $.noop, warn: $.noop }, // http://api.jquery.com/jQuery.noop/

defaults = {

foo : 'bar',

// Callbacks:

onInit : $.noop, // After plugin data initialized.
onAfterInit : $.noop // After plugin initialization.

// Using $.noop shorter than function() {} and slightly better for memory.

},

settings = {},

methods = {

// Initialize!
// Example call:
// $.funkyTown({ foo : 'baz' });
// @constructor
init : function(options) {

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

settings.onInit.call(this, 'that');

console.log('1. init:', settings.foo, _foo_private_method(), methods.foo_public_method());

console.warn('2. I\'m a warning!');

settings.onAfterInit.call(this);

return this; // Is this needed for chaining?

},

// Example call:
// console.log($.funkyTown('foo_public_method', 'Wha?'));
foo_public_method : function(arg1) {

arg1 = (typeof arg1 !== 'undefined') ? arg1 : 'Boo!';

return 'foo_public_method(), arg1: ' + arg1;

},

// Might need to give users the option to destroy what this plugin created:
destroy : function() {

// Undo things here.

}

},

// The _ (underscore) is a naming convention for private members.
_foo_private_method = function() {

return '_foo_private_method(), settings.foo: ' + settings.foo;

};

// Method calling logic/boilerplate:

Solution

What I suggest is read the jQuery source. Check out how they do it. In their init method they return this for certain cases, but not for others.

Like when there is no selector:

if ( !selector ) {
    return this;
}


But if you check out other "utility" plugins in their source like $.map

map: function( elems, callback, arg ) {
var value,
    i = 0,
    length = elems.length,
    isArray = isArraylike( elems ),
    ret = [];

    // Go through the array, translating each of the items to their
    if ( isArray ) {
        for ( ; i < length; i++ ) {
            value = callback( elems[ i ], i, arg );

            if ( value != null ) {
                ret[ ret.length ] = value;
            }
        }

    // Go through every key on the object,
    } else {
        for ( i in elems ) {
            value = callback( elems[ i ], i, arg );

            if ( value != null ) {
                ret[ ret.length ] = value;
            }
        }
    }

    // Flatten any nested arrays
    return core_concat.apply( [], ret );
},


Here they don't return the jQuery object, since this utility is for arrays. My point here is that there's no one shoe fits all. It depends on what you're trying to get from your plugin. Also chaining is expected but not on something like $.map().

Also keep in mind, in your callbacks this should refer to the element in question (ie. in a click callback this refers to the clicked element). If you're not playing with an element, this should refer to the global(window) object.

Code Snippets

if ( !selector ) {
    return this;
}
map: function( elems, callback, arg ) {
var value,
    i = 0,
    length = elems.length,
    isArray = isArraylike( elems ),
    ret = [];

    // Go through the array, translating each of the items to their
    if ( isArray ) {
        for ( ; i < length; i++ ) {
            value = callback( elems[ i ], i, arg );

            if ( value != null ) {
                ret[ ret.length ] = value;
            }
        }

    // Go through every key on the object,
    } else {
        for ( i in elems ) {
            value = callback( elems[ i ], i, arg );

            if ( value != null ) {
                ret[ ret.length ] = value;
            }
        }
    }

    // Flatten any nested arrays
    return core_concat.apply( [], ret );
},

Context

StackExchange Code Review Q#19799, answer score: 3

Revisions (0)

No revisions yet.