Tuesday, May 18, 2010

My first JQuery Plugin - jquery.he3.inputlinks.js

I am writing about my first simple javascript plugin - jquery.he3.inputlinks.js

I have never been particularly strong at Javascript, and lately my own clumsy attempts at writing reusable encapsulated javascript code had me looking around at how these things are done in the wider world. Since I was already using JQuery on My Web Brain I decided to go ahead and see how the thousands of JQuery plugins approached the same problems of packaging and encapsulation.

I present here my first and very rudimentary JQuery plugin - inputlinks. This is a stateless plugin that allows a hyperlink, span or other html container to set the value of a HTML input (type of text, radio or checkbox) or textarea to a known value when it is clicked.


Here is the code (I am considering establishing he3-js-lib on google code, like I did recently with he3-appengine-lib, but will hold off for the moment)

/**
 * jquery.he3.inputlinks.js
 *
 * A JQuery wrapper plugin for allowing a hyperlink to populate entries
 * into a form input (type text, checkbox or radio) or text area.
 *
 * @author Ben Davies
 * @company Helium 3 IT Solutions, www.he3.com.au
 *
 * Usage:
 * wrapped_set.inputlink(target,value)
 *
 * Parameters:
 * wrapped_set - A wrapped set containing any object that can support a click
 * event. Note that when used on spans, they are changed to hyperlinks.
 * target - (string|object) string selector or reference to the input (type =
 * 'input', 'checkbox' or 'radio') or textarea to insert the value into.
 * value - (string|object) string value or object reference whose inner text
 * will be used to provide the value.
 *
 */

(function($){
$.fn.inputlink = function(target, value) {
//convert any span which is the target to a hyperlink before
//continuing

var refined_set = this;
value = value || '';

if(this.filter('span').length > 0){
refined_set = this.filter('span').wrap('');
}


refined_set.click(function(event){

$(target).val(value.innerText? value.innerText : value);
$(target).filter('input[type=radio]').attr('checked','true');
$(target).filter('input[type=checkbox]').attr('checked','true');

event.preventDefault();
}).attr('title','click to set this value');

return this;
};
})(jQuery);


There is nothing amazing here in what I am doing or how I am doing it. In fact I suspect that had my search abilities on plugins.jquery.com been better, I might not have needed to write my own plugin.

But just for the sake of taking this post somewhere useful, I will point out a couple of features that might interest someone with no or little JQuery plugin experience (like me):

  • The entire plugin is wrapped in (function($) { ... })(jQuery); What's that for? This is a technique for making sure the $ function (which is an alias of jQuery) can be used within the plugin without fear of conflicting with another Javascript framework which uses a function named '$' (for example, Prototype). By making the plugin a self-executing anonymous function with a parameter assigned to '$' and receiving the value jQuery, $ happily exists in its own scope with the plugin only. 
  • The work of the plugin is all done within a function assignment inside of this self-executing function. $.fn.inputlink = function( target, value) { ...} dynamically assigns a function the jQuery.fn, which is internally aliased to allow the function (in this case, inputlink) to be called on a jQuery wrapped set. If we did not want the function to operate on a wrapped set, we would have simply extended $ directly. 
  • When working on a wrapped set, you usually want to returned the wrapped set to allow method chaining, and hence the return this; statement at the end of the function. This allows statements such as $('#mylink').inputlink('#myinput','my value').addClass('bright-green');
That is the extent of my wisdom on creating jQuery wrapped set plugins. Hopefully I will learn more as I transition some of the existing code on My Web Brain to JQuery plugins. I am especially keen to try stateful plugins, which made me most uncomfortable when rolling my own reusable Javascript constructs. 

No comments:

Post a Comment