binda 0.0.2 → 0.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (121) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/lib/binda/version.rb +1 -1
  4. data/lib/generators/binda/install/install_generator.rb +11 -2
  5. data/vendor/assets/fonts/bootstrap/glyphicons-halflings-regular.eot +0 -0
  6. data/vendor/assets/fonts/bootstrap/glyphicons-halflings-regular.svg +288 -0
  7. data/vendor/assets/fonts/bootstrap/glyphicons-halflings-regular.ttf +0 -0
  8. data/vendor/assets/fonts/bootstrap/glyphicons-halflings-regular.woff +0 -0
  9. data/vendor/assets/fonts/bootstrap/glyphicons-halflings-regular.woff2 +0 -0
  10. data/vendor/assets/fonts/font-awesome/FontAwesome.otf +0 -0
  11. data/vendor/assets/fonts/font-awesome/fontawesome-webfont.eot +0 -0
  12. data/vendor/assets/fonts/font-awesome/fontawesome-webfont.svg +2671 -0
  13. data/vendor/assets/fonts/font-awesome/fontawesome-webfont.ttf +0 -0
  14. data/vendor/assets/fonts/font-awesome/fontawesome-webfont.woff +0 -0
  15. data/vendor/assets/fonts/font-awesome/fontawesome-webfont.woff2 +0 -0
  16. data/vendor/assets/javascripts/bootstrap-select.js +1895 -0
  17. data/vendor/assets/javascripts/bootstrap/bootstrap-sprockets.js +12 -0
  18. data/vendor/assets/javascripts/bootstrap/bootstrap.js +2377 -0
  19. data/vendor/assets/javascripts/bootstrap/bootstrap.min.js +7 -0
  20. data/vendor/assets/javascripts/bootstrap/bootstrap/affix.js +162 -0
  21. data/vendor/assets/javascripts/bootstrap/bootstrap/alert.js +94 -0
  22. data/vendor/assets/javascripts/bootstrap/bootstrap/button.js +125 -0
  23. data/vendor/assets/javascripts/bootstrap/bootstrap/carousel.js +237 -0
  24. data/vendor/assets/javascripts/bootstrap/bootstrap/collapse.js +212 -0
  25. data/vendor/assets/javascripts/bootstrap/bootstrap/dropdown.js +165 -0
  26. data/vendor/assets/javascripts/bootstrap/bootstrap/modal.js +339 -0
  27. data/vendor/assets/javascripts/bootstrap/bootstrap/popover.js +108 -0
  28. data/vendor/assets/javascripts/bootstrap/bootstrap/scrollspy.js +172 -0
  29. data/vendor/assets/javascripts/bootstrap/bootstrap/tab.js +155 -0
  30. data/vendor/assets/javascripts/bootstrap/bootstrap/tooltip.js +520 -0
  31. data/vendor/assets/javascripts/bootstrap/bootstrap/transition.js +59 -0
  32. data/vendor/assets/stylesheets/bootstrap-select.css +300 -0
  33. data/vendor/assets/stylesheets/bootstrap/_bootstrap-compass.scss +9 -0
  34. data/vendor/assets/stylesheets/bootstrap/_bootstrap-mincer.scss +19 -0
  35. data/vendor/assets/stylesheets/bootstrap/_bootstrap-sprockets.scss +9 -0
  36. data/vendor/assets/stylesheets/bootstrap/bootstrap.scss +58 -0
  37. data/vendor/assets/stylesheets/bootstrap/bootstrap/_alerts.scss +73 -0
  38. data/vendor/assets/stylesheets/bootstrap/bootstrap/_badges.scss +68 -0
  39. data/vendor/assets/stylesheets/bootstrap/bootstrap/_breadcrumbs.scss +28 -0
  40. data/vendor/assets/stylesheets/bootstrap/bootstrap/_button-groups.scss +244 -0
  41. data/vendor/assets/stylesheets/bootstrap/bootstrap/_buttons.scss +168 -0
  42. data/vendor/assets/stylesheets/bootstrap/bootstrap/_carousel.scss +270 -0
  43. data/vendor/assets/stylesheets/bootstrap/bootstrap/_close.scss +36 -0
  44. data/vendor/assets/stylesheets/bootstrap/bootstrap/_code.scss +69 -0
  45. data/vendor/assets/stylesheets/bootstrap/bootstrap/_component-animations.scss +37 -0
  46. data/vendor/assets/stylesheets/bootstrap/bootstrap/_dropdowns.scss +216 -0
  47. data/vendor/assets/stylesheets/bootstrap/bootstrap/_forms.scss +617 -0
  48. data/vendor/assets/stylesheets/bootstrap/bootstrap/_glyphicons.scss +307 -0
  49. data/vendor/assets/stylesheets/bootstrap/bootstrap/_grid.scss +84 -0
  50. data/vendor/assets/stylesheets/bootstrap/bootstrap/_input-groups.scss +171 -0
  51. data/vendor/assets/stylesheets/bootstrap/bootstrap/_jumbotron.scss +54 -0
  52. data/vendor/assets/stylesheets/bootstrap/bootstrap/_labels.scss +66 -0
  53. data/vendor/assets/stylesheets/bootstrap/bootstrap/_list-group.scss +130 -0
  54. data/vendor/assets/stylesheets/bootstrap/bootstrap/_media.scss +66 -0
  55. data/vendor/assets/stylesheets/bootstrap/bootstrap/_mixins.scss +40 -0
  56. data/vendor/assets/stylesheets/bootstrap/bootstrap/_modals.scss +150 -0
  57. data/vendor/assets/stylesheets/bootstrap/bootstrap/_navbar.scss +662 -0
  58. data/vendor/assets/stylesheets/bootstrap/bootstrap/_navs.scss +242 -0
  59. data/vendor/assets/stylesheets/bootstrap/bootstrap/_normalize.scss +424 -0
  60. data/vendor/assets/stylesheets/bootstrap/bootstrap/_pager.scss +54 -0
  61. data/vendor/assets/stylesheets/bootstrap/bootstrap/_pagination.scss +89 -0
  62. data/vendor/assets/stylesheets/bootstrap/bootstrap/_panels.scss +271 -0
  63. data/vendor/assets/stylesheets/bootstrap/bootstrap/_popovers.scss +131 -0
  64. data/vendor/assets/stylesheets/bootstrap/bootstrap/_print.scss +101 -0
  65. data/vendor/assets/stylesheets/bootstrap/bootstrap/_progress-bars.scss +87 -0
  66. data/vendor/assets/stylesheets/bootstrap/bootstrap/_responsive-embed.scss +35 -0
  67. data/vendor/assets/stylesheets/bootstrap/bootstrap/_responsive-utilities.scss +179 -0
  68. data/vendor/assets/stylesheets/bootstrap/bootstrap/_scaffolding.scss +161 -0
  69. data/vendor/assets/stylesheets/bootstrap/bootstrap/_tables.scss +234 -0
  70. data/vendor/assets/stylesheets/bootstrap/bootstrap/_theme.scss +291 -0
  71. data/vendor/assets/stylesheets/bootstrap/bootstrap/_thumbnails.scss +38 -0
  72. data/vendor/assets/stylesheets/bootstrap/bootstrap/_tooltip.scss +101 -0
  73. data/vendor/assets/stylesheets/bootstrap/bootstrap/_type.scss +298 -0
  74. data/vendor/assets/stylesheets/bootstrap/bootstrap/_utilities.scss +55 -0
  75. data/vendor/assets/stylesheets/bootstrap/bootstrap/_variables.scss +875 -0
  76. data/vendor/assets/stylesheets/bootstrap/bootstrap/_wells.scss +29 -0
  77. data/vendor/assets/stylesheets/bootstrap/bootstrap/mixins/_alerts.scss +14 -0
  78. data/vendor/assets/stylesheets/bootstrap/bootstrap/mixins/_background-variant.scss +12 -0
  79. data/vendor/assets/stylesheets/bootstrap/bootstrap/mixins/_border-radius.scss +18 -0
  80. data/vendor/assets/stylesheets/bootstrap/bootstrap/mixins/_buttons.scss +65 -0
  81. data/vendor/assets/stylesheets/bootstrap/bootstrap/mixins/_center-block.scss +7 -0
  82. data/vendor/assets/stylesheets/bootstrap/bootstrap/mixins/_clearfix.scss +22 -0
  83. data/vendor/assets/stylesheets/bootstrap/bootstrap/mixins/_forms.scss +88 -0
  84. data/vendor/assets/stylesheets/bootstrap/bootstrap/mixins/_gradients.scss +58 -0
  85. data/vendor/assets/stylesheets/bootstrap/bootstrap/mixins/_grid-framework.scss +81 -0
  86. data/vendor/assets/stylesheets/bootstrap/bootstrap/mixins/_grid.scss +122 -0
  87. data/vendor/assets/stylesheets/bootstrap/bootstrap/mixins/_hide-text.scss +21 -0
  88. data/vendor/assets/stylesheets/bootstrap/bootstrap/mixins/_image.scss +33 -0
  89. data/vendor/assets/stylesheets/bootstrap/bootstrap/mixins/_labels.scss +12 -0
  90. data/vendor/assets/stylesheets/bootstrap/bootstrap/mixins/_list-group.scss +32 -0
  91. data/vendor/assets/stylesheets/bootstrap/bootstrap/mixins/_nav-divider.scss +10 -0
  92. data/vendor/assets/stylesheets/bootstrap/bootstrap/mixins/_nav-vertical-align.scss +9 -0
  93. data/vendor/assets/stylesheets/bootstrap/bootstrap/mixins/_opacity.scss +8 -0
  94. data/vendor/assets/stylesheets/bootstrap/bootstrap/mixins/_pagination.scss +24 -0
  95. data/vendor/assets/stylesheets/bootstrap/bootstrap/mixins/_panels.scss +24 -0
  96. data/vendor/assets/stylesheets/bootstrap/bootstrap/mixins/_progress-bar.scss +10 -0
  97. data/vendor/assets/stylesheets/bootstrap/bootstrap/mixins/_reset-filter.scss +8 -0
  98. data/vendor/assets/stylesheets/bootstrap/bootstrap/mixins/_reset-text.scss +18 -0
  99. data/vendor/assets/stylesheets/bootstrap/bootstrap/mixins/_resize.scss +6 -0
  100. data/vendor/assets/stylesheets/bootstrap/bootstrap/mixins/_responsive-visibility.scss +21 -0
  101. data/vendor/assets/stylesheets/bootstrap/bootstrap/mixins/_size.scss +10 -0
  102. data/vendor/assets/stylesheets/bootstrap/bootstrap/mixins/_tab-focus.scss +9 -0
  103. data/vendor/assets/stylesheets/bootstrap/bootstrap/mixins/_table-row.scss +28 -0
  104. data/vendor/assets/stylesheets/bootstrap/bootstrap/mixins/_text-emphasis.scss +12 -0
  105. data/vendor/assets/stylesheets/bootstrap/bootstrap/mixins/_text-overflow.scss +8 -0
  106. data/vendor/assets/stylesheets/bootstrap/bootstrap/mixins/_vendor-prefixes.scss +222 -0
  107. data/vendor/assets/stylesheets/font-awesome/_animated.scss +34 -0
  108. data/vendor/assets/stylesheets/font-awesome/_bordered-pulled.scss +25 -0
  109. data/vendor/assets/stylesheets/font-awesome/_core.scss +12 -0
  110. data/vendor/assets/stylesheets/font-awesome/_fixed-width.scss +6 -0
  111. data/vendor/assets/stylesheets/font-awesome/_icons.scss +789 -0
  112. data/vendor/assets/stylesheets/font-awesome/_larger.scss +13 -0
  113. data/vendor/assets/stylesheets/font-awesome/_list.scss +19 -0
  114. data/vendor/assets/stylesheets/font-awesome/_mixins.scss +60 -0
  115. data/vendor/assets/stylesheets/font-awesome/_path.scss +15 -0
  116. data/vendor/assets/stylesheets/font-awesome/_rotated-flipped.scss +20 -0
  117. data/vendor/assets/stylesheets/font-awesome/_screen-reader.scss +5 -0
  118. data/vendor/assets/stylesheets/font-awesome/_stacked.scss +20 -0
  119. data/vendor/assets/stylesheets/font-awesome/_variables.scss +800 -0
  120. data/vendor/assets/stylesheets/font-awesome/font-awesome.scss +18 -0
  121. metadata +119 -3
@@ -0,0 +1,1895 @@
1
+ /*!
2
+ * Bootstrap-select v1.12.2 (http://silviomoreto.github.io/bootstrap-select)
3
+ *
4
+ * Copyright 2013-2017 bootstrap-select
5
+ * Licensed under MIT (https://github.com/silviomoreto/bootstrap-select/blob/master/LICENSE)
6
+ */
7
+
8
+ (function (root, factory) {
9
+ if (typeof define === 'function' && define.amd) {
10
+ // AMD. Register as an anonymous module unless amdModuleId is set
11
+ define(["jquery"], function (a0) {
12
+ return (factory(a0));
13
+ });
14
+ } else if (typeof module === 'object' && module.exports) {
15
+ // Node. Does not work with strict CommonJS, but
16
+ // only CommonJS-like environments that support module.exports,
17
+ // like Node.
18
+ module.exports = factory(require("jquery"));
19
+ } else {
20
+ factory(root["jQuery"]);
21
+ }
22
+ }(this, function (jQuery) {
23
+
24
+ (function ($) {
25
+ 'use strict';
26
+
27
+ //<editor-fold desc="Shims">
28
+ if (!String.prototype.includes) {
29
+ (function () {
30
+ 'use strict'; // needed to support `apply`/`call` with `undefined`/`null`
31
+ var toString = {}.toString;
32
+ var defineProperty = (function () {
33
+ // IE 8 only supports `Object.defineProperty` on DOM elements
34
+ try {
35
+ var object = {};
36
+ var $defineProperty = Object.defineProperty;
37
+ var result = $defineProperty(object, object, object) && $defineProperty;
38
+ } catch (error) {
39
+ }
40
+ return result;
41
+ }());
42
+ var indexOf = ''.indexOf;
43
+ var includes = function (search) {
44
+ if (this == null) {
45
+ throw new TypeError();
46
+ }
47
+ var string = String(this);
48
+ if (search && toString.call(search) == '[object RegExp]') {
49
+ throw new TypeError();
50
+ }
51
+ var stringLength = string.length;
52
+ var searchString = String(search);
53
+ var searchLength = searchString.length;
54
+ var position = arguments.length > 1 ? arguments[1] : undefined;
55
+ // `ToInteger`
56
+ var pos = position ? Number(position) : 0;
57
+ if (pos != pos) { // better `isNaN`
58
+ pos = 0;
59
+ }
60
+ var start = Math.min(Math.max(pos, 0), stringLength);
61
+ // Avoid the `indexOf` call if no match is possible
62
+ if (searchLength + start > stringLength) {
63
+ return false;
64
+ }
65
+ return indexOf.call(string, searchString, pos) != -1;
66
+ };
67
+ if (defineProperty) {
68
+ defineProperty(String.prototype, 'includes', {
69
+ 'value': includes,
70
+ 'configurable': true,
71
+ 'writable': true
72
+ });
73
+ } else {
74
+ String.prototype.includes = includes;
75
+ }
76
+ }());
77
+ }
78
+
79
+ if (!String.prototype.startsWith) {
80
+ (function () {
81
+ 'use strict'; // needed to support `apply`/`call` with `undefined`/`null`
82
+ var defineProperty = (function () {
83
+ // IE 8 only supports `Object.defineProperty` on DOM elements
84
+ try {
85
+ var object = {};
86
+ var $defineProperty = Object.defineProperty;
87
+ var result = $defineProperty(object, object, object) && $defineProperty;
88
+ } catch (error) {
89
+ }
90
+ return result;
91
+ }());
92
+ var toString = {}.toString;
93
+ var startsWith = function (search) {
94
+ if (this == null) {
95
+ throw new TypeError();
96
+ }
97
+ var string = String(this);
98
+ if (search && toString.call(search) == '[object RegExp]') {
99
+ throw new TypeError();
100
+ }
101
+ var stringLength = string.length;
102
+ var searchString = String(search);
103
+ var searchLength = searchString.length;
104
+ var position = arguments.length > 1 ? arguments[1] : undefined;
105
+ // `ToInteger`
106
+ var pos = position ? Number(position) : 0;
107
+ if (pos != pos) { // better `isNaN`
108
+ pos = 0;
109
+ }
110
+ var start = Math.min(Math.max(pos, 0), stringLength);
111
+ // Avoid the `indexOf` call if no match is possible
112
+ if (searchLength + start > stringLength) {
113
+ return false;
114
+ }
115
+ var index = -1;
116
+ while (++index < searchLength) {
117
+ if (string.charCodeAt(start + index) != searchString.charCodeAt(index)) {
118
+ return false;
119
+ }
120
+ }
121
+ return true;
122
+ };
123
+ if (defineProperty) {
124
+ defineProperty(String.prototype, 'startsWith', {
125
+ 'value': startsWith,
126
+ 'configurable': true,
127
+ 'writable': true
128
+ });
129
+ } else {
130
+ String.prototype.startsWith = startsWith;
131
+ }
132
+ }());
133
+ }
134
+
135
+ if (!Object.keys) {
136
+ Object.keys = function (
137
+ o, // object
138
+ k, // key
139
+ r // result array
140
+ ){
141
+ // initialize object and result
142
+ r=[];
143
+ // iterate over object keys
144
+ for (k in o)
145
+ // fill result array with non-prototypical keys
146
+ r.hasOwnProperty.call(o, k) && r.push(k);
147
+ // return result
148
+ return r;
149
+ };
150
+ }
151
+
152
+ // set data-selected on select element if the value has been programmatically selected
153
+ // prior to initialization of bootstrap-select
154
+ // * consider removing or replacing an alternative method *
155
+ var valHooks = {
156
+ useDefault: false,
157
+ _set: $.valHooks.select.set
158
+ };
159
+
160
+ $.valHooks.select.set = function(elem, value) {
161
+ if (value && !valHooks.useDefault) $(elem).data('selected', true);
162
+
163
+ return valHooks._set.apply(this, arguments);
164
+ };
165
+
166
+ var changed_arguments = null;
167
+ $.fn.triggerNative = function (eventName) {
168
+ var el = this[0],
169
+ event;
170
+
171
+ if (el.dispatchEvent) { // for modern browsers & IE9+
172
+ if (typeof Event === 'function') {
173
+ // For modern browsers
174
+ event = new Event(eventName, {
175
+ bubbles: true
176
+ });
177
+ } else {
178
+ // For IE since it doesn't support Event constructor
179
+ event = document.createEvent('Event');
180
+ event.initEvent(eventName, true, false);
181
+ }
182
+
183
+ el.dispatchEvent(event);
184
+ } else if (el.fireEvent) { // for IE8
185
+ event = document.createEventObject();
186
+ event.eventType = eventName;
187
+ el.fireEvent('on' + eventName, event);
188
+ } else {
189
+ // fall back to jQuery.trigger
190
+ this.trigger(eventName);
191
+ }
192
+ };
193
+ //</editor-fold>
194
+
195
+ // Case insensitive contains search
196
+ $.expr.pseudos.icontains = function (obj, index, meta) {
197
+ var $obj = $(obj);
198
+ var haystack = ($obj.data('tokens') || $obj.text()).toString().toUpperCase();
199
+ return haystack.includes(meta[3].toUpperCase());
200
+ };
201
+
202
+ // Case insensitive begins search
203
+ $.expr.pseudos.ibegins = function (obj, index, meta) {
204
+ var $obj = $(obj);
205
+ var haystack = ($obj.data('tokens') || $obj.text()).toString().toUpperCase();
206
+ return haystack.startsWith(meta[3].toUpperCase());
207
+ };
208
+
209
+ // Case and accent insensitive contains search
210
+ $.expr.pseudos.aicontains = function (obj, index, meta) {
211
+ var $obj = $(obj);
212
+ var haystack = ($obj.data('tokens') || $obj.data('normalizedText') || $obj.text()).toString().toUpperCase();
213
+ return haystack.includes(meta[3].toUpperCase());
214
+ };
215
+
216
+ // Case and accent insensitive begins search
217
+ $.expr.pseudos.aibegins = function (obj, index, meta) {
218
+ var $obj = $(obj);
219
+ var haystack = ($obj.data('tokens') || $obj.data('normalizedText') || $obj.text()).toString().toUpperCase();
220
+ return haystack.startsWith(meta[3].toUpperCase());
221
+ };
222
+
223
+ /**
224
+ * Remove all diatrics from the given text.
225
+ * @access private
226
+ * @param {String} text
227
+ * @returns {String}
228
+ */
229
+ function normalizeToBase(text) {
230
+ var rExps = [
231
+ {re: /[\xC0-\xC6]/g, ch: "A"},
232
+ {re: /[\xE0-\xE6]/g, ch: "a"},
233
+ {re: /[\xC8-\xCB]/g, ch: "E"},
234
+ {re: /[\xE8-\xEB]/g, ch: "e"},
235
+ {re: /[\xCC-\xCF]/g, ch: "I"},
236
+ {re: /[\xEC-\xEF]/g, ch: "i"},
237
+ {re: /[\xD2-\xD6]/g, ch: "O"},
238
+ {re: /[\xF2-\xF6]/g, ch: "o"},
239
+ {re: /[\xD9-\xDC]/g, ch: "U"},
240
+ {re: /[\xF9-\xFC]/g, ch: "u"},
241
+ {re: /[\xC7-\xE7]/g, ch: "c"},
242
+ {re: /[\xD1]/g, ch: "N"},
243
+ {re: /[\xF1]/g, ch: "n"}
244
+ ];
245
+ $.each(rExps, function () {
246
+ text = text ? text.replace(this.re, this.ch) : '';
247
+ });
248
+ return text;
249
+ }
250
+
251
+
252
+ // List of HTML entities for escaping.
253
+ var escapeMap = {
254
+ '&': '&amp;',
255
+ '<': '&lt;',
256
+ '>': '&gt;',
257
+ '"': '&quot;',
258
+ "'": '&#x27;',
259
+ '`': '&#x60;'
260
+ };
261
+
262
+ var unescapeMap = {
263
+ '&amp;': '&',
264
+ '&lt;': '<',
265
+ '&gt;': '>',
266
+ '&quot;': '"',
267
+ '&#x27;': "'",
268
+ '&#x60;': '`'
269
+ };
270
+
271
+ // Functions for escaping and unescaping strings to/from HTML interpolation.
272
+ var createEscaper = function(map) {
273
+ var escaper = function(match) {
274
+ return map[match];
275
+ };
276
+ // Regexes for identifying a key that needs to be escaped.
277
+ var source = '(?:' + Object.keys(map).join('|') + ')';
278
+ var testRegexp = RegExp(source);
279
+ var replaceRegexp = RegExp(source, 'g');
280
+ return function(string) {
281
+ string = string == null ? '' : '' + string;
282
+ return testRegexp.test(string) ? string.replace(replaceRegexp, escaper) : string;
283
+ };
284
+ };
285
+
286
+ var htmlEscape = createEscaper(escapeMap);
287
+ var htmlUnescape = createEscaper(unescapeMap);
288
+
289
+ var Selectpicker = function (element, options) {
290
+ // bootstrap-select has been initialized - revert valHooks.select.set back to its original function
291
+ if (!valHooks.useDefault) {
292
+ $.valHooks.select.set = valHooks._set;
293
+ valHooks.useDefault = true;
294
+ }
295
+
296
+ this.$element = $(element);
297
+ this.$newElement = null;
298
+ this.$button = null;
299
+ this.$menu = null;
300
+ this.$lis = null;
301
+ this.options = options;
302
+
303
+ // 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
304
+ // data-attribute)
305
+ if (this.options.title === null) {
306
+ this.options.title = this.$element.attr('title');
307
+ }
308
+
309
+ // Format window padding
310
+ var winPad = this.options.windowPadding;
311
+ if (typeof winPad === 'number') {
312
+ this.options.windowPadding = [winPad, winPad, winPad, winPad];
313
+ }
314
+
315
+ //Expose public methods
316
+ this.val = Selectpicker.prototype.val;
317
+ this.render = Selectpicker.prototype.render;
318
+ this.refresh = Selectpicker.prototype.refresh;
319
+ this.setStyle = Selectpicker.prototype.setStyle;
320
+ this.selectAll = Selectpicker.prototype.selectAll;
321
+ this.deselectAll = Selectpicker.prototype.deselectAll;
322
+ this.destroy = Selectpicker.prototype.destroy;
323
+ this.remove = Selectpicker.prototype.remove;
324
+ this.show = Selectpicker.prototype.show;
325
+ this.hide = Selectpicker.prototype.hide;
326
+
327
+ this.init();
328
+ };
329
+
330
+ Selectpicker.VERSION = '1.12.2';
331
+
332
+ // part of this is duplicated in i18n/defaults-en_US.js. Make sure to update both.
333
+ Selectpicker.DEFAULTS = {
334
+ noneSelectedText: 'Nothing selected',
335
+ noneResultsText: 'No results matched {0}',
336
+ countSelectedText: function (numSelected, numTotal) {
337
+ return (numSelected == 1) ? "{0} item selected" : "{0} items selected";
338
+ },
339
+ maxOptionsText: function (numAll, numGroup) {
340
+ return [
341
+ (numAll == 1) ? 'Limit reached ({n} item max)' : 'Limit reached ({n} items max)',
342
+ (numGroup == 1) ? 'Group limit reached ({n} item max)' : 'Group limit reached ({n} items max)'
343
+ ];
344
+ },
345
+ selectAllText: 'Select All',
346
+ deselectAllText: 'Deselect All',
347
+ doneButton: false,
348
+ doneButtonText: 'Close',
349
+ multipleSeparator: ', ',
350
+ styleBase: 'btn',
351
+ style: 'btn-default',
352
+ size: 'auto',
353
+ title: null,
354
+ selectedTextFormat: 'values',
355
+ width: false,
356
+ container: false,
357
+ hideDisabled: false,
358
+ showSubtext: false,
359
+ showIcon: true,
360
+ showContent: true,
361
+ dropupAuto: true,
362
+ header: false,
363
+ liveSearch: false,
364
+ liveSearchPlaceholder: null,
365
+ liveSearchNormalize: false,
366
+ liveSearchStyle: 'contains',
367
+ actionsBox: false,
368
+ iconBase: 'glyphicon',
369
+ tickIcon: 'glyphicon-ok',
370
+ showTick: false,
371
+ template: {
372
+ caret: '<span class="caret"></span>'
373
+ },
374
+ maxOptions: false,
375
+ mobile: false,
376
+ selectOnTab: false,
377
+ dropdownAlignRight: false,
378
+ windowPadding: 0
379
+ };
380
+
381
+ Selectpicker.prototype = {
382
+
383
+ constructor: Selectpicker,
384
+
385
+ init: function () {
386
+ var that = this,
387
+ id = this.$element.attr('id');
388
+
389
+ this.$element.addClass('bs-select-hidden');
390
+
391
+ // store originalIndex (key) and newIndex (value) in this.liObj for fast accessibility
392
+ // allows us to do this.$lis.eq(that.liObj[index]) instead of this.$lis.filter('[data-original-index="' + index + '"]')
393
+ this.liObj = {};
394
+ this.multiple = this.$element.prop('multiple');
395
+ this.autofocus = this.$element.prop('autofocus');
396
+ this.$newElement = this.createView();
397
+ this.$element
398
+ .after(this.$newElement)
399
+ .appendTo(this.$newElement);
400
+ this.$button = this.$newElement.children('button');
401
+ this.$menu = this.$newElement.children('.dropdown-menu');
402
+ this.$menuInner = this.$menu.children('.inner');
403
+ this.$searchbox = this.$menu.find('input');
404
+
405
+ this.$element.removeClass('bs-select-hidden');
406
+
407
+ if (this.options.dropdownAlignRight === true) this.$menu.addClass('dropdown-menu-right');
408
+
409
+ if (typeof id !== 'undefined') {
410
+ this.$button.attr('data-id', id);
411
+ $('label[for="' + id + '"]').click(function (e) {
412
+ e.preventDefault();
413
+ that.$button.focus();
414
+ });
415
+ }
416
+
417
+ this.checkDisabled();
418
+ this.clickListener();
419
+ if (this.options.liveSearch) this.liveSearchListener();
420
+ this.render();
421
+ this.setStyle();
422
+ this.setWidth();
423
+ if (this.options.container) this.selectPosition();
424
+ this.$menu.data('this', this);
425
+ this.$newElement.data('this', this);
426
+ if (this.options.mobile) this.mobile();
427
+
428
+ this.$newElement.on({
429
+ 'hide.bs.dropdown': function (e) {
430
+ that.$menuInner.attr('aria-expanded', false);
431
+ that.$element.trigger('hide.bs.select', e);
432
+ },
433
+ 'hidden.bs.dropdown': function (e) {
434
+ that.$element.trigger('hidden.bs.select', e);
435
+ },
436
+ 'show.bs.dropdown': function (e) {
437
+ that.$menuInner.attr('aria-expanded', true);
438
+ that.$element.trigger('show.bs.select', e);
439
+ },
440
+ 'shown.bs.dropdown': function (e) {
441
+ that.$element.trigger('shown.bs.select', e);
442
+ }
443
+ });
444
+
445
+ if (that.$element[0].hasAttribute('required')) {
446
+ this.$element.on('invalid', function () {
447
+ that.$button
448
+ .addClass('bs-invalid')
449
+ .focus();
450
+
451
+ that.$element.on({
452
+ 'focus.bs.select': function () {
453
+ that.$button.focus();
454
+ that.$element.off('focus.bs.select');
455
+ },
456
+ 'shown.bs.select': function () {
457
+ that.$element
458
+ .val(that.$element.val()) // set the value to hide the validation message in Chrome when menu is opened
459
+ .off('shown.bs.select');
460
+ },
461
+ 'rendered.bs.select': function () {
462
+ // if select is no longer invalid, remove the bs-invalid class
463
+ if (this.validity.valid) that.$button.removeClass('bs-invalid');
464
+ that.$element.off('rendered.bs.select');
465
+ }
466
+ });
467
+ });
468
+ }
469
+
470
+ setTimeout(function () {
471
+ that.$element.trigger('loaded.bs.select');
472
+ });
473
+ },
474
+
475
+ createDropdown: function () {
476
+ // Options
477
+ // If we are multiple or showTick option is set, then add the show-tick class
478
+ var showTick = (this.multiple || this.options.showTick) ? ' show-tick' : '',
479
+ inputGroup = this.$element.parent().hasClass('input-group') ? ' input-group-btn' : '',
480
+ autofocus = this.autofocus ? ' autofocus' : '';
481
+ // Elements
482
+ var header = this.options.header ? '<div class="popover-title"><button type="button" class="close" aria-hidden="true">&times;</button>' + this.options.header + '</div>' : '';
483
+ var searchbox = this.options.liveSearch ?
484
+ '<div class="bs-searchbox">' +
485
+ '<input type="text" class="form-control" autocomplete="off"' +
486
+ (null === this.options.liveSearchPlaceholder ? '' : ' placeholder="' + htmlEscape(this.options.liveSearchPlaceholder) + '"') + ' role="textbox" aria-label="Search">' +
487
+ '</div>'
488
+ : '';
489
+ var actionsbox = this.multiple && this.options.actionsBox ?
490
+ '<div class="bs-actionsbox">' +
491
+ '<div class="btn-group btn-group-sm btn-block">' +
492
+ '<button type="button" class="actions-btn bs-select-all btn btn-default">' +
493
+ this.options.selectAllText +
494
+ '</button>' +
495
+ '<button type="button" class="actions-btn bs-deselect-all btn btn-default">' +
496
+ this.options.deselectAllText +
497
+ '</button>' +
498
+ '</div>' +
499
+ '</div>'
500
+ : '';
501
+ var donebutton = this.multiple && this.options.doneButton ?
502
+ '<div class="bs-donebutton">' +
503
+ '<div class="btn-group btn-block">' +
504
+ '<button type="button" class="btn btn-sm btn-default">' +
505
+ this.options.doneButtonText +
506
+ '</button>' +
507
+ '</div>' +
508
+ '</div>'
509
+ : '';
510
+ var drop =
511
+ '<div class="btn-group bootstrap-select' + showTick + inputGroup + '">' +
512
+ '<button type="button" class="' + this.options.styleBase + ' dropdown-toggle" data-toggle="dropdown"' + autofocus + ' role="button">' +
513
+ '<span class="filter-option pull-left"></span>&nbsp;' +
514
+ '<span class="bs-caret">' +
515
+ this.options.template.caret +
516
+ '</span>' +
517
+ '</button>' +
518
+ '<div class="dropdown-menu open" role="combobox">' +
519
+ header +
520
+ searchbox +
521
+ actionsbox +
522
+ '<ul class="dropdown-menu inner" role="listbox" aria-expanded="false">' +
523
+ '</ul>' +
524
+ donebutton +
525
+ '</div>' +
526
+ '</div>';
527
+
528
+ return $(drop);
529
+ },
530
+
531
+ createView: function () {
532
+ var $drop = this.createDropdown(),
533
+ li = this.createLi();
534
+
535
+ $drop.find('ul')[0].innerHTML = li;
536
+ return $drop;
537
+ },
538
+
539
+ reloadLi: function () {
540
+ // rebuild
541
+ var li = this.createLi();
542
+ this.$menuInner[0].innerHTML = li;
543
+ },
544
+
545
+ createLi: function () {
546
+ var that = this,
547
+ _li = [],
548
+ optID = 0,
549
+ titleOption = document.createElement('option'),
550
+ liIndex = -1; // increment liIndex whenever a new <li> element is created to ensure liObj is correct
551
+
552
+ // Helper functions
553
+ /**
554
+ * @param content
555
+ * @param [index]
556
+ * @param [classes]
557
+ * @param [optgroup]
558
+ * @returns {string}
559
+ */
560
+ var generateLI = function (content, index, classes, optgroup) {
561
+ return '<li' +
562
+ ((typeof classes !== 'undefined' & '' !== classes) ? ' class="' + classes + '"' : '') +
563
+ ((typeof index !== 'undefined' & null !== index) ? ' data-original-index="' + index + '"' : '') +
564
+ ((typeof optgroup !== 'undefined' & null !== optgroup) ? 'data-optgroup="' + optgroup + '"' : '') +
565
+ '>' + content + '</li>';
566
+ };
567
+
568
+ /**
569
+ * @param text
570
+ * @param [classes]
571
+ * @param [inline]
572
+ * @param [tokens]
573
+ * @returns {string}
574
+ */
575
+ var generateA = function (text, classes, inline, tokens) {
576
+ return '<a tabindex="0"' +
577
+ (typeof classes !== 'undefined' ? ' class="' + classes + '"' : '') +
578
+ (inline ? ' style="' + inline + '"' : '') +
579
+ (that.options.liveSearchNormalize ? ' data-normalized-text="' + normalizeToBase(htmlEscape($(text).html())) + '"' : '') +
580
+ (typeof tokens !== 'undefined' || tokens !== null ? ' data-tokens="' + tokens + '"' : '') +
581
+ ' role="option">' + text +
582
+ '<span class="' + that.options.iconBase + ' ' + that.options.tickIcon + ' check-mark"></span>' +
583
+ '</a>';
584
+ };
585
+
586
+ if (this.options.title && !this.multiple) {
587
+ // this option doesn't create a new <li> element, but does add a new option, so liIndex is decreased
588
+ // since liObj is recalculated on every refresh, liIndex needs to be decreased even if the titleOption is already appended
589
+ liIndex--;
590
+
591
+ if (!this.$element.find('.bs-title-option').length) {
592
+ // Use native JS to prepend option (faster)
593
+ var element = this.$element[0];
594
+ titleOption.className = 'bs-title-option';
595
+ titleOption.innerHTML = this.options.title;
596
+ titleOption.value = '';
597
+ element.insertBefore(titleOption, element.firstChild);
598
+ // Check if selected or data-selected attribute is already set on an option. If not, select the titleOption option.
599
+ // the selected item may have been changed by user or programmatically before the bootstrap select plugin runs,
600
+ // if so, the select will have the data-selected attribute
601
+ var $opt = $(element.options[element.selectedIndex]);
602
+ if ($opt.attr('selected') === undefined && this.$element.data('selected') === undefined) {
603
+ titleOption.selected = true;
604
+ }
605
+ }
606
+ }
607
+
608
+ this.$element.find('option').each(function (index) {
609
+ var $this = $(this);
610
+
611
+ liIndex++;
612
+
613
+ if ($this.hasClass('bs-title-option')) return;
614
+
615
+ // Get the class and text for the option
616
+ var optionClass = this.className || '',
617
+ inline = this.style.cssText,
618
+ text = $this.data('content') ? $this.data('content') : $this.html(),
619
+ tokens = $this.data('tokens') ? $this.data('tokens') : null,
620
+ subtext = typeof $this.data('subtext') !== 'undefined' ? '<small class="text-muted">' + $this.data('subtext') + '</small>' : '',
621
+ icon = typeof $this.data('icon') !== 'undefined' ? '<span class="' + that.options.iconBase + ' ' + $this.data('icon') + '"></span> ' : '',
622
+ $parent = $this.parent(),
623
+ isOptgroup = $parent[0].tagName === 'OPTGROUP',
624
+ isOptgroupDisabled = isOptgroup && $parent[0].disabled,
625
+ isDisabled = this.disabled || isOptgroupDisabled;
626
+
627
+ if (icon !== '' && isDisabled) {
628
+ icon = '<span>' + icon + '</span>';
629
+ }
630
+
631
+ if (that.options.hideDisabled && (isDisabled && !isOptgroup || isOptgroupDisabled)) {
632
+ liIndex--;
633
+ return;
634
+ }
635
+
636
+ if (!$this.data('content')) {
637
+ // Prepend any icon and append any subtext to the main text.
638
+ text = icon + '<span class="text">' + text + subtext + '</span>';
639
+ }
640
+
641
+ if (isOptgroup && $this.data('divider') !== true) {
642
+ if (that.options.hideDisabled && isDisabled) {
643
+ if ($parent.data('allOptionsDisabled') === undefined) {
644
+ var $options = $parent.children();
645
+ $parent.data('allOptionsDisabled', $options.filter(':disabled').length === $options.length);
646
+ }
647
+
648
+ if ($parent.data('allOptionsDisabled')) {
649
+ liIndex--;
650
+ return;
651
+ }
652
+ }
653
+
654
+ var optGroupClass = ' ' + $parent[0].className || '';
655
+
656
+ if ($this.index() === 0) { // Is it the first option of the optgroup?
657
+ optID += 1;
658
+
659
+ // Get the opt group label
660
+ var label = $parent[0].label,
661
+ labelSubtext = typeof $parent.data('subtext') !== 'undefined' ? '<small class="text-muted">' + $parent.data('subtext') + '</small>' : '',
662
+ labelIcon = $parent.data('icon') ? '<span class="' + that.options.iconBase + ' ' + $parent.data('icon') + '"></span> ' : '';
663
+
664
+ label = labelIcon + '<span class="text">' + htmlEscape(label) + labelSubtext + '</span>';
665
+
666
+ if (index !== 0 && _li.length > 0) { // Is it NOT the first option of the select && are there elements in the dropdown?
667
+ liIndex++;
668
+ _li.push(generateLI('', null, 'divider', optID + 'div'));
669
+ }
670
+ liIndex++;
671
+ _li.push(generateLI(label, null, 'dropdown-header' + optGroupClass, optID));
672
+ }
673
+
674
+ if (that.options.hideDisabled && isDisabled) {
675
+ liIndex--;
676
+ return;
677
+ }
678
+
679
+ _li.push(generateLI(generateA(text, 'opt ' + optionClass + optGroupClass, inline, tokens), index, '', optID));
680
+ } else if ($this.data('divider') === true) {
681
+ _li.push(generateLI('', index, 'divider'));
682
+ } else if ($this.data('hidden') === true) {
683
+ _li.push(generateLI(generateA(text, optionClass, inline, tokens), index, 'hidden is-hidden'));
684
+ } else {
685
+ var showDivider = this.previousElementSibling && this.previousElementSibling.tagName === 'OPTGROUP';
686
+
687
+ // if previous element is not an optgroup and hideDisabled is true
688
+ if (!showDivider && that.options.hideDisabled) {
689
+ // get previous elements
690
+ var $prev = $(this).prevAll();
691
+
692
+ for (var i = 0; i < $prev.length; i++) {
693
+ // find the first element in the previous elements that is an optgroup
694
+ if ($prev[i].tagName === 'OPTGROUP') {
695
+ var optGroupDistance = 0;
696
+
697
+ // loop through the options in between the current option and the optgroup
698
+ // and check if they are hidden or disabled
699
+ for (var d = 0; d < i; d++) {
700
+ var prevOption = $prev[d];
701
+ if (prevOption.disabled || $(prevOption).data('hidden') === true) optGroupDistance++;
702
+ }
703
+
704
+ // if all of the options between the current option and the optgroup are hidden or disabled, show the divider
705
+ if (optGroupDistance === i) showDivider = true;
706
+
707
+ break;
708
+ }
709
+ }
710
+ }
711
+
712
+ if (showDivider) {
713
+ liIndex++;
714
+ _li.push(generateLI('', null, 'divider', optID + 'div'));
715
+ }
716
+ _li.push(generateLI(generateA(text, optionClass, inline, tokens), index));
717
+ }
718
+
719
+ that.liObj[index] = liIndex;
720
+ });
721
+
722
+ //If we are not multiple, we don't have a selected item, and we don't have a title, select the first element so something is set in the button
723
+ if (!this.multiple && this.$element.find('option:selected').length === 0 && !this.options.title) {
724
+ this.$element.find('option').eq(0).prop('selected', true).attr('selected', 'selected');
725
+ }
726
+
727
+ return _li.join('');
728
+ },
729
+
730
+ findLis: function () {
731
+ if (this.$lis == null) this.$lis = this.$menu.find('li');
732
+ return this.$lis;
733
+ },
734
+
735
+ /**
736
+ * @param [updateLi] defaults to true
737
+ */
738
+ render: function (updateLi) {
739
+ var that = this,
740
+ notDisabled;
741
+
742
+ //Update the LI to match the SELECT
743
+ if (updateLi !== false) {
744
+ this.$element.find('option').each(function (index) {
745
+ var $lis = that.findLis().eq(that.liObj[index]);
746
+
747
+ that.setDisabled(index, this.disabled || this.parentNode.tagName === 'OPTGROUP' && this.parentNode.disabled, $lis);
748
+ that.setSelected(index, this.selected, $lis);
749
+ });
750
+ }
751
+
752
+ this.togglePlaceholder();
753
+
754
+ this.tabIndex();
755
+
756
+ var selectedItems = this.$element.find('option').map(function () {
757
+ if (this.selected) {
758
+ if (that.options.hideDisabled && (this.disabled || this.parentNode.tagName === 'OPTGROUP' && this.parentNode.disabled)) return;
759
+
760
+ var $this = $(this),
761
+ icon = $this.data('icon') && that.options.showIcon ? '<i class="' + that.options.iconBase + ' ' + $this.data('icon') + '"></i> ' : '',
762
+ subtext;
763
+
764
+ if (that.options.showSubtext && $this.data('subtext') && !that.multiple) {
765
+ subtext = ' <small class="text-muted">' + $this.data('subtext') + '</small>';
766
+ } else {
767
+ subtext = '';
768
+ }
769
+ if (typeof $this.attr('title') !== 'undefined') {
770
+ return $this.attr('title');
771
+ } else if ($this.data('content') && that.options.showContent) {
772
+ return $this.data('content').toString();
773
+ } else {
774
+ return icon + $this.html() + subtext;
775
+ }
776
+ }
777
+ }).toArray();
778
+
779
+ //Fixes issue in IE10 occurring when no default option is selected and at least one option is disabled
780
+ //Convert all the values into a comma delimited string
781
+ var title = !this.multiple ? selectedItems[0] : selectedItems.join(this.options.multipleSeparator);
782
+
783
+ //If this is multi select, and the selectText type is count, the show 1 of 2 selected etc..
784
+ if (this.multiple && this.options.selectedTextFormat.indexOf('count') > -1) {
785
+ var max = this.options.selectedTextFormat.split('>');
786
+ if ((max.length > 1 && selectedItems.length > max[1]) || (max.length == 1 && selectedItems.length >= 2)) {
787
+ notDisabled = this.options.hideDisabled ? ', [disabled]' : '';
788
+ var totalCount = this.$element.find('option').not('[data-divider="true"], [data-hidden="true"]' + notDisabled).length,
789
+ tr8nText = (typeof this.options.countSelectedText === 'function') ? this.options.countSelectedText(selectedItems.length, totalCount) : this.options.countSelectedText;
790
+ title = tr8nText.replace('{0}', selectedItems.length.toString()).replace('{1}', totalCount.toString());
791
+ }
792
+ }
793
+
794
+ if (this.options.title == undefined) {
795
+ this.options.title = this.$element.attr('title');
796
+ }
797
+
798
+ if (this.options.selectedTextFormat == 'static') {
799
+ title = this.options.title;
800
+ }
801
+
802
+ //If we dont have a title, then use the default, or if nothing is set at all, use the not selected text
803
+ if (!title) {
804
+ title = typeof this.options.title !== 'undefined' ? this.options.title : this.options.noneSelectedText;
805
+ }
806
+
807
+ //strip all HTML tags and trim the result, then unescape any escaped tags
808
+ this.$button.attr('title', htmlUnescape($.trim(title.replace(/<[^>]*>?/g, ''))));
809
+ this.$button.children('.filter-option').html(title);
810
+
811
+ this.$element.trigger('rendered.bs.select');
812
+ },
813
+
814
+ /**
815
+ * @param [style]
816
+ * @param [status]
817
+ */
818
+ setStyle: function (style, status) {
819
+ if (this.$element.attr('class')) {
820
+ this.$newElement.addClass(this.$element.attr('class').replace(/selectpicker|mobile-device|bs-select-hidden|validate\[.*\]/gi, ''));
821
+ }
822
+
823
+ var buttonClass = style ? style : this.options.style;
824
+
825
+ if (status == 'add') {
826
+ this.$button.addClass(buttonClass);
827
+ } else if (status == 'remove') {
828
+ this.$button.removeClass(buttonClass);
829
+ } else {
830
+ this.$button.removeClass(this.options.style);
831
+ this.$button.addClass(buttonClass);
832
+ }
833
+ },
834
+
835
+ liHeight: function (refresh) {
836
+ if (!refresh && (this.options.size === false || this.sizeInfo)) return;
837
+
838
+ var newElement = document.createElement('div'),
839
+ menu = document.createElement('div'),
840
+ menuInner = document.createElement('ul'),
841
+ divider = document.createElement('li'),
842
+ li = document.createElement('li'),
843
+ a = document.createElement('a'),
844
+ text = document.createElement('span'),
845
+ header = this.options.header && this.$menu.find('.popover-title').length > 0 ? this.$menu.find('.popover-title')[0].cloneNode(true) : null,
846
+ search = this.options.liveSearch ? document.createElement('div') : null,
847
+ actions = this.options.actionsBox && this.multiple && this.$menu.find('.bs-actionsbox').length > 0 ? this.$menu.find('.bs-actionsbox')[0].cloneNode(true) : null,
848
+ doneButton = this.options.doneButton && this.multiple && this.$menu.find('.bs-donebutton').length > 0 ? this.$menu.find('.bs-donebutton')[0].cloneNode(true) : null;
849
+
850
+ text.className = 'text';
851
+ newElement.className = this.$menu[0].parentNode.className + ' open';
852
+ menu.className = 'dropdown-menu open';
853
+ menuInner.className = 'dropdown-menu inner';
854
+ divider.className = 'divider';
855
+
856
+ text.appendChild(document.createTextNode('Inner text'));
857
+ a.appendChild(text);
858
+ li.appendChild(a);
859
+ menuInner.appendChild(li);
860
+ menuInner.appendChild(divider);
861
+ if (header) menu.appendChild(header);
862
+ if (search) {
863
+ var input = document.createElement('input');
864
+ search.className = 'bs-searchbox';
865
+ input.className = 'form-control';
866
+ search.appendChild(input);
867
+ menu.appendChild(search);
868
+ }
869
+ if (actions) menu.appendChild(actions);
870
+ menu.appendChild(menuInner);
871
+ if (doneButton) menu.appendChild(doneButton);
872
+ newElement.appendChild(menu);
873
+
874
+ document.body.appendChild(newElement);
875
+
876
+ var liHeight = a.offsetHeight,
877
+ headerHeight = header ? header.offsetHeight : 0,
878
+ searchHeight = search ? search.offsetHeight : 0,
879
+ actionsHeight = actions ? actions.offsetHeight : 0,
880
+ doneButtonHeight = doneButton ? doneButton.offsetHeight : 0,
881
+ dividerHeight = $(divider).outerHeight(true),
882
+ // fall back to jQuery if getComputedStyle is not supported
883
+ menuStyle = typeof getComputedStyle === 'function' ? getComputedStyle(menu) : false,
884
+ $menu = menuStyle ? null : $(menu),
885
+ menuPadding = {
886
+ vert: parseInt(menuStyle ? menuStyle.paddingTop : $menu.css('paddingTop')) +
887
+ parseInt(menuStyle ? menuStyle.paddingBottom : $menu.css('paddingBottom')) +
888
+ parseInt(menuStyle ? menuStyle.borderTopWidth : $menu.css('borderTopWidth')) +
889
+ parseInt(menuStyle ? menuStyle.borderBottomWidth : $menu.css('borderBottomWidth')),
890
+ horiz: parseInt(menuStyle ? menuStyle.paddingLeft : $menu.css('paddingLeft')) +
891
+ parseInt(menuStyle ? menuStyle.paddingRight : $menu.css('paddingRight')) +
892
+ parseInt(menuStyle ? menuStyle.borderLeftWidth : $menu.css('borderLeftWidth')) +
893
+ parseInt(menuStyle ? menuStyle.borderRightWidth : $menu.css('borderRightWidth'))
894
+ },
895
+ menuExtras = {
896
+ vert: menuPadding.vert +
897
+ parseInt(menuStyle ? menuStyle.marginTop : $menu.css('marginTop')) +
898
+ parseInt(menuStyle ? menuStyle.marginBottom : $menu.css('marginBottom')) + 2,
899
+ horiz: menuPadding.horiz +
900
+ parseInt(menuStyle ? menuStyle.marginLeft : $menu.css('marginLeft')) +
901
+ parseInt(menuStyle ? menuStyle.marginRight : $menu.css('marginRight')) + 2
902
+ }
903
+
904
+ document.body.removeChild(newElement);
905
+
906
+ this.sizeInfo = {
907
+ liHeight: liHeight,
908
+ headerHeight: headerHeight,
909
+ searchHeight: searchHeight,
910
+ actionsHeight: actionsHeight,
911
+ doneButtonHeight: doneButtonHeight,
912
+ dividerHeight: dividerHeight,
913
+ menuPadding: menuPadding,
914
+ menuExtras: menuExtras
915
+ };
916
+ },
917
+
918
+ setSize: function () {
919
+ this.findLis();
920
+ this.liHeight();
921
+
922
+ if (this.options.header) this.$menu.css('padding-top', 0);
923
+ if (this.options.size === false) return;
924
+
925
+ var that = this,
926
+ $menu = this.$menu,
927
+ $menuInner = this.$menuInner,
928
+ $window = $(window),
929
+ selectHeight = this.$newElement[0].offsetHeight,
930
+ selectWidth = this.$newElement[0].offsetWidth,
931
+ liHeight = this.sizeInfo['liHeight'],
932
+ headerHeight = this.sizeInfo['headerHeight'],
933
+ searchHeight = this.sizeInfo['searchHeight'],
934
+ actionsHeight = this.sizeInfo['actionsHeight'],
935
+ doneButtonHeight = this.sizeInfo['doneButtonHeight'],
936
+ divHeight = this.sizeInfo['dividerHeight'],
937
+ menuPadding = this.sizeInfo['menuPadding'],
938
+ menuExtras = this.sizeInfo['menuExtras'],
939
+ notDisabled = this.options.hideDisabled ? '.disabled' : '',
940
+ menuHeight,
941
+ menuWidth,
942
+ getHeight,
943
+ getWidth,
944
+ selectOffsetTop,
945
+ selectOffsetBot,
946
+ selectOffsetLeft,
947
+ selectOffsetRight,
948
+ getPos = function() {
949
+ var pos = that.$newElement.offset(),
950
+ $container = $(that.options.container),
951
+ containerPos;
952
+
953
+ if (that.options.container && !$container.is('body')) {
954
+ containerPos = $container.offset();
955
+ containerPos.top += parseInt($container.css('borderTopWidth'));
956
+ containerPos.left += parseInt($container.css('borderLeftWidth'));
957
+ } else {
958
+ containerPos = { top: 0, left: 0 };
959
+ }
960
+
961
+ var winPad = that.options.windowPadding;
962
+ selectOffsetTop = pos.top - containerPos.top - $window.scrollTop();
963
+ selectOffsetBot = $window.height() - selectOffsetTop - selectHeight - containerPos.top - winPad[2];
964
+ selectOffsetLeft = pos.left - containerPos.left - $window.scrollLeft();
965
+ selectOffsetRight = $window.width() - selectOffsetLeft - selectWidth - containerPos.left - winPad[1];
966
+ selectOffsetTop -= winPad[0];
967
+ selectOffsetLeft -= winPad[3];
968
+ };
969
+
970
+ getPos();
971
+
972
+ if (this.options.size === 'auto') {
973
+ var getSize = function () {
974
+ var minHeight,
975
+ hasClass = function (className, include) {
976
+ return function (element) {
977
+ if (include) {
978
+ return (element.classList ? element.classList.contains(className) : $(element).hasClass(className));
979
+ } else {
980
+ return !(element.classList ? element.classList.contains(className) : $(element).hasClass(className));
981
+ }
982
+ };
983
+ },
984
+ lis = that.$menuInner[0].getElementsByTagName('li'),
985
+ lisVisible = Array.prototype.filter ? Array.prototype.filter.call(lis, hasClass('hidden', false)) : that.$lis.not('.hidden'),
986
+ optGroup = Array.prototype.filter ? Array.prototype.filter.call(lisVisible, hasClass('dropdown-header', true)) : lisVisible.filter('.dropdown-header');
987
+
988
+ getPos();
989
+ menuHeight = selectOffsetBot - menuExtras.vert;
990
+ menuWidth = selectOffsetRight - menuExtras.horiz;
991
+
992
+ if (that.options.container) {
993
+ if (!$menu.data('height')) $menu.data('height', $menu.height());
994
+ getHeight = $menu.data('height');
995
+
996
+ if (!$menu.data('width')) $menu.data('width', $menu.width());
997
+ getWidth = $menu.data('width');
998
+ } else {
999
+ getHeight = $menu.height();
1000
+ getWidth = $menu.width();
1001
+ }
1002
+
1003
+ if (that.options.dropupAuto) {
1004
+ that.$newElement.toggleClass('dropup', selectOffsetTop > selectOffsetBot && (menuHeight - menuExtras.vert) < getHeight);
1005
+ }
1006
+
1007
+ if (that.$newElement.hasClass('dropup')) {
1008
+ menuHeight = selectOffsetTop - menuExtras.vert;
1009
+ }
1010
+
1011
+ if (that.options.dropdownAlignRight === 'auto') {
1012
+ $menu.toggleClass('dropdown-menu-right', selectOffsetLeft > selectOffsetRight && (menuWidth - menuExtras.horiz) < (getWidth - selectWidth));
1013
+ }
1014
+
1015
+ if ((lisVisible.length + optGroup.length) > 3) {
1016
+ minHeight = liHeight * 3 + menuExtras.vert - 2;
1017
+ } else {
1018
+ minHeight = 0;
1019
+ }
1020
+
1021
+ $menu.css({
1022
+ 'max-height': menuHeight + 'px',
1023
+ 'overflow': 'hidden',
1024
+ 'min-height': minHeight + headerHeight + searchHeight + actionsHeight + doneButtonHeight + 'px'
1025
+ });
1026
+ $menuInner.css({
1027
+ 'max-height': menuHeight - headerHeight - searchHeight - actionsHeight - doneButtonHeight - menuPadding.vert + 'px',
1028
+ 'overflow-y': 'auto',
1029
+ 'min-height': Math.max(minHeight - menuPadding.vert, 0) + 'px'
1030
+ });
1031
+ };
1032
+ getSize();
1033
+ this.$searchbox.off('input.getSize propertychange.getSize').on('input.getSize propertychange.getSize', getSize);
1034
+ $window.off('resize.getSize scroll.getSize').on('resize.getSize scroll.getSize', getSize);
1035
+ } else if (this.options.size && this.options.size != 'auto' && this.$lis.not(notDisabled).length > this.options.size) {
1036
+ var optIndex = this.$lis.not('.divider').not(notDisabled).children().slice(0, this.options.size).last().parent().index(),
1037
+ divLength = this.$lis.slice(0, optIndex + 1).filter('.divider').length;
1038
+ menuHeight = liHeight * this.options.size + divLength * divHeight + menuPadding.vert;
1039
+
1040
+ if (that.options.container) {
1041
+ if (!$menu.data('height')) $menu.data('height', $menu.height());
1042
+ getHeight = $menu.data('height');
1043
+ } else {
1044
+ getHeight = $menu.height();
1045
+ }
1046
+
1047
+ if (that.options.dropupAuto) {
1048
+ //noinspection JSUnusedAssignment
1049
+ this.$newElement.toggleClass('dropup', selectOffsetTop > selectOffsetBot && (menuHeight - menuExtras.vert) < getHeight);
1050
+ }
1051
+ $menu.css({
1052
+ 'max-height': menuHeight + headerHeight + searchHeight + actionsHeight + doneButtonHeight + 'px',
1053
+ 'overflow': 'hidden',
1054
+ 'min-height': ''
1055
+ });
1056
+ $menuInner.css({
1057
+ 'max-height': menuHeight - menuPadding.vert + 'px',
1058
+ 'overflow-y': 'auto',
1059
+ 'min-height': ''
1060
+ });
1061
+ }
1062
+ },
1063
+
1064
+ setWidth: function () {
1065
+ if (this.options.width === 'auto') {
1066
+ this.$menu.css('min-width', '0');
1067
+
1068
+ // Get correct width if element is hidden
1069
+ var $selectClone = this.$menu.parent().clone().appendTo('body'),
1070
+ $selectClone2 = this.options.container ? this.$newElement.clone().appendTo('body') : $selectClone,
1071
+ ulWidth = $selectClone.children('.dropdown-menu').outerWidth(),
1072
+ btnWidth = $selectClone2.css('width', 'auto').children('button').outerWidth();
1073
+
1074
+ $selectClone.remove();
1075
+ $selectClone2.remove();
1076
+
1077
+ // Set width to whatever's larger, button title or longest option
1078
+ this.$newElement.css('width', Math.max(ulWidth, btnWidth) + 'px');
1079
+ } else if (this.options.width === 'fit') {
1080
+ // Remove inline min-width so width can be changed from 'auto'
1081
+ this.$menu.css('min-width', '');
1082
+ this.$newElement.css('width', '').addClass('fit-width');
1083
+ } else if (this.options.width) {
1084
+ // Remove inline min-width so width can be changed from 'auto'
1085
+ this.$menu.css('min-width', '');
1086
+ this.$newElement.css('width', this.options.width);
1087
+ } else {
1088
+ // Remove inline min-width/width so width can be changed
1089
+ this.$menu.css('min-width', '');
1090
+ this.$newElement.css('width', '');
1091
+ }
1092
+ // Remove fit-width class if width is changed programmatically
1093
+ if (this.$newElement.hasClass('fit-width') && this.options.width !== 'fit') {
1094
+ this.$newElement.removeClass('fit-width');
1095
+ }
1096
+ },
1097
+
1098
+ selectPosition: function () {
1099
+ this.$bsContainer = $('<div class="bs-container" />');
1100
+
1101
+ var that = this,
1102
+ $container = $(this.options.container),
1103
+ pos,
1104
+ containerPos,
1105
+ actualHeight,
1106
+ getPlacement = function ($element) {
1107
+ that.$bsContainer.addClass($element.attr('class').replace(/form-control|fit-width/gi, '')).toggleClass('dropup', $element.hasClass('dropup'));
1108
+ pos = $element.offset();
1109
+
1110
+ if (!$container.is('body')) {
1111
+ containerPos = $container.offset();
1112
+ containerPos.top += parseInt($container.css('borderTopWidth')) - $container.scrollTop();
1113
+ containerPos.left += parseInt($container.css('borderLeftWidth')) - $container.scrollLeft();
1114
+ } else {
1115
+ containerPos = { top: 0, left: 0 };
1116
+ }
1117
+
1118
+ actualHeight = $element.hasClass('dropup') ? 0 : $element[0].offsetHeight;
1119
+
1120
+ that.$bsContainer.css({
1121
+ 'top': pos.top - containerPos.top + actualHeight,
1122
+ 'left': pos.left - containerPos.left,
1123
+ 'width': $element[0].offsetWidth
1124
+ });
1125
+ };
1126
+
1127
+ this.$button.on('click', function () {
1128
+ var $this = $(this);
1129
+
1130
+ if (that.isDisabled()) {
1131
+ return;
1132
+ }
1133
+
1134
+ getPlacement(that.$newElement);
1135
+
1136
+ that.$bsContainer
1137
+ .appendTo(that.options.container)
1138
+ .toggleClass('open', !$this.hasClass('open'))
1139
+ .append(that.$menu);
1140
+ });
1141
+
1142
+ $(window).on('resize scroll', function () {
1143
+ getPlacement(that.$newElement);
1144
+ });
1145
+
1146
+ this.$element.on('hide.bs.select', function () {
1147
+ that.$menu.data('height', that.$menu.height());
1148
+ that.$bsContainer.detach();
1149
+ });
1150
+ },
1151
+
1152
+ /**
1153
+ * @param {number} index - the index of the option that is being changed
1154
+ * @param {boolean} selected - true if the option is being selected, false if being deselected
1155
+ * @param {JQuery} $lis - the 'li' element that is being modified
1156
+ */
1157
+ setSelected: function (index, selected, $lis) {
1158
+ if (!$lis) {
1159
+ this.togglePlaceholder(); // check if setSelected is being called by changing the value of the select
1160
+ $lis = this.findLis().eq(this.liObj[index]);
1161
+ }
1162
+
1163
+ $lis.toggleClass('selected', selected).find('a').attr('aria-selected', selected);
1164
+ },
1165
+
1166
+ /**
1167
+ * @param {number} index - the index of the option that is being disabled
1168
+ * @param {boolean} disabled - true if the option is being disabled, false if being enabled
1169
+ * @param {JQuery} $lis - the 'li' element that is being modified
1170
+ */
1171
+ setDisabled: function (index, disabled, $lis) {
1172
+ if (!$lis) {
1173
+ $lis = this.findLis().eq(this.liObj[index]);
1174
+ }
1175
+
1176
+ if (disabled) {
1177
+ $lis.addClass('disabled').children('a').attr('href', '#').attr('tabindex', -1).attr('aria-disabled', true);
1178
+ } else {
1179
+ $lis.removeClass('disabled').children('a').removeAttr('href').attr('tabindex', 0).attr('aria-disabled', false);
1180
+ }
1181
+ },
1182
+
1183
+ isDisabled: function () {
1184
+ return this.$element[0].disabled;
1185
+ },
1186
+
1187
+ checkDisabled: function () {
1188
+ var that = this;
1189
+
1190
+ if (this.isDisabled()) {
1191
+ this.$newElement.addClass('disabled');
1192
+ this.$button.addClass('disabled').attr('tabindex', -1).attr('aria-disabled', true);
1193
+ } else {
1194
+ if (this.$button.hasClass('disabled')) {
1195
+ this.$newElement.removeClass('disabled');
1196
+ this.$button.removeClass('disabled').attr('aria-disabled', false);
1197
+ }
1198
+
1199
+ if (this.$button.attr('tabindex') == -1 && !this.$element.data('tabindex')) {
1200
+ this.$button.removeAttr('tabindex');
1201
+ }
1202
+ }
1203
+
1204
+ this.$button.click(function () {
1205
+ return !that.isDisabled();
1206
+ });
1207
+ },
1208
+
1209
+ togglePlaceholder: function () {
1210
+ var value = this.$element.val();
1211
+ this.$button.toggleClass('bs-placeholder', value === null || value === '' || (value.constructor === Array && value.length === 0));
1212
+ },
1213
+
1214
+ tabIndex: function () {
1215
+ if (this.$element.data('tabindex') !== this.$element.attr('tabindex') &&
1216
+ (this.$element.attr('tabindex') !== -98 && this.$element.attr('tabindex') !== '-98')) {
1217
+ this.$element.data('tabindex', this.$element.attr('tabindex'));
1218
+ this.$button.attr('tabindex', this.$element.data('tabindex'));
1219
+ }
1220
+
1221
+ this.$element.attr('tabindex', -98);
1222
+ },
1223
+
1224
+ clickListener: function () {
1225
+ var that = this,
1226
+ $document = $(document);
1227
+
1228
+ $document.data('spaceSelect', false);
1229
+
1230
+ this.$button.on('keyup', function (e) {
1231
+ if (/(32)/.test(e.keyCode.toString(10)) && $document.data('spaceSelect')) {
1232
+ e.preventDefault();
1233
+ $document.data('spaceSelect', false);
1234
+ }
1235
+ });
1236
+
1237
+ this.$button.on('click', function () {
1238
+ that.setSize();
1239
+ });
1240
+
1241
+ this.$element.on('shown.bs.select', function () {
1242
+ if (!that.options.liveSearch && !that.multiple) {
1243
+ that.$menuInner.find('.selected a').focus();
1244
+ } else if (!that.multiple) {
1245
+ var selectedIndex = that.liObj[that.$element[0].selectedIndex];
1246
+
1247
+ if (typeof selectedIndex !== 'number' || that.options.size === false) return;
1248
+
1249
+ // scroll to selected option
1250
+ var offset = that.$lis.eq(selectedIndex)[0].offsetTop - that.$menuInner[0].offsetTop;
1251
+ offset = offset - that.$menuInner[0].offsetHeight/2 + that.sizeInfo.liHeight/2;
1252
+ that.$menuInner[0].scrollTop = offset;
1253
+ }
1254
+ });
1255
+
1256
+ this.$menuInner.on('click', 'li a', function (e) {
1257
+ var $this = $(this),
1258
+ clickedIndex = $this.parent().data('originalIndex'),
1259
+ prevValue = that.$element.val(),
1260
+ prevIndex = that.$element.prop('selectedIndex'),
1261
+ triggerChange = true;
1262
+
1263
+ // Don't close on multi choice menu
1264
+ if (that.multiple && that.options.maxOptions !== 1) {
1265
+ e.stopPropagation();
1266
+ }
1267
+
1268
+ e.preventDefault();
1269
+
1270
+ //Don't run if we have been disabled
1271
+ if (!that.isDisabled() && !$this.parent().hasClass('disabled')) {
1272
+ var $options = that.$element.find('option'),
1273
+ $option = $options.eq(clickedIndex),
1274
+ state = $option.prop('selected'),
1275
+ $optgroup = $option.parent('optgroup'),
1276
+ maxOptions = that.options.maxOptions,
1277
+ maxOptionsGrp = $optgroup.data('maxOptions') || false;
1278
+
1279
+ if (!that.multiple) { // Deselect all others if not multi select box
1280
+ $options.prop('selected', false);
1281
+ $option.prop('selected', true);
1282
+ that.$menuInner.find('.selected').removeClass('selected').find('a').attr('aria-selected', false);
1283
+ that.setSelected(clickedIndex, true);
1284
+ } else { // Toggle the one we have chosen if we are multi select.
1285
+ $option.prop('selected', !state);
1286
+ that.setSelected(clickedIndex, !state);
1287
+ $this.blur();
1288
+
1289
+ if (maxOptions !== false || maxOptionsGrp !== false) {
1290
+ var maxReached = maxOptions < $options.filter(':selected').length,
1291
+ maxReachedGrp = maxOptionsGrp < $optgroup.find('option:selected').length;
1292
+
1293
+ if ((maxOptions && maxReached) || (maxOptionsGrp && maxReachedGrp)) {
1294
+ if (maxOptions && maxOptions == 1) {
1295
+ $options.prop('selected', false);
1296
+ $option.prop('selected', true);
1297
+ that.$menuInner.find('.selected').removeClass('selected');
1298
+ that.setSelected(clickedIndex, true);
1299
+ } else if (maxOptionsGrp && maxOptionsGrp == 1) {
1300
+ $optgroup.find('option:selected').prop('selected', false);
1301
+ $option.prop('selected', true);
1302
+ var optgroupID = $this.parent().data('optgroup');
1303
+ that.$menuInner.find('[data-optgroup="' + optgroupID + '"]').removeClass('selected');
1304
+ that.setSelected(clickedIndex, true);
1305
+ } else {
1306
+ var maxOptionsText = typeof that.options.maxOptionsText === 'string' ? [that.options.maxOptionsText, that.options.maxOptionsText] : that.options.maxOptionsText,
1307
+ maxOptionsArr = typeof maxOptionsText === 'function' ? maxOptionsText(maxOptions, maxOptionsGrp) : maxOptionsText,
1308
+ maxTxt = maxOptionsArr[0].replace('{n}', maxOptions),
1309
+ maxTxtGrp = maxOptionsArr[1].replace('{n}', maxOptionsGrp),
1310
+ $notify = $('<div class="notify"></div>');
1311
+ // If {var} is set in array, replace it
1312
+ /** @deprecated */
1313
+ if (maxOptionsArr[2]) {
1314
+ maxTxt = maxTxt.replace('{var}', maxOptionsArr[2][maxOptions > 1 ? 0 : 1]);
1315
+ maxTxtGrp = maxTxtGrp.replace('{var}', maxOptionsArr[2][maxOptionsGrp > 1 ? 0 : 1]);
1316
+ }
1317
+
1318
+ $option.prop('selected', false);
1319
+
1320
+ that.$menu.append($notify);
1321
+
1322
+ if (maxOptions && maxReached) {
1323
+ $notify.append($('<div>' + maxTxt + '</div>'));
1324
+ triggerChange = false;
1325
+ that.$element.trigger('maxReached.bs.select');
1326
+ }
1327
+
1328
+ if (maxOptionsGrp && maxReachedGrp) {
1329
+ $notify.append($('<div>' + maxTxtGrp + '</div>'));
1330
+ triggerChange = false;
1331
+ that.$element.trigger('maxReachedGrp.bs.select');
1332
+ }
1333
+
1334
+ setTimeout(function () {
1335
+ that.setSelected(clickedIndex, false);
1336
+ }, 10);
1337
+
1338
+ $notify.delay(750).fadeOut(300, function () {
1339
+ $(this).remove();
1340
+ });
1341
+ }
1342
+ }
1343
+ }
1344
+ }
1345
+
1346
+ if (!that.multiple || (that.multiple && that.options.maxOptions === 1)) {
1347
+ that.$button.focus();
1348
+ } else if (that.options.liveSearch) {
1349
+ that.$searchbox.focus();
1350
+ }
1351
+
1352
+ // Trigger select 'change'
1353
+ if (triggerChange) {
1354
+ if ((prevValue != that.$element.val() && that.multiple) || (prevIndex != that.$element.prop('selectedIndex') && !that.multiple)) {
1355
+ // $option.prop('selected') is current option state (selected/unselected). state is previous option state.
1356
+ changed_arguments = [clickedIndex, $option.prop('selected'), state];
1357
+ that.$element
1358
+ .triggerNative('change');
1359
+ }
1360
+ }
1361
+ }
1362
+ });
1363
+
1364
+ this.$menu.on('click', 'li.disabled a, .popover-title, .popover-title :not(.close)', function (e) {
1365
+ if (e.currentTarget == this) {
1366
+ e.preventDefault();
1367
+ e.stopPropagation();
1368
+ if (that.options.liveSearch && !$(e.target).hasClass('close')) {
1369
+ that.$searchbox.focus();
1370
+ } else {
1371
+ that.$button.focus();
1372
+ }
1373
+ }
1374
+ });
1375
+
1376
+ this.$menuInner.on('click', '.divider, .dropdown-header', function (e) {
1377
+ e.preventDefault();
1378
+ e.stopPropagation();
1379
+ if (that.options.liveSearch) {
1380
+ that.$searchbox.focus();
1381
+ } else {
1382
+ that.$button.focus();
1383
+ }
1384
+ });
1385
+
1386
+ this.$menu.on('click', '.popover-title .close', function () {
1387
+ that.$button.click();
1388
+ });
1389
+
1390
+ this.$searchbox.on('click', function (e) {
1391
+ e.stopPropagation();
1392
+ });
1393
+
1394
+ this.$menu.on('click', '.actions-btn', function (e) {
1395
+ if (that.options.liveSearch) {
1396
+ that.$searchbox.focus();
1397
+ } else {
1398
+ that.$button.focus();
1399
+ }
1400
+
1401
+ e.preventDefault();
1402
+ e.stopPropagation();
1403
+
1404
+ if ($(this).hasClass('bs-select-all')) {
1405
+ that.selectAll();
1406
+ } else {
1407
+ that.deselectAll();
1408
+ }
1409
+ });
1410
+
1411
+ this.$element.change(function () {
1412
+ that.render(false);
1413
+ that.$element.trigger('changed.bs.select', changed_arguments);
1414
+ changed_arguments = null;
1415
+ });
1416
+ },
1417
+
1418
+ liveSearchListener: function () {
1419
+ var that = this,
1420
+ $no_results = $('<li class="no-results"></li>');
1421
+
1422
+ this.$button.on('click.dropdown.data-api', function () {
1423
+ that.$menuInner.find('.active').removeClass('active');
1424
+ if (!!that.$searchbox.val()) {
1425
+ that.$searchbox.val('');
1426
+ that.$lis.not('.is-hidden').removeClass('hidden');
1427
+ if (!!$no_results.parent().length) $no_results.remove();
1428
+ }
1429
+ if (!that.multiple) that.$menuInner.find('.selected').addClass('active');
1430
+ setTimeout(function () {
1431
+ that.$searchbox.focus();
1432
+ }, 10);
1433
+ });
1434
+
1435
+ this.$searchbox.on('click.dropdown.data-api focus.dropdown.data-api touchend.dropdown.data-api', function (e) {
1436
+ e.stopPropagation();
1437
+ });
1438
+
1439
+ this.$searchbox.on('input propertychange', function () {
1440
+ that.$lis.not('.is-hidden').removeClass('hidden');
1441
+ that.$lis.filter('.active').removeClass('active');
1442
+ $no_results.remove();
1443
+
1444
+ if (that.$searchbox.val()) {
1445
+ var $searchBase = that.$lis.not('.is-hidden, .divider, .dropdown-header'),
1446
+ $hideItems;
1447
+ if (that.options.liveSearchNormalize) {
1448
+ $hideItems = $searchBase.find('a').not(':a' + that._searchStyle() + '("' + normalizeToBase(that.$searchbox.val()) + '")');
1449
+ } else {
1450
+ $hideItems = $searchBase.find('a').not(':' + that._searchStyle() + '("' + that.$searchbox.val() + '")');
1451
+ }
1452
+
1453
+ if ($hideItems.length === $searchBase.length) {
1454
+ $no_results.html(that.options.noneResultsText.replace('{0}', '"' + htmlEscape(that.$searchbox.val()) + '"'));
1455
+ that.$menuInner.append($no_results);
1456
+ that.$lis.addClass('hidden');
1457
+ } else {
1458
+ $hideItems.parent().addClass('hidden');
1459
+
1460
+ var $lisVisible = that.$lis.not('.hidden'),
1461
+ $foundDiv;
1462
+
1463
+ // hide divider if first or last visible, or if followed by another divider
1464
+ $lisVisible.each(function (index) {
1465
+ var $this = $(this);
1466
+
1467
+ if ($this.hasClass('divider')) {
1468
+ if ($foundDiv === undefined) {
1469
+ $this.addClass('hidden');
1470
+ } else {
1471
+ if ($foundDiv) $foundDiv.addClass('hidden');
1472
+ $foundDiv = $this;
1473
+ }
1474
+ } else if ($this.hasClass('dropdown-header') && $lisVisible.eq(index + 1).data('optgroup') !== $this.data('optgroup')) {
1475
+ $this.addClass('hidden');
1476
+ } else {
1477
+ $foundDiv = null;
1478
+ }
1479
+ });
1480
+ if ($foundDiv) $foundDiv.addClass('hidden');
1481
+
1482
+ $searchBase.not('.hidden').first().addClass('active');
1483
+ }
1484
+ }
1485
+ });
1486
+ },
1487
+
1488
+ _searchStyle: function () {
1489
+ var styles = {
1490
+ begins: 'ibegins',
1491
+ startsWith: 'ibegins'
1492
+ };
1493
+
1494
+ return styles[this.options.liveSearchStyle] || 'icontains';
1495
+ },
1496
+
1497
+ val: function (value) {
1498
+ if (typeof value !== 'undefined') {
1499
+ this.$element.val(value);
1500
+ this.render();
1501
+
1502
+ return this.$element;
1503
+ } else {
1504
+ return this.$element.val();
1505
+ }
1506
+ },
1507
+
1508
+ changeAll: function (status) {
1509
+ if (!this.multiple) return;
1510
+ if (typeof status === 'undefined') status = true;
1511
+
1512
+ this.findLis();
1513
+
1514
+ var $options = this.$element.find('option'),
1515
+ $lisVisible = this.$lis.not('.divider, .dropdown-header, .disabled, .hidden'),
1516
+ lisVisLen = $lisVisible.length,
1517
+ selectedOptions = [];
1518
+
1519
+ if (status) {
1520
+ if ($lisVisible.filter('.selected').length === $lisVisible.length) return;
1521
+ } else {
1522
+ if ($lisVisible.filter('.selected').length === 0) return;
1523
+ }
1524
+
1525
+ $lisVisible.toggleClass('selected', status);
1526
+
1527
+ for (var i = 0; i < lisVisLen; i++) {
1528
+ var origIndex = $lisVisible[i].getAttribute('data-original-index');
1529
+ selectedOptions[selectedOptions.length] = $options.eq(origIndex)[0];
1530
+ }
1531
+
1532
+ $(selectedOptions).prop('selected', status);
1533
+
1534
+ this.render(false);
1535
+
1536
+ this.togglePlaceholder();
1537
+
1538
+ this.$element
1539
+ .triggerNative('change');
1540
+ },
1541
+
1542
+ selectAll: function () {
1543
+ return this.changeAll(true);
1544
+ },
1545
+
1546
+ deselectAll: function () {
1547
+ return this.changeAll(false);
1548
+ },
1549
+
1550
+ toggle: function (e) {
1551
+ e = e || window.event;
1552
+
1553
+ if (e) e.stopPropagation();
1554
+
1555
+ this.$button.trigger('click');
1556
+ },
1557
+
1558
+ keydown: function (e) {
1559
+ var $this = $(this),
1560
+ $parent = $this.is('input') ? $this.parent().parent() : $this.parent(),
1561
+ $items,
1562
+ that = $parent.data('this'),
1563
+ index,
1564
+ next,
1565
+ first,
1566
+ last,
1567
+ prev,
1568
+ nextPrev,
1569
+ prevIndex,
1570
+ isActive,
1571
+ selector = ':not(.disabled, .hidden, .dropdown-header, .divider)',
1572
+ keyCodeMap = {
1573
+ 32: ' ',
1574
+ 48: '0',
1575
+ 49: '1',
1576
+ 50: '2',
1577
+ 51: '3',
1578
+ 52: '4',
1579
+ 53: '5',
1580
+ 54: '6',
1581
+ 55: '7',
1582
+ 56: '8',
1583
+ 57: '9',
1584
+ 59: ';',
1585
+ 65: 'a',
1586
+ 66: 'b',
1587
+ 67: 'c',
1588
+ 68: 'd',
1589
+ 69: 'e',
1590
+ 70: 'f',
1591
+ 71: 'g',
1592
+ 72: 'h',
1593
+ 73: 'i',
1594
+ 74: 'j',
1595
+ 75: 'k',
1596
+ 76: 'l',
1597
+ 77: 'm',
1598
+ 78: 'n',
1599
+ 79: 'o',
1600
+ 80: 'p',
1601
+ 81: 'q',
1602
+ 82: 'r',
1603
+ 83: 's',
1604
+ 84: 't',
1605
+ 85: 'u',
1606
+ 86: 'v',
1607
+ 87: 'w',
1608
+ 88: 'x',
1609
+ 89: 'y',
1610
+ 90: 'z',
1611
+ 96: '0',
1612
+ 97: '1',
1613
+ 98: '2',
1614
+ 99: '3',
1615
+ 100: '4',
1616
+ 101: '5',
1617
+ 102: '6',
1618
+ 103: '7',
1619
+ 104: '8',
1620
+ 105: '9'
1621
+ };
1622
+
1623
+ if (that.options.liveSearch) $parent = $this.parent().parent();
1624
+
1625
+ if (that.options.container) $parent = that.$menu;
1626
+
1627
+ $items = $('[role="listbox"] li', $parent);
1628
+
1629
+ isActive = that.$newElement.hasClass('open');
1630
+
1631
+ if (!isActive && (e.keyCode >= 48 && e.keyCode <= 57 || e.keyCode >= 96 && e.keyCode <= 105 || e.keyCode >= 65 && e.keyCode <= 90)) {
1632
+ if (!that.options.container) {
1633
+ that.setSize();
1634
+ that.$menu.parent().addClass('open');
1635
+ isActive = true;
1636
+ } else {
1637
+ that.$button.trigger('click');
1638
+ }
1639
+ that.$searchbox.focus();
1640
+ return;
1641
+ }
1642
+
1643
+ if (that.options.liveSearch) {
1644
+ if (/(^9$|27)/.test(e.keyCode.toString(10)) && isActive) {
1645
+ e.preventDefault();
1646
+ e.stopPropagation();
1647
+ that.$menuInner.click();
1648
+ that.$button.focus();
1649
+ }
1650
+ // $items contains li elements when liveSearch is enabled
1651
+ $items = $('[role="listbox"] li' + selector, $parent);
1652
+ if (!$this.val() && !/(38|40)/.test(e.keyCode.toString(10))) {
1653
+ if ($items.filter('.active').length === 0) {
1654
+ $items = that.$menuInner.find('li');
1655
+ if (that.options.liveSearchNormalize) {
1656
+ $items = $items.filter(':a' + that._searchStyle() + '(' + normalizeToBase(keyCodeMap[e.keyCode]) + ')');
1657
+ } else {
1658
+ $items = $items.filter(':' + that._searchStyle() + '(' + keyCodeMap[e.keyCode] + ')');
1659
+ }
1660
+ }
1661
+ }
1662
+ }
1663
+
1664
+ if (!$items.length) return;
1665
+
1666
+ if (/(38|40)/.test(e.keyCode.toString(10))) {
1667
+ index = $items.index($items.find('a').filter(':focus').parent());
1668
+ first = $items.filter(selector).first().index();
1669
+ last = $items.filter(selector).last().index();
1670
+ next = $items.eq(index).nextAll(selector).eq(0).index();
1671
+ prev = $items.eq(index).prevAll(selector).eq(0).index();
1672
+ nextPrev = $items.eq(next).prevAll(selector).eq(0).index();
1673
+
1674
+ if (that.options.liveSearch) {
1675
+ $items.each(function (i) {
1676
+ if (!$(this).hasClass('disabled')) {
1677
+ $(this).data('index', i);
1678
+ }
1679
+ });
1680
+ index = $items.index($items.filter('.active'));
1681
+ first = $items.first().data('index');
1682
+ last = $items.last().data('index');
1683
+ next = $items.eq(index).nextAll().eq(0).data('index');
1684
+ prev = $items.eq(index).prevAll().eq(0).data('index');
1685
+ nextPrev = $items.eq(next).prevAll().eq(0).data('index');
1686
+ }
1687
+
1688
+ prevIndex = $this.data('prevIndex');
1689
+
1690
+ if (e.keyCode == 38) {
1691
+ if (that.options.liveSearch) index--;
1692
+ if (index != nextPrev && index > prev) index = prev;
1693
+ if (index < first) index = first;
1694
+ if (index == prevIndex) index = last;
1695
+ } else if (e.keyCode == 40) {
1696
+ if (that.options.liveSearch) index++;
1697
+ if (index == -1) index = 0;
1698
+ if (index != nextPrev && index < next) index = next;
1699
+ if (index > last) index = last;
1700
+ if (index == prevIndex) index = first;
1701
+ }
1702
+
1703
+ $this.data('prevIndex', index);
1704
+
1705
+ if (!that.options.liveSearch) {
1706
+ $items.eq(index).children('a').focus();
1707
+ } else {
1708
+ e.preventDefault();
1709
+ if (!$this.hasClass('dropdown-toggle')) {
1710
+ $items.removeClass('active').eq(index).addClass('active').children('a').focus();
1711
+ $this.focus();
1712
+ }
1713
+ }
1714
+
1715
+ } else if (!$this.is('input')) {
1716
+ var keyIndex = [],
1717
+ count,
1718
+ prevKey;
1719
+
1720
+ $items.each(function () {
1721
+ if (!$(this).hasClass('disabled')) {
1722
+ if ($.trim($(this).children('a').text().toLowerCase()).substring(0, 1) == keyCodeMap[e.keyCode]) {
1723
+ keyIndex.push($(this).index());
1724
+ }
1725
+ }
1726
+ });
1727
+
1728
+ count = $(document).data('keycount');
1729
+ count++;
1730
+ $(document).data('keycount', count);
1731
+
1732
+ prevKey = $.trim($(':focus').text().toLowerCase()).substring(0, 1);
1733
+
1734
+ if (prevKey != keyCodeMap[e.keyCode]) {
1735
+ count = 1;
1736
+ $(document).data('keycount', count);
1737
+ } else if (count >= keyIndex.length) {
1738
+ $(document).data('keycount', 0);
1739
+ if (count > keyIndex.length) count = 1;
1740
+ }
1741
+
1742
+ $items.eq(keyIndex[count - 1]).children('a').focus();
1743
+ }
1744
+
1745
+ // Select focused option if "Enter", "Spacebar" or "Tab" (when selectOnTab is true) are pressed inside the menu.
1746
+ if ((/(13|32)/.test(e.keyCode.toString(10)) || (/(^9$)/.test(e.keyCode.toString(10)) && that.options.selectOnTab)) && isActive) {
1747
+ if (!/(32)/.test(e.keyCode.toString(10))) e.preventDefault();
1748
+ if (!that.options.liveSearch) {
1749
+ var elem = $(':focus');
1750
+ elem.click();
1751
+ // Bring back focus for multiselects
1752
+ elem.focus();
1753
+ // Prevent screen from scrolling if the user hit the spacebar
1754
+ e.preventDefault();
1755
+ // Fixes spacebar selection of dropdown items in FF & IE
1756
+ $(document).data('spaceSelect', true);
1757
+ } else if (!/(32)/.test(e.keyCode.toString(10))) {
1758
+ that.$menuInner.find('.active a').click();
1759
+ $this.focus();
1760
+ }
1761
+ $(document).data('keycount', 0);
1762
+ }
1763
+
1764
+ if ((/(^9$|27)/.test(e.keyCode.toString(10)) && isActive && (that.multiple || that.options.liveSearch)) || (/(27)/.test(e.keyCode.toString(10)) && !isActive)) {
1765
+ that.$menu.parent().removeClass('open');
1766
+ if (that.options.container) that.$newElement.removeClass('open');
1767
+ that.$button.focus();
1768
+ }
1769
+ },
1770
+
1771
+ mobile: function () {
1772
+ this.$element.addClass('mobile-device');
1773
+ },
1774
+
1775
+ refresh: function () {
1776
+ this.$lis = null;
1777
+ this.liObj = {};
1778
+ this.reloadLi();
1779
+ this.render();
1780
+ this.checkDisabled();
1781
+ this.liHeight(true);
1782
+ this.setStyle();
1783
+ this.setWidth();
1784
+ if (this.$lis) this.$searchbox.trigger('propertychange');
1785
+
1786
+ this.$element.trigger('refreshed.bs.select');
1787
+ },
1788
+
1789
+ hide: function () {
1790
+ this.$newElement.hide();
1791
+ },
1792
+
1793
+ show: function () {
1794
+ this.$newElement.show();
1795
+ },
1796
+
1797
+ remove: function () {
1798
+ this.$newElement.remove();
1799
+ this.$element.remove();
1800
+ },
1801
+
1802
+ destroy: function () {
1803
+ this.$newElement.before(this.$element).remove();
1804
+
1805
+ if (this.$bsContainer) {
1806
+ this.$bsContainer.remove();
1807
+ } else {
1808
+ this.$menu.remove();
1809
+ }
1810
+
1811
+ this.$element
1812
+ .off('.bs.select')
1813
+ .removeData('selectpicker')
1814
+ .removeClass('bs-select-hidden selectpicker');
1815
+ }
1816
+ };
1817
+
1818
+ // SELECTPICKER PLUGIN DEFINITION
1819
+ // ==============================
1820
+ function Plugin(option) {
1821
+ // get the args of the outer function..
1822
+ var args = arguments;
1823
+ // The arguments of the function are explicitly re-defined from the argument list, because the shift causes them
1824
+ // to get lost/corrupted in android 2.3 and IE9 #715 #775
1825
+ var _option = option;
1826
+
1827
+ [].shift.apply(args);
1828
+
1829
+ var value;
1830
+ var chain = this.each(function () {
1831
+ var $this = $(this);
1832
+ if ($this.is('select')) {
1833
+ var data = $this.data('selectpicker'),
1834
+ options = typeof _option == 'object' && _option;
1835
+
1836
+ if (!data) {
1837
+ var config = $.extend({}, Selectpicker.DEFAULTS, $.fn.selectpicker.defaults || {}, $this.data(), options);
1838
+ config.template = $.extend({}, Selectpicker.DEFAULTS.template, ($.fn.selectpicker.defaults ? $.fn.selectpicker.defaults.template : {}), $this.data().template, options.template);
1839
+ $this.data('selectpicker', (data = new Selectpicker(this, config)));
1840
+ } else if (options) {
1841
+ for (var i in options) {
1842
+ if (options.hasOwnProperty(i)) {
1843
+ data.options[i] = options[i];
1844
+ }
1845
+ }
1846
+ }
1847
+
1848
+ if (typeof _option == 'string') {
1849
+ if (data[_option] instanceof Function) {
1850
+ value = data[_option].apply(data, args);
1851
+ } else {
1852
+ value = data.options[_option];
1853
+ }
1854
+ }
1855
+ }
1856
+ });
1857
+
1858
+ if (typeof value !== 'undefined') {
1859
+ //noinspection JSUnusedAssignment
1860
+ return value;
1861
+ } else {
1862
+ return chain;
1863
+ }
1864
+ }
1865
+
1866
+ var old = $.fn.selectpicker;
1867
+ $.fn.selectpicker = Plugin;
1868
+ $.fn.selectpicker.Constructor = Selectpicker;
1869
+
1870
+ // SELECTPICKER NO CONFLICT
1871
+ // ========================
1872
+ $.fn.selectpicker.noConflict = function () {
1873
+ $.fn.selectpicker = old;
1874
+ return this;
1875
+ };
1876
+
1877
+ $(document)
1878
+ .data('keycount', 0)
1879
+ .on('keydown.bs.select', '.bootstrap-select [data-toggle=dropdown], .bootstrap-select [role="listbox"], .bs-searchbox input', Selectpicker.prototype.keydown)
1880
+ .on('focusin.modal', '.bootstrap-select [data-toggle=dropdown], .bootstrap-select [role="listbox"], .bs-searchbox input', function (e) {
1881
+ e.stopPropagation();
1882
+ });
1883
+
1884
+ // SELECTPICKER DATA-API
1885
+ // =====================
1886
+ $(window).on('load.bs.select.data-api', function () {
1887
+ $('.selectpicker').each(function () {
1888
+ var $selectpicker = $(this);
1889
+ Plugin.call($selectpicker, $selectpicker.data());
1890
+ })
1891
+ });
1892
+ })(jQuery);
1893
+
1894
+
1895
+ }));