/* 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.5pre * 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 opts = this.options; var elem = $(this.element); // get the multiselect instance var instance = (this.instance = (elem.data('echMultiselect') || elem.data("multiselect"))); // store header; add filter class so the close/check all/uncheck all links can be positioned correctly var header = (this.header = instance.menu.find('.ui-multiselect-header').addClass('ui-multiselect-hasfilter')); // wrapper elem var 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(this._handler, this), click: $.proxy(this._handler, this) }); // 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'); var _self = this; // do not include hidden elems if the menu isn't open. var selector = instance._isOpen ? ':disabled, :hidden' : ':disabled'; $inputs = $inputs .not(selector) .each(this._toggleState('checked', flag)); // update text this.update(); // gather an array of the values that actually changed 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); } }); // trigger the change event on the select if($inputs.length) { this.element.trigger('change'); } }; // rebuild cache when multiselect is updated var doc = $(document).bind('multiselectrefresh', $.proxy(function() { this.updateCache(); this._handler(); }, this)); // 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 elem = $(this); // account for optgroups if(this.tagName.toLowerCase() === "optgroup") { elem = elem.children(); } return elem.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);