;(function($) {
$.fn.extend(
{
multiselect: function(options) {
var options = $.extend({
changeCallback: null,
single: false,
},
options || {}
);
return this.each(function(){
$(this).multiselect_render(options);
}
)
},
multiselect_render: function(options) {
var $selected_elements = $('<span></span>');
var $options = $('<div></div>');
var $search = $('<input type="text"/>')
.addClass('multiselectSearch')
.keyup(function(e) {
var _val = $(this).val();
if(!_val) {
$options
.children("div")
.show();
} else {
$options
.children("div")
.hide()
.filter(":icontains("+_val+")")
.show();
}
}
);
var $widget = $("<div/>") ;
var $choose;
if(options.single) {
$choose = $search
} else {
$choose = $("<a/>")
.addClass('multiselectChoose')
.text("[Choose...]");
}
$choose.click(function(e) {
e.preventDefault();
$widget.toggle(
0,
function() {
$(document).click(body_click_hide_widget);
}
);
$search.select();
}
);
var body_click_hide_widget = function(e) {
var $$this = $(e.target);
if($$this[0] == $choose[0])
return;
var $$parents = $$this.parents().andSelf();
hide = true;
for (var i=0; i<$$parents.length; i++) {
if($$parents[i] == $widget[0]) {
hide=false;
break;
}
}
if(hide) {
$widget.hide();
$(document).unbind("click", body_click_hide_widget);
}
}
var update_selected_elements = function() {
var arr = new Array();
$options.find(":checked").next('label').each(function() {
arr.push($(this).text());
}
);
$selected_elements.text(arr.join(', '));
};
$widget.append($search);
// button close
if(!options.single) {
$widget
.append(
$("<a/>")
.text("close")
.addClass('multiselectClose')
.click(function(e) {
e.preventDefault();
$widget.hide();
$(document).unbind("click", body_click_hide_widget);
}
)
)
}
var $this = $(this).hide();
var $opts = $this.children("option");
var $parent_id = $this.attr('id');
var $parent_name = $this.attr('name');
var nb_opts = $opts.length;
var type = options.single ? 'radio' : 'checkbox';
var opts_arr = new Array();
$opts.each(
function(idx) {
var $$this = $(this);
var $$this_value = $$this.val()
var input = '<input type="' + type + '" id="' + $parent_id + '-' + $$this_value + '" name="' + $parent_name + '" value="' + $$this_value + '"' + ($$this.is(':selected') ? ' checked=checked' : '') + ' />';
var label = '<label for="' + $parent_id + '-' + $$this_value + '">' + $$this.text() + '</label>';
var option = '<div>'+input+label+'</div>';
opts_arr.push(option);
}
);
$options.append(opts_arr.join(''));
$options
.children('div').addClass('multiselectOption')
.change(
function(e) {
if(options.changeCallback) {
options.changeCallback.call(this);
}
update_selected_elements();
if(options.single) {
$search.val($selected_elements.text());
$widget.hide();
$(document).unbind("click", body_click_hide_widget);
}
}
);
update_selected_elements();
$widget.append($options);
if(options.single) {
$choose.val($selected_elements.text())
$this.before($choose);
} else {
$this.before($selected_elements).before($choose);
}
$this.replaceWith($widget.hide().addClass('multiselectWidget'));
return $widget
}
}
);
}
)(jQuery);
Refactorings
No refactoring yet !
paul.wilkins.myopenid.com
February 4, 2010, February 04, 2010 02:25, permalink
Not to step on your toes, but there'a already a multiselect that has been developed for jQuery UI
http://quasipartikel.at/multiselect/
You may find quite a difference of performance.
cna training
February 26, 2010, February 26, 2010 07:54, permalink
Keep posting stuff like this i really like it
This is a little jQuery script I wrote in order to add a filter field to a selectbox (or multiselectbox). It works fine with few options but is painfully slow with 3000+ options. Any idea to refactor it ?
usage : $("select").multiselect({single: true});