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