/* jshint forin:true, noarg:true, noempty:true, eqeqeq:true, boss:true, undef:true, curly:true, browser:true, jquery:true */
/*
* jQuery MultiSelect UI Widget Filtering Plugin 1.4
* Copyright (c) 2012 Eric Hynds
*
* http://www.erichynds.com/jquery/jquery-ui-multiselect-widget/
*
* Depends:
* - jQuery UI MultiSelect widget
*
* Dual licensed under the MIT and GPL licenses:
* http://www.opensource.org/licenses/mit-license.php
* http://www.gnu.org/licenses/gpl.html
*
*/
(function($){
var rEscape = /[\-\[\]{}()*+?.,\\\^$|#\s]/g;
$.widget("ech.multiselectfilter", {
options: {
label: "Filter:",
width: null, /* override default width set in css file (px). null will inherit */
placeholder: "Enter keywords",
autoReset: false
},
_create: function(){
var self = this,
opts = this.options,
instance = (this.instance = $(this.element).data("multiselect")),
// store header; add filter class so the close/check all/uncheck all links can be positioned correctly
header = (this.header = instance.menu.find(".ui-multiselect-header").addClass("ui-multiselect-hasfilter")),
// wrapper elem
wrapper = (this.wrapper = $('
'+(opts.label.length ? opts.label : '')+'
').prependTo( this.header ));
// reference to the actual inputs
this.inputs = instance.menu.find('input[type="checkbox"], input[type="radio"]');
// build the input box
this.input = wrapper
.find("input")
.bind({
keydown: function( e ){
// prevent the enter key from submitting the form / closing the widget
if( e.which === 13 ){
e.preventDefault();
}
},
keyup: $.proxy(self._handler, self),
click: $.proxy(self._handler, self)
});
// cache input values for searching
this.updateCache();
// rewrite internal _toggleChecked fn so that when checkAll/uncheckAll is fired,
// only the currently filtered elements are checked
instance._toggleChecked = function(flag, group){
var $inputs = (group && group.length) ?
group :
this.labels.find('input'),
_self = this,
// do not include hidden elems if the menu isn't open.
selector = self.instance._isOpen ?
":disabled, :hidden" :
":disabled";
$inputs = $inputs.not( selector ).each(this._toggleState('checked', flag));
// update text
this.update();
// figure out which option tags need to be selected
var values = $inputs.map(function(){
return this.value;
}).get();
// select option tags
this.element
.find('option')
.filter(function(){
if( !this.disabled && $.inArray(this.value, values) > -1 ){
_self._toggleState('selected', flag).call( this );
}
});
};
// rebuild cache when multiselect is updated
var doc = $(document).bind("multiselectrefresh", function(){
self.updateCache();
self._handler();
});
// automatically reset the widget on close?
if(this.options.autoReset) {
doc.bind("multiselectclose", $.proxy(this._reset, this));
}
},
// thx for the logic here ben alman
_handler: function( e ){
var term = $.trim( this.input[0].value.toLowerCase() ),
// speed up lookups
rows = this.rows, inputs = this.inputs, cache = this.cache;
if( !term ){
rows.show();
} else {
rows.hide();
var regex = new RegExp(term.replace(rEscape, "\\$&"), 'gi');
this._trigger( "filter", e, $.map(cache, function(v, i){
if( v.search(regex) !== -1 ){
rows.eq(i).show();
return inputs.get(i);
}
return null;
}));
}
// show/hide optgroups
this.instance.menu.find(".ui-multiselect-optgroup-label").each(function(){
var $this = $(this);
var isVisible = $this.nextUntil('.ui-multiselect-optgroup-label').filter(function(){
return $.css(this, "display") !== 'none';
}).length;
$this[ isVisible ? 'show' : 'hide' ]();
});
},
_reset: function() {
this.input.val('').trigger('keyup');
},
updateCache: function(){
// each list item
this.rows = this.instance.menu.find(".ui-multiselect-checkboxes li:not(.ui-multiselect-optgroup-label)");
// cache
this.cache = this.element.children().map(function(){
var self = $(this);
// account for optgroups
if( this.tagName.toLowerCase() === "optgroup" ){
self = self.children();
}
return self.map(function(){
return this.innerHTML.toLowerCase();
}).get();
}).get();
},
widget: function(){
return this.wrapper;
},
destroy: function(){
$.Widget.prototype.destroy.call( this );
this.input.val('').trigger("keyup");
this.wrapper.remove();
}
});
})(jQuery);