PageSourceSearch

https://wj-kleve.de/admin/include/jquery/jquery.multiselect.js?rev=1781786110

js wj-kleve.de collected 2026-10-05 23:03:20 UTC 41,656 bytes, 965 lines download raw bytes

vendor: 41,656 bytes, lines 1-965
1/**
2 * Display a nice easy to use multiselect list
3 * @Version: 2.4.26
4 * @Author: Patrick Springstubbe
5 * @Contact: @JediNobleclem
6 * @Website: springstubbe.us
7 * @Source: https://github.com/nobleclem/jQuery-MultiSelect
8 *
9 * Usage:
10 *     $('select[multiple]').multiselect();
11 *     $('select[multiple]').multiselect({ texts: { placeholder: 'Select options' } });
12 *     $('select[multiple]').multiselect('reload');
13 *     $('select[multiple]').multiselect( 'loadOptions', [{
14 *         name   : 'Option Name 1',
15 *         value  : 'option-value-1',
16 *         checked: false,
17 *         attributes : {
18 *             custom1: 'value1',
19 *             custom2: 'value2'
20 *         }
21 *     },{
22 *         name   : 'Option Name 2',
23 *         value  : 'option-value-2',
24 *         checked: false,
25 *         attributes : {
26 *             custom1: 'value1',
27 *             custom2: 'value2'
28 *         }
29 *     }]);
30 *
31 **/
32(function($){
33    var defaults = {
34        columns: 1,     // how many columns should be use to show options
35        search : false, // include option search box
36
37        // search filter options
38        searchOptions : {
39            delay        : 250,                  // time (in ms) between keystrokes until search happens
40            showOptGroups: false,                // show option group titles if no options remaining
41            searchText   : true,                 // search within the text
42            searchValue  : false,                // search within the value
43            onSearch     : function( element ){} // fires on keyup before search on options happens
44        },
45
46        // plugin texts
47        texts: {
48            placeholder    : 'Select options', // text to use in dummy input
49            search         : 'Search',         // search input placeholder text
50            searchNoResult : 'No results',     // search results not found text
51            selectedOptions: ' selected',      // selected suffix text
52            selectAll      : 'Select all',     // select all text
53            unselectAll    : 'Unselect all',   // unselect all text
54            noneSelected   : 'None Selected'   // None selected text
55        },
56
57        // general options
58        selectAll              : false, // add select all option
59        selectGroup            : false, // select entire optgroup
60        minHeight              : 200,   // minimum height of option overlay
61        maxHeight              : null,  // maximum height of option overlay
62        maxWidth               : null,  // maximum width of option overlay (or selector)
63        maxPlaceholderWidth    : null,  // maximum width of placeholder button
64        maxPlaceholderOpts     : 10,    // maximum number of placeholder options to show until "# selected" shown instead
65        showAllPlaceholderOpts : false, // always show all the selected options
66        showCheckbox           : true,  // display the checkbox to the user
67        checkboxAutoFit        : false,  // auto calc checkbox padding
68        optionAttributes       : [],    // attributes to copy to the checkbox from the option element
69        replacePlaceholderText : true, // replace text of placeholder if button is too small
70
71        // Callbacks
72        onLoad        : function( element ){},           // fires at end of list initialization
73        onOptionClick : function( element, option ){},   // fires when an option is clicked
74        onControlOpen : function( element ){},           // fires when the options list is opened
75        onControlClose: function( element ){},           // fires when the options list is closed
76        onSelectAll   : function( element, selected ){}, // fires when (un)select all is clicked
77        onPlaceholder : function( element, placeholder, selectedOpts ){}, // fires when the placeholder txt is updated
78    };
79
80    var msCounter    = 1; // counter for each select list
81    var msOptCounter = 1; // counter for each option on page
82
83    // FOR LEGACY BROWSERS (talking to you IE8)
84    if( typeof Array.prototype.map !== 'function' ) {
85        Array.prototype.map = function( callback, thisArg ) {
86            if( typeof thisArg === 'undefined' ) {
87                thisArg = this;
88            }
89
90            return $.isArray( thisArg ) ? $.map( thisArg, callback ) : [];
91        };
92    }
93    if( typeof String.prototype.trim !== 'function' ) {
94        String.prototype.trim = function() {
95            return this.replace(/^\s+|\s+$/g, '');
96        };
97    }
98
99    function MultiSelect( element, options )
100    {
101        this.element           = element;
102        this.options           = $.extend( true, {}, defaults, options );
103        this.updateSelectAll   = true;
104        this.updatePlaceholder = true;
105        this.listNumber        = msCounter;
106
107        msCounter = msCounter + 1; // increment counter
108
109        /* Make sure its a multiselect list */
110        if( !$(this.element).prop('multiple') ) {
111            throw new Error( '[jQuery-MultiSelect] Select list must be a multiselect list in order to use this plugin' );
112        }
113
114        /* Options validation checks */
115        if( this.options.search ){
116            if( !this.options.searchOptions.searchText && !this.options.searchOptions.searchValue ){
117                throw new Error( '[jQuery-MultiSelect] Either searchText or searchValue should be true.' );
118            }
119        }
120
121        /** BACKWARDS COMPATIBILITY **/
122        if( 'placeholder' in this.options ) {
123            this.options.texts.placeholder = this.options.placeholder;
124            delete this.options.placeholder;
125        }
126        if( 'default' in this.options.searchOptions ) {
127            this.options.texts.search = this.options.searchOptions['default'];
128            delete this.options.searchOptions['default'];
129        }
130        /** END BACKWARDS COMPATIBILITY **/
131
132        // load this instance
133        this.load();
134    }
135
136    MultiSelect.prototype = {
137        /* LOAD CUSTOM MULTISELECT DOM/ACTIONS */
138        load: function() {
139            var instance = this;
140
141            // make sure this is a select list and not loaded
142            if( (instance.element.nodeName.toUpperCase() != 'SELECT') || $(instance.element).hasClass('jqmsLoaded') ) {
143                return true;
144            }
145
146            // sanity check so we don't double load on a select element
147            $(instance.element).addClass('jqmsLoaded ms-list-'+ instance.listNumber ).data( 'plugin_multiselect-instance', instance );
148
149            // add option container
150            $(instance.element).after('<div id="ms-list-'+ instance.listNumber +'" class="ms-options-wrap"><button type="button"><span>None Selected</span></button><div class="ms-options"><ul></ul></div></div>');
151
152            var placeholder = $(instance.element).siblings('#ms-list-'+ instance.listNumber +'.ms-options-wrap').find('> button:first-child');
153            var optionsWrap = $(instance.element).siblings('#ms-list-'+ instance.listNumber +'.ms-options-wrap').find('> .ms-options');
154            var optionsList = optionsWrap.find('> ul');
155
156            // don't show checkbox (add class for css to hide checkboxes)
157            if( !instance.options.showCheckbox ) {
158                optionsWrap.addClass('hide-checkbox');
159            }
160            else if( instance.options.checkboxAutoFit ) {
161                optionsWrap.addClass('checkbox-autofit');
162            }
163
164            // check if list is disabled
165            if( $(instance.element).prop( 'disabled' ) ) {
166                placeholder.prop( 'disabled', true );
167            }
168
169            // set placeholder maxWidth
170            if( instance.options.maxPlaceholderWidth ) {
171                placeholder.css( 'maxWidth', instance.options.maxPlaceholderWidth );
172            }
173
174            // override with user defined maxHeight
175            if( instance.options.maxHeight ) {
176                var maxHeight = instance.options.maxHeight;
177            }
178            else {
179                // cacl default maxHeight
180                var maxHeight = ($(window).height() - optionsWrap.offset().top + $(window).scrollTop() - 20);
181            }
182
183            // maxHeight cannot be less than options.minHeight
184            maxHeight = maxHeight < instance.options.minHeight ? instance.options.minHeight : maxHeight;
185
186            optionsWrap.css({
187                maxWidth : instance.options.maxWidth,
188                minHeight: instance.options.minHeight,
189                maxHeight: maxHeight,
190            });
191
192            // isolate options scroll
193            // @source: https://github.com/nobleclem/jQuery-IsolatedScroll
194            optionsWrap.on( 'touchmove mousewheel DOMMouseScroll', function ( e ) {
195                if( ($(this).outerHeight() < $(this)[0].scrollHeight) ) {
196                    var e0 = e.originalEvent,
197                        delta = e0.wheelDelta || -e0.detail;
198
199                    if( ($(this).outerHeight() + $(this)[0].scrollTop) > $(this)[0].scrollHeight ) {
200                        e.preventDefault();
201                        this.scrollTop += ( delta < 0 ? 1 : -1 );
202                    }
203                }
204            });
205
206            // hide options menus if click happens off of the list placeholder button
207            $(document).off('click.ms-hideopts').on('click.ms-hideopts', function( event ){
208                if( !$(event.target).closest('.ms-options-wrap').length ) {
209                    $('.ms-options-wrap.ms-active > .ms-options').each(function(){
210                        $(this).closest('.ms-options-wrap').removeClass('ms-active');
211
212                        var listID = $(this).closest('.ms-options-wrap').attr('id');
213
214                        var thisInst = $(this).parent().siblings('.'+ listID +'.jqmsLoaded').data('plugin_multiselect-instance');
215
216                        // USER CALLBACK
217                        if( typeof thisInst.options.onControlClose == 'function' ) {
218                            thisInst.options.onControlClose( thisInst.element );
219                        }
220                    });
221                }
222            // hide open option lists if escape key pressed
223            }).on('keydown', function( event ){
224                if( (event.keyCode || event.which) == 27 ) { // esc key
225                    $(this).trigger('click.ms-hideopts');
226                }
227            });
228
229            // handle pressing enter|space while tabbing through
230            placeholder.on('keydown', function( event ){
231                var code = (event.keyCode || event.which);
232                if( (code == 13) || (code == 32) ) { // enter OR space
233                    placeholder.trigger( 'mousedown' );
234                }
235            });
236
237            // disable button action
238            placeholder.on( 'mousedown', function( event ){
239                // ignore if its not a left click
240                if( event.which && (event.which != 1) ) {
241                    return true;
242                }
243
244                // hide other menus before showing this one
245                $('.ms-options-wrap.ms-active').each(function(){
246                    if( $(this).siblings( '.'+ $(this).attr('id') +'.jqmsLoaded')[0] != optionsWrap.parent().siblings('.ms-list-'+ instance.listNumber +'.jqmsLoaded')[0] ) {
247                        $(this).removeClass('ms-active');
248
249                        var thisInst = $(this).siblings( '.'+ $(this).attr('id') +'.jqmsLoaded').data('plugin_multiselect-instance');
250
251                        // USER CALLBACK
252                        if( typeof thisInst.options.onControlClose == 'function' ) {
253                            thisInst.options.onControlClose( thisInst.element );
254                        }
255                    }
256                });
257
258                // show/hide options
259                optionsWrap.closest('.ms-options-wrap').toggleClass('ms-active');
260
261                // recalculate height
262                if( optionsWrap.closest('.ms-options-wrap').hasClass('ms-active') ) {
263                    // USER CALLBACK
264                    if( typeof instance.options.onControlOpen == 'function' ) {
265                        instance.options.onControlOpen( instance.element );
266                    }
267
268                    optionsWrap.css( 'maxHeight', '' );
269
270                    // override with user defined maxHeight
271                    if( instance.options.maxHeight ) {
272                        var maxHeight = instance.options.maxHeight;
273                    }
274                    else {
275                        // cacl default maxHeight
276                        var maxHeight = ($(window).height() - optionsWrap.offset().top + $(window).scrollTop() - 20);
277                    }
278
279                    if( maxHeight ) {
280                        // maxHeight cannot be less than options.minHeight
281                        maxHeight = maxHeight < instance.options.minHeight ? instance.options.minHeight : maxHeight;
282
283                        optionsWrap.css( 'maxHeight', maxHeight );
284                    }
285                }
286                else if( typeof instance.options.onControlClose == 'function' ) {
287                    instance.options.onControlClose( instance.element );
288                }
289            }).click(function( event ){ event.preventDefault(); });
290
291            // add placeholder copy
292            if( instance.options.texts.placeholder ) {
293                placeholder.find('span').text( instance.options.texts.placeholder );
294            }
295
296            // add search box
297            if( instance.options.search ) {
298                optionsList.before('<div class="ms-search"><input type="text" value="" placeholder="'+ instance.options.texts.search +'" /></div>');
299                optionsList.after('<div class="no-result-message">' + instance.options.texts.searchNoResult + '</div>');
300
301                var search = optionsWrap.find('.ms-search input');
302
303                search.on('keyup', function(){
304                    // ignore keystrokes that don't make a difference
305                    if( $(this).data('lastsearch') == $(this).val() ) {
306                        return true;
307                    }
308
309                    // pause timeout
310                    if( $(this).data('searchTimeout') ) {
311                        clearTimeout( $(this).data('searchTimeout') );
312                    }
313
314                    var thisSearchElem = $(this);
315
316                    $(this).data('searchTimeout', setTimeout(function(){
317                        thisSearchElem.data('lastsearch', thisSearchElem.val() );
318
319                        // USER CALLBACK
320                        if( typeof instance.options.searchOptions.onSearch == 'function' ) {
321                            instance.options.searchOptions.onSearch( instance.element );
322                        }
323
324                        // search non optgroup li's
325                        var searchString = search.val().toLowerCase().trim();
326                        if( searchString ) {
327                            optionsList.find('li[data-search-term*="'+ searchString +'"]:not(.optgroup)').removeClass('ms-hidden');
328                            optionsList.find('li:not([data-search-term*="'+ searchString +'"], .optgroup)').addClass('ms-hidden');
329                        }
330                        else {
331                            optionsList.find('.ms-hidden').removeClass('ms-hidden');
332                        }
333
334                        // show/hide optgroups based on if there are items visible within
335                        if( !instance.options.searchOptions.showOptGroups ) {
336                            optionsList.find('.optgroup').each(function(){
337                                if( $(this).find('li:not(.ms-hidden)').length ) {
338                                    $(this).show();
339                                }
340                                else {
341                                    $(this).hide();
342                                }
343                            });
344                        }
345
346                        instance._updateSelectAllText();
347                    }, instance.options.searchOptions.delay ));
348                });
349            }
350
351            // add global select all options
352            if( instance.options.selectAll ) {
353                optionsList.before('<a href="#" class="ms-selectall global">' + instance.options.texts.selectAll + '</a>');
354            }
355
356            // handle select all option
357            optionsWrap.on('click', '.ms-selectall', function( event ){
358                event.preventDefault();
359
360                instance.updateSelectAll   = false;
361                instance.updatePlaceholder = false;
362
363                var select = optionsWrap.parent().siblings('.ms-list-'+ instance.listNumber +'.jqmsLoaded');
364
365                if( $(this).hasClass('global') ) {
366                    // check if any options are not selected if so then select them
367                    if( optionsList.find('li:not(.optgroup, .selected, .ms-hidden) input[type="checkbox"]:not(:disabled)').length ) {
368                        // get unselected vals, mark as selected, return val list
369                        optionsList.find('li:not(.optgroup, .selected, .ms-hidden) input[type="checkbox"]:not(:disabled)').closest('li').addClass('selected');
370                        optionsList.find('li.selected input[type="checkbox"]:not(:disabled)').prop( 'checked', true );
371                    }
372                    // deselect everything
373                    else {
374                        optionsList.find('li:not(.optgroup, .ms-hidden).selected input[type="checkbox"]:not(:disabled)').closest('li').removeClass('selected');
375                        optionsList.find('li:not(.optgroup, .ms-hidden, .selected) input[type="checkbox"]:not(:disabled)').prop( 'checked', false );
376                    }
377                }
378                else if( $(this).closest('li').hasClass('optgroup') ) {
379                    var optgroup = $(this).closest('li.optgroup');
380
381                    // check if any selected if so then select them
382                    if( optgroup.find('li:not(.selected, .ms-hidden) input[type="checkbox"]:not(:disabled)').length ) {
383                        optgroup.find('li:not(.selected, .ms-hidden) input[type="checkbox"]:not(:disabled)').closest('li').addClass('selected');
384                        optgroup.find('li.selected input[type="checkbox"]:not(:disabled)').prop( 'checked', true );
385                    }
386                    // deselect everything
387                    else {
388                        optgroup.find('li:not(.ms-hidden).selected input[type="checkbox"]:not(:disabled)').closest('li').removeClass('selected');
389                        optgroup.find('li:not(.ms-hidden, .selected) input[type="checkbox"]:not(:disabled)').prop( 'checked', false );
390                    }
391                }
392
393                var vals = [];
394                optionsList.find('li.selected input[type="checkbox"]').each(function(){
395                    vals.push( $(this).val() );
396                });
397                select.val( vals ).trigger('change');
398
399                instance.updateSelectAll   = true;
400                instance.updatePlaceholder = true;
401
402                // USER CALLBACK
403                if( typeof instance.options.onSelectAll == 'function' ) {
404                    instance.options.onSelectAll( instance.element, vals.length );
405                }
406
407                instance._updateSelectAllText();
408                instance._updatePlaceholderText();
409            });
410
411            // add options to wrapper
412            var options = [];
413            $(instance.element).children().each(function(){
414                if( this.nodeName.toUpperCase() == 'OPTGROUP' ) {
415                    var groupOptions = [];
416
417                    $(this).children('option').each(function(){
418                        var thisOptionAtts = {};
419                        for( var i = 0; i < instance.options.optionAttributes.length; i++ ) {
420                            var thisOptAttr = instance.options.optionAttributes[ i ];
421
422                            if( $(this).attr( thisOptAttr ) !== undefined ) {
423                                thisOptionAtts[ thisOptAttr ] = $(this).attr( thisOptAttr );
424                            }
425                        }
426
427                        groupOptions.push({
428                            name   : $(this).text(),
429                            value  : $(this).val(),
430                            checked: $(this).prop( 'selected' ),
431                            attributes: thisOptionAtts
432                        });
433                    });
434
435                    options.push({
436                        label  : $(this).attr('label'),
437                        options: groupOptions
438                    });
439                }
440                else if( this.nodeName.toUpperCase() == 'OPTION' ) {
441                    var thisOptionAtts = {};
442                    for( var i = 0; i < instance.options.optionAttributes.length; i++ ) {
443                        var thisOptAttr = instance.options.optionAttributes[ i ];
444
445                        if( $(this).attr( thisOptAttr ) !== undefined ) {
446                            thisOptionAtts[ thisOptAttr ] = $(this).attr( thisOptAttr );
447                        }
448                    }
449
450                    options.push({
451                        name      : $(this).text(),
452                        value     : $(this).val(),
453                        checked   : $(this).prop( 'selected' ),
454                        attributes: thisOptionAtts
455                    });
456                }
457                else {
458                    // bad option
459                    return true;
460                }
461            });
462            instance.loadOptions( options, true, false );
463
464            // BIND SELECT ACTION
465            optionsWrap.on( 'click', 'input[type="checkbox"]', function(){
466                $(this).closest( 'li' ).toggleClass( 'selected' );
467
468                var select = optionsWrap.parent().siblings('.ms-list-'+ instance.listNumber +'.jqmsLoaded');
469
470                // toggle clicked option
471                select.find('option[value="'+ instance._escapeSelector( $(this).val() ) +'"]').prop(
472                    'selected', $(this).is(':checked')
473                ).closest('select').trigger('change');
474
475                // USER CALLBACK
476                if( typeof instance.options.onOptionClick == 'function' ) {
477                    instance.options.onOptionClick(instance.element, this);
478                }
479
480                instance._updateSelectAllText();
481                instance._updatePlaceholderText();
482            });
483
484            // BIND FOCUS EVENT
485            optionsWrap.on('focusin', 'input[type="checkbox"]', function(){
486                $(this).closest('label').addClass('focused');
487            }).on('focusout', 'input[type="checkbox"]', function(){
488                $(this).closest('label').removeClass('focused');
489            });
490
491            // USER CALLBACK
492            if( typeof instance.options.onLoad === 'function' ) {
493                instance.options.onLoad( instance.element );
494            }
495
496            // hide native select list
497            $(instance.element).hide();
498        },
499
500        /* LOAD SELECT OPTIONS */
501        loadOptions: function( options, overwrite, updateSelect ) {
502            // console.log( options );
503            overwrite    = (typeof overwrite == 'boolean') ? overwrite : true;
504            updateSelect = (typeof updateSelect == 'boolean') ? updateSelect : true;
505
506            var instance    = this;
507            var select      = $(instance.element);
508            var optionsList = select.siblings('#ms-list-'+ instance.listNumber +'.ms-options-wrap').find('> .ms-options > ul');
509            var optionsWrap = select.siblings('#ms-list-'+ instance.listNumber +'.ms-options-wrap').find('> .ms-options');
510
511            if( overwrite ) {
512                optionsList.find('> li').remove();
513
514                if( updateSelect ) {
515                    select.find('> *').remove();
516                }
517            }
518
519            var containers = [];
520            for( var key in options ) {
521                // Prevent prototype methods injected into options from being iterated over.
522                if( !options.hasOwnProperty( key ) ) {
523                    continue;
524                }
525
526                var thisOption      = options[ key ];
527                var container       = $('<li/>');
528                var appendContainer = true;
529
530                // OPTION
531                if( thisOption.hasOwnProperty('value') ) {
532                    if( instance.options.showCheckbox && instance.options.checkboxAutoFit ) {
533                        container.addClass('ms-reflow');
534                    }
535
536                    // add option to ms dropdown
537                    instance._addOption( container, thisOption );
538
539                    if( updateSelect ) {
540                        var selOption = $('<option/>', {
541                            value: thisOption.value,
542                            text : thisOption.name
543                        });
544
545                        // add custom user attributes
546                        if( thisOption.hasOwnProperty('attributes') && Object.keys( thisOption.attributes ).length ) {
547                            selOption.attr( thisOption.attributes );
548                        }
549
550                        // mark option as selected
551                        if( thisOption.checked ) {
552                            selOption.prop( 'selected', true );
553                        }
554
555                        select.append( selOption );
556                    }
557                }
558                // OPTGROUP
559                else if( thisOption.hasOwnProperty('options') ) {
560                    var optGroup = $('<optgroup/>', {
561                        label: thisOption.label
562                    });
563
564                    optionsList.find('> li.optgroup > span.label').each(function(){
565                        if( $(this).text() == thisOption.label ) {
566                            container       = $(this).closest('.optgroup');
567                            appendContainer = false;
568                        }
569                    });
570
571                    // prepare to append optgroup to select element
572                    if( updateSelect ) {
573                        if( select.find('optgroup[label="'+ thisOption.label +'"]').length ) {
574                            optGroup = select.find('optgroup[label="'+ thisOption.label +'"]');
575                        }
576                        else {
577                            select.append( optGroup );
578                        }
579                    }
580
581                    // setup container
582                    if( appendContainer ) {
583                        container.addClass('optgroup');
584                        container.append('<span class="label">'+ thisOption.label +'</span>');
585                        container.find('> .label').css({
586                            clear: 'both'
587                        });
588
589                        // add select all link
590                        if( instance.options.selectGroup ) {
591                            container.append('<a href="#" class="ms-selectall">' + instance.options.texts.selectAll + '</a>');
592                        }
593
594                        container.append('<ul/>');
595                    }
596
597                    for( var gKey in thisOption.options ) {
598                        // Prevent prototype methods injected into options from
599                        // being iterated over.
600                        if( !thisOption.options.hasOwnProperty( gKey ) ) {
601                            continue;
602                        }
603
604                        var thisGOption = thisOption.options[ gKey ];
605                        var gContainer  = $('<li/>');
606                        if( instance.options.showCheckbox && instance.options.checkboxAutoFit ) {
607                            gContainer.addClass('ms-reflow');
608                        }
609
610                        // no clue what this is we hit (skip)
611                        if( !thisGOption.hasOwnProperty('value') ) {
612                            continue;
613                        }
614
615                        instance._addOption( gContainer, thisGOption );
616
617                        container.find('> ul').append( gContainer );
618
619                        // add option to optgroup in select element
620                        if( updateSelect ) {
621                            var selOption = $('<option/>', {
622                                value: thisGOption.value,
623                                text : thisGOption.name
624                            });
625
626                            // add custom user attributes
627                            if( thisGOption.hasOwnProperty('attributes') && Object.keys( thisGOption.attributes ).length ) {
628                                selOption.attr( thisGOption.attributes );
629                            }
630
631                            // mark option as selected
632                            if( thisGOption.checked ) {
633                                selOption.prop( 'selected', true );
634                            }
635
636                            optGroup.append( selOption );
637                        }
638                    }
639                }
640                else {
641                    // no clue what this is we hit (skip)
642                    continue;
643                }
644
645                if( appendContainer ) {
646                    containers.push( container );
647                }
648            }
649            optionsList.append( containers );
650
651            // pad out label for room for the checkbox
652            if( instance.options.checkboxAutoFit && instance.options.showCheckbox && !optionsWrap.hasClass('hide-checkbox') ) {
653                var chkbx = optionsList.find('.ms-reflow:eq(0) input[type="checkbox"]');
654                if( chkbx.length ) {
655                    var checkboxWidth = chkbx.outerWidth();
656                        checkboxWidth = checkboxWidth ? checkboxWidth : 15;
657
658                    optionsList.find('.ms-reflow label').css(
659                        'padding-left',
660                        (parseInt( chkbx.closest('label').css('padding-left') ) * 2) + checkboxWidth
661                    );
662
663                    optionsList.find('.ms-reflow').removeClass('ms-reflow');
664                }
665            }
666
667            // update placeholder text
668            instance._updatePlaceholderText();
669
670            // RESET COLUMN STYLES
671            optionsWrap.find('ul').css({
672                'column-count'        : '',
673                'column-gap'          : '',
674                '-webkit-column-count': '',
675                '-webkit-column-gap'  : '',
676                '-moz-column-count'   : '',
677                '-moz-column-gap'     : ''
678            });
679
680            // COLUMNIZE
681            if( select.find('optgroup').length ) {
682                // float non grouped options
683                optionsList.find('> li:not(.optgroup)').css({
684                    'float': 'left',
685                    width: (100 / instance.options.columns) +'%'
686                });
687
688                // add CSS3 column styles
689                optionsList.find('li.optgroup').css({
690                    clear: 'both'
691                }).find('> ul').css({
692                    'column-count'        : instance.options.columns,
693                    'column-gap'          : 0,
694                    '-webkit-column-count': instance.options.columns,
695                    '-webkit-column-gap'  : 0,
696                    '-moz-column-count'   : instance.options.columns,
697                    '-moz-column-gap'     : 0
698                });
699
700                // for crappy IE versions float grouped options
701                if( this._ieVersion() && (this._ieVersion() < 10) ) {
702                    optionsList.find('li.optgroup > ul > li').css({
703                        'float': 'left',
704                        width: (100 / instance.options.columns) +'%'
705                    });
706                }
707            }
708            else {
709                // add CSS3 column styles
710                optionsList.css({
711                    'column-count'        : instance.options.columns,
712                    'column-gap'          : 0,
713                    '-webkit-column-count': instance.options.columns,
714                    '-webkit-column-gap'  : 0,
715                    '-moz-column-count'   : instance.options.columns,
716                    '-moz-column-gap'     : 0
717                });
718
719                // for crappy IE versions float grouped options
720                if( this._ieVersion() && (this._ieVersion() < 10) ) {
721                    optionsList.find('> li').css({
722                        'float': 'left',
723                        width: (100 / instance.options.columns) +'%'
724                    });
725                }
726            }
727
728            // update un/select all logic
729            instance._updateSelectAllText();
730        },
731
732        /* UPDATE MULTISELECT CONFIG OPTIONS */
733        settings: function( options ) {
734            this.options = $.extend( true, {}, this.options, options );
735            this.reload();
736        },
737
738        /* RESET THE DOM */
739        unload: function() {
740            $(this.element).siblings('#ms-list-'+ this.listNumber +'.ms-options-wrap').remove();
741            $(this.element).show(function(){
742                $(this).css('display','').removeClass('jqmsLoaded');
743            });
744        },
745
746        /* RELOAD JQ MULTISELECT LIST */
747        reload: function() {
748            // remove existing options
749            $(this.element).siblings('#ms-list-'+ this.listNumber +'.ms-options-wrap').remove();
750            $(this.element).removeClass('jqmsLoaded');
751
752            // load element
753            this.load();
754        },
755
756        // RESET BACK TO DEFAULT VALUES & RELOAD
757        reset: function() {
758            var defaultVals = [];
759            $(this.element).find('option').each(function(){
760                if( $(this).prop('defaultSelected') ) {
761                    defaultVals.push( $(this).val() );
762                }
763            });
764
765            $(this.element).val( defaultVals );
766
767            this.reload();
768        },
769
770        disable: function( status ) {
771            status = (typeof status === 'boolean') ? status : true;
772            $(this.element).prop( 'disabled', status );
773            $(this.element).siblings('#ms-list-'+ this.listNumber +'.ms-options-wrap').find('button:first-child')
774                .prop( 'disabled', status );
775        },
776
777        /** PRIVATE FUNCTIONS **/
778        // update the un/select all texts based on selected options and visibility
779        _updateSelectAllText: function(){
780            if( !this.updateSelectAll ) {
781                return;
782            }
783
784            var instance = this;
785
786            // select all not used at all so just do nothing
787            if( !instance.options.selectAll && !instance.options.selectGroup ) {
788                return;
789            }
790
791            var optionsWrap = $(instance.element).siblings('#ms-list-'+ instance.listNumber +'.ms-options-wrap').find('> .ms-options');
792
793            // update un/select all text
794            optionsWrap.find('.ms-selectall').each(function(){
795                var unselected = $(this).parent().find('li:not(.optgroup,.selected,.ms-hidden)');
796
797                $(this).text(
798                    unselected.length ? instance.options.texts.selectAll : instance.options.texts.unselectAll
799                );
800            });
801
802            var shownOptionsCount = optionsWrap.find('> ul li:not(.optgroup,.ms-hidden)').length;
803
804            // show/hide no-results message
805            optionsWrap.find('.no-result-message').toggle( shownOptionsCount ? false : true );
806
807            // show/hide (un)select all element as necessary
808            optionsWrap.find('.ms-selectall.global').toggle( shownOptionsCount ? true : false );
809        },
810
811        // update selected placeholder text
812        _updatePlaceholderText: function(){
813            if( !this.updatePlaceholder ) {
814                return;
815            }
816
817            var instance       = this;
818            var select         = $(instance.element);
819            var selectVals     = select.val() ? select.val() : [];
820            var placeholder    = select.siblings('#ms-list-'+ instance.listNumber +'.ms-options-wrap').find('> button:first-child');
821            var placeholderTxt = placeholder.find('span');
822            var optionsWrap    = select.siblings('#ms-list-'+ instance.listNumber +'.ms-options-wrap').find('> .ms-options');
823
824            // if there are disabled options get those values as well
825            if( select.find('option:selected:disabled').length ) {
826                selectVals = [];
827                select.find('option:selected').each(function(){
828                    selectVals.push( $(this).val() );
829                });
830            }
831
832            // get selected options
833            var selOpts = [];
834            for( var key in selectVals ) {
835                // Prevent prototype methods injected into options from being iterated over.
836                if( !selectVals.hasOwnProperty( key ) ) {
837                    continue;
838                }
839
840                selOpts.push(
841                    select.find('option[value="'+ instance._escapeSelector( selectVals[ key ] ) +'"]').text().trim()
842                );
843
844                if( selOpts.length >= instance.options.maxPlaceholderOpts ) {
845                    break;
846                }
847            }
848
849            // UPDATE PLACEHOLDER TEXT WITH OPTIONS SELECTED
850            placeholderTxt.text( selOpts.join( ', ' ) );
851
852            if( selOpts.length ) {
853                optionsWrap.closest('.ms-options-wrap').addClass('ms-has-selections');
854
855                // USER CALLBACK
856                if( typeof instance.options.onPlaceholder == 'function' ) {
857                    instance.options.onPlaceholder( instance.element, placeholderTxt, selOpts );
858                }
859            }
860            else {
861                optionsWrap.closest('.ms-options-wrap').removeClass('ms-has-selections');
862            }
863
864            // replace placeholder text
865            if( !selOpts.length ) {
866                placeholderTxt.text( instance.options.texts.placeholder );
867            }
868            // if copy is larger than button width use "# selected"
869            else if( !instance.options.showAllPlaceholderOpts && instance.options.replacePlaceholderText && ((placeholderTxt.width() > placeholder.width()) || (selOpts.length != selectVals.length)) ) {
870                placeholderTxt.text( selectVals.length + instance.options.texts.selectedOptions );
871            }
872        },
873
874        // Add option to the custom dom list
875        _addOption: function( container, option ) {
876            var instance = this;
877            var optionNameText = $('<div/>').html( option.name ).text();
878
879            var thisOption = $('<label/>', {
880                for : 'ms-opt-'+ msOptCounter
881            }).text( optionNameText );
882
883            var thisCheckbox = $('<input>', {
884                type : 'checkbox',
885                title: optionNameText,
886                id   : 'ms-opt-'+ msOptCounter,
887                value: option.value
888            });
889
890            // add user defined attributes
891            if( option.hasOwnProperty('attributes') && Object.keys( option.attributes ).length ) {
892                thisCheckbox.attr( option.attributes );
893            }
894
895            if( option.checked ) {
896                container.addClass('default selected');
897                thisCheckbox.prop( 'checked', true );
898            }
899
900            thisOption.prepend( thisCheckbox );
901
902            var searchTerm = '';
903            if( instance.options.searchOptions.searchText ) {
904                searchTerm += ' ' + optionNameText.toLowerCase();
905            }
906            if( instance.options.searchOptions.searchValue ) {
907                searchTerm += ' ' + option.value.toLowerCase();
908            }
909
910            container.attr( 'data-search-term', searchTerm.trim() ).prepend( thisOption );
911
912            msOptCounter = msOptCounter + 1;
913        },
914
915        // check ie version
916        _ieVersion: function() {
917            var myNav = navigator.userAgent.toLowerCase();
918            return (myNav.indexOf('msie') != -1) ? parseInt(myNav.split('msie')[1]) : false;
919        },
920
921        // escape selector
922        _escapeSelector: function( string ) {
923            if( typeof $.escapeSelector == 'function' ) {
924                return $.escapeSelector( string );
925            }
926            else {
927                return string.replace(/[!"#$%&'()*+,.\/:;<=>?@[\\\]^`{|}~]/g, "\\$&");
928            }
929        }
930    };
931
932    // ENABLE JQUERY PLUGIN FUNCTION
933    $.fn.multiselect = function( options ){
934        if( !this.length ) {
935            return;
936        }
937
938        var args = arguments;
939        var ret;
940
941        // menuize each list
942        if( (options === undefined) || (typeof options === 'object') ) {
943            return this.each(function(){
944                if( !$.data( this, 'plugin_multiselect' ) ) {
945                    $.data( this, 'plugin_multiselect', new MultiSelect( this, options ) );
946                }
947            });
948        } else if( (typeof options === 'string') && (options[0] !== '_') && (options !== 'init') ) {
949            this.each(function(){
950                var instance = $.data( this, 'plugin_multiselect' );
951
952                if( instance instanceof MultiSelect && typeof instance[ options ] === 'function' ) {
953                    ret = instance[ options ].apply( instance, Array.prototype.slice.call( args, 1 ) );
954                }
955
956                // special destruct handler
957                if( options === 'unload' ) {
958                    $.data( this, 'plugin_multiselect', null );
959                }
960            });
961
962            return ret;
963        }
964    };
965}(jQuery));

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.