PageSourceSearch

https://reservas.hosteriadelacascada.com.ar/portal/themes/traveller/js/bootstrap-select.js?v=34

js hosteriadelacascada.com.ar collected 2026-10-05 09:49:51 UTC 44,708 bytes, 1,039 lines download raw bytes

1/*!
2 * bootstrap-select v1.5.4
3 * http://silviomoreto.github.io/bootstrap-select/
4 *
5 * Copyright 2013 bootstrap-select
6 * Licensed under the MIT license
7 */
8
9! function($) {
10
11    'use strict';
12
13    $.expr[':'].icontains = function(obj, index, meta) {
14        return $(obj).text().toUpperCase().indexOf(meta[3].toUpperCase()) >= 0;
15    };
16
17    var Selectpicker = function(element, options, e) {
18        if (e) {
19            e.stopPropagation();
20            e.preventDefault();
21        }
22        this.$element = $(element);
23        this.$newElement = null;
24        this.$button = null;
25        this.$menu = null;
26        this.$lis = null;
27
28        //Merge defaults, options and data-attributes to make our options
29        this.options = $.extend({}, $.fn.selectpicker.defaults, this.$element.data(), typeof options == 'object' && options);
30
31        //If we have no title yet, check the attribute 'title' (this is missed by jq as its not a data-attribute
32        if (this.options.title === null) {
33            this.options.title = this.$element.attr('title');
34        }
35
36        //Expose public methods
37        this.val = Selectpicker.prototype.val;
38        this.render = Selectpicker.prototype.render;
39        this.refresh = Selectpicker.prototype.refresh;
40        this.setStyle = Selectpicker.prototype.setStyle;
41        this.selectAll = Selectpicker.prototype.selectAll;
42        this.deselectAll = Selectpicker.prototype.deselectAll;
43        this.init();
44    };
45
46    Selectpicker.prototype = {
47
48        constructor: Selectpicker,
49
50        init: function() {
51            var that = this,
52                id = this.$element.attr('id');
53
54            this.$element.hide();
55            this.multiple = this.$element.prop('multiple');
56            this.autofocus = this.$element.prop('autofocus');
57            this.$newElement = this.createView();
58            this.$element.after(this.$newElement);
59            this.$menu = this.$newElement.find('> .dropdown-menu');
60            this.$button = this.$newElement.find('> button');
61            this.$searchbox = this.$newElement.find('input');
62
63            if (id !== undefined) {
64                this.$button.attr('data-id', id);
65                $('label[for="' + id + '"]').click(function(e) {
66                    e.preventDefault();
67                    that.$button.focus();
68                });
69            }
70
71            this.checkDisabled();
72            this.clickListener();
73            if (this.options.liveSearch) this.liveSearchListener();
74            this.render();
75            this.liHeight();
76            this.setStyle();
77            this.setWidth();
78            if (this.options.container) this.selectPosition();
79            this.$menu.data('this', this);
80            this.$newElement.data('this', this);
81        },
82
83        createDropdown: function() {
84            //If we are multiple, then add the show-tick class by default
85            var multiple = this.multiple ? ' show-tick' : '';
86            var inputGroup = this.$element.parent().hasClass('input-group') ? ' input-group-btn' : '';
87            var autofocus = this.autofocus ? ' autofocus' : '';
88            var header = this.options.header ? '<div class="popover-title"><button type="button" class="close" aria-hidden="true">&times;</button>' + this.options.header + '</div>' : '';
89            var searchbox = this.options.liveSearch ? '<div class="bootstrap-select-searchbox"><input type="text" class="input-block-level form-control" /></div>' : '';
90            var actionsbox = this.options.actionsBox ? '<div class="bs-actionsbox">' +
91                '<div class="btn-group btn-block">' +
92                '<button class="actions-btn bs-select-all btn btn-sm btn-default">' +
93                'Select All' +
94                '</button>' +
95                '<button class="actions-btn bs-deselect-all btn btn-sm btn-default">' +
96                'Deselect All' +
97                '</button>' +
98                '</div>' +
99                '</div>' : '';
100            var drop =
101                '<div class="btn-group bootstrap-select' + multiple + inputGroup + '">' +
102                '<button type="button" class="btn dropdown-toggle selectpicker" data-toggle="dropdown"' + autofocus + '>' +
103                '<span class="filter-option pull-left"></span>&nbsp;' +
104                '<span class="caret"></span>' +
105                '</button>' +
106                '<div class="dropdown-menu open">' +
107                header +
108                searchbox +
109                actionsbox +
110                '<ul class="dropdown-menu inner selectpicker" role="menu">' +
111                '</ul>' +
112                '</div>' +
113                '</div>';
114
115            return $(drop);
116        },
117
118        createView: function() {
119            var $drop = this.createDropdown();
120            var $li = this.createLi();
121            $drop.find('ul').append($li);
122            return $drop;
123        },
124
125        reloadLi: function() {
126            //Remove all children.
127            this.destroyLi();
128            //Re build
129            var $li = this.createLi();
130            this.$menu.find('ul').append($li);
131        },
132
133        destroyLi: function() {
134            this.$menu.find('li').remove();
135        },
136
137        createLi: function() {
138            var that = this,
139                _liA = [],
140                _liHtml = '';
141
142            this.$element.find('option').each(function() {
143                var $this = $(this);
144
145                //Get the class and text for the option
146                var optionClass = $this.attr('class') || '';
147                var inline = $this.attr('style') || '';
148                var text = $this.data('content') ? $this.data('content') : $this.html();
149                var subtext = $this.data('subtext') !== undefined ? '<small class="muted text-muted">' + $this.data('subtext') + '</small>' : '';
150                var icon = $this.data('icon') !== undefined ? '<i class="' + that.options.iconBase + ' ' + $this.data('icon') + '"></i> ' : '';
151                if (icon !== '' && ($this.is(':disabled') || $this.parent().is(':disabled'))) {
152                    icon = '<span>' + icon + '</span>';
153                }
154
155                if (!$this.data('content')) {
156                    //Prepend any icon and append any subtext to the main text.
157                    text = icon + '<span class="text">
157' + text + subtext + '</span>';
158                }
159
160                if (that.options.hideDisabled && ($this.is(':disabled') || $this.parent().is(':disabled'))) {
161                    _liA.push('<a style="min-height: 0; padding: 0"></a>');
162                } else if ($this.parent().is('optgroup') && $this.data('divider') !== true) {
163                    if ($this.index() === 0) {
164                        //Get the opt group label
165                        var label = $this.parent().attr('label');
166                        var labelSubtext = $this.parent().data('subtext') !== undefined ? '<small class="muted text-muted">' + $this.parent().data('subtext') + '</small>' : '';
167                        var labelIcon = $this.parent().data('icon') ? '<i class="' + $this.parent().data('icon') + '"></i> ' : '';
168                        label = labelIcon + '<span class="text">' + label + labelSubtext + '</span>';
169
170                        if ($this[0].index !== 0) {
171                            _liA.push(
172                                '<div class="div-contain"><div class="divider"></div></div>' +
173                                '<dt>' + label + '</dt>' +
174                                that.createA(text, 'opt ' + optionClass, inline)
175                            );
176                        } else {
177                            _liA.push(
178                                '<dt>' + label + '</dt>' +
179                                that.createA(text, 'opt ' + optionClass, inline));
180                        }
181                    } else {
182                        _liA.push(that.createA(text, 'opt ' + optionClass, inline));
183                    }
184                } else if ($this.data('divider') === true) {
185                    _liA.push('<div class="div-contain"><div class="divider"></div></div>');
186                } else if ($(this).data('hidden') === true) {
187                    _liA.push('<a></a>');
188                } else {
189                    _liA.push(that.createA(text, optionClass, inline));
190                }
191            });
192
193            $.each(_liA, function(i, item) {
194                var hide = item === '<a></a>' ? 'class="hide is-hidden"' : '';
195                _liHtml += '<li rel="' + i + '"' + hide + '>' + item + '</li>';
196            });
197
198            //If we are not multiple, and we dont have a selected item, and we dont have a title, select the first element so something is set in the button
199            if (!this.multiple && this.$element.find('option:selected').length === 0 && !this.options.title) {
200                this.$element.find('option').eq(0).prop('selected', true).attr('selected', 'selected');
201            }
202
203            return $(_liHtml);
204        },
205
206        createA: function(text, classes, inline) {
207            return '<a tabindex="0" class="' + classes + '" style="' + inline + '">' +
208                text +
209                '<i class="' + this.options.iconBase + ' ' + this.options.tickIcon + ' icon-ok check-mark"></i>' +
210                '</a>';
211        },
212
213        render: function(updateLi) {
214            var that = this;
215
216            //Update the LI to match the SELECT
217            if (updateLi !== false) {
218                this.$element.find('option').each(function(index) {
219                    that.setDisabled(index, $(this).is(':disabled') || $(this).parent().is(':disabled'));
220                    that.setSelected(index, $(this).is(':selected'));
221                });
222            }
223
224            this.tabIndex();
225
226            var selectedItems = this.$element.find('option:selected').map(function() {
227                var $this = $(this);
228                var icon = $this.data('icon') && that.options.showIcon ? '<i class="' + that.options.iconBase + ' ' + $this.data('icon') + '"></i> ' : '';
229                var subtext;
230                if (that.options.showSubtext && $this.attr('data-subtext') && !that.multiple) {
231                    subtext = ' <small class="muted text-muted">' + $this.data('subtext') + '</small>';
232                } else {
233                    subtext = '';
234                }
235                if ($this.data('content') && that.options.showContent) {
236                    return $this.data('content');
237                } else if ($this.attr('title') !== undefined) {
238                    return $this.attr('title');
239                } else {
240                    return icon + $this.html() + subtext;
241                }
242            }).toArray();
243
244            //Fixes issue in IE10 occurring when no default option is selected and at least one option is disabled
245            //Convert all the values into a comma delimited string
246            var title = !this.multiple ? selectedItems[0] : selectedItems.join(this.options.multipleSeparator);
247
248            //If this is multi select, and the selectText type is count, the show 1 of 2 selected etc..
249            if (this.multiple && this.options.selectedTextFormat.indexOf('count') > -1) {
250                var max = this.options.selectedTextFormat.split('>');
251                var notDisabled = this.options.hideDisabled ? ':not([disabled])' : '';
252                if ((max.length > 1 && selectedItems.length > max[1]) || (max.length == 1 && selectedItems.length >= 2)) {
253                    title = this.options.countSelectedText.replace('{0}', selectedItems.length).replace('{1}', this.$element.find('option:not([data-divider="true"]):not([data-hidden="true"])' + notDisabled).length);
254                }
255            }
256
257            this.options.title = this.$element.attr('title');
258
259            //If we dont have a title, then use the default, or if nothing is set at all, use the not selected text
260            if (!title) {
261                title = this.options.title !== undefined ? this.options.title : this.options.noneSelectedText;
262            }
263
264            this.$button.attr('title', $.trim(title));
265            this.$newElement.find('.filter-option').html(title);
266        },
267
268        setStyle: function(style, status) {
269            if (this.$element.attr('class')) {
270                this.$newElement.addClass(this.$element.attr('class').replace(/selectpicker|mobile-device/gi, ''));
271            }
272
273            var buttonClass = style ? style : this.options.style;
274
275            if (status == 'add') {
276                this.$button.addClass(buttonClass);
277            } else if (status == 'remove') {
278                this.$button.removeClass(buttonClass);
279            } else {
280                this.$button.removeClass(this.options.style);
281                this.$button.addClass(buttonClass);
282            }
283        },
284
285        liHeight: function() {
286            if (this.options.size === false) return;
287
288            var $selectClone = this.$menu.parent().clone().find('> .dropdown-toggle').prop('autofocus', false).end().appendTo('body'),
289                $menuClone = $selectClone.addClass('open').find('> .dropdown-menu'),
290                liHeight = $menuClone.find('li > a').outerHeight(),
291                headerHeight = this.options.header ? $menuClone.find('.popover-title').outerHeight() : 0,
292                searchHeight = this.options.liveSearch ? $menuClone.find('.bootstrap-select-searchbox').outerHeight() : 0,
293                actionsHeight = this.options.actionsBox ? $menuClone.find('.bs-actionsbox').outerHeight() : 0;
294
295            $selectClone.remove();
296
297            this.$newElement
298                .data('liHeight', liHeight)
299                .data('headerHeight', headerHeight)
300                .data('searchHeight', searchHeight)
301                .data('actionsHeight', actionsHeight);
302        },
303
304        setSize: function() {
305            var that = this,
306                menu = this.$menu,
307                menuInner = menu.find('.inner'),
308                selectHeight = this.$newElement.outerHeight(),
309                liHeight = this.$newElement.data('liHeight'),
310                headerHeight = this.$newElement.data('headerHeight'),
311                searchHeight = this.$newElement.data('searchHeight'),
312                actionsHeight = this.$newElement.data('actionsHeight'),
313                divHeight = menu.find('li .divider').outerHeight(true),
314                menuPadding = parseInt(menu.css('padding-top')) +
315                    parseInt(menu.css('padding-bottom')) +
316                    parseInt(menu.css('border-top-width')) +
317                    parseInt(menu.css('border-bottom-width')),
318                notDisabled = this.options.hideDisabled ? ':not(.disabled)' : '',
319                $window = $(window),
320                menuExtras = menuPadding + parseInt(menu.css('margin-top')) + parseInt(menu.css('margin-bottom')) + 2,
321                menuHeight,
322                selectOffsetTop,
323                selectOffsetBot,
324                posVert = function() {
325                    selectOffsetTop = that.$newElement.offset().top - $window.scrollTop();
326                    selectOffsetBot = $window.height() - selectOffsetTop - selectHeight;
327                };
328            posVert();
329            if (this.options.header) menu.css('padding-top', 0);
330
331            if (this.options.size == 'auto') {
332                var getSize = function() {
333                    var minHeight,
334                        lisVis = that.$lis.not('.hide');
335
336                    posVert();
337                    menuHeight = selectOffsetBot - menuExtras;
338
339                    if (that.options.dropupAuto) {
340                        that.$newElement.toggleClass('dropup', (selectOffsetTop > selectOffsetBot) && ((menuHeight - menuExtras) < menu.height()));
341                    }
342                    if (that.$newElement.hasClass('dropup')) {
343                        menuHeight = selectOffsetTop - menuExtras;
344                    }
345
346                    if ((lisVis.length + lisVis.find('dt').length) > 3) {
347                        minHeight = liHeight * 3 + menuExtras - 2;
348                    } else {
349                        minHeight = 0;
350                    }
351
352                    menu.css({
353                        'max-height': menuHeight + 'px',
354                        'overflow': 'hidden',
355                        'min-height': minHeight + headerHeight + searchHeight + actionsHeight + 'px'
356                    });
357                    menuInner.css({
358                        'max-height': menuHeight - headerHeight - searchHeight - actionsHeight - menuPadding + 'px',
359                        'overflow-y': 'auto',
360                        'min-height': Math.max(minHeight - menuPadding, 0) + 'px'
361                    });
362                };
363                getSize();
364                this.$searchbox.off('input.getSize propertychange.getSize').on('input.getSize propertychange.getSize', getSize);
365                $(window).off('resize.getSize').on('resize.getSize', getSize);
366                $(window).off('scroll.getSize').on('scroll.getSize', getSize);
367            } else if (this.options.size && this.options.size != 'auto' && menu.find('li' + notDisabled).length > this.options.size) {
368                var optIndex = menu.find('li' + notDisabled + ' > *').filter(':not(.div-contain)').slice(0, this.options.size).last().parent().index();
369                var divLength = menu.find('li').slice(0, optIndex + 1).find('.div-contain').length;
370                menuHeight = liHeight * this.options.size + divLength * divHeight + menuPadding;
371                if (that.options.dropupAuto) {
372                    this.$newElement.toggleClass('dropup', (selectOffsetTop > selectOffsetBot) && (menuHeight < menu.height()));
373                }
374                menu.css({
375                    'max-height': menuHeight + headerHeight + searchHeight + actionsHeight + 'px',
376                    'overflow': 'hidden'
377                });
378                menuInner.css({
379                    'max-height': menuHeight - menuPadding + 'px',
380                    'overflow-y': 'auto'
381                });
382            }
383        },
384
385        setWidth: function() {
386            if (this.options.width == 'auto') {
387                this.$menu.css('min-width', '0');
388
389                // Get correct width if element hidden
390                var selectClone = this.$newElement.clone().appendTo('body');
391                var ulWidth = selectClone.find('> .dropdown-menu').css('width');
392                var btnWidth = selectClone.css('width', 'auto').find('> button').css('width');
393                selectClone.remove();
394
395                // Set width to whatever's larger, button title or longest option
396                this.$newElement.css('width', Math.max(parseInt(ulWidth), parseInt(btnWidth)) + 'px');
397            } else if (this.options.width == 'fit') {
398                // Remove inline min-width so width can be changed from 'auto'
399                this.$menu.css('min-width', '');
400                this.$newElement.css('width', '').addClass('fit-width');
401            } else if (this.options.width) {
402                // Remove inline min-width so width can be changed from 'auto'
403                this.$menu.css('min-width', '');
404                this.$newElement.css('width', this.options.width);
405            } else {
406                // Remove inline min-width/width so width can be changed
407                this.$menu.css('min-width', '');
408                this.$newElement.css('width', '');
409            }
410            // Remove fit-width class if width is changed programmatically
411            if (this.$newElement.hasClass('fit-width') && this.options.width !== 'fit') {
412                this.$newElement.removeClass('fit-width');
413            }
414        },
415
416        selectPosition: function() {
417            var that = this,
418                drop = '<div />',
419                $drop = $(drop),
420                pos,
421                actualHeight,
422                getPlacement = function($element) {
423                    $drop.addClass($element.attr('class').replace(/form-control/gi, '')).toggleClass('dropup', $element.hasClass('dropup'));
424                    pos = $element.offset();
425                    actualHeight = $element.hasClass('dropup') ? 0 : $element[0].offsetHeight;
426                    $drop.css({
427                        'top': pos.top + actualHeight,
428                        'left': pos.left,
429                        'width': $element[0].offsetWidth,
430                        'position': 'absolute'
431                    });
432                };
433            this.$newElement.on('click', function() {
434                if (that.isDisabled()) {
435                    return;
436                }
437                getPlacement($(this));
438                $drop.appendTo(that.options.container);
439                $drop.toggleClass('open', !$(this).hasClass('open'));
440                $drop.append(that.$menu);
441            });
442            $(window).resize(function() {
443                getPlacement(that.$newElement);
444            });
445            $(window).on('scroll', function() {
446                getPlacement(that.$newElement);
447            });
448            $('html').on('click', function(e) {
449                if ($(e.target).closest(that.$newElement).length < 1) {
450                    $drop.removeClass('open');
451                }
452            });
453        },
454
455        mobile: function() {
456            this.$element.addClass('mobile-device').appendTo(this.$newElement);
457            if (this.options.container) this.$menu.hide();
458        },
459
460        refresh: function() {
461            this.$lis = null;
462            this.reloadLi();
463            this.render();
464            this.setWidth();
465            this.setStyle();
466            this.checkDisabled();
467            this.liHeight();
468        },
469
470        update: function() {
471            this.reloadLi();
472            this.setWidth();
473            this.setStyle();
474            this.checkDisabled();
475            this.liHeight();
476        },
477
478        setSelected: function(index, selected) {
479            if (this.$lis == null) this.$lis = this.$menu.find('li');
480            $(this.$lis[index]).toggleClass('selected', selected);
481        },
482
483        setDisabled: function(index, disabled) {
484            if (this.$lis == null) this.$lis = this.$menu.find('li');
485            if (disabled) {
486                $(this.$lis[index]).addClass('disabled').find('a').attr('href', '
486#').attr('tabindex', -1);
487            } else {
488                $(this.$lis[index]).removeClass('disabled').find('a').removeAttr('href').attr('tabindex', 0);
489            }
490        },
491
492        isDisabled: function() {
493            return this.$element.is(':disabled');
494        },
495
496        checkDisabled: function() {
497            var that = this;
498
499            if (this.isDisabled()) {
500                this.$button.addClass('disabled').attr('tabindex', -1);
501            } else {
502                if (this.$button.hasClass('disabled')) {
503                    this.$button.removeClass('disabled');
504                }
505
506                if (this.$button.attr('tabindex') == -1) {
507                    if (!this.$element.data('tabindex')) this.$button.removeAttr('tabindex');
508                }
509            }
510
511            this.$button.click(function() {
512                return !that.isDisabled();
513            });
514        },
515
516        tabIndex: function() {
517            if (this.$element.is('[tabindex]')) {
518                this.$element.data('tabindex', this.$element.attr('tabindex'));
519                this.$button.attr('tabindex', this.$element.data('tabindex'));
520            }
521        },
522
523        clickListener: function() {
524            var that = this;
525
526            $('body').on('touchstart.dropdown', '.dropdown-menu', function(e) {
527                e.stopPropagation();
528            });
529
530            this.$newElement.on('click', function() {
531                that.setSize();
532                if (!that.options.liveSearch && !that.multiple) {
533                    setTimeout(function() {
534                        that.$menu.find('.selected a').focus();
535                    }, 10);
536                }
537            });
538
539            this.$menu.on('click', 'li a', function(e) {
540                var clickedIndex = $(this).parent().index(),
541                    prevValue = that.$element.val(),
542                    prevIndex = that.$element.prop('selectedIndex');
543
544                //Dont close on multi choice menu
545                if (that.multiple) {
546                    e.stopPropagation();
547                }
548
549                e.preventDefault();
550
551                //Dont run if we have been disabled
552                if (!that.isDisabled() && !$(this).parent().hasClass('disabled')) {
553                    var $options = that.$element.find('option'),
554                        $option = $options.eq(clickedIndex),
555                        state = $option.prop('selected'),
556                        $optgroup = $option.parent('optgroup'),
557                        maxOptions = that.options.maxOptions,
558                        maxOptionsGrp = $optgroup.data('maxOptions') || false;
559
560                    //Deselect all others if not multi select box
561                    if (!that.multiple) {
562                        $options.prop('selected', false);
563                        $option.prop('selected', true);
564                        that.$menu.find('.selected').removeClass('selected');
565                        that.setSelected(clickedIndex, true);
566                    }
567                    //Else toggle the one we have chosen if we are multi select.
568                    else {
569                        $option.prop('selected', !state);
570                        that.setSelected(clickedIndex, !state);
571
572                        if ((maxOptions !== false) || (maxOptionsGrp !== false)) {
573                            var maxReached = maxOptions < $options.filter(':selected').length,
574                                maxReachedGrp = maxOptionsGrp < $optgroup.find('option:selected').length,
575                                maxOptionsArr = that.options.maxOptionsText,
576                                maxTxt = maxOptionsArr[0].replace('{n}', maxOptions),
577                                maxTxtGrp = maxOptionsArr[1].replace('{n}', maxOptionsGrp),
578                                $notify = $('<div class="notify"></div>');
579
580                            if ((maxOptions && maxReached) || (maxOptionsGrp && maxReachedGrp)) {
581                                // If {var} is set in array, replace it
582                                if (maxOptionsArr[2]) {
583                                    maxTxt = maxTxt.replace('{var}', maxOptionsArr[2][maxOptions > 1 ? 0 : 1]);
584                                    maxTxtGrp = maxTxtGrp.replace('{var}', maxOptionsArr[2][maxOptionsGrp > 1 ? 0 : 1]);
585                                }
586
587                                $option.prop('selected', false);
588
589                                that.$menu.append($notify);
590
591                                if (maxOptions && maxReached) {
592                                    $notify.append($('<div>' + maxTxt + '</div>'));
593                                    that.$element.trigger('maxReached.bs.select');
594                                }
595
596                                if (maxOptionsGrp && maxReachedGrp) {
597                                    $notify.append($('<div>' + maxTxtGrp + '</div>'));
598                                    that.$element.trigger('maxReachedGrp.bs.select');
599                                }
600
601                                setTimeout(function() {
602                                    that.setSelected(clickedIndex, false);
603                                }, 10);
604
605                                $notify.delay(750).fadeOut(300, function() {
606                                    $(this).remove();
607                                });
608                            }
609                        }
610                    }
611
612                    if (!that.multiple) {
613                        that.$button.focus();
614                    } else if (that.options.liveSearch) {
615                        that.$searchbox.focus();
616                    }
617
618                    // Trigger select 'change'
619                    if ((prevValue != that.$element.val() && that.multiple) || (prevIndex != that.$element.prop('selectedIndex') && !that.multiple)) {
620                        that.$element.change();
621                    }
622                }
623            });
624
625            this.$menu.on('click', 'li.disabled a, li dt, li .div-contain, .popover-title, .popover-title :not(.close)', function(e) {
626                if (e.target == this) {
627                    e.preventDefault();
628                    e.stopPropagation();
629                    if (!that.options.liveSearch) {
630                        that.$button.focus();
631                    } else {
632                        that.$searchbox.focus();
633                    }
634                }
635            });
636
637            this.$menu.on('click', '.popover-title .close', function() {
638                that.$button.focus();
639            });
640
641            this.$searchbox.on('click', function(e) {
642                e.stopPropagation();
643            });
644
645
646            this.$menu.on('click', '.actions-btn', function(e) {
647                if (that.options.liveSearch) {
648                    that.$searchbox.focus();
649                } else {
650                    that.$button.focus();
651                }
652
653                e.preventDefault();
654                e.stopPropagation();
655
656                if ($(this).is('.bs-select-all')) {
657                    that.selectAll();
658                } else {
659                    that.deselectAll();
660                }
661                that.$element.change();
662            });
663
664            this.$element.change(function() {
665                that.render(false);
666            });
667        },
668
669        liveSearchListener: function() {
670            var that = this,
671                no_results = $('<li class="no-results"></li>');
672
673            this.$newElement.on('click.dropdown.data-api', function() {
674                that.$menu.find('.active').removeClass('active');
675                if ( !! that.$searchbox.val()) {
676                    that.$searchbox.val('');
677                    that.$lis.not('.is-hidden').removeClass('hide');
678                    if ( !! no_results.parent().length) no_results.remove();
679                }
680                if (!that.multiple) that.$menu.find('.selected').addClass('active');
681                setTimeout(function() {
682                    that.$searchbox.focus();
683                }, 10);
684            });
685
686            this.$searchbox.on('input propertychange', function() {
687                if (that.$searchbox.val()) {
688                    that.$lis.not('.is-hidden').removeClass('hide').find('a').not(':icontains(' + that.$searchbox.val() + ')').parent().addClass('hide');
689
690                    if (!that.$menu.find('li').filter(':visible:not(.no-results)').length) {
691                        if ( !! no_results.parent().length) no_results.remove();
692                        no_results.html(that.options.noneResultsText + ' "' + that.$searchbox.val() + '"').show();
693                        that.$menu.find('li').last().after(no_results);
694                    } else if ( !! no_results.parent().length) {
695                        no_results.remove();
696                    }
697
698                } else {
699                    that.$lis.not('.is-hidden').removeClass('hide');
700                    if ( !! no_results.parent().length) no_results.remove();
701                }
702
703                that.$menu.find('li.active').removeClass('active');
704                that.$menu.find('li').filter(':visible:not(.divider)').eq(0).addClass('active').find('a').focus();
705                $(this).focus();
706            });
707
708            this.$menu.on('mouseenter', 'a', function(e) {
709                that.$menu.find('.active').removeClass('active');
710                $(e.currentTarget).parent().not('.disabled').addClass('active');
711            });
712
713            this.$menu.on('mouseleave', 'a', function() {
714                that.$menu.find('.active').removeClass('active');
715            });
716        },
717
718        val: function(value) {
719
720            if (value !== undefined) {
721                this.$element.val(value);
722
723                this.$element.change();
724                return this.$element;
725            } else {
726                return this.$element.val();
727            }
728        },
729
730        selectAll: function() {
731            if (this.$lis == null) this.$lis = this.$menu.find('li');
732            this.$element.find('option:enabled').prop('selected', true);
733            $(this.$lis).filter(':not(.disabled)').addClass('selected');
734            this.render(false);
735        },
736
737        deselectAll: function() {
738            if (this.$lis == null) this.$lis = this.$menu.find('li');
739            this.$element.find('option:enabled').prop('selected', false);
740            $(this.$lis).filter(':not(.disabled)').removeClass('selected');
741            this.render(false);
742        },
743
744        keydown: function(e) {
745            var $this,
746                $items,
747                $parent,
748                index,
749                next,
750                first,
751                last,
752                prev,
753                nextPrev,
754                that,
755                prevIndex,
756                isActive,
757                keyCodeMap = {
758                    32: ' ',
759                    48: '0',
760                    49: '1',
761                    50: '2',
762                    51: '3',
763                    52: '4',
764                    53: '5',
765                    54: '6',
766                    55: '7',
767                    56: '8',
768                    57: '9',
769                    59: ';',
770                    65: 'a',
771                    66: 'b',
772                    67: 'c',
773                    68: 'd',
774                    69: 'e',
775                    70: 'f',
776                    71: 'g',
777                    72: 'h',
778                    73: 'i',
779                    74: 'j',
780                    75: 'k',
781                    76: 'l',
782                    77: 'm',
783                    78: 'n',
784                    79: 'o',
785                    80: 'p',
786                    81: 'q',
787                    82: 'r',
788                    83: 's',
789                    84: 't',
790                    85: 'u',
791                    86: 'v',
792                    87: 'w',
793                    88: 'x',
794                    89: 'y',
795                    90: 'z',
796                    96: '0',
797                    97: '1',
798                    98: '2',
799                    99: '3',
800                    100: '4',
801                    101: '5',
802                    102: '6',
803                    103: '7',
804                    104: '8',
805                    105: '9'
806                };
807
808            $this = $(this);
809
810            $parent = $this.parent();
811
812            if ($this.is('input')) $parent = $this.parent().parent();
813
814            that = $parent.data('this');
815
816            if (that.options.liveSearch) $parent = $this.parent().parent();
817
818            if (that.options.container) $parent = that.$menu;
819
820            $items = $('[role=menu] li:not(.divider) a', $parent);
821
822            isActive = that.$menu.parent().hasClass('open');
823
824            if (!isActive && /([0-9]|[A-z])/.test(String.fromCharCode(e.keyCode))) {
825                if (!that.options.container) {
826                    that.setSize();
827                    that.$menu.parent().addClass('open');
828                    isActive = that.$menu.parent().hasClass('open');
829                } else {
830                    that.$newElement.trigger('click');
831                }
832                that.$searchbox.focus();
833            }
834
835            if (that.options.liveSearch) {
836                if (/(^9$|27)/.test(e.keyCode) && isActive && that.$menu.find('.active').length === 0) {
837                    e.preventDefault();
838                    that.$menu.parent().removeClass('open');
839                    that.$button.focus();
840                }
841                $items = $('[role=menu] li:not(.divider):visible', $parent);
842                if (!$this.val() && !/(38|40)/.test(e.keyCode)) {
843                    if ($items.filter('.active').length === 0) {
844                        $items = that.$newElement.find('li').filter(':icontains(' + keyCodeMap[e.keyCode] + ')');
845                    }
846                }
847            }
848
849            if (!$items.length) return;
850
851            if (/(38|40)/.test(e.keyCode)) {
852
853                index = $items.index($items.filter(':focus'));
854                first = $items.parent(':not(.disabled):visible').first().index();
855                last = $items.parent(':not(.disabled):visible').last().index();
856                next = $items.eq(index).parent().nextAll(':not(.disabled):visible').eq(0).index();
857                prev = $items.eq(index).parent().prevAll(':not(.disabled):visible').eq(0).index();
858                nextPrev = $items.eq(next).parent().prevAll(':not(.disabled):visible').eq(0).index();
859
860                if (that.options.liveSearch) {
861                    $items.each(function(i) {
862                        if ($(this).is(':not(.disabled)')) {
863                            $(this).data('index', i);
864                        }
865                    });
866                    index = $items.index($items.filter('.active'));
867                    first = $items.filter(':not(.disabled):visible').first().data('index');
868                    last = $items.filter(':not(.disabled):visible').last().data('index');
869                    next = $items.eq(index).nextAll(':not(.disabled):visible').eq(0).data('index');
870                    prev = $items.eq(index).prevAll(':not(.disabled):visible').eq(0).data('index');
871                    nextPrev = $items.eq(next).prevAll(':not(.disabled):visible').eq(0).data('index');
872                }
873
874                prevIndex = $this.data('prevIndex');
875
876                if (e.keyCode == 38) {
877                    if (that.options.liveSearch) index -= 1;
878                    if (index != nextPrev && index > prev) index = prev;
879                    if (index < first) index = first;
880                    if (index == prevIndex) index = last;
881                }
882
883                if (e.keyCode == 40) {
884                    if (that.options.liveSearch) index += 1;
885                    if (index == -1) index = 0;
886                    if (index != nextPrev && index < next) index = next;
887                    if (index > last) index = last;
888                    if (index == prevIndex) index = first;
889                }
890
891                $this.data('prevIndex', index);
892
893                if (!that.options.liveSearch) {
894                    $items.eq(index).focus();
895                } else {
896                    e.preventDefault();
897                    if (!$this.is('.dropdown-toggle')) {
898                        $items.removeClass('active');
899                        $items.eq(index).addClass('active').find('a').focus();
900                        $this.focus();
901                    }
902                }
903
904            } else if (!$this.is('input')) {
905
906                var keyIndex = [],
907                    count,
908                    prevKey;
909
910                $items.each(function() {
911                    if ($(this).parent().is(':not(.disabled)')) {
912                        if ($.trim($(this).text().toLowerCase()).substring(0, 1) == keyCodeMap[e.keyCode]) {
913                            keyIndex.push($(this).parent().index());
914                        }
915                    }
916                });
917
918                count = $(document).data('keycount');
919                count++;
920                $(document).data('keycount', count);
921
922                prevKey = $.trim($(':focus').text().toLowerCase()).substring(0, 1);
923
924                if (prevKey != keyCodeMap[e.keyCode]) {
925                    count = 1;
926                    $(document).data('keycount', count);
927                } else if (count >= keyIndex.length) {
928                    $(document).data('keycount', 0);
929                    if (count > keyIndex.length) count = 1;
930                }
931
932                $items.eq(keyIndex[count - 1]).focus();
933            }
934
935            // Select focused option if "Enter", "Spacebar", "Tab" are pressed inside the menu.
936            if (/(13|32|^9$)/.test(e.keyCode) && isActive) {
937                if (!/(32)/.test(e.keyCode)) e.preventDefault();
938                if (!that.options.liveSearch) {
939                    $(':focus').click();
940                } else if (!/(32)/.test(e.keyCode)) {
941                    that.$menu.find('.active a').click();
942                    $this.focus();
943                }
944                $(document).data('keycount', 0);
945            }
946
947            if ((/(^9$|27)/.test(e.keyCode) && isActive && (that.multiple || that.options.liveSearch)) || (/(27)/.test(e.keyCode) && !isActive)) {
948                that.$menu.parent().removeClass('open');
949                that.$button.focus();
950            }
951
952        },
953
954        hide: function() {
955            this.$newElement.hide();
956        },
957
958        show: function() {
959            this.$newElement.show();
960        },
961
962        destroy: function() {
963            this.$newElement.remove();
964            this.$element.remove();
965        }
966    };
967
968    $.fn.selectpicker = function(option, event) {
969        //get the args of the outer function..
970        var args = arguments;
971        var value;
972        var chain = this.each(function() {
973            if ($(this).is('select')) {
974                var $this = $(this),
975                    data = $this.data('selectpicker'),
976                    options = typeof option == 'object' && option;
977
978                if (!data) {
979                    $this.data('selectpicker', (data = new Selectpicker(this, options, event)));
980                } else if (options) {
981                    for (var i in options) {
982                        data.options[i] = options[i];
983                    }
984                }
985
986                if (typeof option == 'string') {
987                    //Copy the value of option, as once we shift the arguments
988                    //it also shifts the value of option.
989                    var property = option;
990                    if (data[property] instanceof Function) {
991                        [].shift.apply(args);
992                        value = data[property].apply(data, args);
993                    } else {
994                        value = data.options[property];
995                    }
996                }
997            }
998        });
999
1000        if (value !== undefined) {
1001            return value;
1002        } else {
1003            return chain;
1004        }
1005    };
1006
1007    $.fn.selectpicker.defaults = {
1008        style: 'btn-default',
1009        size: 'auto',
1010        title: null,
1011        selectedTextFormat: 'values',
1012        noneSelectedText: 'Nothing selected',
1013        noneResultsText: 'No results match',
1014        countSelectedText: '{0} of {1} selected',
1015        maxOptionsText: ['Limit reached ({n} {var} max)', 'Group limit reached ({n} {var} max)', ['items', 'item']],
1016        width: false,
1017        container: false,
1018        hideDisabled: false,
1019        showSubtext: false,
1020        showIcon: true,
1021        showContent: true,
1022        dropupAuto: true,
1023        header: false,
1024        liveSearch: false,
1025        actionsBox: false,
1026        multipleSeparator: ', ',
1027        iconBase: 'glyphicon',
1028        tickIcon: 'glyphicon-ok',
1029        maxOptions: false
1030    };
1031
1032    $(document)
1033        .data('keycount', 0)
1034        .on('keydown', '.bootstrap-select [data-toggle=dropdown], .bootstrap-select [role=menu], .bootstrap-select-searchbox input', Selectpicker.prototype.keydown)
1035        .on('focusin.modal', '.bootstrap-select [data-toggle=dropdown], .bootstrap-select [role=menu], .bootstrap-select-searchbox input', function(e) {
1036            e.stopPropagation();
1037        });
1038
1039}(window.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.