PageSourceSearch

https://www.griefencounter.org.uk/wp-content/plugins/tickera-event…/jquery.multiselect.js?ver=1.1.3

js griefencounter.org.uk collected 2026-09-24 10:09:21 UTC 39,898 bytes, 939 lines download raw bytes

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