PageSourceSearch

https://tcecam.camaramadrid.es/tcex/js/plugins/bootstrap-selectpicker.js

js camaramadrid.es collected 2026-09-24 17:39:33 UTC 101,633 bytes, 2,776 lines download raw bytes

vendor: 10,739 bytes, lines 1-415
1/*!
2 * Bootstrap-select v1.13.2 (https://developer.snapappointments.com/bootstrap-select)
3 *
4 * Copyright 2012-2018 SnapAppointments, LLC
5 * Licensed under MIT (https://github.com/snapappointments/bootstrap-select/blob/master/LICENSE)
6 */
7
8(function(root, factory) {
9  if (root === undefined && window !== undefined) root = window;
10  if (typeof define === 'function' && define.amd) {
11    // AMD. Register as an anonymous module unless amdModuleId is set
12    define(["jquery"], function(a0) {
13      return (factory(a0));
14    });
15  } else if (typeof module === 'object' && module.exports) {
16    // Node. Does not work with strict CommonJS, but
17    // only CommonJS-like environments that support module.exports,
18    // like Node.
19    module.exports = factory(require("jquery"));
20  } else {
21    factory(root["jQuery"]);
22  }
23}(this, function(jQuery) {
24
25  (function($) {
26    'use strict';
27
28    var testElement = document.createElement('_');
29
30    testElement.classList.toggle('c3', false);
31
32    // Polyfill for IE 10 and Firefox <24, where classList.toggle does not
33    // support the second argument.
34    if (testElement.classList.contains('c3')) {
35      var _toggle = DOMTokenList.prototype.toggle;
36
37      DOMTokenList.prototype.toggle = function(token, force) {
38        if (1 in arguments && !this.contains(token) === !force) {
39          return force;
40        } else {
41          return _toggle.call(this, token);
42        }
43      };
44    }
45
46    // shallow array comparison
47    function isEqual(array1, array2) {
48      return array1.length === array2.length && array1.every(function(element, index) {
49        return element === array2[index];
50      });
51    };
52
53    //<editor-fold desc="Shims">
54    if (!String.prototype.startsWith) {
55      (function() {
56        'use strict'; // needed to support `apply`/`call` with `undefined`/`null`
57        var defineProperty = (function() {
58          // IE 8 only supports `Object.defineProperty` on DOM elements
59          try {
60            var object = {};
61            var $defineProperty = Object.defineProperty;
62            var result = $defineProperty(object, object, object) && $defineProperty;
63          } catch (error) {}
64          return result;
65        }());
66        var toString = {}.toString;
67        var startsWith = function(search) {
68          if (this == null) {
69            throw new TypeError();
70          }
71          var string = String(this);
72          if (search && toString.call(search) == '[object RegExp]') {
73            throw new TypeError();
74          }
75          var stringLength = string.length;
76          var searchString = String(search);
77          var searchLength = searchString.length;
78          var position = arguments.length > 1 ? arguments[1] : undefined;
79          // `ToInteger`
80          var pos = position ? Number(position) : 0;
81          if (pos != pos) { // better `isNaN`
82            pos = 0;
83          }
84          var start = Math.min(Math.max(pos, 0), stringLength);
85          // Avoid the `indexOf` call if no match is possible
86          if (searchLength + start > stringLength) {
87            return false;
88          }
89          var index = -1;
90          while (++index < searchLength) {
91            if (string.charCodeAt(start + index) != searchString.charCodeAt(index)) {
92              return false;
93            }
94          }
95          return true;
96        };
97        if (defineProperty) {
98          defineProperty(String.prototype, 'startsWith', {
99            'value': startsWith,
100            'configurable': true,
101            'writable': true
102          });
103        } else {
104          String.prototype.startsWith = startsWith;
105        }
106      }());
107    }
108
109    if (!Object.keys) {
110      Object.keys = function(
111        o, // object
112        k, // key
113        r // result array
114      ) {
115        // initialize object and result
116        r = [];
117        // iterate over object keys
118        for (k in o)
119          // fill result array with non-prototypical keys
120          r.hasOwnProperty.call(o, k) && r.push(k);
121        // return result
122        return r;
123      };
124    }
125
126    // much faster than $.val()
127    function getSelectValues(select) {
128      var result = [];
129      var options = select && select.options;
130      var opt;
131
132      if (select.multiple) {
133        for (var i = 0, len = options.length; i < len; i++) {
134          opt = options[i];
135
136          if (opt.selected) {
137            result.push(opt.value || opt.text);
138          }
139        }
140      } else {
141        result = select.value;
142      }
143
144      return result;
145    }
146
147    // set data-selected on select element if the value has been programmatically selected
148    // prior to initialization of bootstrap-select
149    // * consider removing or replacing an alternative method *
150    var valHooks = {
151      useDefault: false,
152      _set: $.valHooks.select.set
153    };
154
155    $.valHooks.select.set = function(elem, value) {
156      if (value && !valHooks.useDefault) $(elem).data('selected', true);
157
158      return valHooks._set.apply(this, arguments);
159    };
160
161    var changed_arguments = null;
162
163    var EventIsSupported = (function() {
164      try {
165        new Event('change');
166        return true;
167      } catch (e) {
168        return false;
169      }
170    })();
171
172    $.fn.triggerNative = function(eventName) {
173      var el = this[0],
174        event;
175
176      if (el.dispatchEvent) { // for modern browsers & IE9+
177        if (EventIsSupported) {
178          // For modern browsers
179          event = new Event(eventName, {
180            bubbles: true
181          });
182        } else {
183          // For IE since it doesn't support Event constructor
184          event = document.createEvent('Event');
185          event.initEvent(eventName, true, false);
186        }
187
188        el.dispatchEvent(event);
189      } else if (el.fireEvent) { // for IE8
190        event = document.createEventObject();
191        event.eventType = eventName;
192        el.fireEvent('on' + eventName, event);
193      } else {
194        // fall back to jQuery.trigger
195        this.trigger(eventName);
196      }
197    };
198    //</editor-fold>
199
200    function stringSearch(li, searchString, method, normalize) {
201      var stringTypes = [
202          'content',
203          'subtext',
204          'tokens'
205        ],
206        searchSuccess = false;
207
208      for (var i = 0; i < stringTypes.length; i++) {
209        var stringType = stringTypes[i],
210          string = li[stringType];
211
212        if (string) {
213          string = string.toString();
214
215          // Strip HTML tags. This isn't perfect, but it's much faster than any other method
216          if (stringType === 'content') {
217            string = string.replace(/<[^>]+>/g, '');
218          }
219
220          if (normalize) string = normalizeToBase(string);
221          string = string.toUpperCase();
222
223          if (method === 'contains') {
224            searchSuccess = string.indexOf(searchString) >= 0;
225          } else {
226            searchSuccess = string.startsWith(searchString);
227          }
228
229          if (searchSuccess) break;
230        }
231      }
232
233      return searchSuccess;
234    }
235
236    function toInteger(value) {
237      return parseInt(value, 10) || 0;
238    }
239
240    /**
241     * Remove all diatrics from the given text.
242     * @access private
243     * @param {String} text
244     * @returns {String}
245     */
246    function normalizeToBase(text) {
247      var rExps = [{
248          re: /[\xC0-\xC6]/g,
249          ch: "A"
250        },
251        {
252          re: /[\xE0-\xE6]/g,
253          ch: "a"
254        },
255        {
256          re: /[\xC8-\xCB]/g,
257          ch: "E"
258        },
259        {
260          re: /[\xE8-\xEB]/g,
261          ch: "e"
262        },
263        {
264          re: /[\xCC-\xCF]/g,
265          ch: "I"
266        },
267        {
268          re: /[\xEC-\xEF]/g,
269          ch: "i"
270        },
271        {
272          re: /[\xD2-\xD6]/g,
273          ch: "O"
274        },
275        {
276          re: /[\xF2-\xF6]/g,
277          ch: "o"
278        },
279        {
280          re: /[\xD9-\xDC]/g,
281          ch: "U"
282        },
283        {
284          re: /[\xF9-\xFC]/g,
285          ch: "u"
286        },
287        {
288          re: /[\xC7-\xE7]/g,
289          ch: "c"
290        },
291        {
292          re: /[\xD1]/g,
293          ch: "N"
294        },
295        {
296          re: /[\xF1]/g,
297          ch: "n"
298        }
299      ];
300      $.each(rExps, function() {
301        text = text ? text.replace(this.re, this.ch) : '';
302      });
303      return text;
304    }
305
306
307    // List of HTML entities for escaping.
308    var escapeMap = {
309      '&': '&amp;',
310      '<': '&lt;',
311      '>': '&gt;',
312      '"': '&quot;',
313      "'": '&#x27;',
314      '`': '&#x60;'
315    };
316
317    var unescapeMap = {
318      '&amp;': '&',
319      '&lt;': '<',
320      '&gt;': '>',
321      '&quot;': '"',
322      '&#x27;': "'",
323      '&#x60;': '`'
324    };
325
326    // Functions for escaping and unescaping strings to/from HTML interpolation.
327    var createEscaper = function(map) {
328      var escaper = function(match) {
329        return map[match];
330      };
331      // Regexes for identifying a key that needs to be escaped.
332      var source = '(?:' + Object.keys(map).join('|') + ')';
333      var testRegexp = RegExp(source);
334      var replaceRegexp = RegExp(source, 'g');
335      return function(string) {
336        string = string == null ? '' : '' + string;
337        return testRegexp.test(string) ? string.replace(replaceRegexp, escaper) : string;
338      };
339    };
340
341    var htmlEscape = createEscaper(escapeMap);
342    var htmlUnescape = createEscaper(unescapeMap);
343
344    /**
345     * ------------------------------------------------------------------------
346     * Constants
347     * ------------------------------------------------------------------------
348     */
349
350    var keyCodeMap = {
351      32: ' ',
352      48: '0',
353      49: '1',
354      50: '2',
355      51: '3',
356      52: '4',
357      53: '5',
358      54: '6',
359      55: '7',
360      56: '8',
361      57: '9',
362      59: ';',
363      65: 'A',
364      66: 'B',
365      67: 'C',
366      68: 'D',
367      69: 'E',
368      70: 'F',
369      71: 'G',
370      72: 'H',
371      73: 'I',
372      74: 'J',
373      75: 'K',
374      76: 'L',
375      77: 'M',
376      78: 'N',
377      79: 'O',
378      80: 'P',
379      81: 'Q',
380      82: 'R',
381      83: 'S',
382      84: 'T',
383      85: 'U',
384      86: 'V',
385      87: 'W',
386      88: 'X',
387      89: 'Y',
388      90: 'Z',
389      96: '0',
390      97: '1',
391      98: '2',
392      99: '3',
393      100: '4',
394      101: '5',
395      102: '6',
396      103: '7',
397      104: '8',
398      105: '9'
399    };
400
401    var keyCodes = {
402      ESCAPE: 27, // KeyboardEvent.which value for Escape (Esc) key
403      ENTER: 13, // KeyboardEvent.which value for Enter key
404      SPACE: 32, // KeyboardEvent.which value for space key
405      TAB: 9, // KeyboardEvent.which value for tab key
406      ARROW_UP: 38, // KeyboardEvent.which value for up arrow key
407      ARROW_DOWN: 40 // KeyboardEvent.which value for down arrow key
408    }
409
410    var version = {
411      success: false,
412      major: '3'
413    };
414
415    try {
416      version.full = ($.fn.dropdown.Constructor.VERSION || '').split(' ')[0].split('.');
417      version.major = version.full[0];
418      version.success = true;
419    } catch (err) {
420      console.warn(
421        'There was an issue retrieving Bootstrap\'s version. ' +
422        'Ensure Bootstrap is being loaded before bootstrap-select and there is no namespace collision. ' +
423        'If loading Bootstrap asynchronously, the version may need to be manually specified via $.fn.selectpicker.Constructor.BootstrapVersion.', err);
424    }
425
426    var classNames = {
427      DISABLED: 'disabled',
428      DIVIDER: 'divider',
429      SHOW: 'open',
430      DROPUP: 'dropup',
431      MENU: 'dropdown-menu',
432      MENURIGHT: 'dropdown-menu-right',
433      MENULEFT: 'dropdown-menu-left',
434      // to-do: replace with more advanced template/customization options
435      BUTTONCLASS: 'btn-default',
436      POPOVERHEADER: 'popover-title'
437    }
438
439    var Selector = {
440      MENU: '.' + classNames.MENU
441    }
442
443    if (version.major === '4') {
444      classNames.DIVIDER = 'dropdown-divider';
445      classNames.SHOW = 'show';
446      classNames.BUTTONCLASS = 'btn-light';
447      classNames.POPOVERHEADER = 'popover-header';
448    }
449
450    var REGEXP_ARROW = new RegExp(keyCodes.ARROW_UP + '|' + keyCodes.ARROW_DOWN);
451    var REGEXP_TAB_OR_ESCAPE = new RegExp('^' + keyCodes.TAB + '$|' + keyCodes.ESCAPE);
452    var REGEXP_ENTER_OR_SPACE = new RegExp(keyCodes.ENTER + '|' + keyCodes.SPACE);
453
454    var Selectpicker = function(element, options) {
455      var that = this;
456
457      // bootstrap-select has been initialized - revert valHooks.select.set back to its original function
458      if (!valHooks.useDefault) {
459        $.valHooks.select.set = valHooks._set;
460        valHooks.useDefault = true;
461      }
462
463      this.$element = $(element);
464      this.$newElement = null;
465      this.$button = null;
466      this.$menu = null;
467      this.options = options;
468      this.selectpicker = {
469        main: {
470          // store originalIndex (key) and newIndex (value) in this.selectpicker.main.map.newIndex for fast accessibility
471          // allows us to do this.main.elements[this.selectpicker.main.map.newIndex[index]] to select an element based on the originalIndex
472          map: {
473            newIndex: {},
474            originalIndex: {}
475          }
476        },
477        current: {
478          map: {}
479        }, // current changes if a search is in progress
480        search: {
481          map: {}
482        },
483        view: {},
484        keydown: {
485          keyHistory: '',
486          resetKeyHistory: {
487            start: function() {
488              return setTimeout(function() {
489                that.selectpicker.keydown.keyHistory = '';
490              }, 800);
491            }
492          }
493        }
494      };
495      // If we have no title yet, try to pull it from the html title attribute (jQuery doesnt' pick it up as it's not a
496      // data-attribute)
497      if (this.options.title === null) {
498        this.options.title = this.$element.attr('title');
499      }
500
501      // Format window padding
502      var winPad = this.options.windowPadding;
503      if (typeof winPad === 'number') {
504        this.options.windowPadding = [winPad, winPad, winPad, winPad];
505      }
506
507      //Expose public methods
508      this.val = Selectpicker.prototype.val;
509      this.render = Selectpicker.prototype.render;
510      this.refresh = Selectpicker.prototype.refresh;
511      this.setStyle = Selectpicker.prototype.setStyle;
512      this.selectAll = Selectpicker.prototype.selectAll;
513      this.deselectAll = Selectpicker.prototype.deselectAll;
514      this.destroy = Selectpicker.prototype.destroy;
515      this.remove = Selectpicker.prototype.remove;
516      this.show = Selectpicker.prototype.show;
517      this.hide = Selectpicker.prototype.hide;
518
519      this.init();
520    };
521
522    Selectpicker.VERSION = '1.13.2';
523
524    Selectpicker.BootstrapVersion = version.major;
525
526    // part of this is duplicated in i18n/defaults-en_US.js. Make sure to update both.
527    Selectpicker.DEFAULTS = {
528      noneSelectedText: 'Nothing selected',
529      noneResultsText: 'No results matched {0}',
530      countSelectedText: function(numSelected, numTotal) {
531        return (numSelected == 1) ? "{0} item selected" : "{0} items selected";
532      },
533      maxOptionsText: function(numAll, numGroup) {
534        return [
535          (numAll == 1) ? 'Limit reached ({n} item max)' : 'Limit reached ({n} items max)',
536          (numGroup == 1) ? 'Group limit reached ({n} item max)' : 'Group limit reached ({n} items max)'
537        ];
538      },
539      selectAllText: 'Select All',
540      deselectAllText: 'Deselect All',
541      doneButton: false,
542      doneButtonText: 'Close',
543      multipleSeparator: ', ',
544      styleBase: 'btn',
545      style: classNames.BUTTONCLASS,
546      size: 'auto',
547      title: null,
548      selectedTextFormat: 'values',
549      width: false,
550      container: false,
551      hideDisabled: false,
552      showSubtext: false,
553      showIcon: true,
554      showContent: true,
555      dropupAuto: true,
556      header: false,
557      liveSearch: false,
558      liveSearchPlaceholder: null,
559      liveSearchNormalize: false,
560      liveSearchStyle: 'contains',
561      actionsBox: false,
562      iconBase: 'glyphicon',
563      tickIcon: 'glyphicon-ok',
564      showTick: false,
565      template: {
566        caret: '<span class="caret"></span>'
567      },
568      maxOptions: false,
569      mobile: false,
570      selectOnTab: false,
571      dropdownAlignRight: false,
572      windowPadding: 0,
573      virtualScroll: 600,
574      display: false
575    };
576
577    if (version.major === '4') {
578      Selectpicker.DEFAULTS.style = 'btn-light';
579      Selectpicker.DEFAULTS.iconBase = '';
580      Selectpicker.DEFAULTS.tickIcon = 'bs-ok-default';
581    }
582
583    Selectpicker.prototype = {
584
585      constructor: Selectpicker,
586
587      init: function() {
588        var that = this,
589          id = this.$element.attr('id');
590
591        this.$element.addClass('bs-select-hidden');
592
593        this.multiple = this.$element.prop('multiple');
594        this.autofocus = this.$element.prop('autofocus');
595        this.$newElement = this.createDropdown();
596        this.createLi();
597        this.$element
598          .after(this.$newElement)
599          .prependTo(this.$newElement);
600        this.$button = this.$newElement.children('button');
601        this.$menu = this.$newElement.children(Selector.MENU);
602        this.$menuInner = this.$menu.children('.inner');
603        this.$searchbox = this.$menu.find('input');
604
605        this.$element.removeClass('bs-select-hidden');
606
607        if (this.options.dropdownAlignRight === true) this.$menu.addClass(classNames.MENURIGHT);
608
609        if (typeof id !== 'undefined') {
610          this.$button.attr('data-id', id);
611        }
612
613        this.checkDisabled();
614        this.clickListener();
615        if (this.options.liveSearch) this.liveSearchListener();
616        this.render();
617        this.setStyle();
618        this.setWidth();
619        if (this.options.container) {
620          this.selectPosition();
621        } else {
622          this.$element.on('hide.bs.select', function() {
623            if (that.isVirtual()) {
624              // empty menu on close
625              var menuInner = that.$menuInner[0],
626                emptyMenu = menuInner.firstChild.cloneNode(false);
627
628              // replace the existing UL with an empty one - this is faster than $.empty() or innerHTML = ''
629              menuInner.replaceChild(emptyMenu, menuInner.firstChild);
630              menuInner.scrollTop = 0;
631            }
632          });
633        }
634        this.$menu.data('this', this);
635        this.$newElement.data('this', this);
636        if (this.options.mobile) this.mobile();
637
638        this.$newElement.on({
639          'hide.bs.dropdown': function(e) {
640            that.$menuInner.attr('aria-expanded', false);
641            that.$element.trigger('hide.bs.select', e);
642          },
643          'hidden.bs.dropdown': function(e) {
644            that.$element.trigger('hidden.bs.select', e);
645          },
646          'show.bs.dropdown': function(e) {
647            that.$menuInner.attr('aria-expanded', true);
648            that.$element.trigger('show.bs.select', e);
649          },
650          'shown.bs.dropdown': function(e) {
651            that.$element.trigger('shown.bs.select', e);
652          }
653        });
654
655        if (that.$element[0].hasAttribute('required')) {
656          this.$element.on('invalid', function() {
657            that.$button.addClass('bs-invalid');
658
659            that.$element.on({
660              'shown.bs.select': function() {
661                that.$element
662                  .val(that.$element.val()) // set the value to hide the validation message in Chrome when menu is opened
663                  .off('shown.bs.select');
664              },
665              'rendered.bs.select': function() {
666                // if select is no longer invalid, remove the bs-invalid class
667                if (this.validity.valid) that.$button.removeClass('bs-invalid');
668                that.$element.off('rendered.bs.select');
669              }
670            });
671
672            that.$button.on('blur.bs.select', function() {
673              that.$element.focus().blur();
674              that.$button.off('blur.bs.select');
675            });
676          });
677        }
678
679        setTimeout(function() {
680          that.$element.trigger('loaded.bs.select');
681        });
682      },
683
684      createDropdown: function() {
685        // Options
686        // If we are multiple or showTick option is set, then add the show-tick class
687        var showTick = (this.multiple || this.options.showTick) ? ' show-tick' : '',
688          autofocus = this.autofocus ? ' autofocus' : '';
689        // Elements
690        var header = this.options.header ? '<div class="' + classNames.POPOVERHEADER + '"><button type="button" class="close" aria-hidden="true">&times;</button>' + this.options.header + '</div>' : '';
691        var searchbox = this.options.liveSearch ?
692          '<div class="bs-searchbox">' +
693          '<input type="text" class="form-control" autocomplete="off"' +
694          (null === this.options.liveSearchPlaceholder ? '' : ' placeholder="' + htmlEscape(this.options.liveSearchPlaceholder) + '"') + ' role="textbox" aria-label="Search">' +
695          '</div>' :
696          '';
697        var actionsbox = this.multiple && this.options.actionsBox ?
698          '<div class="bs-actionsbox">' +
699          '<div class="btn-group btn-group-sm btn-block">' +
700          '<button type="button" class="actions-btn bs-select-all btn ' + classNames.BUTTONCLASS + '">' +
701          this.options.selectAllText +
702          '</button>' +
703          '<button type="button" class="actions-btn bs-deselect-all btn ' + classNames.BUTTONCLASS + '">' +
704          this.options.deselectAllText +
705          '</button>' +
706          '</div>' +
707          '</div>' :
708          '';
709        var donebutton = this.multiple && this.options.doneButton ?
710          '<div class="bs-donebutton">' +
711          '<div class="btn-group btn-block">' +
712          '<button type="button" class="btn btn-sm ' + classNames.BUTTONCLASS + '">' +
713          this.options.doneButtonText +
714          '</button>' +
715          '</div>' +
716          '</div>' :
717          '';
718        var drop =
719          '<div class="dropdown bootstrap-select' + showTick + '">' +
720          '<button type="button" class="' + this.options.styleBase + ' dropdown-toggle" ' + (this.options.display === 'static' ? 'data-display="static"' : '') + 'data-toggle="dropdown"' + autofocus + ' role="button">' +
721          '<div class="filter-option">' +
722          '<div class="filter-option-inner">' +
723          '<div class="filter-option-inner-inner"></div>' +
724          '</div> ' +
725          '</div>' +
726          (version.major === '4' ?
727            '' :
728            '<span class="bs-caret">' +
729            this.options.template.caret +
730            '</span>'
731          ) +
732          '</button>' +
733          '<div class="' + classNames.MENU + ' ' + (version.major === '4' ? '' : classNames.SHOW) + '" role="combobox">' +
734          header +
735          searchbox +
736          actionsbox +
737          '<div class="inner ' + classNames.SHOW + '" role="listbox" aria-expanded="false" tabindex="-1">' +
738          '<ul class="' + classNames.MENU + ' inner ' + (version.major === '4' ? classNames.SHOW : '') + '">' +
739          '</ul>' +
740          '</div>' +
741          donebutton +
742          '</div>' +
743          '</div>';
744
745        return $(drop);
746      },
747
748      setPositionData: function() {
749        this.selectpicker.view.canHighlight = [];
750
751        for (var i = 0; i < this.selectpicker.current.data.length; i++) {
752          var li = this.selectpicker.current.data[i],
753            canHighlight = true;
754
755          if (li.type === 'divider') {
756            canHighlight = false;
757            li.height = this.sizeInfo.dividerHeight;
758          } else if (li.type === 'optgroup-label') {
759            canHighlight = false;
760            li.height = this.sizeInfo.dropdownHeaderHeight;
761          } else {
762            li.height = this.sizeInfo.liHeight;
763          }
764
765          if (li.disabled) canHighlight = false;
766
767          this.selectpicker.view.canHighlight.push(canHighlight);
768
769          li.position = (i === 0 ? 0 : this.selectpicker.current.data[i - 1].position) + li.height;
770        }
771      },
772
773      isVirtual: function() {
774        return (this.options.virtualScroll !== false) && this.selectpicker.main.elements.length >= this.options.virtualScroll || this.options.virtualScroll === true;
775      },
776
777      createView: function(isSearching, scrollTop) {
778        scrollTop = scrollTop || 0;
779
780        var that = this;
781
782        this.selectpicker.current = isSearching ? this.selectpicker.search : this.selectpicker.main;
783
784        var $lis;
785        var active = [];
786        var selected;
787        var prevActive;
788        var activeIndex;
789        var prevActiveIndex;
790
791        this.setPositionData();
792
793        scroll(scrollTop, true);
794
795        this.$menuInner.off('scroll.createView').on('scroll.createView', function(e, updateValue) {
796          if (!that.noScroll) scroll(this.scrollTop, updateValue);
797          that.noScroll = false;
798        });
799
800        function scroll(scrollTop, init) {
801          var size = that.selectpicker.current.elements.length,
802            chunks = [],
803            chunkSize,
804            chunkCount,
805            firstChunk,
806            lastChunk,
807            currentChunk = undefined,
808            prevPositions,
809            positionIsDifferent,
810            previousElements,
811            menuIsDifferent = true,
812            isVirtual = that.isVirtual();
813
814          that.selectpicker.view.scrollTop = scrollTop;
815
816          if (isVirtual === true) {
817            // if an option that is encountered that is wider than the current menu width, update the menu width accordingly
818            if (that.sizeInfo.hasScrollBar && that.$menu[0].offsetWidth > that.sizeInfo.totalMenuWidth) {
819              that.sizeInfo.menuWidth = that.$menu[0].offsetWidth;
820              that.sizeInfo.totalMenuWidth = that.sizeInfo.menuWidth + that.sizeInfo.scrollBarWidth;
821              that.$menu.css('min-width', that.sizeInfo.menuWidth);
822            }
823          }
824
825          chunkSize = Math.ceil(that.sizeInfo.menuInnerHeight / that.sizeInfo.liHeight * 1.5); // number of options in a chunk
826          chunkCount = Math.round(size / chunkSize) || 1; // number of chunks
827
828          for (var i = 0; i < chunkCount; i++) {
829            var end_of_chunk = (i + 1) * chunkSize;
830
831            if (i === chunkCount - 1) {
832              end_of_chunk = size;
833            }
834
835            chunks[i] = [
836              (i) * chunkSize + (!i ? 0 : 1),
837              end_of_chunk
838            ];
839
840            if (!size) break;
841
842            if (currentChunk === undefined && scrollTop <= that.selectpicker.current.data[end_of_chunk - 1].position - that.sizeInfo.menuInnerHeight) {
843              currentChunk = i;
844            }
845          }
846
847          if (currentChunk === undefined) currentChunk = 0;
848
849          prevPositions = [that.selectpicker.view.position0, that.selectpicker.view.position1];
850
851          // always display previous, current, and next chunks
852          firstChunk = Math.max(0, currentChunk - 1);
853          lastChunk = Math.min(chunkCount - 1, currentChunk + 1);
854
855          that.selectpicker.view.position0 = Math.max(0, chunks[firstChunk][0]) || 0;
856          that.selectpicker.view.position1 = Math.min(size, chunks[lastChunk][1]) || 0;
857
858          positionIsDifferent = prevPositions[0] !== that.selectpicker.view.position0 || prevPositions[1] !== that.selectpicker.view.position1;
859
860          if (that.activeIndex !== undefined) {
861            prevActive = that.selectpicker.current.elements[that.selectpicker.current.map.newIndex[that.prevActiveIndex]];
862            active = that.selectpicker.current.elements[that.selectpicker.current.map.newIndex[that.activeIndex]];
863            selected = that.selectpicker.current.elements[that.selectpicker.current.map.newIndex[that.selectedIndex]];
864
865            if (init) {
866              if (that.activeIndex !== that.selectedIndex) {
867                active.classList.remove('active');
868                if (active.firstChild) active.firstChild.classList.remove('active');
869              }
870              that.activeIndex = undefined;
871            }
872
873            if (that.activeIndex && that.activeIndex !== that.selectedIndex && selected && selected.length) {
874              selected.classList.remove('active');
875              if (selected.firstChild) selected.firstChild.classList.remove('active');
876            }
877          }
878
879          if (that.prevActiveIndex !== undefined && that.prevActiveIndex !== that.activeIndex && that.prevActiveIndex !== that.selectedIndex && prevActive && prevActive.length) {
880            prevActive.classList.remove('active');
881            if (prevActive.firstChild) prevActive.firstChild.classList.remove('active');
882          }
883
884          if (init || positionIsDifferent) {
885            previousElements = that.selectpicker.view.visibleElements ? that.selectpicker.view.visibleElements.slice() : [];
886
887            that.selectpicker.view.visibleElements = that.selectpicker.current.elements.slice(that.selectpicker.view.position0, that.selectpicker.view.position1);
888
889            that.setOptionStatus();
890
891            // if searching, check to make sure the list has actually been updated before updating DOM
892            // this prevents unnecessary repaints
893            if (isSearching || (isVirtual === false && init)) menuIsDifferent = !isEqual(previousElements, that.selectpicker.view.visibleElements);
894
895            // if virtual scroll is disabled and not searching,
896            // menu should never need to be updated more than once
897            if ((init || isVirtual === true) && menuIsDifferent) {
898              var menuInner = that.$menuInner[0],
899                menuFragment = document.createDocumentFragment(),
900                emptyMenu = menuInner.firstChild.cloneNode(false),
901                marginTop,
902                marginBottom,
903                elements = isVirtual === true ? that.selectpicker.view.visibleElements : that.selectpicker.current.elements;
904
905              // replace the existing UL with an empty one - this is faster than $.empty()
906              menuInner.replaceChild(emptyMenu, menuInner.firstChild);
907
908              for (var i = 0, visibleElementsLen = elements.length; i < visibleElementsLen; i++) {
909                menuFragment.appendChild(elements[i]);
910              }
911
912              if (isVirtual === true) {
913                marginTop = (that.selectpicker.view.position0 === 0 ? 0 : that.selectpicker.current.data[that.selectpicker.view.position0 - 1].position),
914                  marginBottom = (that.selectpicker.view.position1 > size - 1 ? 0 : that.selectpicker.current.data[size - 1].position - that.selectpicker.current.data[that.selectpicker.view.position1 - 1].position);
915
916                menuInner.firstChild.style.marginTop = marginTop + 'px';
917                menuInner.firstChild.style.marginBottom = marginBottom + 'px';
918              }
919
920              menuInner.firstChild.appendChild(menuFragment);
921            }
922          }
923
924          that.prevActiveIndex = that.activeIndex;
925
926          if (!that.options.liveSearch) {
927            that.$menuInner.focus();
928          } else if (isSearching && init) {
929            var index = 0,
930              newActive;
931
932            if (!that.selectpicker.view.canHighlight[index]) {
933              index = 1 + that.selectpicker.view.canHighlight.slice(1).indexOf(true);
934            }
935
936            newActive = that.selectpicker.view.visibleElements[index];
937
938            if (that.selectpicker.view.currentActive) {
939              that.selectpicker.view.currentActive.classList.remove('active');
940              if (that.selectpicker.view.currentActive.firstChild) that.selectpicker.view.currentActive.firstChild.classList.remove('active');
941            }
942
943            if (newActive) {
944              newActive.classList.add('active');
945              if (newActive.firstChild) newActive.firstChild.classList.add('active');
946            }
947
948            that.activeIndex = that.selectpicker.current.map.originalIndex[index];
949          }
950        }
951
952        $(window).off('resize.createView').on('resize.createView', function() {
953          scroll(that.$menuInner[0].scrollTop);
954        });
955      },
956
957      createLi: function() {
958        var that = this,
959          mainElements = [],
960          widestOption,
961          availableOptionsCount = 0,
962          widestOptionLength = 0,
963          mainData = [],
964          optID = 0,
965          headerIndex = 0,
966          liIndex = -1; // increment liIndex whenever a new <li> element is created to ensure newIndex is correct
967
968        if (!this.selectpicker.view.titleOption) this.selectpicker.view.titleOption = document.createElement('option');
969
970        var elementTemplates = {
971            span: document.createElement('span'),
972            subtext: document.createElement('small'),
973            a: document.createElement('a'),
974            li: document.createElement('li'),
975            whitespace: document.createTextNode("\u00A0")
976          },
977          checkMark = elementTemplates.span.cloneNode(false),
978          fragment = document.createDocumentFragment();
979
980        checkMark.className = that.options.iconBase + ' ' + that.options.tickIcon + ' check-mark';
981        elementTemplates.a.appendChild(checkMark);
982        elementTemplates.a.setAttribute('role', 'option');
983
984        elementTemplates.subtext.className = 'text-muted';
985
986        elementTemplates.text = elementTemplates.span.cloneNode(false);
987        elementTemplates.text.className = 'text';
988
989        // Helper functions
990        /**
991         * @param content
992         * @param [index]
993         * @param [classes]
994         * @param [optgroup]
995         * @returns {HTMLElement}
996         */
997        var generateLI = function(content, index, classes, optgroup) {
998          var li = elementTemplates.li.cloneNode(false);
999
1000          if (content) {
1001            if (content.nodeType === 1 || content.nodeType === 11) {
1002              li.appendChild(content);
1003            } else {
1004              li.innerHTML = content;
1005            }
1006          }
1007
1008          if (typeof classes !== 'undefined' && '' !== classes) li.className = classes;
1009          if (typeof optgroup !== 'undefined' && null !== optgroup) li.classList.add('optgroup-' + optgroup);
1010
1011          return li;
1012        };
1013
1014        /**
1015         * @param text
1016         * @param [classes]
1017         * @param [inline]
1018         * @returns {string}
1019         */
1020        var generateA = function(text, classes, inline) {
1021          var a = elementTemplates.a.cloneNode(true);
1022
1023          if (text) {
1024            if (text.nodeType === 11) {
1025              a.appendChild(text);
1026            } else {
1027              a.insertAdjacentHTML('beforeend', text);
1028            }
1029          }
1030
1031          if (typeof classes !== 'undefined' & '' !== classes) a.className = classes;
1032          if (version.major === '4') a.classList.add('dropdown-item');
1033          if (inline) a.setAttribute('style', inline);
1034
1035          return a;
1036        };
1037
1038        var generateText = function(options) {
1039          var textElement = elementTemplates.text.cloneNode(false),
1040            optionSubtextElement,
1041            optionIconElement;
1042
1043          if (options.optionContent) {
1044            textElement.innerHTML = options.optionContent;
1045          } else {
1046            textElement.textContent = options.text;
1047
1048            if (options.optionIcon) {
1049              var whitespace = elementTemplates.whitespace.cloneNode(false);
1050
1051              optionIconElement = elementTemplates.span.cloneNode(false);
1052              optionIconElement.className = that.options.iconBase + ' ' + options.optionIcon;
1053
1054              fragment.appendChild(optionIconElement);
1055              fragment.appendChild(whitespace);
1056            }
1057
1058            if (options.optionSubtext) {
1059              optionSubtextElement = elementTemplates.subtext.cloneNode(false);
1060              optionSubtextElement.innerHTML = options.optionSubtext;
1061              textElement.appendChild(optionSubtextElement);
1062            }
1063          }
1064
1065          fragment.appendChild(textElement);
1066
1067          return fragment;
1068        };
1069
1070        var generateLabel = function(options) {
1071          var labelTextElement = elementTemplates.text.cloneNode(false),
1072            labelSubtextElement,
1073            labelIconElement;
1074
1075          labelTextElement.innerHTML = options.labelEscaped;
1076
1077          if (options.labelIcon) {
1078            var whitespace = elementTemplates.whitespace.cloneNode(false);
1079
1080            labelIconElement = elementTemplates.span.cloneNode(false);
1081            labelIconElement.className = that.options.iconBase + ' ' + options.labelIcon;
1082
1083            fragment.appendChild(labelIconElement);
1084            fragment.appendChild(whitespace);
1085          }
1086
1087          if (options.labelSubtext) {
1088            labelSubtextElement = elementTemplates.subtext.cloneNode(false);
1089            labelSubtextElement.textContent = options.labelSubtext;
1090            labelTextElement.appendChild(labelSubtextElement);
1091          }
1092
1093          fragment.appendChild(labelTextElement);
1094
1095          return fragment;
1096        }
1097
1098        if (this.options.title && !this.multiple) {
1099          // this option doesn't create a new <li> element, but does add a new option, so liIndex is decreased
1100          // since newIndex is recalculated on every refresh, liIndex needs to be decreased even if the titleOption is already appended
1101          liIndex--;
1102
1103          var element = this.$element[0],
1104            isSelected = false,
1105            titleNotAppended = !this.selectpicker.view.titleOption.parentNode;
1106
1107          if (titleNotAppended) {
1108            // Use native JS to prepend option (faster)
1109            this.selectpicker.view.titleOption.className = 'bs-title-option';
1110            this.selectpicker.view.titleOption.value = '';
1111
1112            // Check if selected or data-selected attribute is already set on an option. If not, select the titleOption option.
1113            // the selected item may have been changed by user or programmatically before the bootstrap select plugin runs,
1114            // if so, the select will have the data-selected attribute
1115            var $opt = $(element.options[element.selectedIndex]);
1116            isSelected = $opt.attr('selected') === undefined && this.$element.data('selected') === undefined;
1117          }
1118
1119          if (titleNotAppended || this.selectpicker.view.titleOption.index !== 0) {
1120            element.insertBefore(this.selectpicker.view.titleOption, element.firstChild);
1121          }
1122
1123          // Set selected *after* appending to select,
1124          // otherwise the option doesn't get selected in IE
1125          // set using selectedIndex, as setting the selected attr to true here doesn't work in IE11
1126          if (isSelected) element.selectedIndex = 0;
1127        }
1128
1129        var $selectOptions = this.$element.find('option');
1130
1131        $selectOptions.each(function(index) {
1132          var $this = $(this);
1133
1134          liIndex++;
1135
1136          if ($this.hasClass('bs-title-option')) return;
1137
1138          var thisData = $this.data();
1139
1140          // Get the class and text for the option
1141          var optionClass = this.className || '',
1142            inline = htmlEscape(this.style.cssText),
1143            optionContent = thisData.content,
1144            text = this.textContent,
1145            tokens = thisData.tokens,
1146            subtext = thisData.subtext,
1147            icon = thisData.icon,
1148            $parent = $this.parent(),
1149            parent = $parent[0],
1150            isOptgroup = parent.tagName === 'OPTGROUP',
1151            isOptgroupDisabled = isOptgroup && parent.disabled,
1152            isDisabled = this.disabled || isOptgroupDisabled,
1153            prevHiddenIndex,
1154            showDivider = this.previousElementSibling && this.previousElementSibling.tagName === 'OPTGROUP',
1155            textElement;
1156
1157          var parentData = $parent.data();
1158
1159          if (thisData.hidden === true || that.options.hideDisabled && (isDisabled && !isOptgroup || isOptgroupDisabled)) {
1160            // set prevHiddenIndex - the index of the first hidden option in a group of hidden options
1161            // used to determine whether or not a divider should be placed after an optgroup if there are
1162            // hidden options between the optgroup and the first visible option
1163            prevHiddenIndex = thisData.prevHiddenIndex;
1164            $this.next().data('prevHiddenIndex', (prevHiddenIndex !== undefined ? prevHiddenIndex : index));
1165
1166            liIndex--;
1167
1168            // if previous element is not an optgroup
1169            if (!showDivider) {
1170              if (prevHiddenIndex !== undefined) {
1171                // select the element **before** the first hidden element in the group
1172                var prevHidden = $selectOptions[prevHiddenIndex].previousElementSibling;
1173
1174                if (prevHidden && prevHidden.tagName === 'OPTGROUP' && !prevHidden.disabled) {
1175                  showDivider = true;
1176                }
1177              }
1178            }
1179
1180            if (showDivider && mainData[mainData.length - 1].type !== 'divider') {
1181              liIndex++;
1182              mainElements.push(
1183                generateLI(
1184                  false,
1185                  null,
1186                  classNames.DIVIDER,
1187                  optID + 'div'
1188                )
1189              );
1190              mainData.push({
1191                type: 'divider',
1192                optID: optID
1193              });
1194            }
1195
1196            return;
1197          }
1198
1199          if (isOptgroup && thisData.divider !== true) {
1200            if (that.options.hideDisabled && isDisabled) {
1201              if (parentData.allOptionsDisabled === undefined) {
1202                var $options = $parent.children();
1203                $parent.data('allOptionsDisabled', $options.filter(':disabled').length === $options.length);
1204              }
1205
1206              if ($parent.data('allOptionsDisabled')) {
1207                liIndex--;
1208                return;
1209              }
1210            }
1211
1212            var optGroupClass = ' ' + parent.className || '';
1213
1214            if (!this.previousElementSibling) { // Is it the first option of the optgroup?
1215              optID += 1;
1216
1217              // Get the opt group label
1218              var label = parent.label,
1219                labelEscaped = htmlEscape(label),
1220                labelSubtext = parentData.subtext,
1221                labelIcon = parentData.icon;
1222
1223              if (index !== 0 && mainElements.length > 0) { // Is it NOT the first option of the select && are there elements in the dropdown?
1224                liIndex++;
1225                mainElements.push(
1226                  generateLI(
1227                    false,
1228                    null,
1229                    classNames.DIVIDER,
1230                    optID + 'div'
1231                  )
1232                );
1233                mainData.push({
1234                  type: 'divider',
1235                  optID: optID
1236                });
1237              }
1238              liIndex++;
1239
1240              var labelElement = generateLabel({
1241                labelEscaped: labelEscaped,
1242                labelSubtext: labelSubtext,
1243                labelIcon: labelIcon
1244              });
1245
1246              mainElements.push(generateLI(labelElement, null, 'dropdown-header' + optGroupClass, optID));
1247              mainData.push({
1248                content: labelEscaped,
1249                subtext: labelSubtext,
1250                type: 'optgroup-label',
1251                optID: optID
1252              });
1253
1254              headerIndex = liIndex - 1;
1255            }
1256
1257            if (that.options.hideDisabled && isDisabled || thisData.hidden === true) {
1258              liIndex--;
1259              return;
1260            }
1261
1262            textElement = generateText({
1263              text: text,
1264              optionContent: optionContent,
1265              optionSubtext: subtext,
1266              optionIcon: icon
1267            });
1268
1269            mainElements.push(generateLI(generateA(textElement, 'opt ' + optionClass + optGroupClass, inline), index, '', optID));
1270            mainData.push({
1271              content: optionContent || text,
1272              subtext: subtext,
1273              tokens: tokens,
1274              type: 'option',
1275              optID: optID,
1276              headerIndex: headerIndex,
1277              lastIndex: headerIndex + parent.childElementCount,
1278              originalIndex: index,
1279              data: thisData
1280            });
1281
1282            availableOptionsCount++;
1283          } else if (thisData.divider === true) {
1284            mainElements.push(generateLI(false, index, classNames.DIVIDER));
1285            mainData.push({
1286              type: 'divider',
1287              originalIndex: index,
1288              data: thisData
1289            });
1290          } else {
1291            // if previous element is not an optgroup and hideDisabled is true
1292            if (!showDivider && that.options.hideDisabled) {
1293              prevHiddenIndex = thisData.prevHiddenIndex;
1294
1295              if (prevHiddenIndex !== undefined) {
1296                // select the element **before** the first hidden element in the group
1297                var prevHidden = $selectOptions[prevHiddenIndex].previousElementSibling;
1298
1299                if (prevHidden && prevHidden.tagName === 'OPTGROUP' && !prevHidden.disabled) {
1300                  showDivider = true;
1301                }
1302              }
1303            }
1304
1305            if (showDivider && mainData[mainData.length - 1].type !== 'divider') {
1306              liIndex++;
1307              mainElements.push(
1308                generateLI(
1309                  false,
1310                  null,
1311                  classNames.DIVIDER,
1312                  optID + 'div'
1313                )
1314              );
1315              mainData.push({
1316                type: 'divider',
1317                optID: optID
1318              });
1319            }
1320
1321            textElement = generateText({
1322              text: text,
1323              optionContent: optionContent,
1324              optionSubtext: subtext,
1325              optionIcon: icon
1326            });
1327
1328            mainElements.push(generateLI(generateA(textElement, optionClass, inline), index));
1329            mainData.push({
1330              content: optionContent || text,
1331              subtext: subtext,
1332              tokens: tokens,
1333              type: 'option',
1334              originalIndex: index,
1335              data: thisData
1336            });
1337
1338            availableOptionsCount++;
1339          }
1340
1341          that.selectpicker.main.map.newIndex[index] = liIndex;
1342          that.selectpicker.main.map.originalIndex[liIndex] = index;
1343
1344          // get the most recent option info added to mainData
1345          var _mainDataLast = mainData[mainData.length - 1];
1346
1347          _mainDataLast.disabled = isDisabled;
1348
1349          var combinedLength = 0;
1350
1351          // count the number of characters in the option - not perfect, but should work in most cases
1352          if (_mainDataLast.content) combinedLength += _mainDataLast.content.length;
1353          if (_mainDataLast.subtext) combinedLength += _mainDataLast.subtext.length;
1354          // if there is an icon, ensure this option's width is checked
1355          if (icon) combinedLength += 1;
1356
1357          if (combinedLength > widestOptionLength) {
1358            widestOptionLength = combinedLength;
1359
1360            // guess which option is the widest
1361            // use this when calculating menu width
1362            // not perfect, but it's fast, and the width will be updating accordingly when scrolling
1363            widestOption = mainElements[mainElements.length - 1];
1364          }
1365        });
1366
1367        this.selectpicker.main.elements = mainElements;
1368        this.selectpicker.main.data = mainData;
1369
1370        this.selectpicker.current = this.selectpicker.main;
1371
1372        this.selectpicker.view.widestOption = widestOption;
1373        this.selectpicker.view.availableOptionsCount = availableOptionsCount; // faster way to get # of available options without filter
1374      },
1375
1376      findLis: function() {
1377        return this.$menuInner.find('.inner > li');
1378      },
1379
1380      render: function() {
1381        var that = this,
1382          $selectOptions = this.$element.find('option'),
1383          selectedItems = [],
1384          selectedItemsInTitle = [];
1385
1386        this.togglePlaceholder();
1387
1388        this.tabIndex();
1389
1390        for (var i = 0, len = this.selectpicker.main.elements.length; i < len; i++) {
1391          var index = this.selectpicker.main.map.originalIndex[i],
1392            option = $selectOptions[index];
1393
1394          if (option && option.selected) {
1395            selectedItems.push(option);
1396
1397            if (selectedItemsInTitle.length < 100 && that.options.selectedTextFormat !== 'count' || selectedItems.length === 1) {
1398              if (that.options.hideDisabled && (option.disabled || option.parentNode.tagName === 'OPTGROUP' && option.parentNode.disabled)) return;
1399
1400              var thisData = this.selectpicker.main.data[i].data,
1401                icon = thisData.icon && that.options.showIcon ? '<i class="' + that.options.iconBase + ' ' + thisData.icon + '"></i> ' : '',
1402                subtext,
1403                titleItem;
1404
1405              if (that.options.showSubtext && thisData.subtext && !that.multiple) {
1406                subtext = ' <small class="text-muted">' + thisData.subtext + '</small>';
1407              } else {
1408                subtext = '';
1409              }
1410
1411              if (option.title) {
1412                titleItem = option.title;
1413              } else if (thisData.content && that.options.showContent) {
1414                titleItem = thisData.content.toString();
1415              } else {
1416                titleItem = icon + option.innerHTML.trim() + subtext;
1417              }
1418
1419              selectedItemsInTitle.push(titleItem);
1420            }
1421          }
1422        }
1423
1424        //Fixes issue in IE10 occurring when no default option is selected and at least one option is disabled
1425        //Convert all the values into a comma delimited string
1426        var title = !this.multiple ? selectedItemsInTitle[0] : selectedItemsInTitle.join(this.options.multipleSeparator);
1427
1428        // add ellipsis
1429        if (selectedItems.length > 50) title += '...';
1430
1431        // If this is a multiselect, and selectedTextFormat is count, then show 1 of 2 selected etc..
1432        if (this.multiple && this.options.selectedTextFormat.indexOf('count') !== -1) {
1433          var max = this.options.selectedTextFormat.split('>');
1434
1435          if ((max.length > 1 && selectedItems.length > max[1]) || (max.length === 1 && selectedItems.length >= 2)) {
1436            var totalCount = this.selectpicker.view.availableOptionsCount,
1437              tr8nText = (typeof this.options.countSelectedText === 'function') ? this.options.countSelectedText(selectedItems.length, totalCount) : this.options.countSelectedText;
1438
1439            title = tr8nText.replace('{0}', selectedItems.length.toString()).replace('{1}', totalCount.toString());
1440          }
1441        }
1442
1443        if (this.options.title == undefined) {
1444          // use .attr to ensure undefined is returned if title attribute is not set
1445          this.options.title = this.$element.attr('title');
1446        }
1447
1448        if (this.options.selectedTextFormat == 'static') {
1449          title = this.options.title;
1450        }
1451
1452        //If we dont have a title, then use the default, or if nothing is set at all, use the not selected text
1453        if (!title) {
1454          title = typeof this.options.title !== 'undefined' ? this.options.title : this.options.noneSelectedText;
1455        }
1456
1457        //strip all HTML tags and trim the result, then unescape any escaped tags
1458        this.$button[0].title = htmlUnescape(title.replace(/<[^>]*>?/g, '').trim());
1459        this.$button.find('.filter-option-inner-inner')[0].innerHTML = title;
1460
1461        this.$element.trigger('rendered.bs.select');
1462      },
1463
1464      /**
1465       * @param [style]
1466       * @param [status]
1467       */
1468      setStyle: function(style, status) {
1469        if (this.$element.attr('class')) {
1470          this.$newElement.addClass(this.$element.attr('class').replace(/selectpicker|mobile-device|bs-select-hidden|validate\[.*\]/gi, ''));
1471        }
1472
1473        var buttonClass = style ? style : this.options.style;
1474
1475        if (status == 'add') {
1476          this.$button.addClass(buttonClass);
1477        } else if (status == 'remove') {
1478          this.$button.removeClass(buttonClass);
1479        } else {
1480          this.$button.removeClass(this.options.style);
1481          this.$button.addClass(buttonClass);
1482        }
1483      },
1484
1485      liHeight: function(refresh) {
1486        if (!refresh && (this.options.size === false || this.sizeInfo)) return;
1487
1488        if (!this.sizeInfo) this.sizeInfo = {};
1489
1490        var newElement = document.createElement('div'),
1491          menu = document.createElement('div'),
1492          menuInner = document.createElement('div'),
1493          menuInnerInner = document.createElement('ul'),
1494          divider = document.createElement('li'),
1495          dropdownHeader = document.createElement('li'),
1496          li = document.createElement('li'),
1497          a = document.createElement('a'),
1498          text = document.createElement('span'),
1499          header = this.options.header && this.$menu.find('.' + classNames.POPOVERHEADER).length > 0 ? this.$menu.find('.' + classNames.POPOVERHEADER)[0].cloneNode(true) : null,
1500          search = this.options.liveSearch ? document.createElement('div') : null,
1501          actions = this.options.actionsBox && this.multiple && this.$menu.find('.bs-actionsbox').length > 0 ? this.$menu.find('.bs-actionsbox')[0].cloneNode(true) : null,
1502          doneButton = this.options.doneButton && this.multiple && this.$menu.find('.bs-donebutton').length > 0 ? this.$menu.find('.bs-donebutton')[0].cloneNode(true) : null;
1503
1504        this.sizeInfo.selectWidth = this.$newElement[0].offsetWidth;
1505
1506        text.className = 'text';
1507        a.className = 'dropdown-item ' + this.$element.find('option')[0].className;
1508        newElement.className = this.$menu[0].parentNode.className + ' ' + classNames.SHOW;
1509        newElement.style.width = this.sizeInfo.selectWidth + 'px';
1510        if (this.options.width === 'auto') menu.style.minWidth = 0;
1511        menu.className = classNames.MENU + ' ' + classNames.SHOW;
1512        menuInner.className = 'inner ' + classNames.SHOW;
1513        menuInnerInner.className = classNames.MENU + ' inner ' + (version.major === '4' ? classNames.SHOW : '');
1514        divider.className = classNames.DIVIDER;
1515        dropdownHeader.className = 'dropdown-header';
1516
1517        text.appendChild(document.createTextNode('Inner text'));
1518        a.appendChild(text);
1519        li.appendChild(a);
1520        dropdownHeader.appendChild(text.cloneNode(true));
1521
1522        if (this.selectpicker.view.widestOption) {
1523          menuInnerInner.appendChild(this.selectpicker.view.widestOption.cloneNode(true));
1524        }
1525
1526        menuInnerInner.appendChild(li);
1527        menuInnerInner.appendChild(divider);
1528        menuInnerInner.appendChild(dropdownHeader);
1529        if (header) menu.appendChild(header);
1530        if (search) {
1531          var input = document.createElement('input');
1532          search.className = 'bs-searchbox';
1533          input.className = 'form-control';
1534          search.appendChild(input);
1535          menu.appendChild(search);
1536        }
1537        if (actions) menu.appendChild(actions);
1538        menuInner.appendChild(menuInnerInner);
1539        menu.appendChild(menuInner);
1540        if (doneButton) menu.appendChild(doneButton);
1541        newElement.appendChild(menu);
1542
1543        document.body.appendChild(newElement);
1544
1545        var liHeight = a.offsetHeight,
1546          dropdownHeaderHeight = dropdownHeader ? dropdownHeader.offsetHeight : 0,
1547          headerHeight = header ? header.offsetHeight : 0,
1548          searchHeight = search ? search.offsetHeight : 0,
1549          actionsHeight = actions ? actions.offsetHeight : 0,
1550          doneButtonHeight = doneButton ? doneButton.offsetHeight : 0,
1551          dividerHeight = $(divider).outerHeight(true),
1552          // fall back to jQuery if getComputedStyle is not supported
1553          menuStyle = window.getComputedStyle ? window.getComputedStyle(menu) : false,
1554          menuWidth = menu.offsetWidth,
1555          $menu = menuStyle ? null : $(menu),
1556          menuPadding = {
1557            vert: toInteger(menuStyle ? menuStyle.paddingTop : $menu.css('paddingTop')) +
1558              toInteger(menuStyle ? menuStyle.paddingBottom : $menu.css('paddingBottom')) +
1559              toInteger(menuStyle ? menuStyle.borderTopWidth : $menu.css('borderTopWidth')) +
1560              toInteger(menuStyle ? menuStyle.borderBottomWidth : $menu.css('borderBottomWidth')),
1561            horiz: toInteger(menuStyle ? menuStyle.paddingLeft : $menu.css('paddingLeft')) +
1562              toInteger(menuStyle ? menuStyle.paddingRight : $menu.css('paddingRight')) +
1563              toInteger(menuStyle ? menuStyle.borderLeftWidth : $menu.css('borderLeftWidth')) +
1564              toInteger(menuStyle ? menuStyle.borderRightWidth : $menu.css('borderRightWidth'))
1565          },
1566          menuExtras = {
1567            vert: menuPadding.vert +
1568              toInteger(menuStyle ? menuStyle.marginTop : $menu.css('marginTop')) +
1569              toInteger(menuStyle ? menuStyle.marginBottom : $menu.css('marginBottom')) + 2,
1570            horiz: menuPadding.horiz +
1571              toInteger(menuStyle ? menuStyle.marginLeft : $menu.css('marginLeft')) +
1572              toInteger(menuStyle ? menuStyle.marginRight : $menu.css('marginRight')) + 2
1573          },
1574          scrollBarWidth;
1575
1576        menuInner.style.overflowY = 'scroll';
1577
1578        scrollBarWidth = menu.offsetWidth - menuWidth;
1579
1580        document.body.removeChild(newElement);
1581
1582        this.sizeInfo.liHeight = liHeight;
1583        this.sizeInfo.dropdownHeaderHeight = dropdownHeaderHeight;
1584        this.sizeInfo.headerHeight = headerHeight;
1585        this.sizeInfo.searchHeight = searchHeight;
1586        this.sizeInfo.actionsHeight = actionsHeight;
1587        this.sizeInfo.doneButtonHeight = doneButtonHeight;
vendor: 6,118 bytes, lines 1588-1723
1588        this.sizeInfo.dividerHeight = dividerHeight;
1589        this.sizeInfo.menuPadding = menuPadding;
1590        this.sizeInfo.menuExtras = menuExtras;
1591        this.sizeInfo.menuWidth = menuWidth;
1592        this.sizeInfo.totalMenuWidth = this.sizeInfo.menuWidth;
1593        this.sizeInfo.scrollBarWidth = scrollBarWidth;
1594        this.sizeInfo.selectHeight = this.$newElement[0].offsetHeight;
1595
1596        this.setPositionData();
1597      },
1598
1599      getSelectPosition: function() {
1600        var that = this,
1601          $window = $(window),
1602          pos = that.$newElement.offset(),
1603          $container = $(that.options.container),
1604          containerPos;
1605
1606        if (that.options.container && !$container.is('body')) {
1607          containerPos = $container.offset();
1608          containerPos.top += parseInt($container.css('borderTopWidth'));
1609          containerPos.left += parseInt($container.css('borderLeftWidth'));
1610        } else {
1611          containerPos = {
1612            top: 0,
1613            left: 0
1614          };
1615        }
1616
1617        var winPad = that.options.windowPadding;
1618
1619        this.sizeInfo.selectOffsetTop = pos.top - containerPos.top - $window.scrollTop();
1620        this.sizeInfo.selectOffsetBot = $window.height() - this.sizeInfo.selectOffsetTop - this.sizeInfo['selectHeight'] - containerPos.top - winPad[2];
1621        this.sizeInfo.selectOffsetLeft = pos.left - containerPos.left - $window.scrollLeft();
1622        this.sizeInfo.selectOffsetRight = $window.width() - this.sizeInfo.selectOffsetLeft - this.sizeInfo['selectWidth'] - containerPos.left - winPad[1];
1623        this.sizeInfo.selectOffsetTop -= winPad[0];
1624        this.sizeInfo.selectOffsetLeft -= winPad[3];
1625      },
1626
1627      setMenuSize: function(isAuto) {
1628        this.getSelectPosition();
1629
1630        var selectWidth = this.sizeInfo['selectWidth'],
1631          liHeight = this.sizeInfo['liHeight'],
1632          headerHeight = this.sizeInfo['headerHeight'],
1633          searchHeight = this.sizeInfo['searchHeight'],
1634          actionsHeight = this.sizeInfo['actionsHeight'],
1635          doneButtonHeight = this.sizeInfo['doneButtonHeight'],
1636          divHeight = this.sizeInfo['dividerHeight'],
1637          menuPadding = this.sizeInfo['menuPadding'],
1638          menuInnerHeight,
1639          menuHeight,
1640          divLength = 0,
1641          minHeight,
1642          _minHeight,
1643          maxHeight,
1644          menuInnerMinHeight,
1645          estimate;
1646
1647        if (this.options.dropupAuto) {
1648          // Get the estimated height of the menu without scrollbars.
1649          // This is useful for smaller menus, where there might be plenty of room
1650          // below the button without setting dropup, but we can't know
1651          // the exact height of the menu until createView is called later
1652          estimate = liHeight * this.selectpicker.current.elements.length + menuPadding.vert;
1653          this.$newElement.toggleClass(classNames.DROPUP, this.sizeInfo.selectOffsetTop - this.sizeInfo.selectOffsetBot > this.sizeInfo.menuExtras.vert && estimate + this.sizeInfo.menuExtras.vert + 50 > this.sizeInfo.selectOffsetBot);
1654        }
1655
1656        if (this.options.size === 'auto') {
1657          _minHeight = this.selectpicker.current.elements.length > 3 ? this.sizeInfo.liHeight * 3 + this.sizeInfo.menuExtras.vert - 2 : 0;
1658          menuHeight = this.sizeInfo.selectOffsetBot - this.sizeInfo.menuExtras.vert;
1659          minHeight = _minHeight + headerHeight + searchHeight + actionsHeight + doneButtonHeight;
1660          menuInnerMinHeight = Math.max(_minHeight - menuPadding.vert, 0);
1661
1662          if (this.$newElement.hasClass(classNames.DROPUP)) {
1663            menuHeight = this.sizeInfo.selectOffsetTop - this.sizeInfo.menuExtras.vert;
1664          }
1665
1666          maxHeight = menuHeight;
1667          menuInnerHeight = menuHeight - headerHeight - searchHeight - actionsHeight - doneButtonHeight - menuPadding.vert;
1668        } else if (this.options.size && this.options.size != 'auto' && this.selectpicker.current.elements.length > this.options.size) {
1669          for (var i = 0; i < this.options.size; i++) {
1670            if (this.selectpicker.current.data[i].type === 'divider') divLength++;
1671          }
1672
1673          menuHeight = liHeight * this.options.size + divLength * divHeight + menuPadding.vert;
1674          menuInnerHeight = menuHeight - menuPadding.vert;
1675          maxHeight = menuHeight + headerHeight + searchHeight + actionsHeight + doneButtonHeight;
1676          minHeight = menuInnerMinHeight = '';
1677        }
1678
1679        if (this.options.dropdownAlignRight === 'auto') {
1680          this.$menu.toggleClass(classNames.MENURIGHT, this.sizeInfo.selectOffsetLeft > this.sizeInfo.selectOffsetRight && this.sizeInfo.selectOffsetRight < (this.$menu[0].offsetWidth - selectWidth));
1681        }
1682
1683        this.$menu.css({
1684          'max-height': maxHeight + 'px',
1685          'overflow': 'hidden',
1686          'min-height': minHeight + 'px'
1687        });
1688
1689        this.$menuInner.css({
1690          'max-height': menuInnerHeight + 'px',
1691          'overflow-y': 'auto',
1692          'min-height': menuInnerMinHeight + 'px'
1693        });
1694
1695        this.sizeInfo['menuInnerHeight'] = menuInnerHeight;
1696
1697        if (this.selectpicker.current.data.length && this.selectpicker.current.data[this.selectpicker.current.data.length - 1].position > this.sizeInfo.menuInnerHeight) {
1698          this.sizeInfo.hasScrollBar = true;
1699          this.sizeInfo.totalMenuWidth = this.sizeInfo.menuWidth + this.sizeInfo.scrollBarWidth;
1700
1701          this.$menu.css('min-width', this.sizeInfo.totalMenuWidth);
1702        }
1703
1704        if (this.dropdown && this.dropdown._popper) this.dropdown._popper.update();
1705      },
1706
1707      setSize: function(refresh) {
1708        this.liHeight(refresh);
1709
1710        if (this.options.header) this.$menu.css('padding-top', 0);
1711        if (this.options.size === false) return;
1712
1713        var that = this,
1714          $window = $(window),
1715          selectedIndex,
1716          offset = 0;
1717
1718        this.setMenuSize();
1719
1720        if (this.options.size === 'auto') {
1721          this.$searchbox.off('input.setMenuSize propertychange.setMenuSize').on('input.setMenuSize propertychange.setMenuSize', function() {
1722            return that.setMenuSize();
1723          });
1724          $window.off('resize.setMenuSize scroll.setMenuSize').on('resize.setMenuSize scroll.setMenuSize', function() {
1725            return that.setMenuSize();
1726          });
1727        } else if (this.options.size && this.options.size != 'auto' && this.selectpicker.current.elements.length > this.options.size) {
1728          this.$searchbox.off('input.setMenuSize propertychange.setMenuSize');
1729          $window.off('resize.setMenuSize scroll.setMenuSize');
1730        }
1731
1732        if (refresh) {
1733          offset = this.$menuInner[0].scrollTop;
1734        } else if (!that.multiple) {
1735          selectedIndex = that.selectpicker.main.map.newIndex[that.$element[0].selectedIndex];
1736
1737          if (typeof selectedIndex === 'number' && that.options.size !== false) {
1738            offset = that.sizeInfo.liHeight * selectedIndex;
1739            offset = offset - (that.sizeInfo.menuInnerHeight / 2) + (that.sizeInfo.liHeight / 2);
1740          }
1741        }
1742
1743        that.createView(false, offset);
1744      },
1745
1746      setWidth: function() {
1747        var that = this;
1748
1749        if (this.options.width === 'auto') {
1750          requestAnimationFrame(function() {
1751            that.$menu.css('min-width', '0');
1752            that.liHeight();
1753            that.setMenuSize();
1754
1755            // Get correct width if element is hidden
1756            var $selectClone = that.$newElement.clone().appendTo('body'),
1757              btnWidth = $selectClone.css('width', 'auto').children('button').outerWidth();
1758
1759            $selectClone.remove();
1760
1761            // Set width to whatever's larger, button title or longest option
1762            that.sizeInfo.selectWidth = Math.max(that.sizeInfo.totalMenuWidth, btnWidth);
1763            that.$newElement.css('width', that.sizeInfo.selectWidth + 'px');
1764          });
1765        } else if (this.options.width === 'fit') {
1766          // Remove inline min-width so width can be changed from 'auto'
1767          this.$menu.css('min-width', '');
1768          this.$newElement.css('width', '').addClass('fit-width');
1769        } else if (this.options.width) {
1770          // Remove inline min-width so width can be changed from 'auto'
1771          this.$menu.css('min-width', '');
1772          this.$newElement.css('width', this.options.width);
1773        } else {
1774          // Remove inline min-width/width so width can be changed
1775          this.$menu.css('min-width', '');
1776          this.$newElement.css('width', '');
1777        }
1778        // Remove fit-width class if width is changed programmatically
1779        if (this.$newElement.hasClass('fit-width') && this.options.width !== 'fit') {
1780          this.$newElement.removeClass('fit-width');
1781        }
1782      },
1783
1784      selectPosition: function() {
1785        this.$bsContainer = $('<div class="bs-container" />');
1786
1787        var that = this,
1788          $container = $(this.options.container),
1789          pos,
1790          containerPos,
1791          actualHeight,
1792          getPlacement = function($element) {
1793            var containerPosition = {},
1794              // fall back to dropdown's default display setting if display is not manually set
1795              display = that.options.display || $.fn.dropdown.Constructor.Default.display;
1796
1797            that.$bsContainer.addClass($element.attr('class').replace(/form-control|fit-width/gi, '')).toggleClass(classNames.DROPUP, $element.hasClass(classNames.DROPUP));
1798            pos = $element.offset();
1799
1800            if (!$container.is('body')) {
1801              containerPos = $container.offset();
1802              containerPos.top += parseInt($container.css('borderTopWidth')) - $container.scrollTop();
1803              containerPos.left += parseInt($container.css('borderLeftWidth')) - $container.scrollLeft();
1804            } else {
1805              containerPos = {
1806                top: 0,
1807                left: 0
1808              };
1809            }
1810
1811            actualHeight = $element.hasClass(classNames.DROPUP) ? 0 : $element[0].offsetHeight;
1812
1813            // Bootstrap 4+ uses Popper for menu positioning
1814            if (version.major < 4 || display === 'static') {
1815              containerPosition['top'] = pos.top - containerPos.top + actualHeight;
1816              containerPosition['left'] = pos.left - containerPos.left;
1817            }
1818
1819            containerPosition['width'] = $element[0].offsetWidth;
1820
1821            that.$bsContainer.css(containerPosition);
1822          };
1823
1824        this.$button.on('click.bs.dropdown.data-api', function() {
1825          if (that.isDisabled()) {
1826            return;
1827          }
1828
1829          getPlacement(that.$newElement);
1830
1831          that.$bsContainer
1832            .appendTo(that.options.container)
1833            .toggleClass(classNames.SHOW, !that.$button.hasClass(classNames.SHOW))
1834            .append(that.$menu);
1835        });
1836
1837        $(window).on('resize scroll', function() {
1838          getPlacement(that.$newElement);
1839        });
1840
1841        this.$element.on('hide.bs.select', function() {
1842          that.$menu.data('height', that.$menu.height());
1843          that.$bsContainer.detach();
1844        });
1845      },
1846
1847      setOptionStatus: function() {
1848        var that = this,
1849          $selectOptions = this.$element.find('option');
1850
1851        that.noScroll = false;
1852
1853        if (that.selectpicker.view.visibleElements && that.selectpicker.view.visibleElements.length) {
1854          for (var i = 0; i < that.selectpicker.view.visibleElements.length; i++) {
1855            var index = that.selectpicker.current.map.originalIndex[i + that.selectpicker.view.position0], // faster than $(li).data('originalIndex')
1856              option = $selectOptions[index];
1857
1858            if (option) {
1859              var liIndex = this.selectpicker.main.map.newIndex[index],
1860                li = this.selectpicker.main.elements[liIndex];
1861
1862              that.setDisabled(
1863                index,
1864                option.disabled || option.parentNode.tagName === 'OPTGROUP' && option.parentNode.disabled,
1865                liIndex,
1866                li
1867              );
1868
1869              that.setSelected(
1870                index,
1871                option.selected,
1872                liIndex,
1873                li
1874              );
1875            }
1876          }
1877        }
1878      },
1879
1880      /**
1881       * @param {number} index - the index of the option that is being changed
1882       * @param {boolean} selected - true if the option is being selected, false if being deselected
1883       */
1884      setSelected: function(index, selected, liIndex, li) {
1885        var activeIndexIsSet = this.activeIndex !== undefined,
1886          thisIsActive = this.activeIndex === index,
1887          prevActiveIndex,
1888          prevActive,
1889          a,
1890          // if current option is already active
1891          // OR
1892          // if the current option is being selected, it's NOT multiple, and
1893          // activeIndex is undefined:
1894          //  - when the menu is first being opened, OR
1895          //  - after a search has been performed, OR
1896          //  - when retainActive is false when selecting a new option (i.e. index of the newly selected option is not the same as the current activeIndex)
1897          keepActive = thisIsActive || selected && !this.multiple && !activeIndexIsSet;
1898
1899        if (!liIndex) liIndex = this.selectpicker.main.map.newIndex[index];
1900        if (!li) li = this.selectpicker.main.elements[liIndex];
1901
1902        a = li.firstChild;
1903
1904        if (selected) {
1905          this.selectedIndex = index;
1906        }
1907
1908        li.classList.toggle('selected', selected);
1909        li.classList.toggle('active', keepActive);
1910
1911        if (keepActive) {
1912          this.selectpicker.view.currentActive = li;
1913          this.activeIndex = index;
1914        }
1915
1916        if (a) {
1917          a.classList.toggle('selected', selected);
1918          a.classList.toggle('active', keepActive);
1919          a.setAttribute('aria-selected', selected);
1920        }
1921
1922        if (!keepActive) {
1923          if (!activeIndexIsSet && selected && this.prevActiveIndex !== undefined) {
1924            prevActiveIndex = this.selectpicker.main.map.newIndex[this.prevActiveIndex];
1925            prevActive = this.selectpicker.main.elements[prevActiveIndex];
1926
1927            prevActive.classList.toggle('selected', selected);
1928            prevActive.classList.remove('active');
1929            if (prevActive.firstChild) {
1930              prevActive.firstChild.classList.toggle('selected', selected);
1931              prevActive.firstChild.classList.remove('active');
1932            }
1933          }
1934        }
1935      },
1936
1937      /**
1938       * @param {number} index - the index of the option that is being disabled
1939       * @param {boolean} disabled - true if the option is being disabled, false if being enabled
1940       */
1941      setDisabled: function(index, disabled, liIndex, li) {
1942        var a;
1943
1944        if (!liIndex) liIndex = this.selectpicker.main.map.newIndex[index];
1945        if (!li) li = this.selectpicker.main.elements[liIndex];
1946
1947        a = li.firstChild;
1948
1949        li.classList.toggle(classNames.DISABLED, disabled);
1950
1951        if (a) {
1952          if (version.major === '4') a.classList.toggle(classNames.DISABLED, disabled);
1953
1954          a.setAttribute('aria-disabled', disabled);
1955
1956          if (disabled) {
1957            a.setAttribute('tabindex', -1);
1958          } else {
1959            a.setAttribute('tabindex', 0);
1960          }
1961        }
1962      },
1963
1964      isDisabled: function() {
1965        return this.$element[0].disabled;
1966      },
1967
1968      checkDisabled: function() {
1969        var that = this;
1970
1971        if (this.isDisabled()) {
1972          this.$newElement.addClass(classNames.DISABLED);
1973          this.$button.addClass(classNames.DISABLED).attr('tabindex', -1).attr('aria-disabled', true);
1974        } else {
1975          if (this.$button.hasClass(classNames.DISABLED)) {
1976            this.$newElement.removeClass(classNames.DISABLED);
1977            this.$button.removeClass(classNames.DISABLED).attr('aria-disabled', false);
1978          }
1979
1980          if (this.$button.attr('tabindex') == -1 && !this.$element.data('tabindex')) {
1981            this.$button.removeAttr('tabindex');
1982          }
1983        }
1984
1985        this.$button.click(function() {
1986          return !that.isDisabled();
1987        });
1988      },
1989
1990      togglePlaceholder: function() {
1991        // much faster than calling $.val()
1992        var element = this.$element[0],
1993          selectedIndex = element.selectedIndex,
1994          nothingSelected = selectedIndex === -1;
1995
1996        if (!nothingSelected && !element.options[selectedIndex].value) nothingSelected = true;
1997
1998        this.$button.toggleClass('bs-placeholder', nothingSelected);
1999      },
2000
2001      tabIndex: function() {
2002        if (this.$element.data('tabindex') !== this.$element.attr('tabindex') &&
2003          (this.$element.attr('tabindex') !== -98 && this.$element.attr('tabindex') !== '-98')) {
2004          this.$element.data('tabindex', this.$element.attr('tabindex'));
2005          this.$button.attr('tabindex', this.$element.data('tabindex'));
2006        }
2007
2008        this.$element.attr('tabindex', -98);
2009      },
2010
2011      clickListener: function() {
2012        var that = this,
2013          $document = $(document);
2014
2015        $document.data('spaceSelect', false);
2016
2017        this.$button.on('keyup', function(e) {
2018          if (/(32)/.test(e.keyCode.toString(10)) && $document.data('spaceSelect')) {
2019            e.preventDefault();
2020            $document.data('spaceSelect', false);
2021          }
2022        });
2023
2024        this.$newElement.on('show.bs.dropdown', function() {
2025          if (version.major > 3 && !that.dropdown) {
2026            that.dropdown = that.$button.data('bs.dropdown');
2027            that.dropdown._menu = that.$menu[0];
2028          }
2029        });
2030
2031        this.$button.on('click.bs.dropdown.data-api', function() {
2032          if (!that.$newElement.hasClass(classNames.SHOW)) {
2033            that.setSize();
2034          }
2035        });
2036
2037        function setFocus() {
2038          if (that.options.liveSearch) {
2039            that.$searchbox.focus();
2040          } else {
2041            that.$menuInner.focus();
2042          }
2043        }
2044
2045        function checkPopperExists() {
2046          if (that.dropdown && that.dropdown._popper && that.dropdown._popper.state.isCreated) {
2047            setFocus();
2048          } else {
2049            requestAnimationFrame(checkPopperExists);
2050          }
2051        }
2052
2053        this.$element.on('shown.bs.select', function() {
2054          if (that.$menuInner[0].scrollTop !== that.selectpicker.view.scrollTop) {
2055            that.$menuInner[0].scrollTop = that.selectpicker.view.scrollTop;
2056          }
2057
2058          if (version.major > 3) {
2059            requestAnimationFrame(checkPopperExists);
2060          } else {
2061            setFocus();
2062          }
2063        });
2064
2065        this.$menuInner.on('click', 'li a', function(e, retainActive) {
2066          var $this = $(this),
2067            position0 = that.isVirtual() ? that.selectpicker.view.position0 : 0,
2068            clickedIndex = that.selectpicker.current.map.originalIndex[$this.parent().index() + position0],
2069            prevValue = getSelectValues(that.$element[0]),
2070            prevIndex = that.$element.prop('selectedIndex'),
2071            triggerChange = true;
2072
2073          // Don't close on multi choice menu
2074          if (that.multiple && that.options.maxOptions !== 1) {
2075            e.stopPropagation();
2076          }
2077
2078          e.preventDefault();
2079
2080          //Don't run if we have been disabled
2081          if (!that.isDisabled() && !$this.parent().hasClass(classNames.DISABLED)) {
2082            var $options = that.$element.find('option'),
2083              $option = $options.eq(clickedIndex),
2084              state = $option.prop('selected'),
2085              $optgroup = $option.parent('optgroup'),
2086              $optgroupOptions = $optgroup.find('option'),
2087              maxOptions = that.options.maxOptions,
2088              maxOptionsGrp = $optgroup.data('maxOptions') || false;
2089
2090            if (clickedIndex === that.activeIndex) retainActive = true;
2091
2092            if (!retainActive) {
2093              that.prevActiveIndex = that.activeIndex;
2094              that.activeIndex = undefined;
2095            }
2096
2097            if (!that.multiple) { // Deselect all others if not multi select box
2098              $options.prop('selected', false);
2099              $option.prop('selected', true);
2100              that.setSelected(clickedIndex, true);
2101            } else { // Toggle the one we have chosen if we are multi select.
2102              $option.prop('selected', !state);
2103
2104              that.setSelected(clickedIndex, !state);
2105              $this.blur();
2106
2107              if (maxOptions !== false || maxOptionsGrp !== false) {
2108                var maxReached = maxOptions < $options.filter(':selected').length,
2109                  maxReachedGrp = maxOptionsGrp < $optgroup.find('option:selected').length;
2110
2111                if ((maxOptions && maxReached) || (maxOptionsGrp && maxReachedGrp)) {
2112                  if (maxOptions && maxOptions == 1) {
2113                    $options.prop('selected', false);
2114                    $option.prop('selected', true);
2115
2116                    for (var i = 0; i < $options.length; i++) {
2117                      that.setSelected(i, false);
2118                    }
2119
2120                    that.setSelected(clickedIndex, true);
2121                  } else if (maxOptionsGrp && maxOptionsGrp == 1) {
2122                    $optgroup.find('option:selected').prop('selected', false);
2123                    $option.prop('selected', true);
2124
2125                    for (var i = 0; i < $optgroupOptions.length; i++) {
2126                      var option = $optgroupOptions[i];
2127                      that.setSelected($options.index(option), false);
2128                    }
2129
2130                    that.setSelected(clickedIndex, true);
2131                  } else {
2132                    var maxOptionsText = typeof that.options.maxOptionsText === 'string' ? [that.options.maxOptionsText, that.options.maxOptionsText] : that.options.maxOptionsText,
2133                      maxOptionsArr = typeof maxOptionsText === 'function' ? maxOptionsText(maxOptions, maxOptionsGrp) : maxOptionsText,
2134                      maxTxt = maxOptionsArr[0].replace('{n}', maxOptions),
2135                      maxTxtGrp = maxOptionsArr[1].replace('{n}', maxOptionsGrp),
2136                      $notify = $('<div class="notify"></div>');
2137                    // If {var} is set in array, replace it
2138                    /** @deprecated */
2139                    if (maxOptionsArr[2]) {
2140                      maxTxt = maxTxt.replace('{var}', maxOptionsArr[2][maxOptions > 1 ? 0 : 1]);
2141                      maxTxtGrp = maxTxtGrp.replace('{var}', maxOptionsArr[2][maxOptionsGrp > 1 ? 0 : 1]);
2142                    }
2143
2144                    $option.prop('selected', false);
2145
2146                    that.$menu.append($notify);
2147
2148                    if (maxOptions && maxReached) {
2149                      $notify.append($('<div>' + maxTxt + '</div>'));
2150                      triggerChange = false;
2151                      that.$element.trigger('maxReached.bs.select');
2152                    }
2153
2154                    if (maxOptionsGrp && maxReachedGrp) {
2155                      $notify.append($('<div>' + maxTxtGrp + '</div>'));
2156                      triggerChange = false;
2157                      that.$element.trigger('maxReachedGrp.bs.select');
2158                    }
2159
2160                    setTimeout(function() {
2161                      that.setSelected(clickedIndex, false);
2162                    }, 10);
2163
2164                    $notify.delay(750).fadeOut(300, function() {
2165                      $(this).remove();
2166                    });
2167                  }
2168                }
2169              }
2170            }
2171
2172            if (!that.multiple || (that.multiple && that.options.maxOptions === 1)) {
2173              that.$button.focus();
2174            } else if (that.options.liveSearch) {
2175              that.$searchbox.focus();
2176            }
2177
2178            // Trigger select 'change'
2179            if (triggerChange) {
2180              if ((prevValue != getSelectValues(that.$element[0]) && that.multiple) || (prevIndex != that.$element.prop('selectedIndex') && !that.multiple)) {
2181                // $option.prop('selected') is current option state (selected/unselected). prevValue is the value of the select prior to being changed.
2182                changed_arguments = [clickedIndex, $option.prop('selected'), prevValue];
2183                that.$element
2184                  .triggerNative('change');
2185              }
2186            }
2187          }
2188        });
2189
2190        this.$menu.on('click', 'li.' + classNames.DISABLED + ' a, .' + classNames.POPOVERHEADER + ', .' + classNames.POPOVERHEADER + ' :not(.close)', function(e) {
2191          if (e.currentTarget == this) {
2192            e.preventDefault();
2193            e.stopPropagation();
2194            if (that.options.liveSearch && !$(e.target).hasClass('close')) {
2195              that.$searchbox.focus();
2196            } else {
2197              that.$button.focus();
2198            }
2199          }
2200        });
2201
2202        this.$menuInner.on('click', '.divider, .dropdown-header', function(e) {
2203          e.preventDefault();
2204          e.stopPropagation();
2205          if (that.options.liveSearch) {
2206            that.$searchbox.focus();
2207          } else {
2208            that.$button.focus();
2209          }
2210        });
2211
2212        this.$menu.on('click', '.' + classNames.POPOVERHEADER + ' .close', function() {
2213          that.$button.click();
2214        });
2215
2216        this.$searchbox.on('click', function(e) {
2217          e.stopPropagation();
2218        });
2219
2220        this.$menu.on('click', '.actions-btn', function(e) {
2221          if (that.options.liveSearch) {
2222            that.$searchbox.focus();
2223          } else {
2224            that.$button.focus();
2225          }
2226
2227          e.preventDefault();
2228          e.stopPropagation();
2229
2230          if ($(this).hasClass('bs-select-all')) {
2231            that.selectAll();
2232          } else {
2233            that.deselectAll();
2234          }
2235        });
2236
2237        this.$element.on({
2238          'change': function() {
2239            that.render();
2240            that.$element.trigger('changed.bs.select', changed_arguments);
2241            changed_arguments = null;
2242          },
2243          'focus': function() {
2244            that.$button.focus();
2245          }
2246        });
2247      },
2248
2249      liveSearchListener: function() {
2250        var that = this,
2251          no_results = document.createElement('li');
2252
2253        this.$button.on('click.bs.dropdown.data-api', function() {
2254          if (!!that.$searchbox.val()) {
2255            that.$searchbox.val('');
2256          }
2257        });
2258
2259        this.$searchbox.on('click.bs.dropdown.data-api focus.bs.dropdown.data-api touchend.bs.dropdown.data-api', function(e) {
2260          e.stopPropagation();
2261        });
2262
2263        this.$searchbox.on('input propertychange', function() {
2264          var searchValue = that.$searchbox.val();
2265
2266          that.selectpicker.search.map.newIndex = {};
2267          that.selectpicker.search.map.originalIndex = {};
2268          that.selectpicker.search.elements = [];
2269          that.selectpicker.search.data = [];
2270
2271          if (searchValue) {
2272            var i,
2273              searchMatch = [],
2274              q = searchValue.toUpperCase(),
2275              cache = {},
2276              cacheArr = [],
2277              searchStyle = that._searchStyle(),
2278              normalizeSearch = that.options.liveSearchNormalize;
2279
2280            that._$lisSelected = that.$menuInner.find('.selected');
2281
2282            for (var i = 0; i < that.selectpicker.main.data.length; i++) {
2283              var li = that.selectpicker.main.data[i];
2284
2285              if (!cache[i]) {
2286                cache[i] = stringSearch(li, q, searchStyle, normalizeSearch);
2287              }
2288
2289              if (cache[i] && li.headerIndex !== undefined && cacheArr.indexOf(li.headerIndex) === -1) {
2290                if (li.headerIndex > 0) {
2291                  cache[li.headerIndex - 1] = true;
2292                  cacheArr.push(li.headerIndex - 1);
2293                }
2294
2295                cache[li.headerIndex] = true;
2296                cacheArr.push(li.headerIndex);
2297
2298                cache[li.lastIndex + 1] = true;
2299              }
2300
2301              if (cache[i] && li.type !== 'optgroup-label') cacheArr.push(i);
2302            }
2303
2304            for (var i = 0, cacheLen = cacheArr.length; i < cacheLen; i++) {
2305              var index = cacheArr[i],
2306                prevIndex = cacheArr[i - 1],
2307                li = that.selectpicker.main.data[index],
2308                liPrev = that.selectpicker.main.data[prevIndex];
2309
2310              if (li.type !== 'divider' || (li.type === 'divider' && liPrev && liPrev.type !== 'divider' && cacheLen - 1 !== i)) {
2311                that.selectpicker.search.data.push(li);
2312                searchMatch.push(that.selectpicker.main.elements[index]);
2313
2314                if (li.hasOwnProperty('originalIndex')) {
2315                  that.selectpicker.search.map.newIndex[li.originalIndex] = searchMatch.length - 1;
2316                  that.selectpicker.search.map.originalIndex[searchMatch.length - 1] = li.originalIndex;
2317                }
2318              }
2319            }
2320
2321            that.activeIndex = undefined;
2322            that.noScroll = true;
2323            that.$menuInner.scrollTop(0);
2324            that.selectpicker.search.elements = searchMatch;
2325            that.createView(true);
2326
2327            if (!searchMatch.length) {
2328              no_results.className = 'no-results';
2329              no_results.innerHTML = that.options.noneResultsText.replace('{0}', '"' + htmlEscape(searchValue) + '"');
2330              that.$menuInner[0].firstChild.appendChild(no_results);
2331            }
2332          } else {
2333            that.$menuInner.scrollTop(0);
2334            that.createView(false);
2335          }
2336        });
2337      },
2338
2339      _searchStyle: function() {
2340        return this.options.liveSearchStyle || 'contains';
2341      },
2342
2343      val: function(value) {
2344        if (typeof value !== 'undefined') {
2345          this.$element
2346            .val(value)
2347            .triggerNative('change');
2348
2349          return this.$element;
2350        } else {
2351          return this.$element.val();
2352        }
2353      },
2354
2355      changeAll: function(status) {
2356        if (!this.multiple) return;
2357        if (typeof status === 'undefined') status = true;
2358
2359        var $selectOptions = this.$element.find('option'),
2360          previousSelected = 0,
2361          currentSelected = 0,
2362          prevValue = getSelectValues(this.$element[0]);
2363
2364        this.$element.addClass('bs-select-hidden');
2365
2366        for (var i = 0; i < this.selectpicker.current.elements.length; i++) {
2367          var liData = this.selectpicker.current.data[i],
2368            index = this.selectpicker.current.map.originalIndex[i], // faster than $(li).data('originalIndex')
2369            option = $selectOptions[index];
2370
2371          if (option && !option.disabled && liData.type !== 'divider') {
2372            if (option.selected) previousSelected++;
2373            option.selected = status;
2374            if (option.selected) currentSelected++;
2375          }
2376        }
2377
2378        this.$element.removeClass('bs-select-hidden');
2379
2380        if (previousSelected === currentSelected) return;
2381
2382        this.setOptionStatus();
2383
2384        this.togglePlaceholder();
2385
2386        changed_arguments = [null, null, prevValue];
2387
2388        this.$element
2389          .triggerNative('change');
2390      },
2391
2392      selectAll: function() {
2393        return this.changeAll(true);
2394      },
2395
2396      deselectAll: function() {
2397        return this.changeAll(false);
2398      },
2399
2400      toggle: function(e) {
2401        e = e || window.event;
2402
2403        if (e) e.stopPropagation();
2404
2405        this.$button.trigger('click.bs.dropdown.data-api');
2406      },
2407
2408      keydown: function(e) {
2409        var $this = $(this),
2410          isToggle = $this.hasClass('dropdown-toggle'),
2411          $parent = isToggle ? $this.closest('.dropdown') : $this.closest(Selector.MENU),
2412          that = $parent.data('this'),
2413          $items = that.findLis(),
2414          index,
2415          isActive,
2416          liActive,
2417          activeLi,
2418          offset,
2419          updateScroll = false,
2420          downOnTab = e.which === keyCodes.TAB && !isToggle && !that.options.selectOnTab,
2421          isArrowKey = REGEXP_ARROW.test(e.which) || downOnTab,
2422          scrollTop = that.$menuInner[0].scrollTop,
2423          isVirtual = that.isVirtual(),
2424          position0 = isVirtual === true ? that.selectpicker.view.position0 : 0;
2425
2426        isActive = that.$newElement.hasClass(classNames.SHOW);
2427
2428        if (!isActive &&
2429          (
2430            isArrowKey ||
2431            e.which >= 48 && e.which <= 57 ||
2432            e.which >= 96 && e.which <= 105 ||
2433            e.which >= 65 && e.which <= 90
2434          )
2435        ) {
2436          that.$button.trigger('click.bs.dropdown.data-api');
2437        }
2438
2439        if (e.which === keyCodes.ESCAPE && isActive) {
2440          e.preventDefault();
2441          that.$button.trigger('click.bs.dropdown.data-api').focus();
2442        }
2443
2444        if (isArrowKey) { // if up or down
2445          if (!$items.length) return;
2446
2447          // $items.index/.filter is too slow with a large list and no virtual scroll
2448          index = isVirtual === true ? $items.index($items.filter('.active')) : that.selectpicker.current.map.newIndex[that.activeIndex];
2449
2450          if (index === undefined) index = -1;
2451
2452          if (index !== -1) {
2453            liActive = that.selectpicker.current.elements[index + position0];
2454            liActive.classList.remove('active');
2455            if (liActive.firstChild) liActive.firstChild.classList.remove('active');
2456          }
2457
2458          if (e.which === keyCodes.ARROW_UP) { // up
2459            if (index !== -1) index--;
2460            if (index + position0 < 0) index += $items.length;
2461
2462            if (!that.selectpicker.view.canHighlight[index + position0]) {
2463              index = that.selectpicker.view.canHighlight.slice(0, index + position0).lastIndexOf(true) - position0;
2464              if (index === -1) index = $items.length - 1;
2465            }
2466          } else if (e.which === keyCodes.ARROW_DOWN || downOnTab) { // down
2467            index++;
2468            if (index + position0 >= that.selectpicker.view.canHighlight.length) index = 0;
2469
2470            if (!that.selectpicker.view.canHighlight[index + position0]) {
2471              index = index + 1 + that.selectpicker.view.canHighlight.slice(index + position0 + 1).indexOf(true);
2472            }
2473          }
2474
2475          e.preventDefault();
2476
2477          var liActiveIndex = position0 + index;
2478
2479          if (e.which === keyCodes.ARROW_UP) { // up
2480            // scroll to bottom and highlight last option
2481            if (position0 === 0 && index === $items.length - 1) {
2482              that.$menuInner[0].scrollTop = that.$menuInner[0].scrollHeight;
2483
2484              liActiveIndex = that.selectpicker.current.elements.length - 1;
2485            } else {
2486              activeLi = that.selectpicker.current.data[liActiveIndex];
2487              offset = activeLi.position - activeLi.height;
2488
2489              updateScroll = offset < scrollTop;
2490            }
2491          } else if (e.which === keyCodes.ARROW_DOWN || downOnTab) { // down
2492            // scroll to top and highlight first option
2493            if (index === 0) {
2494              that.$menuInner[0].scrollTop = 0;
2495
2496              liActiveIndex = 0;
2497            } else {
2498              activeLi = that.selectpicker.current.data[liActiveIndex];
2499              offset = activeLi.position - that.sizeInfo.menuInnerHeight;
2500
2501              updateScroll = offset > scrollTop;
2502            }
2503          }
2504
2505          liActive = that.selectpicker.current.elements[liActiveIndex];
2506
2507          if (liActive) {
2508            liActive.classList.add('active');
2509            if (liActive.firstChild) liActive.firstChild.classList.add('active');
2510          }
2511
2512          that.activeIndex = that.selectpicker.current.map.originalIndex[liActiveIndex];
2513
2514          that.selectpicker.view.currentActive = liActive;
2515
2516          if (updateScroll) that.$menuInner[0].scrollTop = offset;
2517
2518          if (that.options.liveSearch) {
2519            that.$searchbox.focus();
2520          } else {
2521            $this.focus();
2522          }
2523        } else if (!$this.is('input') &&
2524          !REGEXP_TAB_OR_ESCAPE.test(e.which) ||
2525          (e.which === keyCodes.SPACE && that.selectpicker.keydown.keyHistory)
2526        ) {
2527          var searchMatch,
2528            matches = [],
2529            keyHistory;
2530
2531          e.preventDefault();
2532
2533          that.selectpicker.keydown.keyHistory += keyCodeMap[e.which];
2534
2535          if (that.selectpicker.keydown.resetKeyHistory.cancel) clearTimeout(that.selectpicker.keydown.resetKeyHistory.cancel);
2536          that.selectpicker.keydown.resetKeyHistory.cancel = that.selectpicker.keydown.resetKeyHistory.start();
2537
2538          keyHistory = that.selectpicker.keydown.keyHistory;
2539
2540          // if all letters are the same, set keyHistory to just the first character when searching
2541          if (/^(.)\1+$/.test(keyHistory)) {
2542            keyHistory = keyHistory.charAt(0);
2543          }
2544
2545          // find matches
2546          for (var i = 0; i < that.selectpicker.current.data.length; i++) {
2547            var li = that.selectpicker.current.data[i],
2548              hasMatch;
2549
2550            hasMatch = stringSearch(li, keyHistory, 'startsWith', true);
2551
2552            if (hasMatch && that.selectpicker.view.canHighlight[i]) {
2553              li.index = i;
2554              matches.push(li.originalIndex);
2555            }
2556          }
2557
2558          if (matches.length) {
2559            var matchIndex = 0;
2560
2561            $items.removeClass('active').find('a').removeClass('active');
2562
2563            // either only one key has been pressed or they are all the same key
2564            if (keyHistory.length === 1) {
2565              matchIndex = matches.indexOf(that.activeIndex);
2566
2567              if (matchIndex === -1 || matchIndex === matches.length - 1) {
2568                matchIndex = 0;
2569              } else {
2570                matchIndex++;
2571              }
2572            }
2573
2574            searchMatch = that.selectpicker.current.map.newIndex[matches[matchIndex]];
2575
2576            activeLi = that.selectpicker.current.data[searchMatch];
2577
2578            if (scrollTop - activeLi.position > 0) {
2579              offset = activeLi.position - activeLi.height;
2580              updateScroll = true;
2581            } else {
2582              offset = activeLi.position - that.sizeInfo.menuInnerHeight;
2583              // if the option is already visible at the current scroll position, just keep it the same
2584              updateScroll = activeLi.position > scrollTop + that.sizeInfo.menuInnerHeight;
2585            }
2586
2587            liActive = that.selectpicker.current.elements[searchMatch];
2588            liActive.classList.add('active');
2589            if (liActive.firstChild) liActive.firstChild.classList.add('active');
2590            that.activeIndex = matches[matchIndex];
2591
2592            liActive.firstChild.focus();
2593
2594            if (updateScroll) that.$menuInner[0].scrollTop = offset;
2595
2596            $this.focus();
2597          }
2598        }
2599
2600        // Select focused option if "Enter", "Spacebar" or "Tab" (when selectOnTab is true) are pressed inside the menu.
2601        if (
2602          isActive &&
2603          (
2604            (e.which === keyCodes.SPACE && !that.selectpicker.keydown.keyHistory) ||
2605            e.which === keyCodes.ENTER ||
2606            (e.which === keyCodes.TAB && that.options.selectOnTab)
2607          )
2608        ) {
2609          if (e.which !== keyCodes.SPACE) e.preventDefault();
2610
2611          if (!that.options.liveSearch || e.which !== keyCodes.SPACE) {
2612            that.$menuInner.find('.active a').trigger('click', true); // retain active class
2613            $this.focus();
2614
2615            if (!that.options.liveSearch) {
2616              // Prevent screen from scrolling if the user hits the spacebar
2617              e.preventDefault();
2618              // Fixes spacebar selection of dropdown items in FF & IE
2619              $(document).data('spaceSelect', true);
2620            }
2621          }
2622        }
2623      },
2624
2625      mobile: function() {
2626        this.$element.addClass('mobile-device');
2627      },
2628
2629      refresh: function() {
2630        // update options if data attributes have been changed
2631        var config = $.extend({}, this.options, this.$element.data());
2632        this.options = config;
2633
2634        this.selectpicker.main.map.newIndex = {};
2635        this.selectpicker.main.map.originalIndex = {};
2636        this.createLi();
2637        this.checkDisabled();
2638        this.render();
2639        this.setStyle();
2640        this.setWidth();
2641
2642        this.setSize(true);
2643
2644        this.$element.trigger('refreshed.bs.select');
2645      },
2646
2647      hide: function() {
2648        this.$newElement.hide();
2649      },
2650
2651      show: function() {
2652        this.$newElement.show();
2653      },
2654
2655      remove: function() {
2656        this.$newElement.remove();
2657        this.$element.remove();
2658      },
2659
2660      destroy: function() {
2661        this.$newElement.before(this.$element).remove();
2662
2663        if (this.$bsContainer) {
2664          this.$bsContainer.remove();
2665        } else {
2666          this.$menu.remove();
2667        }
2668
2669        this.$element
2670          .off('.bs.select')
2671          .removeData('selectpicker')
2672          .removeClass('bs-select-hidden selectpicker');
2673      }
2674    };
2675
2676    // SELECTPICKER PLUGIN DEFINITION
2677    // ==============================
2678    function Plugin(option) {
2679      // get the args of the outer function..
2680      var args = arguments;
2681      // The arguments of the function are explicitly re-defined from the argument list, because the shift causes them
2682      // to get lost/corrupted in android 2.3 and IE9 #715 #775
2683      var _option = option;
2684
2685      [].shift.apply(args);
2686
2687      // if the version was not set successfully
2688      if (!version.success) {
2689        // try to retreive it again
2690        try {
2691          version.full = ($.fn.dropdown.Constructor.VERSION || '').split(' ')[0].split('.');
2692        }
2693        // fall back to use BootstrapVersion
2694        catch (err) {
2695          version.full = Selectpicker.BootstrapVersion.split(' ')[0].split('.');
2696        }
2697
2698        version.major = version.full[0];
2699        version.success = true;
2700
2701        if (version.major === '4') {
2702          classNames.DIVIDER = 'dropdown-divider';
2703          classNames.SHOW = 'show';
2704          classNames.BUTTONCLASS = 'btn-light';
2705          Selectpicker.DEFAULTS.style = classNames.BUTTONCLASS = 'btn-light';
2706          classNames.POPOVERHEADER = 'popover-header';
2707        }
2708      }
2709
2710      var value;
2711      var chain = this.each(function() {
2712        var $this = $(this);
2713        if ($this.is('select')) {
2714          var data = $this.data('selectpicker'),
2715            options = typeof _option == 'object' && _option;
2716
2717          if (!data) {
2718            var config = $.extend({}, Selectpicker.DEFAULTS, $.fn.selectpicker.defaults || {}, $this.data(), options);
2719            config.template = $.extend({}, Selectpicker.DEFAULTS.template, ($.fn.selectpicker.defaults ? $.fn.selectpicker.defaults.template : {}), $this.data().template, options.template);
2720            $this.data('selectpicker', (data = new Selectpicker(this, config)));
2721          } else if (options) {
2722            for (var i in options) {
2723              if (options.hasOwnProperty(i)) {
2724                data.options[i] = options[i];
2725              }
2726            }
2727          }
2728
2729          if (typeof _option == 'string') {
2730            if (data[_option] instanceof Function) {
2731              value = data[_option].apply(data, args);
2732            } else {
2733              value = data.options[_option];
2734            }
2735          }
2736        }
2737      });
2738
2739      if (typeof value !== 'undefined') {
2740        //noinspection JSUnusedAssignment
2741        return value;
2742      } else {
2743        return chain;
2744      }
2745    }
2746
2747    var old = $.fn.selectpicker;
2748    $.fn.selectpicker = Plugin;
2749    $.fn.selectpicker.Constructor = Selectpicker;
2750
2751    // SELECTPICKER NO CONFLICT
2752    // ========================
2753    $.fn.selectpicker.noConflict = function() {
2754      $.fn.selectpicker = old;
2755      return this;
2756    };
2757
2758    $(document)
2759      .off('keydown.bs.dropdown.data-api')
2760      .on('keydown.bs.select', '.bootstrap-select [data-toggle="dropdown"], .bootstrap-select [role="listbox"], .bs-searchbox input', Selectpicker.prototype.keydown)
2761      .on('focusin.modal', '.bootstrap-select [data-toggle="dropdown"], .bootstrap-select [role="listbox"], .bs-searchbox input', function(e) {
2762        e.stopPropagation();
2763      });
2764
2765    // SELECTPICKER DATA-API
2766    // =====================
2767    $(window).on('load.bs.select.data-api', function() {
2768      $('.selectpicker').each(function() {
2769        var $selectpicker = $(this);
2770        Plugin.call($selectpicker, $selectpicker.data());
2771      })
2772    });
2773  })(jQuery);
2774
2775
2776}));

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.