| /* 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 = $('<div class="ui-multiselect-filter">' + (opts.label.length ? opts.label : '') + '<input placeholder="'+opts.placeholder+'" type="search"' + (/\d/.test(opts.width) ? 'style="width:'+opts.width+'px"' : '') + ' /></div>').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); |