Advantages of this pattern:
References can be maintained between jQuery objects, components, and instances.
The code is clear.
Easy to extend.
You can get rid of some complicated mechanisms and complete the components by hand.
The last point is the most interesting. If you follow this pattern, both the constructor and the prototype method can be freely controlled. What you can get rid of are some inherited hacks, and even jQuery is not necessary.
Handmade ones are always the best.
A simple DEMO
/*
* @by ambar_li
* @create 2010-11-30
* Tag selection, verification
*/
(function($){
var tagSelector = function( input,options){
var me = this;
var opt = me.opt = $.extend({
limit : 5
,tags : null
,delimiter : ','
}, options || {});
var $el = me.input = $(input);
var $tags = me.tags = $(opt.tags);
if (!$el.length || !$tags.length) return;
$tags.click(function(e){
e.preventDefault();
var tag = $(this).text ();
me[me.has(tag)?'remove':'add'](tag);
});
};
tagSelector.prototype = {
add : function(tag){
if(tag){
var me = this, tags = me.get(), del = me.opt.delimiter;
tags.push(tag);
me.input.val( tags.join(del) );
}
return me;
}
,remove : function(tag){
var me = this, exist = function(v){ return v !=tag; };
me.input.val( $.grep(me.get(),exist) );
return me;
}
, cleanify : function(){
return this.remove();
}
,limit : function(){
var me = this, tags = me.cleanify().get()
,len = tags.length, max = me.opt.limit;
if(len>max){
me.input.val( tags.slice(0,max) );
}
return me;
}
,has : function(tag){
return $.inArray(tag,this.get()) > -1;
}
, get : function(){
var val = $.trim(this.input.val());
return val ? $.map( val.split(/[,,] /), $.trim ) : [];
}
};
$.fn.tagSelector = function(options){
return this.each(function(){
$(this).data( 'tagSelector',new tagSelector(this,options));
});
};
})(jQuery);
The most important thing is the last paragraph.
jQueryUI comparison, there is initialization check:
this. each(function() {
var instance = $.data( this, name );
if ( instance ) {
instance.option( options || {} )._init();
} else {
$.data( this, name, new object( options, this ) );
}
});
Two calling methods
var $input = $('#tb_tags').tagSelector( { tags :'div.tag_group a:not(.btn_tag_more)'} );
var api = $input.data('tagSelector');
// var api = new tagSelector('#tb_tags',{ tags :'div.tag_group a:not(.btn_tag_more)' });
Full demo: