/*! * bootstrap-select v1.12.1 (http://silviomoreto.github.io/bootstrap-select) * * copyright 2013-2016 bootstrap-select * licensed under mit (https://github.com/silviomoreto/bootstrap-select/blob/master/license) */ (function (root, factory) { if (typeof define === 'function' && define.amd) { // amd. register as an anonymous module unless amdmoduleid is set define(["jquery"], function (a0) { return (factory(a0)); }); } else if (typeof module === 'object' && module.exports) { // node. does not work with strict commonjs, but // only commonjs-like environments that support module.exports, // like node. module.exports = factory(require("jquery")); } else { factory(root["jquery"]); } }(this, function (jquery) { (function ($) { 'use strict'; // if (!string.prototype.includes) { (function () { 'use strict'; // needed to support `apply`/`call` with `undefined`/`null` var tostring = {}.tostring; var defineproperty = (function () { // ie 8 only supports `object.defineproperty` on dom elements try { var object = {}; var $defineproperty = object.defineproperty; var result = $defineproperty(object, object, object) && $defineproperty; } catch (error) { } return result; }()); var indexof = ''.indexof; var includes = function (search) { if (this == null) { throw new typeerror(); } var string = string(this); if (search && tostring.call(search) == '[object regexp]') { throw new typeerror(); } var stringlength = string.length; var searchstring = string(search); var searchlength = searchstring.length; var position = arguments.length > 1 ? arguments[1] : undefined; // `tointeger` var pos = position ? number(position) : 0; if (pos != pos) { // better `isnan` pos = 0; } var start = math.min(math.max(pos, 0), stringlength); // avoid the `indexof` call if no match is possible if (searchlength + start > stringlength) { return false; } return indexof.call(string, searchstring, pos) != -1; }; if (defineproperty) { defineproperty(string.prototype, 'includes', { 'value': includes, 'configurable': true, 'writable': true }); } else { string.prototype.includes = includes; } }()); } if (!string.prototype.startswith) { (function () { 'use strict'; // needed to support `apply`/`call` with `undefined`/`null` var defineproperty = (function () { // ie 8 only supports `object.defineproperty` on dom elements try { var object = {}; var $defineproperty = object.defineproperty; var result = $defineproperty(object, object, object) && $defineproperty; } catch (error) { } return result; }()); var tostring = {}.tostring; var startswith = function (search) { if (this == null) { throw new typeerror(); } var string = string(this); if (search && tostring.call(search) == '[object regexp]') { throw new typeerror(); } var stringlength = string.length; var searchstring = string(search); var searchlength = searchstring.length; var position = arguments.length > 1 ? arguments[1] : undefined; // `tointeger` var pos = position ? number(position) : 0; if (pos != pos) { // better `isnan` pos = 0; } var start = math.min(math.max(pos, 0), stringlength); // avoid the `indexof` call if no match is possible if (searchlength + start > stringlength) { return false; } var index = -1; while (++index < searchlength) { if (string.charcodeat(start + index) != searchstring.charcodeat(index)) { return false; } } return true; }; if (defineproperty) { defineproperty(string.prototype, 'startswith', { 'value': startswith, 'configurable': true, 'writable': true }); } else { string.prototype.startswith = startswith; } }()); } if (!object.keys) { object.keys = function ( o, // object k, // key r // result array ){ // initialize object and result r=[]; // iterate over object keys for (k in o) // fill result array with non-prototypical keys r.hasownproperty.call(o, k) && r.push(k); // return result return r; }; } // set data-selected on select element if the value has been programmatically selected // prior to initialization of bootstrap-select // * consider removing or replacing an alternative method * var valhooks = { usedefault: false, _set: $.valhooks.select.set }; $.valhooks.select.set = function(elem, value) { if (value && !valhooks.usedefault) $(elem).data('selected', true); return valhooks._set.apply(this, arguments); }; var changed_arguments = null; $.fn.triggernative = function (eventname) { var el = this[0], event; if (el.dispatchevent) { // for modern browsers & ie9+ if (typeof event === 'function') { // for modern browsers event = new event(eventname, { bubbles: true }); } else { // for ie since it doesn't support event constructor event = document.createevent('event'); event.initevent(eventname, true, false); } el.dispatchevent(event); } else if (el.fireevent) { // for ie8 event = document.createeventobject(); event.eventtype = eventname; el.fireevent('on' + eventname, event); } else { // fall back to jquery.trigger this.trigger(eventname); } }; // // case insensitive contains search $.expr.pseudos.icontains = function (obj, index, meta) { var $obj = $(obj); var haystack = ($obj.data('tokens') || $obj.text()).tostring().touppercase(); return haystack.includes(meta[3].touppercase()); }; // case insensitive begins search $.expr.pseudos.ibegins = function (obj, index, meta) { var $obj = $(obj); var haystack = ($obj.data('tokens') || $obj.text()).tostring().touppercase(); return haystack.startswith(meta[3].touppercase()); }; // case and accent insensitive contains search $.expr.pseudos.aicontains = function (obj, index, meta) { var $obj = $(obj); var haystack = ($obj.data('tokens') || $obj.data('normalizedtext') || $obj.text()).tostring().touppercase(); return haystack.includes(meta[3].touppercase()); }; // case and accent insensitive begins search $.expr.pseudos.aibegins = function (obj, index, meta) { var $obj = $(obj); var haystack = ($obj.data('tokens') || $obj.data('normalizedtext') || $obj.text()).tostring().touppercase(); return haystack.startswith(meta[3].touppercase()); }; /** * remove all diatrics from the given text. * @access private * @param {string} text * @returns {string} */ function normalizetobase(text) { var rexps = [ {re: /[\xc0-\xc6]/g, ch: "a"}, {re: /[\xe0-\xe6]/g, ch: "a"}, {re: /[\xc8-\xcb]/g, ch: "e"}, {re: /[\xe8-\xeb]/g, ch: "e"}, {re: /[\xcc-\xcf]/g, ch: "i"}, {re: /[\xec-\xef]/g, ch: "i"}, {re: /[\xd2-\xd6]/g, ch: "o"}, {re: /[\xf2-\xf6]/g, ch: "o"}, {re: /[\xd9-\xdc]/g, ch: "u"}, {re: /[\xf9-\xfc]/g, ch: "u"}, {re: /[\xc7-\xe7]/g, ch: "c"}, {re: /[\xd1]/g, ch: "n"}, {re: /[\xf1]/g, ch: "n"} ]; $.each(rexps, function () { text = text ? text.replace(this.re, this.ch) : ''; }); return text; } // list of html entities for escaping. var escapemap = { '&': '&', '<': '<', '>': '>', '"': '"', "'": ''', '`': '`' }; var unescapemap = { '&': '&', '<': '<', '>': '>', '"': '"', ''': "'", '`': '`' }; // functions for escaping and unescaping strings to/from html interpolation. var createescaper = function(map) { var escaper = function(match) { return map[match]; }; // regexes for identifying a key that needs to be escaped. var source = '(?:' + object.keys(map).join('|') + ')'; var testregexp = regexp(source); var replaceregexp = regexp(source, 'g'); return function(string) { string = string == null ? '' : '' + string; return testregexp.test(string) ? string.replace(replaceregexp, escaper) : string; }; }; var htmlescape = createescaper(escapemap); var htmlunescape = createescaper(unescapemap); var selectpicker = function (element, options) { // bootstrap-select has been initialized - revert valhooks.select.set back to its original function if (!valhooks.usedefault) { $.valhooks.select.set = valhooks._set; valhooks.usedefault = true; } this.$element = $(element); this.$newelement = null; this.$button = null; this.$menu = null; this.$lis = null; this.options = options; // 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 // data-attribute) if (this.options.title === null) { this.options.title = this.$element.attr('title'); } // format window padding var winpad = this.options.windowpadding; if (typeof winpad === 'number') { this.options.windowpadding = [winpad, winpad, winpad, winpad]; } //expose public methods this.val = selectpicker.prototype.val; this.render = selectpicker.prototype.render; this.refresh = selectpicker.prototype.refresh; this.setstyle = selectpicker.prototype.setstyle; this.selectall = selectpicker.prototype.selectall; this.deselectall = selectpicker.prototype.deselectall; this.destroy = selectpicker.prototype.destroy; this.remove = selectpicker.prototype.remove; this.show = selectpicker.prototype.show; this.hide = selectpicker.prototype.hide; this.init(); }; selectpicker.version = '1.12.1'; // part of this is duplicated in i18n/defaults-en_us.js. make sure to update both. selectpicker.defaults = { noneselectedtext: 'nothing selected', noneresultstext: 'no results matched {0}', countselectedtext: function (numselected, numtotal) { return (numselected == 1) ? "{0} item selected" : "{0} items selected"; }, maxoptionstext: function (numall, numgroup) { return [ (numall == 1) ? 'limit reached ({n} item max)' : 'limit reached ({n} items max)', (numgroup == 1) ? 'group limit reached ({n} item max)' : 'group limit reached ({n} items max)' ]; }, selectalltext: 'select all', deselectalltext: 'deselect all', donebutton: false, donebuttontext: 'close', multipleseparator: ', ', stylebase: 'btn', style: 'btn-default', size: 'auto', title: null, selectedtextformat: 'values', width: false, container: false, hidedisabled: false, showsubtext: false, showicon: true, showcontent: true, dropupauto: true, header: false, livesearch: false, livesearchplaceholder: null, livesearchnormalize: false, livesearchstyle: 'contains', actionsbox: false, iconbase: 'glyphicon', tickicon: 'glyphicon-ok', showtick: false, template: { caret: '' }, maxoptions: false, mobile: false, selectontab: false, dropdownalignright: false, windowpadding: 0 }; selectpicker.prototype = { constructor: selectpicker, init: function () { var that = this, id = this.$element.attr('id'); this.$element.addclass('bs-select-hidden'); // store originalindex (key) and newindex (value) in this.liobj for fast accessibility // allows us to do this.$lis.eq(that.liobj[index]) instead of this.$lis.filter('[data-original-index="' + index + '"]') this.liobj = {}; this.multiple = this.$element.prop('multiple'); this.autofocus = this.$element.prop('autofocus'); this.$newelement = this.createview(); this.$element .after(this.$newelement) .appendto(this.$newelement); this.$button = this.$newelement.children('button'); this.$menu = this.$newelement.children('.dropdown-menu'); this.$menuinner = this.$menu.children('.inner'); this.$searchbox = this.$menu.find('input'); this.$element.removeclass('bs-select-hidden'); if (this.options.dropdownalignright === true) this.$menu.addclass('dropdown-menu-right'); if (typeof id !== 'undefined') { this.$button.attr('data-id', id); $('label[for="' + id + '"]').click(function (e) { e.preventdefault(); that.$button.focus(); }); } this.checkdisabled(); this.clicklistener(); if (this.options.livesearch) this.livesearchlistener(); this.render(); this.setstyle(); this.setwidth(); if (this.options.container) this.selectposition(); this.$menu.data('this', this); this.$newelement.data('this', this); if (this.options.mobile) this.mobile(); this.$newelement.on({ 'hide.bs.dropdown': function (e) { that.$menuinner.attr('aria-expanded', false); that.$element.trigger('hide.bs.select', e); }, 'hidden.bs.dropdown': function (e) { that.$element.trigger('hidden.bs.select', e); }, 'show.bs.dropdown': function (e) { that.$menuinner.attr('aria-expanded', true); that.$element.trigger('show.bs.select', e); }, 'shown.bs.dropdown': function (e) { that.$element.trigger('shown.bs.select', e); } }); if (that.$element[0].hasattribute('required')) { this.$element.on('invalid', function () { that.$button .addclass('bs-invalid') .focus(); that.$element.on({ 'focus.bs.select': function () { that.$button.focus(); that.$element.off('focus.bs.select'); }, 'shown.bs.select': function () { that.$element .val(that.$element.val()) // set the value to hide the validation message in chrome when menu is opened .off('shown.bs.select'); }, 'rendered.bs.select': function () { // if select is no longer invalid, remove the bs-invalid class if (this.validity.valid) that.$button.removeclass('bs-invalid'); that.$element.off('rendered.bs.select'); } }); }); } settimeout(function () { that.$element.trigger('loaded.bs.select'); }); }, createdropdown: function () { // options // if we are multiple or showtick option is set, then add the show-tick class var showtick = (this.multiple || this.options.showtick) ? ' show-tick' : '', inputgroup = this.$element.parent().hasclass('input-group') ? ' input-group-btn' : '', autofocus = this.autofocus ? ' autofocus' : ''; // elements var header = this.options.header ? '
' + this.options.header + '
' : ''; var searchbox = this.options.livesearch ? '' : ''; var actionsbox = this.multiple && this.options.actionsbox ? '
' + '
' + '' + '' + '
' + '
' : ''; var donebutton = this.multiple && this.options.donebutton ? '
' + '
' + '' + '
' + '
' : ''; var drop = '
' + '' + '' + '
'; return $(drop); }, createview: function () { var $drop = this.createdropdown(), li = this.createli(); $drop.find('ul')[0].innerhtml = li; return $drop; }, reloadli: function () { // rebuild var li = this.createli(); this.$menuinner[0].innerhtml = li; }, createli: function () { var that = this, _li = [], optid = 0, titleoption = document.createelement('option'), liindex = -1; // increment liindex whenever a new
  • element is created to ensure liobj is correct // helper functions /** * @param content * @param [index] * @param [classes] * @param [optgroup] * @returns {string} */ var generateli = function (content, index, classes, optgroup) { return '' + content + '
  • '; }; /** * @param text * @param [classes] * @param [inline] * @param [tokens] * @returns {string} */ var generatea = function (text, classes, inline, tokens) { return '' + text + '' + ''; }; if (this.options.title && !this.multiple) { // this option doesn't create a new
  • element, but does add a new option, so liindex is decreased // since liobj is recalculated on every refresh, liindex needs to be decreased even if the titleoption is already appended liindex--; if (!this.$element.find('.bs-title-option').length) { // use native js to prepend option (faster) var element = this.$element[0]; titleoption.classname = 'bs-title-option'; titleoption.innerhtml = this.options.title; titleoption.value = ''; element.insertbefore(titleoption, element.firstchild); // check if selected or data-selected attribute is already set on an option. if not, select the titleoption option. // the selected item may have been changed by user or programmatically before the bootstrap select plugin runs, // if so, the select will have the data-selected attribute var $opt = $(element.options[element.selectedindex]); if ($opt.attr('selected') === undefined && this.$element.data('selected') === undefined) { titleoption.selected = true; } } } this.$element.find('option').each(function (index) { var $this = $(this); liindex++; if ($this.hasclass('bs-title-option')) return; // get the class and text for the option var optionclass = this.classname || '', inline = this.style.csstext, text = $this.data('content') ? $this.data('content') : $this.html(), tokens = $this.data('tokens') ? $this.data('tokens') : null, subtext = typeof $this.data('subtext') !== 'undefined' ? '' + $this.data('subtext') + '' : '', icon = typeof $this.data('icon') !== 'undefined' ? ' ' : '', $parent = $this.parent(), isoptgroup = $parent[0].tagname === 'optgroup', isoptgroupdisabled = isoptgroup && $parent[0].disabled, isdisabled = this.disabled || isoptgroupdisabled; if (icon !== '' && isdisabled) { icon = '' + icon + ''; } if (that.options.hidedisabled && (isdisabled && !isoptgroup || isoptgroupdisabled)) { liindex--; return; } if (!$this.data('content')) { // prepend any icon and append any subtext to the main text. text = icon + '' + text + subtext + ''; } if (isoptgroup && $this.data('divider') !== true) { if (that.options.hidedisabled && isdisabled) { if ($parent.data('alloptionsdisabled') === undefined) { var $options = $parent.children(); $parent.data('alloptionsdisabled', $options.filter(':disabled').length === $options.length); } if ($parent.data('alloptionsdisabled')) { liindex--; return; } } var optgroupclass = ' ' + $parent[0].classname || ''; if ($this.index() === 0) { // is it the first option of the optgroup? optid += 1; // get the opt group label var label = $parent[0].label, labelsubtext = typeof $parent.data('subtext') !== 'undefined' ? '' + $parent.data('subtext') + '' : '', labelicon = $parent.data('icon') ? ' ' : ''; label = labelicon + '' + htmlescape(label) + labelsubtext + ''; if (index !== 0 && _li.length > 0) { // is it not the first option of the select && are there elements in the dropdown? liindex++; _li.push(generateli('', null, 'divider', optid + 'div')); } liindex++; _li.push(generateli(label, null, 'dropdown-header' + optgroupclass, optid)); } if (that.options.hidedisabled && isdisabled) { liindex--; return; } _li.push(generateli(generatea(text, 'opt ' + optionclass + optgroupclass, inline, tokens), index, '', optid)); } else if ($this.data('divider') === true) { _li.push(generateli('', index, 'divider')); } else if ($this.data('hidden') === true) { _li.push(generateli(generatea(text, optionclass, inline, tokens), index, 'hidden is-hidden')); } else { var showdivider = this.previouselementsibling && this.previouselementsibling.tagname === 'optgroup'; // if previous element is not an optgroup and hidedisabled is true if (!showdivider && that.options.hidedisabled) { // get previous elements var $prev = $(this).prevall(); for (var i = 0; i < $prev.length; i++) { // find the first element in the previous elements that is an optgroup if ($prev[i].tagname === 'optgroup') { var optgroupdistance = 0; // loop through the options in between the current option and the optgroup // and check if they are hidden or disabled for (var d = 0; d < i; d++) { var prevoption = $prev[d]; if (prevoption.disabled || $(prevoption).data('hidden') === true) optgroupdistance++; } // if all of the options between the current option and the optgroup are hidden or disabled, show the divider if (optgroupdistance === i) showdivider = true; break; } } } if (showdivider) { liindex++; _li.push(generateli('', null, 'divider', optid + 'div')); } _li.push(generateli(generatea(text, optionclass, inline, tokens), index)); } that.liobj[index] = liindex; }); //if we are not multiple, we don't have a selected item, and we don't have a title, select the first element so something is set in the button if (!this.multiple && this.$element.find('option:selected').length === 0 && !this.options.title) { this.$element.find('option').eq(0).prop('selected', true).attr('selected', 'selected'); } return _li.join(''); }, findlis: function () { if (this.$lis == null) this.$lis = this.$menu.find('li'); return this.$lis; }, /** * @param [updateli] defaults to true */ render: function (updateli) { var that = this, notdisabled; //update the li to match the select if (updateli !== false) { this.$element.find('option').each(function (index) { var $lis = that.findlis().eq(that.liobj[index]); that.setdisabled(index, this.disabled || this.parentnode.tagname === 'optgroup' && this.parentnode.disabled, $lis); that.setselected(index, this.selected, $lis); }); } this.toggleplaceholder(); this.tabindex(); var selecteditems = this.$element.find('option').map(function () { if (this.selected) { if (that.options.hidedisabled && (this.disabled || this.parentnode.tagname === 'optgroup' && this.parentnode.disabled)) return; var $this = $(this), icon = $this.data('icon') && that.options.showicon ? ' ' : '', subtext; if (that.options.showsubtext && $this.data('subtext') && !that.multiple) { subtext = ' ' + $this.data('subtext') + ''; } else { subtext = ''; } if (typeof $this.attr('title') !== 'undefined') { return $this.attr('title'); } else if ($this.data('content') && that.options.showcontent) { return $this.data('content').tostring(); } else { return icon + $this.html() + subtext; } } }).toarray(); //fixes issue in ie10 occurring when no default option is selected and at least one option is disabled //convert all the values into a comma delimited string var title = !this.multiple ? selecteditems[0] : selecteditems.join(this.options.multipleseparator); //if this is multi select, and the selecttext type is count, the show 1 of 2 selected etc.. if (this.multiple && this.options.selectedtextformat.indexof('count') > -1) { var max = this.options.selectedtextformat.split('>'); if ((max.length > 1 && selecteditems.length > max[1]) || (max.length == 1 && selecteditems.length >= 2)) { notdisabled = this.options.hidedisabled ? ', [disabled]' : ''; var totalcount = this.$element.find('option').not('[data-divider="true"], [data-hidden="true"]' + notdisabled).length, tr8ntext = (typeof this.options.countselectedtext === 'function') ? this.options.countselectedtext(selecteditems.length, totalcount) : this.options.countselectedtext; title = tr8ntext.replace('{0}', selecteditems.length.tostring()).replace('{1}', totalcount.tostring()); } } if (this.options.title == undefined) { this.options.title = this.$element.attr('title'); } if (this.options.selectedtextformat == 'static') { title = this.options.title; } //if we dont have a title, then use the default, or if nothing is set at all, use the not selected text if (!title) { title = typeof this.options.title !== 'undefined' ? this.options.title : this.options.noneselectedtext; } //strip all html tags and trim the result, then unescape any escaped tags this.$button.attr('title', htmlunescape($.trim(title.replace(/<[^>]*>?/g, '')))); this.$button.children('.filter-option').html(title); this.$element.trigger('rendered.bs.select'); }, /** * @param [style] * @param [status] */ setstyle: function (style, status) { if (this.$element.attr('class')) { this.$newelement.addclass(this.$element.attr('class').replace(/selectpicker|mobile-device|bs-select-hidden|validate\[.*\]/gi, '')); } var buttonclass = style ? style : this.options.style; if (status == 'add') { this.$button.addclass(buttonclass); } else if (status == 'remove') { this.$button.removeclass(buttonclass); } else { this.$button.removeclass(this.options.style); this.$button.addclass(buttonclass); } }, liheight: function (refresh) { if (!refresh && (this.options.size === false || this.sizeinfo)) return; var newelement = document.createelement('div'), menu = document.createelement('div'), menuinner = document.createelement('ul'), divider = document.createelement('li'), li = document.createelement('li'), a = document.createelement('a'), text = document.createelement('span'), header = this.options.header && this.$menu.find('.popover-title').length > 0 ? this.$menu.find('.popover-title')[0].clonenode(true) : null, search = this.options.livesearch ? document.createelement('div') : null, actions = this.options.actionsbox && this.multiple && this.$menu.find('.bs-actionsbox').length > 0 ? this.$menu.find('.bs-actionsbox')[0].clonenode(true) : null, donebutton = this.options.donebutton && this.multiple && this.$menu.find('.bs-donebutton').length > 0 ? this.$menu.find('.bs-donebutton')[0].clonenode(true) : null; text.classname = 'text'; newelement.classname = this.$menu[0].parentnode.classname + ' open'; menu.classname = 'dropdown-menu open'; menuinner.classname = 'dropdown-menu inner'; divider.classname = 'divider'; text.appendchild(document.createtextnode('inner text')); a.appendchild(text); li.appendchild(a); menuinner.appendchild(li); menuinner.appendchild(divider); if (header) menu.appendchild(header); if (search) { // create a span instead of input as creating an input element is slower var input = document.createelement('span'); search.classname = 'bs-searchbox'; input.classname = 'form-control'; search.appendchild(input); menu.appendchild(search); } if (actions) menu.appendchild(actions); menu.appendchild(menuinner); if (donebutton) menu.appendchild(donebutton); newelement.appendchild(menu); document.body.appendchild(newelement); var liheight = a.offsetheight, headerheight = header ? header.offsetheight : 0, searchheight = search ? search.offsetheight : 0, actionsheight = actions ? actions.offsetheight : 0, donebuttonheight = donebutton ? donebutton.offsetheight : 0, dividerheight = $(divider).outerheight(true), // fall back to jquery if getcomputedstyle is not supported menustyle = typeof getcomputedstyle === 'function' ? getcomputedstyle(menu) : false, $menu = menustyle ? null : $(menu), menupadding = { vert: parseint(menustyle ? menustyle.paddingtop : $menu.css('paddingtop')) + parseint(menustyle ? menustyle.paddingbottom : $menu.css('paddingbottom')) + parseint(menustyle ? menustyle.bordertopwidth : $menu.css('bordertopwidth')) + parseint(menustyle ? menustyle.borderbottomwidth : $menu.css('borderbottomwidth')), horiz: parseint(menustyle ? menustyle.paddingleft : $menu.css('paddingleft')) + parseint(menustyle ? menustyle.paddingright : $menu.css('paddingright')) + parseint(menustyle ? menustyle.borderleftwidth : $menu.css('borderleftwidth')) + parseint(menustyle ? menustyle.borderrightwidth : $menu.css('borderrightwidth')) }, menuextras = { vert: menupadding.vert + parseint(menustyle ? menustyle.margintop : $menu.css('margintop')) + parseint(menustyle ? menustyle.marginbottom : $menu.css('marginbottom')) + 2, horiz: menupadding.horiz + parseint(menustyle ? menustyle.marginleft : $menu.css('marginleft')) + parseint(menustyle ? menustyle.marginright : $menu.css('marginright')) + 2 } document.body.removechild(newelement); this.sizeinfo = { liheight: liheight, headerheight: headerheight, searchheight: searchheight, actionsheight: actionsheight, donebuttonheight: donebuttonheight, dividerheight: dividerheight, menupadding: menupadding, menuextras: menuextras }; }, setsize: function () { this.findlis(); this.liheight(); if (this.options.header) this.$menu.css('padding-top', 0); if (this.options.size === false) return; var that = this, $menu = this.$menu, $menuinner = this.$menuinner, $window = $(window), selectheight = this.$newelement[0].offsetheight, selectwidth = this.$newelement[0].offsetwidth, liheight = this.sizeinfo['liheight'], headerheight = this.sizeinfo['headerheight'], searchheight = this.sizeinfo['searchheight'], actionsheight = this.sizeinfo['actionsheight'], donebuttonheight = this.sizeinfo['donebuttonheight'], divheight = this.sizeinfo['dividerheight'], menupadding = this.sizeinfo['menupadding'], menuextras = this.sizeinfo['menuextras'], notdisabled = this.options.hidedisabled ? '.disabled' : '', menuheight, menuwidth, getheight, getwidth, selectoffsettop, selectoffsetbot, selectoffsetleft, selectoffsetright, getpos = function() { var pos = that.$newelement.offset(), $container = $(that.options.container), containerpos; if (that.options.container && !$container.is('body')) { containerpos = $container.offset(); containerpos.top += parseint($container.css('bordertopwidth')); containerpos.left += parseint($container.css('borderleftwidth')); } else { containerpos = { top: 0, left: 0 }; } var winpad = that.options.windowpadding; selectoffsettop = pos.top - containerpos.top - $window.scrolltop(); selectoffsetbot = $window.height() - selectoffsettop - selectheight - containerpos.top - winpad[2]; selectoffsetleft = pos.left - containerpos.left - $window.scrollleft(); selectoffsetright = $window.width() - selectoffsetleft - selectwidth - containerpos.left - winpad[1]; selectoffsettop -= winpad[0]; selectoffsetleft -= winpad[3]; }; getpos(); if (this.options.size === 'auto') { var getsize = function () { var minheight, hasclass = function (classname, include) { return function (element) { if (include) { return (element.classlist ? element.classlist.contains(classname) : $(element).hasclass(classname)); } else { return !(element.classlist ? element.classlist.contains(classname) : $(element).hasclass(classname)); } }; }, lis = that.$menuinner[0].getelementsbytagname('li'), lisvisible = array.prototype.filter ? array.prototype.filter.call(lis, hasclass('hidden', false)) : that.$lis.not('.hidden'), optgroup = array.prototype.filter ? array.prototype.filter.call(lisvisible, hasclass('dropdown-header', true)) : lisvisible.filter('.dropdown-header'); getpos(); menuheight = selectoffsetbot - menuextras.vert; menuwidth = selectoffsetright - menuextras.horiz; if (that.options.container) { if (!$menu.data('height')) $menu.data('height', $menu.height()); getheight = $menu.data('height'); if (!$menu.data('width')) $menu.data('width', $menu.width()); getwidth = $menu.data('width'); } else { getheight = $menu.height(); getwidth = $menu.width(); } if (that.options.dropupauto) { that.$newelement.toggleclass('dropup', selectoffsettop > selectoffsetbot && (menuheight - menuextras.vert) < getheight); } if (that.$newelement.hasclass('dropup')) { menuheight = selectoffsettop - menuextras.vert; } if (that.options.dropdownalignright === 'auto') { $menu.toggleclass('dropdown-menu-right', selectoffsetleft > selectoffsetright && (menuwidth - menuextras.horiz) < (getwidth - selectwidth)); } if ((lisvisible.length + optgroup.length) > 3) { minheight = liheight * 3 + menuextras.vert - 2; } else { minheight = 0; } $menu.css({ 'max-height': menuheight + 'px', 'overflow': 'hidden', 'min-height': minheight + headerheight + searchheight + actionsheight + donebuttonheight + 'px' }); $menuinner.css({ 'max-height': menuheight - headerheight - searchheight - actionsheight - donebuttonheight - menupadding.vert + 'px', 'overflow-y': 'auto', 'min-height': math.max(minheight - menupadding.vert, 0) + 'px' }); }; getsize(); this.$searchbox.off('input.getsize propertychange.getsize').on('input.getsize propertychange.getsize', getsize); $window.off('resize.getsize scroll.getsize').on('resize.getsize scroll.getsize', getsize); } else if (this.options.size && this.options.size != 'auto' && this.$lis.not(notdisabled).length > this.options.size) { var optindex = this.$lis.not('.divider').not(notdisabled).children().slice(0, this.options.size).last().parent().index(), divlength = this.$lis.slice(0, optindex + 1).filter('.divider').length; menuheight = liheight * this.options.size + divlength * divheight + menupadding.vert; if (that.options.container) { if (!$menu.data('height')) $menu.data('height', $menu.height()); getheight = $menu.data('height'); } else { getheight = $menu.height(); } if (that.options.dropupauto) { //noinspection jsunusedassignment this.$newelement.toggleclass('dropup', selectoffsettop > selectoffsetbot && (menuheight - menuextras.vert) < getheight); } $menu.css({ 'max-height': menuheight + headerheight + searchheight + actionsheight + donebuttonheight + 'px', 'overflow': 'hidden', 'min-height': '' }); $menuinner.css({ 'max-height': menuheight - menupadding.vert + 'px', 'overflow-y': 'auto', 'min-height': '' }); } }, setwidth: function () { if (this.options.width === 'auto') { this.$menu.css('min-width', '0'); // get correct width if element is hidden var $selectclone = this.$menu.parent().clone().appendto('body'), $selectclone2 = this.options.container ? this.$newelement.clone().appendto('body') : $selectclone, ulwidth = $selectclone.children('.dropdown-menu').outerwidth(), btnwidth = $selectclone2.css('width', 'auto').children('button').outerwidth(); $selectclone.remove(); $selectclone2.remove(); // set width to whatever's larger, button title or longest option this.$newelement.css('width', math.max(ulwidth, btnwidth) + 'px'); } else if (this.options.width === 'fit') { // remove inline min-width so width can be changed from 'auto' this.$menu.css('min-width', ''); this.$newelement.css('width', '').addclass('fit-width'); } else if (this.options.width) { // remove inline min-width so width can be changed from 'auto' this.$menu.css('min-width', ''); this.$newelement.css('width', this.options.width); } else { // remove inline min-width/width so width can be changed this.$menu.css('min-width', ''); this.$newelement.css('width', ''); } // remove fit-width class if width is changed programmatically if (this.$newelement.hasclass('fit-width') && this.options.width !== 'fit') { this.$newelement.removeclass('fit-width'); } }, selectposition: function () { this.$bscontainer = $('
    '); var that = this, $container = $(this.options.container), pos, containerpos, actualheight, getplacement = function ($element) { that.$bscontainer.addclass($element.attr('class').replace(/form-control|fit-width/gi, '')).toggleclass('dropup', $element.hasclass('dropup')); pos = $element.offset(); if (!$container.is('body')) { containerpos = $container.offset(); containerpos.top += parseint($container.css('bordertopwidth')) - $container.scrolltop(); containerpos.left += parseint($container.css('borderleftwidth')) - $container.scrollleft(); } else { containerpos = { top: 0, left: 0 }; } actualheight = $element.hasclass('dropup') ? 0 : $element[0].offsetheight; that.$bscontainer.css({ 'top': pos.top - containerpos.top + actualheight, 'left': pos.left - containerpos.left, 'width': $element[0].offsetwidth }); }; this.$button.on('click', function () { var $this = $(this); if (that.isdisabled()) { return; } getplacement(that.$newelement); that.$bscontainer .appendto(that.options.container) .toggleclass('open', !$this.hasclass('open')) .append(that.$menu); }); $(window).on('resize scroll', function () { getplacement(that.$newelement); }); this.$element.on('hide.bs.select', function () { that.$menu.data('height', that.$menu.height()); that.$bscontainer.detach(); }); }, /** * @param {number} index - the index of the option that is being changed * @param {boolean} selected - true if the option is being selected, false if being deselected * @param {jquery} $lis - the 'li' element that is being modified */ setselected: function (index, selected, $lis) { if (!$lis) { this.toggleplaceholder(); // check if setselected is being called by changing the value of the select $lis = this.findlis().eq(this.liobj[index]); } $lis.toggleclass('selected', selected).find('a').attr('aria-selected', selected); }, /** * @param {number} index - the index of the option that is being disabled * @param {boolean} disabled - true if the option is being disabled, false if being enabled * @param {jquery} $lis - the 'li' element that is being modified */ setdisabled: function (index, disabled, $lis) { if (!$lis) { $lis = this.findlis().eq(this.liobj[index]); } if (disabled) { $lis.addclass('disabled').children('a').attr('href', '#').attr('tabindex', -1).attr('aria-disabled', true); } else { $lis.removeclass('disabled').children('a').removeattr('href').attr('tabindex', 0).attr('aria-disabled', false); } }, isdisabled: function () { return this.$element[0].disabled; }, checkdisabled: function () { var that = this; if (this.isdisabled()) { this.$newelement.addclass('disabled'); this.$button.addclass('disabled').attr('tabindex', -1).attr('aria-disabled', true); } else { if (this.$button.hasclass('disabled')) { this.$newelement.removeclass('disabled'); this.$button.removeclass('disabled').attr('aria-disabled', false); } if (this.$button.attr('tabindex') == -1 && !this.$element.data('tabindex')) { this.$button.removeattr('tabindex'); } } this.$button.click(function () { return !that.isdisabled(); }); }, toggleplaceholder: function () { var value = this.$element.val(); this.$button.toggleclass('bs-placeholder', value === null || value === '' || (value.constructor === array && value.length === 0)); }, tabindex: function () { if (this.$element.data('tabindex') !== this.$element.attr('tabindex') && (this.$element.attr('tabindex') !== -98 && this.$element.attr('tabindex') !== '-98')) { this.$element.data('tabindex', this.$element.attr('tabindex')); this.$button.attr('tabindex', this.$element.data('tabindex')); } this.$element.attr('tabindex', -98); }, clicklistener: function () { var that = this, $document = $(document); $document.data('spaceselect', false); this.$button.on('keyup', function (e) { if (/(32)/.test(e.keycode.tostring(10)) && $document.data('spaceselect')) { e.preventdefault(); $document.data('spaceselect', false); } }); this.$button.on('click', function () { that.setsize(); }); this.$element.on('shown.bs.select', function () { if (!that.options.livesearch && !that.multiple) { that.$menuinner.find('.selected a').focus(); } else if (!that.multiple) { var selectedindex = that.liobj[that.$element[0].selectedindex]; if (typeof selectedindex !== 'number' || that.options.size === false) return; // scroll to selected option var offset = that.$lis.eq(selectedindex)[0].offsettop - that.$menuinner[0].offsettop; offset = offset - that.$menuinner[0].offsetheight/2 + that.sizeinfo.liheight/2; that.$menuinner[0].scrolltop = offset; } }); this.$menuinner.on('click', 'li a', function (e) { var $this = $(this), clickedindex = $this.parent().data('originalindex'), prevvalue = that.$element.val(), previndex = that.$element.prop('selectedindex'), triggerchange = true; // don't close on multi choice menu if (that.multiple && that.options.maxoptions !== 1) { e.stoppropagation(); } e.preventdefault(); //don't run if we have been disabled if (!that.isdisabled() && !$this.parent().hasclass('disabled')) { var $options = that.$element.find('option'), $option = $options.eq(clickedindex), state = $option.prop('selected'), $optgroup = $option.parent('optgroup'), maxoptions = that.options.maxoptions, maxoptionsgrp = $optgroup.data('maxoptions') || false; if (!that.multiple) { // deselect all others if not multi select box $options.prop('selected', false); $option.prop('selected', true); that.$menuinner.find('.selected').removeclass('selected').find('a').attr('aria-selected', false); that.setselected(clickedindex, true); } else { // toggle the one we have chosen if we are multi select. $option.prop('selected', !state); that.setselected(clickedindex, !state); $this.blur(); if (maxoptions !== false || maxoptionsgrp !== false) { var maxreached = maxoptions < $options.filter(':selected').length, maxreachedgrp = maxoptionsgrp < $optgroup.find('option:selected').length; if ((maxoptions && maxreached) || (maxoptionsgrp && maxreachedgrp)) { if (maxoptions && maxoptions == 1) { $options.prop('selected', false); $option.prop('selected', true); that.$menuinner.find('.selected').removeclass('selected'); that.setselected(clickedindex, true); } else if (maxoptionsgrp && maxoptionsgrp == 1) { $optgroup.find('option:selected').prop('selected', false); $option.prop('selected', true); var optgroupid = $this.parent().data('optgroup'); that.$menuinner.find('[data-optgroup="' + optgroupid + '"]').removeclass('selected'); that.setselected(clickedindex, true); } else { var maxoptionstext = typeof that.options.maxoptionstext === 'string' ? [that.options.maxoptionstext, that.options.maxoptionstext] : that.options.maxoptionstext, maxoptionsarr = typeof maxoptionstext === 'function' ? maxoptionstext(maxoptions, maxoptionsgrp) : maxoptionstext, maxtxt = maxoptionsarr[0].replace('{n}', maxoptions), maxtxtgrp = maxoptionsarr[1].replace('{n}', maxoptionsgrp), $notify = $('
    '); // if {var} is set in array, replace it /** @deprecated */ if (maxoptionsarr[2]) { maxtxt = maxtxt.replace('{var}', maxoptionsarr[2][maxoptions > 1 ? 0 : 1]); maxtxtgrp = maxtxtgrp.replace('{var}', maxoptionsarr[2][maxoptionsgrp > 1 ? 0 : 1]); } $option.prop('selected', false); that.$menu.append($notify); if (maxoptions && maxreached) { $notify.append($('
    ' + maxtxt + '
    ')); triggerchange = false; that.$element.trigger('maxreached.bs.select'); } if (maxoptionsgrp && maxreachedgrp) { $notify.append($('
    ' + maxtxtgrp + '
    ')); triggerchange = false; that.$element.trigger('maxreachedgrp.bs.select'); } settimeout(function () { that.setselected(clickedindex, false); }, 10); $notify.delay(750).fadeout(300, function () { $(this).remove(); }); } } } } if (!that.multiple || (that.multiple && that.options.maxoptions === 1)) { that.$button.focus(); } else if (that.options.livesearch) { that.$searchbox.focus(); } // trigger select 'change' if (triggerchange) { if ((prevvalue != that.$element.val() && that.multiple) || (previndex != that.$element.prop('selectedindex') && !that.multiple)) { // $option.prop('selected') is current option state (selected/unselected). state is previous option state. changed_arguments = [clickedindex, $option.prop('selected'), state]; that.$element .triggernative('change'); } } } }); this.$menu.on('click', 'li.disabled a, .popover-title, .popover-title :not(.close)', function (e) { if (e.currenttarget == this) { e.preventdefault(); e.stoppropagation(); if (that.options.livesearch && !$(e.target).hasclass('close')) { that.$searchbox.focus(); } else { that.$button.focus(); } } }); this.$menuinner.on('click', '.divider, .dropdown-header', function (e) { e.preventdefault(); e.stoppropagation(); if (that.options.livesearch) { that.$searchbox.focus(); } else { that.$button.focus(); } }); this.$menu.on('click', '.popover-title .close', function () { that.$button.click(); }); this.$searchbox.on('click', function (e) { e.stoppropagation(); }); this.$menu.on('click', '.actions-btn', function (e) { if (that.options.livesearch) { that.$searchbox.focus(); } else { that.$button.focus(); } e.preventdefault(); e.stoppropagation(); if ($(this).hasclass('bs-select-all')) { that.selectall(); } else { that.deselectall(); } }); this.$element.change(function () { that.render(false); that.$element.trigger('changed.bs.select', changed_arguments); changed_arguments = null; }); }, livesearchlistener: function () { var that = this, $no_results = $('
  • '); this.$button.on('click.dropdown.data-api', function () { that.$menuinner.find('.active').removeclass('active'); if (!!that.$searchbox.val()) { that.$searchbox.val(''); that.$lis.not('.is-hidden').removeclass('hidden'); if (!!$no_results.parent().length) $no_results.remove(); } if (!that.multiple) that.$menuinner.find('.selected').addclass('active'); settimeout(function () { that.$searchbox.focus(); }, 10); }); this.$searchbox.on('click.dropdown.data-api focus.dropdown.data-api touchend.dropdown.data-api', function (e) { e.stoppropagation(); }); this.$searchbox.on('input propertychange', function () { that.$lis.not('.is-hidden').removeclass('hidden'); that.$lis.filter('.active').removeclass('active'); $no_results.remove(); if (that.$searchbox.val()) { var $searchbase = that.$lis.not('.is-hidden, .divider, .dropdown-header'), $hideitems; if (that.options.livesearchnormalize) { $hideitems = $searchbase.not(':a' + that._searchstyle() + '("' + normalizetobase(that.$searchbox.val()) + '")'); } else { $hideitems = $searchbase.not(':' + that._searchstyle() + '("' + that.$searchbox.val() + '")'); } if ($hideitems.length === $searchbase.length) { $no_results.html(that.options.noneresultstext.replace('{0}', '"' + htmlescape(that.$searchbox.val()) + '"')); that.$menuinner.append($no_results); that.$lis.addclass('hidden'); } else { $hideitems.addclass('hidden'); var $lisvisible = that.$lis.not('.hidden'), $founddiv; // hide divider if first or last visible, or if followed by another divider $lisvisible.each(function (index) { var $this = $(this); if ($this.hasclass('divider')) { if ($founddiv === undefined) { $this.addclass('hidden'); } else { if ($founddiv) $founddiv.addclass('hidden'); $founddiv = $this; } } else if ($this.hasclass('dropdown-header') && $lisvisible.eq(index + 1).data('optgroup') !== $this.data('optgroup')) { $this.addclass('hidden'); } else { $founddiv = null; } }); if ($founddiv) $founddiv.addclass('hidden'); $searchbase.not('.hidden').first().addclass('active'); } } }); }, _searchstyle: function () { var styles = { begins: 'ibegins', startswith: 'ibegins' }; return styles[this.options.livesearchstyle] || 'icontains'; }, val: function (value) { if (typeof value !== 'undefined') { this.$element.val(value); this.render(); return this.$element; } else { return this.$element.val(); } }, changeall: function (status) { if (!this.multiple) return; if (typeof status === 'undefined') status = true; this.findlis(); var $options = this.$element.find('option'), $lisvisible = this.$lis.not('.divider, .dropdown-header, .disabled, .hidden'), lisvislen = $lisvisible.length, selectedoptions = []; if (status) { if ($lisvisible.filter('.selected').length === $lisvisible.length) return; } else { if ($lisvisible.filter('.selected').length === 0) return; } $lisvisible.toggleclass('selected', status); for (var i = 0; i < lisvislen; i++) { var origindex = $lisvisible[i].getattribute('data-original-index'); selectedoptions[selectedoptions.length] = $options.eq(origindex)[0]; } $(selectedoptions).prop('selected', status); this.render(false); this.toggleplaceholder(); this.$element .triggernative('change'); }, selectall: function () { return this.changeall(true); }, deselectall: function () { return this.changeall(false); }, toggle: function (e) { e = e || window.event; if (e) e.stoppropagation(); this.$button.trigger('click'); }, keydown: function (e) { var $this = $(this), $parent = $this.is('input') ? $this.parent().parent() : $this.parent(), $items, that = $parent.data('this'), index, next, first, last, prev, nextprev, previndex, isactive, selector = ':not(.disabled, .hidden, .dropdown-header, .divider)', keycodemap = { 32: ' ', 48: '0', 49: '1', 50: '2', 51: '3', 52: '4', 53: '5', 54: '6', 55: '7', 56: '8', 57: '9', 59: ';', 65: 'a', 66: 'b', 67: 'c', 68: 'd', 69: 'e', 70: 'f', 71: 'g', 72: 'h', 73: 'i', 74: 'j', 75: 'k', 76: 'l', 77: 'm', 78: 'n', 79: 'o', 80: 'p', 81: 'q', 82: 'r', 83: 's', 84: 't', 85: 'u', 86: 'v', 87: 'w', 88: 'x', 89: 'y', 90: 'z', 96: '0', 97: '1', 98: '2', 99: '3', 100: '4', 101: '5', 102: '6', 103: '7', 104: '8', 105: '9' }; if (that.options.livesearch) $parent = $this.parent().parent(); if (that.options.container) $parent = that.$menu; $items = $('[role="listbox"] li', $parent); isactive = that.$newelement.hasclass('open'); if (!isactive && (e.keycode >= 48 && e.keycode <= 57 || e.keycode >= 96 && e.keycode <= 105 || e.keycode >= 65 && e.keycode <= 90)) { if (!that.options.container) { that.setsize(); that.$menu.parent().addclass('open'); isactive = true; } else { that.$button.trigger('click'); } that.$searchbox.focus(); return; } if (that.options.livesearch) { if (/(^9$|27)/.test(e.keycode.tostring(10)) && isactive) { e.preventdefault(); e.stoppropagation(); that.$menuinner.click(); that.$button.focus(); } // $items contains li elements when livesearch is enabled $items = $('[role="listbox"] li' + selector, $parent); if (!$this.val() && !/(38|40)/.test(e.keycode.tostring(10))) { if ($items.filter('.active').length === 0) { $items = that.$menuinner.find('li'); if (that.options.livesearchnormalize) { $items = $items.filter(':a' + that._searchstyle() + '(' + normalizetobase(keycodemap[e.keycode]) + ')'); } else { $items = $items.filter(':' + that._searchstyle() + '(' + keycodemap[e.keycode] + ')'); } } } } if (!$items.length) return; if (/(38|40)/.test(e.keycode.tostring(10))) { index = $items.index($items.find('a').filter(':focus').parent()); first = $items.filter(selector).first().index(); last = $items.filter(selector).last().index(); next = $items.eq(index).nextall(selector).eq(0).index(); prev = $items.eq(index).prevall(selector).eq(0).index(); nextprev = $items.eq(next).prevall(selector).eq(0).index(); if (that.options.livesearch) { $items.each(function (i) { if (!$(this).hasclass('disabled')) { $(this).data('index', i); } }); index = $items.index($items.filter('.active')); first = $items.first().data('index'); last = $items.last().data('index'); next = $items.eq(index).nextall().eq(0).data('index'); prev = $items.eq(index).prevall().eq(0).data('index'); nextprev = $items.eq(next).prevall().eq(0).data('index'); } previndex = $this.data('previndex'); if (e.keycode == 38) { if (that.options.livesearch) index--; if (index != nextprev && index > prev) index = prev; if (index < first) index = first; if (index == previndex) index = last; } else if (e.keycode == 40) { if (that.options.livesearch) index++; if (index == -1) index = 0; if (index != nextprev && index < next) index = next; if (index > last) index = last; if (index == previndex) index = first; } $this.data('previndex', index); if (!that.options.livesearch) { $items.eq(index).children('a').focus(); } else { e.preventdefault(); if (!$this.hasclass('dropdown-toggle')) { $items.removeclass('active').eq(index).addclass('active').children('a').focus(); $this.focus(); } } } else if (!$this.is('input')) { var keyindex = [], count, prevkey; $items.each(function () { if (!$(this).hasclass('disabled')) { if ($.trim($(this).children('a').text().tolowercase()).substring(0, 1) == keycodemap[e.keycode]) { keyindex.push($(this).index()); } } }); count = $(document).data('keycount'); count++; $(document).data('keycount', count); prevkey = $.trim($(':focus').text().tolowercase()).substring(0, 1); if (prevkey != keycodemap[e.keycode]) { count = 1; $(document).data('keycount', count); } else if (count >= keyindex.length) { $(document).data('keycount', 0); if (count > keyindex.length) count = 1; } $items.eq(keyindex[count - 1]).children('a').focus(); } // select focused option if "enter", "spacebar" or "tab" (when selectontab is true) are pressed inside the menu. if ((/(13|32)/.test(e.keycode.tostring(10)) || (/(^9$)/.test(e.keycode.tostring(10)) && that.options.selectontab)) && isactive) { if (!/(32)/.test(e.keycode.tostring(10))) e.preventdefault(); if (!that.options.livesearch) { var elem = $(':focus'); elem.click(); // bring back focus for multiselects elem.focus(); // prevent screen from scrolling if the user hit the spacebar e.preventdefault(); // fixes spacebar selection of dropdown items in ff & ie $(document).data('spaceselect', true); } else if (!/(32)/.test(e.keycode.tostring(10))) { that.$menuinner.find('.active a').click(); $this.focus(); } $(document).data('keycount', 0); } if ((/(^9$|27)/.test(e.keycode.tostring(10)) && isactive && (that.multiple || that.options.livesearch)) || (/(27)/.test(e.keycode.tostring(10)) && !isactive)) { that.$menu.parent().removeclass('open'); if (that.options.container) that.$newelement.removeclass('open'); that.$button.focus(); } }, mobile: function () { this.$element.addclass('mobile-device'); }, refresh: function () { this.$lis = null; this.liobj = {}; this.reloadli(); this.render(); this.checkdisabled(); this.liheight(true); this.setstyle(); this.setwidth(); if (this.$lis) this.$searchbox.trigger('propertychange'); this.$element.trigger('refreshed.bs.select'); }, hide: function () { this.$newelement.hide(); }, show: function () { this.$newelement.show(); }, remove: function () { this.$newelement.remove(); this.$element.remove(); }, destroy: function () { this.$newelement.before(this.$element).remove(); if (this.$bscontainer) { this.$bscontainer.remove(); } else { this.$menu.remove(); } this.$element .off('.bs.select') .removedata('selectpicker') .removeclass('bs-select-hidden selectpicker'); } }; // selectpicker plugin definition // ============================== function plugin(option) { // get the args of the outer function.. var args = arguments; // the arguments of the function are explicitly re-defined from the argument list, because the shift causes them // to get lost/corrupted in android 2.3 and ie9 #715 #775 var _option = option; [].shift.apply(args); var value; var chain = this.each(function () { var $this = $(this); if ($this.is('select')) { var data = $this.data('selectpicker'), options = typeof _option == 'object' && _option; if (!data) { var config = $.extend({}, selectpicker.defaults, $.fn.selectpicker.defaults || {}, $this.data(), options); config.template = $.extend({}, selectpicker.defaults.template, ($.fn.selectpicker.defaults ? $.fn.selectpicker.defaults.template : {}), $this.data().template, options.template); $this.data('selectpicker', (data = new selectpicker(this, config))); } else if (options) { for (var i in options) { if (options.hasownproperty(i)) { data.options[i] = options[i]; } } } if (typeof _option == 'string') { if (data[_option] instanceof function) { value = data[_option].apply(data, args); } else { value = data.options[_option]; } } } }); if (typeof value !== 'undefined') { //noinspection jsunusedassignment return value; } else { return chain; } } var old = $.fn.selectpicker; $.fn.selectpicker = plugin; $.fn.selectpicker.constructor = selectpicker; // selectpicker no conflict // ======================== $.fn.selectpicker.noconflict = function () { $.fn.selectpicker = old; return this; }; $(document) .data('keycount', 0) .on('keydown.bs.select', '.bootstrap-select [data-toggle=dropdown], .bootstrap-select [role="listbox"], .bs-searchbox input', selectpicker.prototype.keydown) .on('focusin.modal', '.bootstrap-select [data-toggle=dropdown], .bootstrap-select [role="listbox"], .bs-searchbox input', function (e) { e.stoppropagation(); }); // selectpicker data-api // ===================== $(window).on('load.bs.select.data-api', function () { $('.selectpicker').each(function () { var $selectpicker = $(this); plugin.call($selectpicker, $selectpicker.data()); }) }); })(jquery); }));