bootstrap-select-rails 1.6.2 → 1.6.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: e50e69dd81e893f3a23930cf8f29969c3aac337b
4
- data.tar.gz: 8f6c90b9fce9fa026a72d6aaff1a6d9d0ea1d965
3
+ metadata.gz: 3b75bf2df726ace801fc359d9c893e78e5675325
4
+ data.tar.gz: 42c42b49a997f18f4bc73bf149d96f2321aa3ded
5
5
  SHA512:
6
- metadata.gz: a088e190043a5d63c4ef3908d6ab4d1423f2b1fca32dfff366c31eb011b927e6d6409e3e5b114202c5503198488684193b77cba3135e88d9438dba872855c463
7
- data.tar.gz: 433f79a27a1bb4f214c2f3fbc7d9bc17ce04eea6e319bf75d627e963dca720d2084165cb6dec25b827d9c7e0196386000c96f3e53c688b85d594b702eb212004
6
+ metadata.gz: 8a5ddf97188b75c21c5771ad6daf4cf3b75d0dc54e48ad7137db6d42a1948b04b47fb52dd617ca9bcdc270ec7d85b3aeece4de602aa6f1b38b185194d6161245
7
+ data.tar.gz: 2e564e4a04a721ae222ba0badfac640261c43ea9b98e0a5a93554d9bcf787eca57f90b42bd1c361a8150c34fa34d452c0d7e67af45be4f23ec8f2585cbd5935a
@@ -1,7 +1,7 @@
1
1
  module Bootstrap
2
2
  module Select
3
3
  module Rails
4
- VERSION = "1.6.2"
4
+ VERSION = "1.6.3"
5
5
  end
6
6
  end
7
7
  end
@@ -1,1145 +1,1216 @@
1
1
  /*!
2
- * Bootstrap-select v1.6.2 (http://silviomoreto.github.io/bootstrap-select/)
2
+ * Bootstrap-select v1.6.3 (http://silviomoreto.github.io/bootstrap-select/)
3
3
  *
4
4
  * Copyright 2013-2014 bootstrap-select
5
5
  * Licensed under MIT (https://github.com/silviomoreto/bootstrap-select/blob/master/LICENSE)
6
6
  */
7
7
  (function ($) {
8
- 'use strict';
9
-
10
- // Case insensitive search
11
- $.expr[':'].icontains = function (obj, index, meta) {
12
- return icontains($(obj).text(), meta[3]);
13
- };
14
-
15
- // Case and accent insensitive search
16
- $.expr[':'].aicontains = function (obj, index, meta) {
17
- return icontains($(obj).data('normalizedText') || $(obj).text(), meta[3]);
8
+ 'use strict';
9
+
10
+ // Case insensitive search
11
+ $.expr[':'].icontains = function (obj, index, meta) {
12
+ return icontains($(obj).text(), meta[3]);
13
+ };
14
+
15
+ // Case and accent insensitive search
16
+ $.expr[':'].aicontains = function (obj, index, meta) {
17
+ return icontains($(obj).data('normalizedText') || $(obj).text(), meta[3]);
18
+ };
19
+
20
+ /**
21
+ * Actual implementation of the case insensitive search.
22
+ * @access private
23
+ * @param {String} haystack
24
+ * @param {String} needle
25
+ * @returns {boolean}
26
+ */
27
+ function icontains(haystack, needle) {
28
+ return haystack.toUpperCase().indexOf(needle.toUpperCase()) > -1;
29
+ }
30
+
31
+ /**
32
+ * Remove all diatrics from the given text.
33
+ * @access private
34
+ * @param {String} text
35
+ * @returns {String}
36
+ */
37
+ function normalizeToBase(text) {
38
+ var rExps = [
39
+ {re: /[\xC0-\xC6]/g, ch: "A"},
40
+ {re: /[\xE0-\xE6]/g, ch: "a"},
41
+ {re: /[\xC8-\xCB]/g, ch: "E"},
42
+ {re: /[\xE8-\xEB]/g, ch: "e"},
43
+ {re: /[\xCC-\xCF]/g, ch: "I"},
44
+ {re: /[\xEC-\xEF]/g, ch: "i"},
45
+ {re: /[\xD2-\xD6]/g, ch: "O"},
46
+ {re: /[\xF2-\xF6]/g, ch: "o"},
47
+ {re: /[\xD9-\xDC]/g, ch: "U"},
48
+ {re: /[\xF9-\xFC]/g, ch: "u"},
49
+ {re: /[\xC7-\xE7]/g, ch: "c"},
50
+ {re: /[\xD1]/g, ch: "N"},
51
+ {re: /[\xF1]/g, ch: "n"}
52
+ ];
53
+ $.each(rExps, function () {
54
+ text = text.replace(this.re, this.ch);
55
+ });
56
+ return text;
57
+ }
58
+
59
+
60
+ function htmlEscape(html) {
61
+ var escapeMap = {
62
+ '&': '&',
63
+ '<': '&lt;',
64
+ '>': '&gt;',
65
+ '"': '&quot;',
66
+ "'": '&#x27;',
67
+ '`': '&#x60;'
18
68
  };
19
-
20
- /**
21
- * Actual implementation of the case insensitive search.
22
- * @access private
23
- * @param {String} haystack
24
- * @param {String} needle
25
- * @returns {boolean}
26
- */
27
- function icontains(haystack, needle) {
28
- return haystack.toUpperCase().indexOf(needle.toUpperCase()) > -1;
69
+ var source = '(?:' + Object.keys(escapeMap).join('|') + ')',
70
+ testRegexp = new RegExp(source),
71
+ replaceRegexp = new RegExp(source, 'g'),
72
+ string = html == null ? '' : '' + html;
73
+ return testRegexp.test(string) ? string.replace(replaceRegexp, function (match) {
74
+ return escapeMap[match];
75
+ }) : string;
76
+ }
77
+
78
+ var Selectpicker = function (element, options, e) {
79
+ if (e) {
80
+ e.stopPropagation();
81
+ e.preventDefault();
29
82
  }
30
83
 
31
- /**
32
- * Remove all diatrics from the given text.
33
- * @access private
34
- * @param {String} text
35
- * @returns {String}
36
- */
37
- function normalizeToBase(text) {
38
- var rExps = [
39
- {re: /[\xC0-\xC6]/g, ch: "A"},
40
- {re: /[\xE0-\xE6]/g, ch: "a"},
41
- {re: /[\xC8-\xCB]/g, ch: "E"},
42
- {re: /[\xE8-\xEB]/g, ch: "e"},
43
- {re: /[\xCC-\xCF]/g, ch: "I"},
44
- {re: /[\xEC-\xEF]/g, ch: "i"},
45
- {re: /[\xD2-\xD6]/g, ch: "O"},
46
- {re: /[\xF2-\xF6]/g, ch: "o"},
47
- {re: /[\xD9-\xDC]/g, ch: "U"},
48
- {re: /[\xF9-\xFC]/g, ch: "u"},
49
- {re: /[\xC7-\xE7]/g, ch: "c"},
50
- {re: /[\xD1]/g, ch: "N"},
51
- {re: /[\xF1]/g, ch: "n"}
52
- ];
53
- $.each(rExps, function () {
54
- text = text.replace(this.re, this.ch);
55
- });
56
- return text;
84
+ this.$element = $(element);
85
+ this.$newElement = null;
86
+ this.$button = null;
87
+ this.$menu = null;
88
+ this.$lis = null;
89
+ this.options = options;
90
+
91
+ // 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
92
+ // data-attribute)
93
+ if (this.options.title === null) {
94
+ this.options.title = this.$element.attr('title');
57
95
  }
58
96
 
59
- var Selectpicker = function (element, options, e) {
60
- if (e) {
61
- e.stopPropagation();
62
- e.preventDefault();
97
+ //Expose public methods
98
+ this.val = Selectpicker.prototype.val;
99
+ this.render = Selectpicker.prototype.render;
100
+ this.refresh = Selectpicker.prototype.refresh;
101
+ this.setStyle = Selectpicker.prototype.setStyle;
102
+ this.selectAll = Selectpicker.prototype.selectAll;
103
+ this.deselectAll = Selectpicker.prototype.deselectAll;
104
+ this.destroy = Selectpicker.prototype.remove;
105
+ this.remove = Selectpicker.prototype.remove;
106
+ this.show = Selectpicker.prototype.show;
107
+ this.hide = Selectpicker.prototype.hide;
108
+
109
+ this.init();
110
+ };
111
+
112
+ Selectpicker.VERSION = '1.6.3';
113
+
114
+ // part of this is duplicated in i18n/defaults-en_US.js. Make sure to update both.
115
+ Selectpicker.DEFAULTS = {
116
+ noneSelectedText: 'Nothing selected',
117
+ noneResultsText: 'No results match',
118
+ countSelectedText: function (numSelected, numTotal) {
119
+ return (numSelected == 1) ? "{0} item selected" : "{0} items selected";
120
+ },
121
+ maxOptionsText: function (numAll, numGroup) {
122
+ var arr = [];
123
+
124
+ arr[0] = (numAll == 1) ? 'Limit reached ({n} item max)' : 'Limit reached ({n} items max)';
125
+ arr[1] = (numGroup == 1) ? 'Group limit reached ({n} item max)' : 'Group limit reached ({n} items max)';
126
+
127
+ return arr;
128
+ },
129
+ selectAllText: 'Select All',
130
+ deselectAllText: 'Deselect All',
131
+ multipleSeparator: ', ',
132
+ style: 'btn-default',
133
+ size: 'auto',
134
+ title: null,
135
+ selectedTextFormat: 'values',
136
+ width: false,
137
+ container: false,
138
+ hideDisabled: false,
139
+ showSubtext: false,
140
+ showIcon: true,
141
+ showContent: true,
142
+ dropupAuto: true,
143
+ header: false,
144
+ liveSearch: false,
145
+ liveSearchPlaceholder: null,
146
+ actionsBox: false,
147
+ iconBase: 'glyphicon',
148
+ tickIcon: 'glyphicon-ok',
149
+ maxOptions: false,
150
+ mobile: false,
151
+ selectOnTab: false,
152
+ dropdownAlignRight: false,
153
+ searchAccentInsensitive: false
154
+ };
155
+
156
+ Selectpicker.prototype = {
157
+
158
+ constructor: Selectpicker,
159
+
160
+ init: function () {
161
+ var that = this,
162
+ id = this.$element.attr('id');
163
+
164
+ this.$element.hide();
165
+ this.multiple = this.$element.prop('multiple');
166
+ this.autofocus = this.$element.prop('autofocus');
167
+ this.$newElement = this.createView();
168
+ this.$element.after(this.$newElement);
169
+ this.$menu = this.$newElement.find('> .dropdown-menu');
170
+ this.$button = this.$newElement.find('> button');
171
+ this.$searchbox = this.$newElement.find('input');
172
+
173
+ if (this.options.dropdownAlignRight)
174
+ this.$menu.addClass('dropdown-menu-right');
175
+
176
+ if (typeof id !== 'undefined') {
177
+ this.$button.attr('data-id', id);
178
+ $('label[for="' + id + '"]').click(function (e) {
179
+ e.preventDefault();
180
+ that.$button.focus();
181
+ });
182
+ }
183
+
184
+ this.checkDisabled();
185
+ this.clickListener();
186
+ if (this.options.liveSearch) this.liveSearchListener();
187
+ this.render();
188
+ this.liHeight();
189
+ this.setStyle();
190
+ this.setWidth();
191
+ if (this.options.container) this.selectPosition();
192
+ this.$menu.data('this', this);
193
+ this.$newElement.data('this', this);
194
+ if (this.options.mobile) this.mobile();
195
+ },
196
+
197
+ createDropdown: function () {
198
+ // Options
199
+ // If we are multiple, then add the show-tick class by default
200
+ var multiple = this.multiple ? ' show-tick' : '',
201
+ inputGroup = this.$element.parent().hasClass('input-group') ? ' input-group-btn' : '',
202
+ autofocus = this.autofocus ? ' autofocus' : '',
203
+ btnSize = this.$element.parents().hasClass('form-group-lg') ? ' btn-lg' : (this.$element.parents().hasClass('form-group-sm') ? ' btn-sm' : '');
204
+ // Elements
205
+ var header = this.options.header ? '<div class="popover-title"><button type="button" class="close" aria-hidden="true">&times;</button>' + this.options.header + '</div>' : '';
206
+ var searchbox = this.options.liveSearch ?
207
+ '<div class="bs-searchbox">' +
208
+ '<input type="text" class="form-control" autocomplete="off"' +
209
+ (null === this.options.liveSearchPlaceholder ? '' : ' placeholder="' + htmlEscape(this.options.liveSearchPlaceholder) + '"') + '>' +
210
+ '</div>'
211
+ : '';
212
+ var actionsbox = this.options.actionsBox ?
213
+ '<div class="bs-actionsbox">' +
214
+ '<div class="btn-group btn-block">' +
215
+ '<button class="actions-btn bs-select-all btn btn-sm btn-default">' +
216
+ this.options.selectAllText +
217
+ '</button>' +
218
+ '<button class="actions-btn bs-deselect-all btn btn-sm btn-default">' +
219
+ this.options.deselectAllText +
220
+ '</button>' +
221
+ '</div>' +
222
+ '</div>'
223
+ : '';
224
+ var drop =
225
+ '<div class="btn-group bootstrap-select' + multiple + inputGroup + '">' +
226
+ '<button type="button" class="btn dropdown-toggle form-control selectpicker' + btnSize + '" data-toggle="dropdown"' + autofocus + '>' +
227
+ '<span class="filter-option pull-left"></span>&nbsp;' +
228
+ '<span class="caret"></span>' +
229
+ '</button>' +
230
+ '<div class="dropdown-menu open">' +
231
+ header +
232
+ searchbox +
233
+ actionsbox +
234
+ '<ul class="dropdown-menu inner selectpicker" role="menu">' +
235
+ '</ul>' +
236
+ '</div>' +
237
+ '</div>';
238
+
239
+ return $(drop);
240
+ },
241
+
242
+ createView: function () {
243
+ var $drop = this.createDropdown();
244
+ var $li = this.createLi();
245
+ $drop.find('ul').append($li);
246
+ return $drop;
247
+ },
248
+
249
+ reloadLi: function () {
250
+ //Remove all children.
251
+ this.destroyLi();
252
+ //Re build
253
+ var $li = this.createLi();
254
+ this.$menu.find('ul').append($li);
255
+ },
256
+
257
+ destroyLi: function () {
258
+ this.$menu.find('li').remove();
259
+ },
260
+
261
+ createLi: function () {
262
+ var that = this,
263
+ _li = [],
264
+ optID = 0;
265
+
266
+ // Helper functions
267
+ /**
268
+ * @param content
269
+ * @param [index]
270
+ * @param [classes]
271
+ * @returns {string}
272
+ */
273
+ var generateLI = function (content, index, classes) {
274
+ return '<li' +
275
+ (typeof classes !== 'undefined' ? ' class="' + classes + '"' : '') +
276
+ (typeof index !== 'undefined' | null === index ? ' data-original-index="' + index + '"' : '') +
277
+ '>' + content + '</li>';
278
+ };
279
+
280
+ /**
281
+ * @param text
282
+ * @param [classes]
283
+ * @param [inline]
284
+ * @param [optgroup]
285
+ * @returns {string}
286
+ */
287
+ var generateA = function (text, classes, inline, optgroup) {
288
+ var normText = normalizeToBase(htmlEscape(text));
289
+ return '<a tabindex="0"' +
290
+ (typeof classes !== 'undefined' ? ' class="' + classes + '"' : '') +
291
+ (typeof inline !== 'undefined' ? ' style="' + inline + '"' : '') +
292
+ (typeof optgroup !== 'undefined' ? 'data-optgroup="' + optgroup + '"' : '') +
293
+ ' data-normalized-text="' + normText + '"' +
294
+ '>' + text +
295
+ '<span class="' + that.options.iconBase + ' ' + that.options.tickIcon + ' check-mark"></span>' +
296
+ '</a>';
297
+ };
298
+
299
+ this.$element.find('option').each(function () {
300
+ var $this = $(this);
301
+
302
+ // Get the class and text for the option
303
+ var optionClass = $this.attr('class') || '',
304
+ inline = $this.attr('style'),
305
+ text = $this.data('content') ? $this.data('content') : $this.html(),
306
+ subtext = typeof $this.data('subtext') !== 'undefined' ? '<small class="muted text-muted">' + $this.data('subtext') + '</small>' : '',
307
+ icon = typeof $this.data('icon') !== 'undefined' ? '<span class="' + that.options.iconBase + ' ' + $this.data('icon') + '"></span> ' : '',
308
+ isDisabled = $this.is(':disabled') || $this.parent().is(':disabled'),
309
+ index = $this.index();
310
+ if (icon !== '' && isDisabled) {
311
+ icon = '<span>' + icon + '</span>';
63
312
  }
64
313
 
65
- this.$element = $(element);
66
- this.$newElement = null;
67
- this.$button = null;
68
- this.$menu = null;
69
- this.$lis = null;
70
- this.options = options;
71
-
72
- // 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
73
- // data-attribute)
74
- if (this.options.title === null) {
75
- this.options.title = this.$element.attr('title');
314
+ if (!$this.data('content')) {
315
+ // Prepend any icon and append any subtext to the main text.
316
+ text = icon + '<span class="text">' + text + subtext + '</span>';
76
317
  }
77
318
 
78
- //Expose public methods
79
- this.val = Selectpicker.prototype.val;
80
- this.render = Selectpicker.prototype.render;
81
- this.refresh = Selectpicker.prototype.refresh;
82
- this.setStyle = Selectpicker.prototype.setStyle;
83
- this.selectAll = Selectpicker.prototype.selectAll;
84
- this.deselectAll = Selectpicker.prototype.deselectAll;
85
- this.destroy = Selectpicker.prototype.remove;
86
- this.remove = Selectpicker.prototype.remove;
87
- this.show = Selectpicker.prototype.show;
88
- this.hide = Selectpicker.prototype.hide;
89
-
90
- this.init();
91
- };
92
-
93
- Selectpicker.VERSION = '1.6.2';
94
-
95
- // part of this is duplicated in i18n/defaults-en_US.js. Make sure to update both.
96
- Selectpicker.DEFAULTS = {
97
- noneSelectedText: 'Nothing selected',
98
- noneResultsText: 'No results match',
99
- countSelectedText: function (numSelected, numTotal) {
100
- return (numSelected == 1) ? "{0} item selected" : "{0} items selected";
101
- },
102
- maxOptionsText: function (numAll, numGroup) {
103
- var arr = [];
104
-
105
- arr[0] = (numAll == 1) ? 'Limit reached ({n} item max)' : 'Limit reached ({n} items max)';
106
- arr[1] = (numGroup == 1) ? 'Group limit reached ({n} item max)' : 'Group limit reached ({n} items max)';
107
-
108
- return arr;
109
- },
110
- selectAllText: 'Select All',
111
- deselectAllText: 'Deselect All',
112
- multipleSeparator: ', ',
113
- style: 'btn-default',
114
- size: 'auto',
115
- title: null,
116
- selectedTextFormat: 'values',
117
- width: false,
118
- container: false,
119
- hideDisabled: false,
120
- showSubtext: false,
121
- showIcon: true,
122
- showContent: true,
123
- dropupAuto: true,
124
- header: false,
125
- liveSearch: false,
126
- actionsBox: false,
127
- iconBase: 'glyphicon',
128
- tickIcon: 'glyphicon-ok',
129
- maxOptions: false,
130
- mobile: false,
131
- selectOnTab: false,
132
- dropdownAlignRight: false,
133
- searchAccentInsensitive: false
134
- };
135
-
136
- Selectpicker.prototype = {
137
-
138
- constructor: Selectpicker,
139
-
140
- init: function () {
141
- var that = this,
142
- id = this.$element.attr('id');
143
-
144
- this.$element.hide();
145
- this.multiple = this.$element.prop('multiple');
146
- this.autofocus = this.$element.prop('autofocus');
147
- this.$newElement = this.createView();
148
- this.$element.after(this.$newElement);
149
- this.$menu = this.$newElement.find('> .dropdown-menu');
150
- this.$button = this.$newElement.find('> button');
151
- this.$searchbox = this.$newElement.find('input');
152
-
153
- if (this.options.dropdownAlignRight)
154
- this.$menu.addClass('dropdown-menu-right');
155
-
156
- if (typeof id !== 'undefined') {
157
- this.$button.attr('data-id', id);
158
- $('label[for="' + id + '"]').click(function (e) {
159
- e.preventDefault();
160
- that.$button.focus();
161
- });
162
- }
163
-
164
- this.checkDisabled();
165
- this.clickListener();
166
- if (this.options.liveSearch) this.liveSearchListener();
167
- this.render();
168
- this.liHeight();
169
- this.setStyle();
170
- this.setWidth();
171
- if (this.options.container) this.selectPosition();
172
- this.$menu.data('this', this);
173
- this.$newElement.data('this', this);
174
- if (this.options.mobile) this.mobile();
175
- },
176
-
177
- createDropdown: function () {
178
- // Options
179
- // If we are multiple, then add the show-tick class by default
180
- var multiple = this.multiple ? ' show-tick' : '',
181
- inputGroup = this.$element.parent().hasClass('input-group') ? ' input-group-btn' : '',
182
- autofocus = this.autofocus ? ' autofocus' : '',
183
- btnSize = this.$element.parents().hasClass('form-group-lg') ? ' btn-lg' : (this.$element.parents().hasClass('form-group-sm') ? ' btn-sm' : '');
184
- // Elements
185
- var header = this.options.header ? '<div class="popover-title"><button type="button" class="close" aria-hidden="true">&times;</button>' + this.options.header + '</div>' : '';
186
- var searchbox = this.options.liveSearch ? '<div class="bs-searchbox"><input type="text" class="input-block-level form-control" autocomplete="off" /></div>' : '';
187
- var actionsbox = this.options.actionsBox ? '<div class="bs-actionsbox">' +
188
- '<div class="btn-group btn-block">' +
189
- '<button class="actions-btn bs-select-all btn btn-sm btn-default">' +
190
- this.options.selectAllText +
191
- '</button>' +
192
- '<button class="actions-btn bs-deselect-all btn btn-sm btn-default">' +
193
- this.options.deselectAllText +
194
- '</button>' +
195
- '</div>' +
196
- '</div>' : '';
197
- var drop =
198
- '<div class="btn-group bootstrap-select' + multiple + inputGroup + '">' +
199
- '<button type="button" class="btn dropdown-toggle selectpicker' + btnSize + '" data-toggle="dropdown"' + autofocus + '>' +
200
- '<span class="filter-option pull-left"></span>&nbsp;' +
201
- '<span class="caret"></span>' +
202
- '</button>' +
203
- '<div class="dropdown-menu open">' +
204
- header +
205
- searchbox +
206
- actionsbox +
207
- '<ul class="dropdown-menu inner selectpicker" role="menu">' +
208
- '</ul>' +
209
- '</div>' +
210
- '</div>';
211
-
212
- return $(drop);
213
- },
214
-
215
- createView: function () {
216
- var $drop = this.createDropdown();
217
- var $li = this.createLi();
218
- $drop.find('ul').append($li);
219
- return $drop;
220
- },
221
-
222
- reloadLi: function () {
223
- //Remove all children.
224
- this.destroyLi();
225
- //Re build
226
- var $li = this.createLi();
227
- this.$menu.find('ul').append($li);
228
- },
229
-
230
- destroyLi: function () {
231
- this.$menu.find('li').remove();
232
- },
233
-
234
- createLi: function () {
235
- var that = this,
236
- _li = [],
237
- optID = 0;
238
-
239
- // Helper functions
240
- /**
241
- * @param content
242
- * @param [index]
243
- * @param [classes]
244
- * @returns {string}
245
- */
246
- var generateLI = function (content, index, classes) {
247
- return '<li' +
248
- (typeof classes !== 'undefined' ? ' class="' + classes + '"' : '') +
249
- (typeof index !== 'undefined' | null === index ? ' data-original-index="' + index + '"' : '') +
250
- '>' + content + '</li>';
251
- };
252
-
253
- /**
254
- * @param text
255
- * @param [classes]
256
- * @param [inline]
257
- * @param [optgroup]
258
- * @returns {string}
259
- */
260
- var generateA = function (text, classes, inline, optgroup) {
261
- var normText = normalizeToBase($.trim($("<div/>").html(text).text()).replace(/\s\s+/g, ' '));
262
- return '<a tabindex="0"' +
263
- (typeof classes !== 'undefined' ? ' class="' + classes + '"' : '') +
264
- (typeof inline !== 'undefined' ? ' style="' + inline + '"' : '') +
265
- (typeof optgroup !== 'undefined' ? 'data-optgroup="' + optgroup + '"' : '') +
266
- ' data-normalized-text="' + normText + '"' +
267
- '>' + text +
268
- '<span class="' + that.options.iconBase + ' ' + that.options.tickIcon + ' icon-ok check-mark"></span>' +
269
- '</a>';
270
- };
271
-
272
- this.$element.find('option').each(function () {
273
- var $this = $(this);
274
-
275
- // Get the class and text for the option
276
- var optionClass = $this.attr('class') || '',
277
- inline = $this.attr('style'),
278
- text = $this.data('content') ? $this.data('content') : $this.html(),
279
- subtext = typeof $this.data('subtext') !== 'undefined' ? '<small class="muted text-muted">' + $this.data('subtext') + '</small>' : '',
280
- icon = typeof $this.data('icon') !== 'undefined' ? '<span class="' + that.options.iconBase + ' ' + $this.data('icon') + '"></span> ' : '',
281
- isDisabled = $this.is(':disabled') || $this.parent().is(':disabled'),
282
- index = $this[0].index;
283
- if (icon !== '' && isDisabled) {
284
- icon = '<span>' + icon + '</span>';
285
- }
286
-
287
- if (!$this.data('content')) {
288
- // Prepend any icon and append any subtext to the main text.
289
- text = icon + '<span class="text">' + text + subtext + '</span>';
290
- }
291
-
292
- if (that.options.hideDisabled && isDisabled) {
293
- return;
294
- }
295
-
296
- if ($this.parent().is('optgroup') && $this.data('divider') !== true) {
297
- if ($this.index() === 0) { // Is it the first option of the optgroup?
298
- optID += 1;
299
-
300
- // Get the opt group label
301
- var label = $this.parent().attr('label');
302
- var labelSubtext = typeof $this.parent().data('subtext') !== 'undefined' ? '<small class="muted text-muted">' + $this.parent().data('subtext') + '</small>' : '';
303
- var labelIcon = $this.parent().data('icon') ? '<span class="' + that.options.iconBase + ' ' + $this.parent().data('icon') + '"></span> ' : '';
304
- label = labelIcon + '<span class="text">' + label + labelSubtext + '</span>';
305
-
306
- if (index !== 0 && _li.length > 0) { // Is it NOT the first option of the select && are there elements in the dropdown?
307
- _li.push(generateLI('', null, 'divider'));
308
- }
309
-
310
- _li.push(generateLI(label, null, 'dropdown-header'));
311
- }
312
-
313
- _li.push(generateLI(generateA(text, 'opt ' + optionClass, inline, optID), index));
314
- } else if ($this.data('divider') === true) {
315
- _li.push(generateLI('', index, 'divider'));
316
- } else if ($this.data('hidden') === true) {
317
- _li.push(generateLI(generateA(text, optionClass, inline), index, 'hide is-hidden'));
318
- } else {
319
- _li.push(generateLI(generateA(text, optionClass, inline), index));
320
- }
321
- });
322
-
323
- //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
324
- if (!this.multiple && this.$element.find('option:selected').length === 0 && !this.options.title) {
325
- this.$element.find('option').eq(0).prop('selected', true).attr('selected', 'selected');
326
- }
327
-
328
- return $(_li.join(''));
329
- },
330
-
331
- findLis: function () {
332
- if (this.$lis == null) this.$lis = this.$menu.find('li');
333
- return this.$lis;
334
- },
335
-
336
- /**
337
- * @param [updateLi] defaults to true
338
- */
339
- render: function (updateLi) {
340
- var that = this;
341
-
342
- //Update the LI to match the SELECT
343
- if (updateLi !== false) {
344
- this.$element.find('option').each(function (index) {
345
- that.setDisabled(index, $(this).is(':disabled') || $(this).parent().is(':disabled'));
346
- that.setSelected(index, $(this).is(':selected'));
347
- });
348
- }
349
-
350
- this.tabIndex();
351
- var notDisabled = this.options.hideDisabled ? ':not([disabled])' : '';
352
- var selectedItems = this.$element.find('option:selected' + notDisabled).map(function () {
353
- var $this = $(this);
354
- var icon = $this.data('icon') && that.options.showIcon ? '<i class="' + that.options.iconBase + ' ' + $this.data('icon') + '"></i> ' : '';
355
- var subtext;
356
- if (that.options.showSubtext && $this.attr('data-subtext') && !that.multiple) {
357
- subtext = ' <small class="muted text-muted">' + $this.data('subtext') + '</small>';
358
- } else {
359
- subtext = '';
360
- }
361
- if ($this.data('content') && that.options.showContent) {
362
- return $this.data('content');
363
- } else if (typeof $this.attr('title') !== 'undefined') {
364
- return $this.attr('title');
365
- } else {
366
- return icon + $this.html() + subtext;
367
- }
368
- }).toArray();
369
-
370
- //Fixes issue in IE10 occurring when no default option is selected and at least one option is disabled
371
- //Convert all the values into a comma delimited string
372
- var title = !this.multiple ? selectedItems[0] : selectedItems.join(this.options.multipleSeparator);
373
-
374
- //If this is multi select, and the selectText type is count, the show 1 of 2 selected etc..
375
- if (this.multiple && this.options.selectedTextFormat.indexOf('count') > -1) {
376
- var max = this.options.selectedTextFormat.split('>');
377
- if ((max.length > 1 && selectedItems.length > max[1]) || (max.length == 1 && selectedItems.length >= 2)) {
378
- notDisabled = this.options.hideDisabled ? ', [disabled]' : '';
379
- var totalCount = this.$element.find('option').not('[data-divider="true"], [data-hidden="true"]' + notDisabled).length,
380
- tr8nText = (typeof this.options.countSelectedText === 'function') ? this.options.countSelectedText(selectedItems.length, totalCount) : this.options.countSelectedText;
381
- title = tr8nText.replace('{0}', selectedItems.length.toString()).replace('{1}', totalCount.toString());
382
- }
383
- }
384
-
385
- this.options.title = this.$element.attr('title');
386
-
387
- if (this.options.selectedTextFormat == 'static') {
388
- title = this.options.title;
389
- }
390
-
391
- //If we dont have a title, then use the default, or if nothing is set at all, use the not selected text
392
- if (!title) {
393
- title = typeof this.options.title !== 'undefined' ? this.options.title : this.options.noneSelectedText;
394
- }
395
-
396
- this.$button.attr('title', $.trim($("<div/>").html(title).text()).replace(/\s\s+/g, ' '));
397
- this.$newElement.find('.filter-option').html(title);
398
- },
399
-
400
- /**
401
- * @param [style]
402
- * @param [status]
403
- */
404
- setStyle: function (style, status) {
405
- if (this.$element.attr('class')) {
406
- this.$newElement.addClass(this.$element.attr('class').replace(/selectpicker|mobile-device|validate\[.*\]/gi, ''));
407
- }
408
-
409
- var buttonClass = style ? style : this.options.style;
410
-
411
- if (status == 'add') {
412
- this.$button.addClass(buttonClass);
413
- } else if (status == 'remove') {
414
- this.$button.removeClass(buttonClass);
415
- } else {
416
- this.$button.removeClass(this.options.style);
417
- this.$button.addClass(buttonClass);
418
- }
419
- },
420
-
421
- liHeight: function () {
422
- if (this.options.size === false) return;
423
-
424
- var $selectClone = this.$menu.parent().clone().find('> .dropdown-toggle').prop('autofocus', false).end().appendTo('body'),
425
- $menuClone = $selectClone.addClass('open').find('> .dropdown-menu'),
426
- liHeight = $menuClone.find('li').not('.divider').not('.dropdown-header').filter(':visible').children('a').outerHeight(),
427
- headerHeight = this.options.header ? $menuClone.find('.popover-title').outerHeight() : 0,
428
- searchHeight = this.options.liveSearch ? $menuClone.find('.bs-searchbox').outerHeight() : 0,
429
- actionsHeight = this.options.actionsBox ? $menuClone.find('.bs-actionsbox').outerHeight() : 0;
430
-
431
- $selectClone.remove();
432
-
433
- this.$newElement
434
- .data('liHeight', liHeight)
435
- .data('headerHeight', headerHeight)
436
- .data('searchHeight', searchHeight)
437
- .data('actionsHeight', actionsHeight);
438
- },
439
-
440
- setSize: function () {
441
- this.findLis();
442
- var that = this,
443
- menu = this.$menu,
444
- menuInner = menu.find('.inner'),
445
- selectHeight = this.$newElement.outerHeight(),
446
- liHeight = this.$newElement.data('liHeight'),
447
- headerHeight = this.$newElement.data('headerHeight'),
448
- searchHeight = this.$newElement.data('searchHeight'),
449
- actionsHeight = this.$newElement.data('actionsHeight'),
450
- divHeight = this.$lis.filter('.divider').outerHeight(true),
451
- menuPadding = parseInt(menu.css('padding-top')) +
452
- parseInt(menu.css('padding-bottom')) +
453
- parseInt(menu.css('border-top-width')) +
454
- parseInt(menu.css('border-bottom-width')),
455
- notDisabled = this.options.hideDisabled ? ', .disabled' : '',
456
- $window = $(window),
457
- menuExtras = menuPadding + parseInt(menu.css('margin-top')) + parseInt(menu.css('margin-bottom')) + 2,
458
- menuHeight,
459
- selectOffsetTop,
460
- selectOffsetBot,
461
- posVert = function () {
462
- // JQuery defines a scrollTop function, but in pure JS it's a property
463
- //noinspection JSValidateTypes
464
- selectOffsetTop = that.$newElement.offset().top - $window.scrollTop();
465
- selectOffsetBot = $window.height() - selectOffsetTop - selectHeight;
466
- };
467
- posVert();
468
- if (this.options.header) menu.css('padding-top', 0);
469
-
470
- if (this.options.size == 'auto') {
471
- var getSize = function () {
472
- var minHeight,
473
- lisVis = that.$lis.not('.hide');
474
-
475
- posVert();
476
- menuHeight = selectOffsetBot - menuExtras;
477
-
478
- if (that.options.dropupAuto) {
479
- that.$newElement.toggleClass('dropup', (selectOffsetTop > selectOffsetBot) && ((menuHeight - menuExtras) < menu.height()));
480
- }
481
- if (that.$newElement.hasClass('dropup')) {
482
- menuHeight = selectOffsetTop - menuExtras;
483
- }
484
-
485
- if ((lisVis.length + lisVis.filter('.dropdown-header').length) > 3) {
486
- minHeight = liHeight * 3 + menuExtras - 2;
487
- } else {
488
- minHeight = 0;
489
- }
490
-
491
- menu.css({'max-height': menuHeight + 'px', 'overflow': 'hidden', 'min-height': minHeight + headerHeight + searchHeight + actionsHeight + 'px'});
492
- menuInner.css({'max-height': menuHeight - headerHeight - searchHeight - actionsHeight - menuPadding + 'px', 'overflow-y': 'auto', 'min-height': Math.max(minHeight - menuPadding, 0) + 'px'});
493
- };
494
- getSize();
495
- this.$searchbox.off('input.getSize propertychange.getSize').on('input.getSize propertychange.getSize', getSize);
496
- $(window).off('resize.getSize').on('resize.getSize', getSize);
497
- $(window).off('scroll.getSize').on('scroll.getSize', getSize);
498
- } else if (this.options.size && this.options.size != 'auto' && menu.find('li' + notDisabled).length > this.options.size) {
499
- var optIndex = this.$lis.not('.divider' + notDisabled).find(' > *').slice(0, this.options.size).last().parent().index();
500
- var divLength = this.$lis.slice(0, optIndex + 1).filter('.divider').length;
501
- menuHeight = liHeight * this.options.size + divLength * divHeight + menuPadding;
502
- if (that.options.dropupAuto) {
503
- //noinspection JSUnusedAssignment
504
- this.$newElement.toggleClass('dropup', (selectOffsetTop > selectOffsetBot) && (menuHeight < menu.height()));
505
- }
506
- menu.css({'max-height': menuHeight + headerHeight + searchHeight + actionsHeight + 'px', 'overflow': 'hidden'});
507
- menuInner.css({'max-height': menuHeight - menuPadding + 'px', 'overflow-y': 'auto'});
508
- }
509
- },
510
-
511
- setWidth: function () {
512
- if (this.options.width == 'auto') {
513
- this.$menu.css('min-width', '0');
514
-
515
- // Get correct width if element hidden
516
- var selectClone = this.$newElement.clone().appendTo('body');
517
- var ulWidth = selectClone.find('> .dropdown-menu').css('width');
518
- var btnWidth = selectClone.css('width', 'auto').find('> button').css('width');
519
- selectClone.remove();
520
-
521
- // Set width to whatever's larger, button title or longest option
522
- this.$newElement.css('width', Math.max(parseInt(ulWidth), parseInt(btnWidth)) + 'px');
523
- } else if (this.options.width == 'fit') {
524
- // Remove inline min-width so width can be changed from 'auto'
525
- this.$menu.css('min-width', '');
526
- this.$newElement.css('width', '').addClass('fit-width');
527
- } else if (this.options.width) {
528
- // Remove inline min-width so width can be changed from 'auto'
529
- this.$menu.css('min-width', '');
530
- this.$newElement.css('width', this.options.width);
531
- } else {
532
- // Remove inline min-width/width so width can be changed
533
- this.$menu.css('min-width', '');
534
- this.$newElement.css('width', '');
535
- }
536
- // Remove fit-width class if width is changed programmatically
537
- if (this.$newElement.hasClass('fit-width') && this.options.width !== 'fit') {
538
- this.$newElement.removeClass('fit-width');
539
- }
540
- },
541
-
542
- selectPosition: function () {
543
- var that = this,
544
- drop = '<div />',
545
- $drop = $(drop),
546
- pos,
547
- actualHeight,
548
- getPlacement = function ($element) {
549
- $drop.addClass($element.attr('class').replace(/form-control/gi, '')).toggleClass('dropup', $element.hasClass('dropup'));
550
- pos = $element.offset();
551
- actualHeight = $element.hasClass('dropup') ? 0 : $element[0].offsetHeight;
552
- $drop.css({'top': pos.top + actualHeight, 'left': pos.left, 'width': $element[0].offsetWidth, 'position': 'absolute'});
553
- };
554
- this.$newElement.on('click', function () {
555
- if (that.isDisabled()) {
556
- return;
557
- }
558
- getPlacement($(this));
559
- $drop.appendTo(that.options.container);
560
- $drop.toggleClass('open', !$(this).hasClass('open'));
561
- $drop.append(that.$menu);
562
- });
563
- $(window).resize(function () {
564
- getPlacement(that.$newElement);
565
- });
566
- $(window).on('scroll', function () {
567
- getPlacement(that.$newElement);
568
- });
569
- $('html').on('click', function (e) {
570
- if ($(e.target).closest(that.$newElement).length < 1) {
571
- $drop.removeClass('open');
572
- }
573
- });
574
- },
575
-
576
- setSelected: function (index, selected) {
577
- this.findLis();
578
- this.$lis.filter('[data-original-index="' + index + '"]').toggleClass('selected', selected);
579
- },
580
-
581
- setDisabled: function (index, disabled) {
582
- this.findLis();
583
- if (disabled) {
584
- this.$lis.filter('[data-original-index="' + index + '"]').addClass('disabled').find('a').attr('href', '#').attr('tabindex', -1);
585
- } else {
586
- this.$lis.filter('[data-original-index="' + index + '"]').removeClass('disabled').find('a').removeAttr('href').attr('tabindex', 0);
587
- }
588
- },
319
+ if (that.options.hideDisabled && isDisabled) {
320
+ return;
321
+ }
589
322
 
590
- isDisabled: function () {
591
- return this.$element.is(':disabled');
592
- },
323
+ if ($this.parent().is('optgroup') && $this.data('divider') !== true) {
324
+ if ($this.index() === 0) { // Is it the first option of the optgroup?
325
+ optID += 1;
593
326
 
594
- checkDisabled: function () {
595
- var that = this;
327
+ // Get the opt group label
328
+ var label = $this.parent().attr('label');
329
+ var labelSubtext = typeof $this.parent().data('subtext') !== 'undefined' ? '<small class="muted text-muted">' + $this.parent().data('subtext') + '</small>' : '';
330
+ var labelIcon = $this.parent().data('icon') ? '<span class="' + that.options.iconBase + ' ' + $this.parent().data('icon') + '"></span> ' : '';
331
+ label = labelIcon + '<span class="text">' + label + labelSubtext + '</span>';
596
332
 
597
- if (this.isDisabled()) {
598
- this.$button.addClass('disabled').attr('tabindex', -1);
599
- } else {
600
- if (this.$button.hasClass('disabled')) {
601
- this.$button.removeClass('disabled');
602
- }
603
-
604
- if (this.$button.attr('tabindex') == -1) {
605
- if (!this.$element.data('tabindex')) this.$button.removeAttr('tabindex');
606
- }
333
+ if (index !== 0 && _li.length > 0) { // Is it NOT the first option of the select && are there elements in the dropdown?
334
+ _li.push(generateLI('', null, 'divider'));
607
335
  }
608
336
 
609
- this.$button.click(function () {
610
- return !that.isDisabled();
611
- });
612
- },
613
-
614
- tabIndex: function () {
615
- if (this.$element.is('[tabindex]')) {
616
- this.$element.data('tabindex', this.$element.attr('tabindex'));
617
- this.$button.attr('tabindex', this.$element.data('tabindex'));
618
- }
619
- },
337
+ _li.push(generateLI(label, null, 'dropdown-header'));
338
+ }
620
339
 
621
- clickListener: function () {
622
- var that = this;
340
+ _li.push(generateLI(generateA(text, 'opt ' + optionClass, inline, optID), index));
341
+ } else if ($this.data('divider') === true) {
342
+ _li.push(generateLI('', index, 'divider'));
343
+ } else if ($this.data('hidden') === true) {
344
+ _li.push(generateLI(generateA(text, optionClass, inline), index, 'hidden is-hidden'));
345
+ } else {
346
+ _li.push(generateLI(generateA(text, optionClass, inline), index));
347
+ }
348
+ });
623
349
 
624
- this.$newElement.on('touchstart.dropdown', '.dropdown-menu', function (e) {
625
- e.stopPropagation();
626
- });
350
+ //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
351
+ if (!this.multiple && this.$element.find('option:selected').length === 0 && !this.options.title) {
352
+ this.$element.find('option').eq(0).prop('selected', true).attr('selected', 'selected');
353
+ }
627
354
 
628
- this.$newElement.on('click', function () {
629
- that.setSize();
630
- if (!that.options.liveSearch && !that.multiple) {
631
- setTimeout(function () {
632
- that.$menu.find('.selected a').focus();
633
- }, 10);
634
- }
635
- });
355
+ return $(_li.join(''));
356
+ },
636
357
 
637
- this.$menu.on('click', 'li a', function (e) {
638
- var $this = $(this),
639
- clickedIndex = $this.parent().data('originalIndex'),
640
- prevValue = that.$element.val(),
641
- prevIndex = that.$element.prop('selectedIndex');
358
+ findLis: function () {
359
+ if (this.$lis == null) this.$lis = this.$menu.find('li');
360
+ return this.$lis;
361
+ },
642
362
 
643
- // Don't close on multi choice menu
644
- if (that.multiple) {
645
- e.stopPropagation();
646
- }
363
+ /**
364
+ * @param [updateLi] defaults to true
365
+ */
366
+ render: function (updateLi) {
367
+ var that = this;
368
+
369
+ //Update the LI to match the SELECT
370
+ if (updateLi !== false) {
371
+ this.$element.find('option').each(function (index) {
372
+ that.setDisabled(index, $(this).is(':disabled') || $(this).parent().is(':disabled'));
373
+ that.setSelected(index, $(this).is(':selected'));
374
+ });
375
+ }
376
+
377
+ this.tabIndex();
378
+ var notDisabled = this.options.hideDisabled ? ':not([disabled])' : '';
379
+ var selectedItems = this.$element.find('option:selected' + notDisabled).map(function () {
380
+ var $this = $(this);
381
+ var icon = $this.data('icon') && that.options.showIcon ? '<i class="' + that.options.iconBase + ' ' + $this.data('icon') + '"></i> ' : '';
382
+ var subtext;
383
+ if (that.options.showSubtext && $this.attr('data-subtext') && !that.multiple) {
384
+ subtext = ' <small class="muted text-muted">' + $this.data('subtext') + '</small>';
385
+ } else {
386
+ subtext = '';
387
+ }
388
+ if ($this.data('content') && that.options.showContent) {
389
+ return $this.data('content');
390
+ } else if (typeof $this.attr('title') !== 'undefined') {
391
+ return $this.attr('title');
392
+ } else {
393
+ return icon + $this.html() + subtext;
394
+ }
395
+ }).toArray();
396
+
397
+ //Fixes issue in IE10 occurring when no default option is selected and at least one option is disabled
398
+ //Convert all the values into a comma delimited string
399
+ var title = !this.multiple ? selectedItems[0] : selectedItems.join(this.options.multipleSeparator);
400
+
401
+ //If this is multi select, and the selectText type is count, the show 1 of 2 selected etc..
402
+ if (this.multiple && this.options.selectedTextFormat.indexOf('count') > -1) {
403
+ var max = this.options.selectedTextFormat.split('>');
404
+ if ((max.length > 1 && selectedItems.length > max[1]) || (max.length == 1 && selectedItems.length >= 2)) {
405
+ notDisabled = this.options.hideDisabled ? ', [disabled]' : '';
406
+ var totalCount = this.$element.find('option').not('[data-divider="true"], [data-hidden="true"]' + notDisabled).length,
407
+ tr8nText = (typeof this.options.countSelectedText === 'function') ? this.options.countSelectedText(selectedItems.length, totalCount) : this.options.countSelectedText;
408
+ title = tr8nText.replace('{0}', selectedItems.length.toString()).replace('{1}', totalCount.toString());
409
+ }
410
+ }
647
411
 
648
- e.preventDefault();
649
-
650
- //Don't run if we have been disabled
651
- if (!that.isDisabled() && !$this.parent().hasClass('disabled')) {
652
- var $options = that.$element.find('option'),
653
- $option = $options.eq(clickedIndex),
654
- state = $option.prop('selected'),
655
- $optgroup = $option.parent('optgroup'),
656
- maxOptions = that.options.maxOptions,
657
- maxOptionsGrp = $optgroup.data('maxOptions') || false;
658
-
659
- if (!that.multiple) { // Deselect all others if not multi select box
660
- $options.prop('selected', false);
661
- $option.prop('selected', true);
662
- that.$menu.find('.selected').removeClass('selected');
663
- that.setSelected(clickedIndex, true);
664
- } else { // Toggle the one we have chosen if we are multi select.
665
- $option.prop('selected', !state);
666
- that.setSelected(clickedIndex, !state);
667
- $this.blur();
668
-
669
- if ((maxOptions !== false) || (maxOptionsGrp !== false)) {
670
- var maxReached = maxOptions < $options.filter(':selected').length,
671
- maxReachedGrp = maxOptionsGrp < $optgroup.find('option:selected').length;
672
-
673
- if ((maxOptions && maxReached) || (maxOptionsGrp && maxReachedGrp)) {
674
- if (maxOptions && maxOptions == 1) {
675
- $options.prop('selected', false);
676
- $option.prop('selected', true);
677
- that.$menu.find('.selected').removeClass('selected');
678
- that.setSelected(clickedIndex, true);
679
- } else if (maxOptionsGrp && maxOptionsGrp == 1) {
680
- $optgroup.find('option:selected').prop('selected', false);
681
- $option.prop('selected', true);
682
- var optgroupID = $this.data('optgroup');
683
-
684
- that.$menu.find('.selected').has('a[data-optgroup="' + optgroupID + '"]').removeClass('selected');
685
-
686
- that.setSelected(clickedIndex, true);
687
- } else {
688
- var maxOptionsArr = (typeof that.options.maxOptionsText === 'function') ?
689
- that.options.maxOptionsText(maxOptions, maxOptionsGrp) : that.options.maxOptionsText,
690
- maxTxt = maxOptionsArr[0].replace('{n}', maxOptions),
691
- maxTxtGrp = maxOptionsArr[1].replace('{n}', maxOptionsGrp),
692
- $notify = $('<div class="notify"></div>');
693
- // If {var} is set in array, replace it
694
- /** @deprecated */
695
- if (maxOptionsArr[2]) {
696
- maxTxt = maxTxt.replace('{var}', maxOptionsArr[2][maxOptions > 1 ? 0 : 1]);
697
- maxTxtGrp = maxTxtGrp.replace('{var}', maxOptionsArr[2][maxOptionsGrp > 1 ? 0 : 1]);
698
- }
699
-
700
- $option.prop('selected', false);
701
-
702
- that.$menu.append($notify);
703
-
704
- if (maxOptions && maxReached) {
705
- $notify.append($('<div>' + maxTxt + '</div>'));
706
- that.$element.trigger('maxReached.bs.select');
707
- }
708
-
709
- if (maxOptionsGrp && maxReachedGrp) {
710
- $notify.append($('<div>' + maxTxtGrp + '</div>'));
711
- that.$element.trigger('maxReachedGrp.bs.select');
712
- }
713
-
714
- setTimeout(function () {
715
- that.setSelected(clickedIndex, false);
716
- }, 10);
717
-
718
- $notify.delay(750).fadeOut(300, function () {
719
- $(this).remove();
720
- });
721
- }
722
- }
723
- }
724
- }
725
-
726
- if (!that.multiple) {
727
- that.$button.focus();
728
- } else if (that.options.liveSearch) {
729
- that.$searchbox.focus();
730
- }
731
-
732
- // Trigger select 'change'
733
- if ((prevValue != that.$element.val() && that.multiple) || (prevIndex != that.$element.prop('selectedIndex') && !that.multiple)) {
734
- that.$element.change();
735
- }
736
- }
737
- });
412
+ this.options.title = this.$element.attr('title');
738
413
 
739
- this.$menu.on('click', 'li.disabled a, .popover-title, .popover-title :not(.close)', function (e) {
740
- if (e.target == this) {
741
- e.preventDefault();
742
- e.stopPropagation();
743
- if (!that.options.liveSearch) {
744
- that.$button.focus();
745
- } else {
746
- that.$searchbox.focus();
747
- }
748
- }
749
- });
414
+ if (this.options.selectedTextFormat == 'static') {
415
+ title = this.options.title;
416
+ }
750
417
 
751
- this.$menu.on('click', 'li.divider, li.dropdown-header', function (e) {
752
- e.preventDefault();
753
- e.stopPropagation();
754
- if (!that.options.liveSearch) {
755
- that.$button.focus();
756
- } else {
757
- that.$searchbox.focus();
758
- }
759
- });
418
+ //If we dont have a title, then use the default, or if nothing is set at all, use the not selected text
419
+ if (!title) {
420
+ title = typeof this.options.title !== 'undefined' ? this.options.title : this.options.noneSelectedText;
421
+ }
760
422
 
761
- this.$menu.on('click', '.popover-title .close', function () {
762
- that.$button.focus();
763
- });
423
+ //strip all html-tags and trim the result
424
+ this.$button.attr('title', $.trim(title.replace(/<[^>]*>?/g, '')));
425
+ this.$newElement.find('.filter-option').html(title);
426
+ },
764
427
 
765
- this.$searchbox.on('click', function (e) {
766
- e.stopPropagation();
428
+ /**
429
+ * @param [style]
430
+ * @param [status]
431
+ */
432
+ setStyle: function (style, status) {
433
+ if (this.$element.attr('class')) {
434
+ this.$newElement.addClass(this.$element.attr('class').replace(/selectpicker|mobile-device|validate\[.*\]/gi, ''));
435
+ }
436
+
437
+ var buttonClass = style ? style : this.options.style;
438
+
439
+ if (status == 'add') {
440
+ this.$button.addClass(buttonClass);
441
+ } else if (status == 'remove') {
442
+ this.$button.removeClass(buttonClass);
443
+ } else {
444
+ this.$button.removeClass(this.options.style);
445
+ this.$button.addClass(buttonClass);
446
+ }
447
+ },
448
+
449
+ liHeight: function () {
450
+ if (this.options.size === false) return;
451
+
452
+ var $selectClone = this.$menu.parent().clone().find('> .dropdown-toggle').prop('autofocus', false).end().appendTo('body'),
453
+ $menuClone = $selectClone.addClass('open').find('> .dropdown-menu'),
454
+ liHeight = $menuClone.find('li').not('.divider').not('.dropdown-header').filter(':visible').children('a').outerHeight(),
455
+ headerHeight = this.options.header ? $menuClone.find('.popover-title').outerHeight() : 0,
456
+ searchHeight = this.options.liveSearch ? $menuClone.find('.bs-searchbox').outerHeight() : 0,
457
+ actionsHeight = this.options.actionsBox ? $menuClone.find('.bs-actionsbox').outerHeight() : 0;
458
+
459
+ $selectClone.remove();
460
+
461
+ this.$newElement
462
+ .data('liHeight', liHeight)
463
+ .data('headerHeight', headerHeight)
464
+ .data('searchHeight', searchHeight)
465
+ .data('actionsHeight', actionsHeight);
466
+ },
467
+
468
+ setSize: function () {
469
+ this.findLis();
470
+ var that = this,
471
+ menu = this.$menu,
472
+ menuInner = menu.find('.inner'),
473
+ selectHeight = this.$newElement.outerHeight(),
474
+ liHeight = this.$newElement.data('liHeight'),
475
+ headerHeight = this.$newElement.data('headerHeight'),
476
+ searchHeight = this.$newElement.data('searchHeight'),
477
+ actionsHeight = this.$newElement.data('actionsHeight'),
478
+ divHeight = this.$lis.filter('.divider').outerHeight(true),
479
+ menuPadding = parseInt(menu.css('padding-top')) +
480
+ parseInt(menu.css('padding-bottom')) +
481
+ parseInt(menu.css('border-top-width')) +
482
+ parseInt(menu.css('border-bottom-width')),
483
+ notDisabled = this.options.hideDisabled ? ', .disabled' : '',
484
+ $window = $(window),
485
+ menuExtras = menuPadding + parseInt(menu.css('margin-top')) + parseInt(menu.css('margin-bottom')) + 2,
486
+ menuHeight,
487
+ selectOffsetTop,
488
+ selectOffsetBot,
489
+ posVert = function () {
490
+ // JQuery defines a scrollTop function, but in pure JS it's a property
491
+ //noinspection JSValidateTypes
492
+ selectOffsetTop = that.$newElement.offset().top - $window.scrollTop();
493
+ selectOffsetBot = $window.height() - selectOffsetTop - selectHeight;
494
+ };
495
+ posVert();
496
+ if (this.options.header) menu.css('padding-top', 0);
497
+
498
+ if (this.options.size == 'auto') {
499
+ var getSize = function () {
500
+ var minHeight,
501
+ lisVis = that.$lis.not('.hidden');
502
+
503
+ posVert();
504
+ menuHeight = selectOffsetBot - menuExtras;
505
+
506
+ if (that.options.dropupAuto) {
507
+ that.$newElement.toggleClass('dropup', (selectOffsetTop > selectOffsetBot) && ((menuHeight - menuExtras) < menu.height()));
508
+ }
509
+ if (that.$newElement.hasClass('dropup')) {
510
+ menuHeight = selectOffsetTop - menuExtras;
511
+ }
512
+
513
+ if ((lisVis.length + lisVis.filter('.dropdown-header').length) > 3) {
514
+ minHeight = liHeight * 3 + menuExtras - 2;
515
+ } else {
516
+ minHeight = 0;
517
+ }
518
+
519
+ menu.css({
520
+ 'max-height': menuHeight + 'px',
521
+ 'overflow': 'hidden',
522
+ 'min-height': minHeight + headerHeight + searchHeight + actionsHeight + 'px'
523
+ });
524
+ menuInner.css({
525
+ 'max-height': menuHeight - headerHeight - searchHeight - actionsHeight - menuPadding + 'px',
526
+ 'overflow-y': 'auto',
527
+ 'min-height': Math.max(minHeight - menuPadding, 0) + 'px'
528
+ });
529
+ };
530
+ getSize();
531
+ this.$searchbox.off('input.getSize propertychange.getSize').on('input.getSize propertychange.getSize', getSize);
532
+ $(window).off('resize.getSize').on('resize.getSize', getSize);
533
+ $(window).off('scroll.getSize').on('scroll.getSize', getSize);
534
+ } else if (this.options.size && this.options.size != 'auto' && menu.find('li' + notDisabled).length > this.options.size) {
535
+ var optIndex = this.$lis.not('.divider' + notDisabled).find(' > *').slice(0, this.options.size).last().parent().index();
536
+ var divLength = this.$lis.slice(0, optIndex + 1).filter('.divider').length;
537
+ menuHeight = liHeight * this.options.size + divLength * divHeight + menuPadding;
538
+ if (that.options.dropupAuto) {
539
+ //noinspection JSUnusedAssignment
540
+ this.$newElement.toggleClass('dropup', (selectOffsetTop > selectOffsetBot) && (menuHeight < menu.height()));
541
+ }
542
+ menu.css({'max-height': menuHeight + headerHeight + searchHeight + actionsHeight + 'px', 'overflow': 'hidden'});
543
+ menuInner.css({'max-height': menuHeight - menuPadding + 'px', 'overflow-y': 'auto'});
544
+ }
545
+ },
546
+
547
+ setWidth: function () {
548
+ if (this.options.width == 'auto') {
549
+ this.$menu.css('min-width', '0');
550
+
551
+ // Get correct width if element hidden
552
+ var selectClone = this.$newElement.clone().appendTo('body');
553
+ var ulWidth = selectClone.find('> .dropdown-menu').css('width');
554
+ var btnWidth = selectClone.css('width', 'auto').find('> button').css('width');
555
+ selectClone.remove();
556
+
557
+ // Set width to whatever's larger, button title or longest option
558
+ this.$newElement.css('width', Math.max(parseInt(ulWidth), parseInt(btnWidth)) + 'px');
559
+ } else if (this.options.width == 'fit') {
560
+ // Remove inline min-width so width can be changed from 'auto'
561
+ this.$menu.css('min-width', '');
562
+ this.$newElement.css('width', '').addClass('fit-width');
563
+ } else if (this.options.width) {
564
+ // Remove inline min-width so width can be changed from 'auto'
565
+ this.$menu.css('min-width', '');
566
+ this.$newElement.css('width', this.options.width);
567
+ } else {
568
+ // Remove inline min-width/width so width can be changed
569
+ this.$menu.css('min-width', '');
570
+ this.$newElement.css('width', '');
571
+ }
572
+ // Remove fit-width class if width is changed programmatically
573
+ if (this.$newElement.hasClass('fit-width') && this.options.width !== 'fit') {
574
+ this.$newElement.removeClass('fit-width');
575
+ }
576
+ },
577
+
578
+ selectPosition: function () {
579
+ var that = this,
580
+ drop = '<div />',
581
+ $drop = $(drop),
582
+ pos,
583
+ actualHeight,
584
+ getPlacement = function ($element) {
585
+ $drop.addClass($element.attr('class').replace(/form-control/gi, '')).toggleClass('dropup', $element.hasClass('dropup'));
586
+ pos = $element.offset();
587
+ actualHeight = $element.hasClass('dropup') ? 0 : $element[0].offsetHeight;
588
+ $drop.css({
589
+ 'top': pos.top + actualHeight,
590
+ 'left': pos.left,
591
+ 'width': $element[0].offsetWidth,
592
+ 'position': 'absolute'
767
593
  });
594
+ };
595
+ this.$newElement.on('click', function () {
596
+ if (that.isDisabled()) {
597
+ return;
598
+ }
599
+ getPlacement($(this));
600
+ $drop.appendTo(that.options.container);
601
+ $drop.toggleClass('open', !$(this).hasClass('open'));
602
+ $drop.append(that.$menu);
603
+ });
604
+ $(window).resize(function () {
605
+ getPlacement(that.$newElement);
606
+ });
607
+ $(window).on('scroll', function () {
608
+ getPlacement(that.$newElement);
609
+ });
610
+ $('html').on('click', function (e) {
611
+ if ($(e.target).closest(that.$newElement).length < 1) {
612
+ $drop.removeClass('open');
613
+ }
614
+ });
615
+ },
616
+
617
+ setSelected: function (index, selected) {
618
+ this.findLis();
619
+ this.$lis.filter('[data-original-index="' + index + '"]').toggleClass('selected', selected);
620
+ },
621
+
622
+ setDisabled: function (index, disabled) {
623
+ this.findLis();
624
+ if (disabled) {
625
+ this.$lis.filter('[data-original-index="' + index + '"]').addClass('disabled').find('a').attr('href', '#').attr('tabindex', -1);
626
+ } else {
627
+ this.$lis.filter('[data-original-index="' + index + '"]').removeClass('disabled').find('a').removeAttr('href').attr('tabindex', 0);
628
+ }
629
+ },
630
+
631
+ isDisabled: function () {
632
+ return this.$element.is(':disabled');
633
+ },
634
+
635
+ checkDisabled: function () {
636
+ var that = this;
637
+
638
+ if (this.isDisabled()) {
639
+ this.$button.addClass('disabled').attr('tabindex', -1);
640
+ } else {
641
+ if (this.$button.hasClass('disabled')) {
642
+ this.$button.removeClass('disabled');
643
+ }
768
644
 
645
+ if (this.$button.attr('tabindex') == -1) {
646
+ if (!this.$element.data('tabindex')) this.$button.removeAttr('tabindex');
647
+ }
648
+ }
649
+
650
+ this.$button.click(function () {
651
+ return !that.isDisabled();
652
+ });
653
+ },
654
+
655
+ tabIndex: function () {
656
+ if (this.$element.is('[tabindex]')) {
657
+ this.$element.data('tabindex', this.$element.attr('tabindex'));
658
+ this.$button.attr('tabindex', this.$element.data('tabindex'));
659
+ }
660
+ },
661
+
662
+ clickListener: function () {
663
+ var that = this;
664
+
665
+ this.$newElement.on('touchstart.dropdown', '.dropdown-menu', function (e) {
666
+ e.stopPropagation();
667
+ });
668
+
669
+ this.$newElement.on('click', function () {
670
+ that.setSize();
671
+ if (!that.options.liveSearch && !that.multiple) {
672
+ setTimeout(function () {
673
+ that.$menu.find('.selected a').focus();
674
+ }, 10);
675
+ }
676
+ });
769
677
 
770
- this.$menu.on('click', '.actions-btn', function (e) {
771
- if (that.options.liveSearch) {
772
- that.$searchbox.focus();
773
- } else {
774
- that.$button.focus();
775
- }
678
+ this.$menu.on('click', 'li a', function (e) {
679
+ var $this = $(this),
680
+ clickedIndex = $this.parent().data('originalIndex'),
681
+ prevValue = that.$element.val(),
682
+ prevIndex = that.$element.prop('selectedIndex');
776
683
 
777
- e.preventDefault();
778
- e.stopPropagation();
684
+ // Don't close on multi choice menu
685
+ if (that.multiple) {
686
+ e.stopPropagation();
687
+ }
779
688
 
780
- if ($(this).is('.bs-select-all')) {
781
- that.selectAll();
689
+ e.preventDefault();
690
+
691
+ //Don't run if we have been disabled
692
+ if (!that.isDisabled() && !$this.parent().hasClass('disabled')) {
693
+ var $options = that.$element.find('option'),
694
+ $option = $options.eq(clickedIndex),
695
+ state = $option.prop('selected'),
696
+ $optgroup = $option.parent('optgroup'),
697
+ maxOptions = that.options.maxOptions,
698
+ maxOptionsGrp = $optgroup.data('maxOptions') || false;
699
+
700
+ if (!that.multiple) { // Deselect all others if not multi select box
701
+ $options.prop('selected', false);
702
+ $option.prop('selected', true);
703
+ that.$menu.find('.selected').removeClass('selected');
704
+ that.setSelected(clickedIndex, true);
705
+ } else { // Toggle the one we have chosen if we are multi select.
706
+ $option.prop('selected', !state);
707
+ that.setSelected(clickedIndex, !state);
708
+ $this.blur();
709
+
710
+ if ((maxOptions !== false) || (maxOptionsGrp !== false)) {
711
+ var maxReached = maxOptions < $options.filter(':selected').length,
712
+ maxReachedGrp = maxOptionsGrp < $optgroup.find('option:selected').length;
713
+
714
+ if ((maxOptions && maxReached) || (maxOptionsGrp && maxReachedGrp)) {
715
+ if (maxOptions && maxOptions == 1) {
716
+ $options.prop('selected', false);
717
+ $option.prop('selected', true);
718
+ that.$menu.find('.selected').removeClass('selected');
719
+ that.setSelected(clickedIndex, true);
720
+ } else if (maxOptionsGrp && maxOptionsGrp == 1) {
721
+ $optgroup.find('option:selected').prop('selected', false);
722
+ $option.prop('selected', true);
723
+ var optgroupID = $this.data('optgroup');
724
+
725
+ that.$menu.find('.selected').has('a[data-optgroup="' + optgroupID + '"]').removeClass('selected');
726
+
727
+ that.setSelected(clickedIndex, true);
782
728
  } else {
783
- that.deselectAll();
729
+ var maxOptionsArr = (typeof that.options.maxOptionsText === 'function') ?
730
+ that.options.maxOptionsText(maxOptions, maxOptionsGrp) : that.options.maxOptionsText,
731
+ maxTxt = maxOptionsArr[0].replace('{n}', maxOptions),
732
+ maxTxtGrp = maxOptionsArr[1].replace('{n}', maxOptionsGrp),
733
+ $notify = $('<div class="notify"></div>');
734
+ // If {var} is set in array, replace it
735
+ /** @deprecated */
736
+ if (maxOptionsArr[2]) {
737
+ maxTxt = maxTxt.replace('{var}', maxOptionsArr[2][maxOptions > 1 ? 0 : 1]);
738
+ maxTxtGrp = maxTxtGrp.replace('{var}', maxOptionsArr[2][maxOptionsGrp > 1 ? 0 : 1]);
739
+ }
740
+
741
+ $option.prop('selected', false);
742
+
743
+ that.$menu.append($notify);
744
+
745
+ if (maxOptions && maxReached) {
746
+ $notify.append($('<div>' + maxTxt + '</div>'));
747
+ that.$element.trigger('maxReached.bs.select');
748
+ }
749
+
750
+ if (maxOptionsGrp && maxReachedGrp) {
751
+ $notify.append($('<div>' + maxTxtGrp + '</div>'));
752
+ that.$element.trigger('maxReachedGrp.bs.select');
753
+ }
754
+
755
+ setTimeout(function () {
756
+ that.setSelected(clickedIndex, false);
757
+ }, 10);
758
+
759
+ $notify.delay(750).fadeOut(300, function () {
760
+ $(this).remove();
761
+ });
784
762
  }
785
- that.$element.change();
786
- });
787
-
788
- this.$element.change(function () {
789
- that.render(false);
790
- });
791
- },
792
-
793
- liveSearchListener: function () {
794
- var that = this,
795
- no_results = $('<li class="no-results"></li>');
796
-
797
- this.$newElement.on('click.dropdown.data-api', function () {
798
- that.$menu.find('.active').removeClass('active');
799
- if (!!that.$searchbox.val()) {
800
- that.$searchbox.val('');
801
- that.$lis.not('.is-hidden').removeClass('hide');
802
- if (!!no_results.parent().length) no_results.remove();
803
- }
804
- if (!that.multiple) that.$menu.find('.selected').addClass('active');
805
- setTimeout(function () {
806
- that.$searchbox.focus();
807
- }, 10);
808
- });
763
+ }
764
+ }
765
+ }
766
+
767
+ if (!that.multiple) {
768
+ that.$button.focus();
769
+ } else if (that.options.liveSearch) {
770
+ that.$searchbox.focus();
771
+ }
772
+
773
+ // Trigger select 'change'
774
+ if ((prevValue != that.$element.val() && that.multiple) || (prevIndex != that.$element.prop('selectedIndex') && !that.multiple)) {
775
+ that.$element.change();
776
+ }
777
+ }
778
+ });
779
+
780
+ this.$menu.on('click', 'li.disabled a, .popover-title, .popover-title :not(.close)', function (e) {
781
+ if (e.currentTarget == this) {
782
+ e.preventDefault();
783
+ e.stopPropagation();
784
+ if (!that.options.liveSearch) {
785
+ that.$button.focus();
786
+ } else {
787
+ that.$searchbox.focus();
788
+ }
789
+ }
790
+ });
809
791
 
810
- this.$searchbox.on('input propertychange', function () {
811
- if (that.$searchbox.val()) {
792
+ this.$menu.on('click', 'li.divider, li.dropdown-header', function (e) {
793
+ e.preventDefault();
794
+ e.stopPropagation();
795
+ if (!that.options.liveSearch) {
796
+ that.$button.focus();
797
+ } else {
798
+ that.$searchbox.focus();
799
+ }
800
+ });
812
801
 
813
- if (that.options.searchAccentInsensitive) {
814
- that.$lis.not('.is-hidden').removeClass('hide').find('a').not(':aicontains(' + normalizeToBase(that.$searchbox.val()) + ')').parent().addClass('hide');
815
- } else {
816
- that.$lis.not('.is-hidden').removeClass('hide').find('a').not(':icontains(' + that.$searchbox.val() + ')').parent().addClass('hide');
817
- }
802
+ this.$menu.on('click', '.popover-title .close', function () {
803
+ that.$button.focus();
804
+ });
818
805
 
819
- if (!that.$menu.find('li').filter(':visible:not(.no-results)').length) {
820
- if (!!no_results.parent().length) no_results.remove();
821
- no_results.html(that.options.noneResultsText + ' "' + that.$searchbox.val() + '"').show();
822
- that.$menu.find('li').last().after(no_results);
823
- } else if (!!no_results.parent().length) {
824
- no_results.remove();
825
- }
806
+ this.$searchbox.on('click', function (e) {
807
+ e.stopPropagation();
808
+ });
826
809
 
827
- } else {
828
- that.$lis.not('.is-hidden').removeClass('hide');
829
- if (!!no_results.parent().length) no_results.remove();
830
- }
831
810
 
832
- that.$menu.find('li.active').removeClass('active');
833
- that.$menu.find('li').filter(':visible:not(.divider)').eq(0).addClass('active').find('a').focus();
834
- $(this).focus();
835
- });
811
+ this.$menu.on('click', '.actions-btn', function (e) {
812
+ if (that.options.liveSearch) {
813
+ that.$searchbox.focus();
814
+ } else {
815
+ that.$button.focus();
816
+ }
836
817
 
837
- this.$menu.on('mouseenter', 'a', function (e) {
838
- that.$menu.find('.active').removeClass('active');
839
- $(e.currentTarget).parent().not('.disabled').addClass('active');
840
- });
818
+ e.preventDefault();
819
+ e.stopPropagation();
841
820
 
842
- this.$menu.on('mouseleave', 'a', function () {
843
- that.$menu.find('.active').removeClass('active');
844
- });
845
- },
821
+ if ($(this).is('.bs-select-all')) {
822
+ that.selectAll();
823
+ } else {
824
+ that.deselectAll();
825
+ }
826
+ that.$element.change();
827
+ });
828
+
829
+ this.$element.change(function () {
830
+ that.render(false);
831
+ });
832
+ },
833
+
834
+ liveSearchListener: function () {
835
+ var that = this,
836
+ no_results = $('<li class="no-results"></li>');
837
+
838
+ this.$newElement.on('click.dropdown.data-api touchstart.dropdown.data-api', function () {
839
+ that.$menu.find('.active').removeClass('active');
840
+ if (!!that.$searchbox.val()) {
841
+ that.$searchbox.val('');
842
+ that.$lis.not('.is-hidden').removeClass('hidden');
843
+ if (!!no_results.parent().length) no_results.remove();
844
+ }
845
+ if (!that.multiple) that.$menu.find('.selected').addClass('active');
846
+ setTimeout(function () {
847
+ that.$searchbox.focus();
848
+ }, 10);
849
+ });
850
+
851
+ this.$searchbox.on('click.dropdown.data-api focus.dropdown.data-api touchend.dropdown.data-api', function (e) {
852
+ e.stopPropagation();
853
+ });
854
+
855
+ this.$searchbox.on('input propertychange', function () {
856
+ if (that.$searchbox.val()) {
857
+
858
+ if (that.options.searchAccentInsensitive) {
859
+ that.$lis.not('.is-hidden').removeClass('hidden').find('a').not(':aicontains(' + normalizeToBase(that.$searchbox.val()) + ')').parent().addClass('hidden');
860
+ } else {
861
+ that.$lis.not('.is-hidden').removeClass('hidden').find('a').not(':icontains(' + that.$searchbox.val() + ')').parent().addClass('hidden');
862
+ }
863
+
864
+ if (!that.$menu.find('li').filter(':visible:not(.no-results)').length) {
865
+ if (!!no_results.parent().length) no_results.remove();
866
+ no_results.html(that.options.noneResultsText + ' "' + htmlEscape(that.$searchbox.val()) + '"').show();
867
+ that.$menu.find('li').last().after(no_results);
868
+ } else if (!!no_results.parent().length) {
869
+ no_results.remove();
870
+ }
846
871
 
847
- val: function (value) {
848
- if (typeof value !== 'undefined') {
849
- this.$element.val(value);
850
- this.render();
872
+ } else {
873
+ that.$lis.not('.is-hidden').removeClass('hidden');
874
+ if (!!no_results.parent().length) no_results.remove();
875
+ }
851
876
 
852
- return this.$element;
877
+ that.$menu.find('li.active').removeClass('active');
878
+ that.$menu.find('li').filter(':visible:not(.divider)').eq(0).addClass('active').find('a').focus();
879
+ $(this).focus();
880
+ });
881
+ },
882
+
883
+ val: function (value) {
884
+ if (typeof value !== 'undefined') {
885
+ this.$element.val(value);
886
+ this.render();
887
+
888
+ return this.$element;
889
+ } else {
890
+ return this.$element.val();
891
+ }
892
+ },
893
+
894
+ selectAll: function () {
895
+ this.findLis();
896
+ this.$lis.not('.divider').not('.disabled').not('.selected').filter(':visible').find('a').click();
897
+ },
898
+
899
+ deselectAll: function () {
900
+ this.findLis();
901
+ this.$lis.not('.divider').not('.disabled').filter('.selected').filter(':visible').find('a').click();
902
+ },
903
+
904
+ keydown: function (e) {
905
+ var $this = $(this),
906
+ $parent = ($this.is('input')) ? $this.parent().parent() : $this.parent(),
907
+ $items,
908
+ that = $parent.data('this'),
909
+ index,
910
+ next,
911
+ first,
912
+ last,
913
+ prev,
914
+ nextPrev,
915
+ prevIndex,
916
+ isActive,
917
+ keyCodeMap = {
918
+ 32: ' ',
919
+ 48: '0',
920
+ 49: '1',
921
+ 50: '2',
922
+ 51: '3',
923
+ 52: '4',
924
+ 53: '5',
925
+ 54: '6',
926
+ 55: '7',
927
+ 56: '8',
928
+ 57: '9',
929
+ 59: ';',
930
+ 65: 'a',
931
+ 66: 'b',
932
+ 67: 'c',
933
+ 68: 'd',
934
+ 69: 'e',
935
+ 70: 'f',
936
+ 71: 'g',
937
+ 72: 'h',
938
+ 73: 'i',
939
+ 74: 'j',
940
+ 75: 'k',
941
+ 76: 'l',
942
+ 77: 'm',
943
+ 78: 'n',
944
+ 79: 'o',
945
+ 80: 'p',
946
+ 81: 'q',
947
+ 82: 'r',
948
+ 83: 's',
949
+ 84: 't',
950
+ 85: 'u',
951
+ 86: 'v',
952
+ 87: 'w',
953
+ 88: 'x',
954
+ 89: 'y',
955
+ 90: 'z',
956
+ 96: '0',
957
+ 97: '1',
958
+ 98: '2',
959
+ 99: '3',
960
+ 100: '4',
961
+ 101: '5',
962
+ 102: '6',
963
+ 103: '7',
964
+ 104: '8',
965
+ 105: '9'
966
+ };
967
+
968
+ if (that.options.liveSearch) $parent = $this.parent().parent();
969
+
970
+ if (that.options.container) $parent = that.$menu;
971
+
972
+ $items = $('[role=menu] li a', $parent);
973
+
974
+ isActive = that.$menu.parent().hasClass('open');
975
+
976
+ if (!isActive && /([0-9]|[A-z])/.test(String.fromCharCode(e.keyCode))) {
977
+ if (!that.options.container) {
978
+ that.setSize();
979
+ that.$menu.parent().addClass('open');
980
+ isActive = true;
981
+ } else {
982
+ that.$newElement.trigger('click');
983
+ }
984
+ that.$searchbox.focus();
985
+ }
986
+
987
+ if (that.options.liveSearch) {
988
+ if (/(^9$|27)/.test(e.keyCode.toString(10)) && isActive && that.$menu.find('.active').length === 0) {
989
+ e.preventDefault();
990
+ that.$menu.parent().removeClass('open');
991
+ that.$button.focus();
992
+ }
993
+ $items = $('[role=menu] li:not(.divider):not(.dropdown-header):visible', $parent);
994
+ if (!$this.val() && !/(38|40)/.test(e.keyCode.toString(10))) {
995
+ if ($items.filter('.active').length === 0) {
996
+ if (that.options.searchAccentInsensitive) {
997
+ $items = that.$newElement.find('li').filter(':aicontains(' + normalizeToBase(keyCodeMap[e.keyCode]) + ')');
853
998
  } else {
854
- return this.$element.val();
855
- }
856
- },
857
-
858
- selectAll: function () {
859
- this.findLis();
860
- this.$lis.not('.divider').not('.disabled').not('.selected').filter(':visible').find('a').click();
861
- },
862
-
863
- deselectAll: function () {
864
- this.findLis();
865
- this.$lis.not('.divider').not('.disabled').filter('.selected').filter(':visible').find('a').click();
866
- },
867
-
868
- keydown: function (e) {
869
- var $this,
870
- $items,
871
- $parent,
872
- index,
873
- next,
874
- first,
875
- last,
876
- prev,
877
- nextPrev,
878
- that,
879
- prevIndex,
880
- isActive,
881
- keyCodeMap = {
882
- 32: ' ', 48: '0', 49: '1', 50: '2', 51: '3', 52: '4', 53: '5', 54: '6', 55: '7', 56: '8', 57: '9', 59: ';',
883
- 65: 'a', 66: 'b', 67: 'c', 68: 'd', 69: 'e', 70: 'f', 71: 'g', 72: 'h', 73: 'i', 74: 'j', 75: 'k', 76: 'l',
884
- 77: 'm', 78: 'n', 79: 'o', 80: 'p', 81: 'q', 82: 'r', 83: 's', 84: 't', 85: 'u', 86: 'v', 87: 'w', 88: 'x',
885
- 89: 'y', 90: 'z', 96: '0', 97: '1', 98: '2', 99: '3', 100: '4', 101: '5', 102: '6', 103: '7', 104: '8', 105: '9'
886
- };
887
-
888
- $this = $(this);
889
-
890
- $parent = $this.parent();
891
-
892
- if ($this.is('input')) $parent = $this.parent().parent();
893
-
894
- that = $parent.data('this');
895
-
896
- if (that.options.liveSearch) $parent = $this.parent().parent();
897
-
898
- if (that.options.container) $parent = that.$menu;
899
-
900
- $items = $('[role=menu] li a', $parent);
901
-
902
- isActive = that.$menu.parent().hasClass('open');
903
-
904
- if (!isActive && /([0-9]|[A-z])/.test(String.fromCharCode(e.keyCode))) {
905
- if (!that.options.container) {
906
- that.setSize();
907
- that.$menu.parent().addClass('open');
908
- isActive = true;
909
- } else {
910
- that.$newElement.trigger('click');
911
- }
912
- that.$searchbox.focus();
999
+ $items = that.$newElement.find('li').filter(':icontains(' + keyCodeMap[e.keyCode] + ')');
913
1000
  }
914
-
915
- if (that.options.liveSearch) {
916
- if (/(^9$|27)/.test(e.keyCode.toString(10)) && isActive && that.$menu.find('.active').length === 0) {
917
- e.preventDefault();
918
- that.$menu.parent().removeClass('open');
919
- that.$button.focus();
920
- }
921
- $items = $('[role=menu] li:not(.divider):not(.dropdown-header):visible', $parent);
922
- if (!$this.val() && !/(38|40)/.test(e.keyCode.toString(10))) {
923
- if ($items.filter('.active').length === 0) {
924
- if (that.options.searchAccentInsensitive) {
925
- $items = that.$newElement.find('li').filter(':aicontains(' + normalizeToBase(keyCodeMap[e.keyCode]) + ')');
926
- } else {
927
- $items = that.$newElement.find('li').filter(':icontains(' + keyCodeMap[e.keyCode] + ')');
928
- }
929
- }
930
- }
1001
+ }
1002
+ }
1003
+ }
1004
+
1005
+ if (!$items.length) return;
1006
+
1007
+ if (/(38|40)/.test(e.keyCode.toString(10))) {
1008
+ index = $items.index($items.filter(':focus'));
1009
+ first = $items.parent(':not(.disabled):visible').first().index();
1010
+ last = $items.parent(':not(.disabled):visible').last().index();
1011
+ next = $items.eq(index).parent().nextAll(':not(.disabled):visible').eq(0).index();
1012
+ prev = $items.eq(index).parent().prevAll(':not(.disabled):visible').eq(0).index();
1013
+ nextPrev = $items.eq(next).parent().prevAll(':not(.disabled):visible').eq(0).index();
1014
+
1015
+ if (that.options.liveSearch) {
1016
+ $items.each(function (i) {
1017
+ if ($(this).is(':not(.disabled)')) {
1018
+ $(this).data('index', i);
931
1019
  }
1020
+ });
1021
+ index = $items.index($items.filter('.active'));
1022
+ first = $items.filter(':not(.disabled):visible').first().data('index');
1023
+ last = $items.filter(':not(.disabled):visible').last().data('index');
1024
+ next = $items.eq(index).nextAll(':not(.disabled):visible').eq(0).data('index');
1025
+ prev = $items.eq(index).prevAll(':not(.disabled):visible').eq(0).data('index');
1026
+ nextPrev = $items.eq(next).prevAll(':not(.disabled):visible').eq(0).data('index');
1027
+ }
932
1028
 
933
- if (!$items.length) return;
934
-
935
- if (/(38|40)/.test(e.keyCode.toString(10))) {
936
- index = $items.index($items.filter(':focus'));
937
- first = $items.parent(':not(.disabled):visible').first().index();
938
- last = $items.parent(':not(.disabled):visible').last().index();
939
- next = $items.eq(index).parent().nextAll(':not(.disabled):visible').eq(0).index();
940
- prev = $items.eq(index).parent().prevAll(':not(.disabled):visible').eq(0).index();
941
- nextPrev = $items.eq(next).parent().prevAll(':not(.disabled):visible').eq(0).index();
942
-
943
- if (that.options.liveSearch) {
944
- $items.each(function (i) {
945
- if ($(this).is(':not(.disabled)')) {
946
- $(this).data('index', i);
947
- }
948
- });
949
- index = $items.index($items.filter('.active'));
950
- first = $items.filter(':not(.disabled):visible').first().data('index');
951
- last = $items.filter(':not(.disabled):visible').last().data('index');
952
- next = $items.eq(index).nextAll(':not(.disabled):visible').eq(0).data('index');
953
- prev = $items.eq(index).prevAll(':not(.disabled):visible').eq(0).data('index');
954
- nextPrev = $items.eq(next).prevAll(':not(.disabled):visible').eq(0).data('index');
955
- }
956
-
957
- prevIndex = $this.data('prevIndex');
1029
+ prevIndex = $this.data('prevIndex');
958
1030
 
959
- if (e.keyCode == 38) {
960
- if (that.options.liveSearch) index -= 1;
961
- if (index != nextPrev && index > prev) index = prev;
962
- if (index < first) index = first;
963
- if (index == prevIndex) index = last;
964
- }
1031
+ if (e.keyCode == 38) {
1032
+ if (that.options.liveSearch) index -= 1;
1033
+ if (index != nextPrev && index > prev) index = prev;
1034
+ if (index < first) index = first;
1035
+ if (index == prevIndex) index = last;
1036
+ }
965
1037
 
966
- if (e.keyCode == 40) {
967
- if (that.options.liveSearch) index += 1;
968
- if (index == -1) index = 0;
969
- if (index != nextPrev && index < next) index = next;
970
- if (index > last) index = last;
971
- if (index == prevIndex) index = first;
972
- }
1038
+ if (e.keyCode == 40) {
1039
+ if (that.options.liveSearch) index += 1;
1040
+ if (index == -1) index = 0;
1041
+ if (index != nextPrev && index < next) index = next;
1042
+ if (index > last) index = last;
1043
+ if (index == prevIndex) index = first;
1044
+ }
973
1045
 
974
- $this.data('prevIndex', index);
1046
+ $this.data('prevIndex', index);
975
1047
 
976
- if (!that.options.liveSearch) {
977
- $items.eq(index).focus();
978
- } else {
979
- e.preventDefault();
980
- if (!$this.is('.dropdown-toggle')) {
981
- $items.removeClass('active');
982
- $items.eq(index).addClass('active').find('a').focus();
983
- $this.focus();
984
- }
985
- }
1048
+ if (!that.options.liveSearch) {
1049
+ $items.eq(index).focus();
1050
+ } else {
1051
+ e.preventDefault();
1052
+ if (!$this.is('.dropdown-toggle')) {
1053
+ $items.removeClass('active');
1054
+ $items.eq(index).addClass('active').find('a').focus();
1055
+ $this.focus();
1056
+ }
1057
+ }
986
1058
 
987
- } else if (!$this.is('input')) {
988
- var keyIndex = [],
989
- count,
990
- prevKey;
991
-
992
- $items.each(function () {
993
- if ($(this).parent().is(':not(.disabled)')) {
994
- if ($.trim($(this).text().toLowerCase()).substring(0, 1) == keyCodeMap[e.keyCode]) {
995
- keyIndex.push($(this).parent().index());
996
- }
997
- }
998
- });
999
-
1000
- count = $(document).data('keycount');
1001
- count++;
1002
- $(document).data('keycount', count);
1003
-
1004
- prevKey = $.trim($(':focus').text().toLowerCase()).substring(0, 1);
1005
-
1006
- if (prevKey != keyCodeMap[e.keyCode]) {
1007
- count = 1;
1008
- $(document).data('keycount', count);
1009
- } else if (count >= keyIndex.length) {
1010
- $(document).data('keycount', 0);
1011
- if (count > keyIndex.length) count = 1;
1012
- }
1059
+ } else if (!$this.is('input')) {
1060
+ var keyIndex = [],
1061
+ count,
1062
+ prevKey;
1013
1063
 
1014
- $items.eq(keyIndex[count - 1]).focus();
1015
- }
1016
-
1017
- // Select focused option if "Enter", "Spacebar" or "Tab" (when selectOnTab is true) are pressed inside the menu.
1018
- if ((/(13|32)/.test(e.keyCode.toString(10)) || (/(^9$)/.test(e.keyCode.toString(10)) && that.options.selectOnTab)) && isActive) {
1019
- if (!/(32)/.test(e.keyCode.toString(10))) e.preventDefault();
1020
- if (!that.options.liveSearch) {
1021
- $(':focus').click();
1022
- } else if (!/(32)/.test(e.keyCode.toString(10))) {
1023
- that.$menu.find('.active a').click();
1024
- $this.focus();
1025
- }
1026
- $(document).data('keycount', 0);
1064
+ $items.each(function () {
1065
+ if ($(this).parent().is(':not(.disabled)')) {
1066
+ if ($.trim($(this).text().toLowerCase()).substring(0, 1) == keyCodeMap[e.keyCode]) {
1067
+ keyIndex.push($(this).parent().index());
1027
1068
  }
1069
+ }
1070
+ });
1028
1071
 
1029
- if ((/(^9$|27)/.test(e.keyCode.toString(10)) && isActive && (that.multiple || that.options.liveSearch)) || (/(27)/.test(e.keyCode.toString(10)) && !isActive)) {
1030
- that.$menu.parent().removeClass('open');
1031
- that.$button.focus();
1032
- }
1033
- },
1034
-
1035
- mobile: function () {
1036
- this.$element.addClass('mobile-device').appendTo(this.$newElement);
1037
- if (this.options.container) this.$menu.hide();
1038
- },
1039
-
1040
- refresh: function () {
1041
- this.$lis = null;
1042
- this.reloadLi();
1043
- this.render();
1044
- this.setWidth();
1045
- this.setStyle();
1046
- this.checkDisabled();
1047
- this.liHeight();
1048
- },
1049
-
1050
- update: function () {
1051
- this.reloadLi();
1052
- this.setWidth();
1053
- this.setStyle();
1054
- this.checkDisabled();
1055
- this.liHeight();
1056
- },
1057
-
1058
- hide: function () {
1059
- this.$newElement.hide();
1060
- },
1061
-
1062
- show: function () {
1063
- this.$newElement.show();
1064
- },
1065
-
1066
- remove: function () {
1067
- this.$newElement.remove();
1068
- this.$element.remove();
1069
- }
1070
- };
1072
+ count = $(document).data('keycount');
1073
+ count++;
1074
+ $(document).data('keycount', count);
1071
1075
 
1072
- // SELECTPICKER PLUGIN DEFINITION
1073
- // ==============================
1074
- function Plugin(option, event) {
1075
- // get the args of the outer function..
1076
- var args = arguments;
1077
- // The arguments of the function are explicitly re-defined from the argument list, because the shift causes them
1078
- // to get lost
1079
- //noinspection JSDuplicatedDeclaration
1080
- var option = args[0],
1081
- event = args[1];
1082
- [].shift.apply(args);
1083
- var value;
1084
- var chain = this.each(function () {
1085
- var $this = $(this);
1086
- if ($this.is('select')) {
1087
- var data = $this.data('selectpicker'),
1088
- options = typeof option == 'object' && option;
1089
-
1090
- if (!data) {
1091
- var config = $.extend({}, Selectpicker.DEFAULTS, $.fn.selectpicker.defaults, $this.data(), options);
1092
- $this.data('selectpicker', (data = new Selectpicker(this, config, event)));
1093
- } else if (options) {
1094
- for (var i in options) {
1095
- if (options.hasOwnProperty(i)) {
1096
- data.options[i] = options[i];
1097
- }
1098
- }
1099
- }
1076
+ prevKey = $.trim($(':focus').text().toLowerCase()).substring(0, 1);
1100
1077
 
1101
- if (typeof option == 'string') {
1102
- if (data[option] instanceof Function) {
1103
- value = data[option].apply(data, args);
1104
- } else {
1105
- value = data.options[option];
1106
- }
1107
- }
1108
- }
1109
- });
1078
+ if (prevKey != keyCodeMap[e.keyCode]) {
1079
+ count = 1;
1080
+ $(document).data('keycount', count);
1081
+ } else if (count >= keyIndex.length) {
1082
+ $(document).data('keycount', 0);
1083
+ if (count > keyIndex.length) count = 1;
1084
+ }
1110
1085
 
1111
- if (typeof value !== 'undefined') {
1112
- //noinspection JSUnusedAssignment
1113
- return value;
1114
- } else {
1115
- return chain;
1086
+ $items.eq(keyIndex[count - 1]).focus();
1087
+ }
1088
+
1089
+ // Select focused option if "Enter", "Spacebar" or "Tab" (when selectOnTab is true) are pressed inside the menu.
1090
+ if ((/(13|32)/.test(e.keyCode.toString(10)) || (/(^9$)/.test(e.keyCode.toString(10)) && that.options.selectOnTab)) && isActive) {
1091
+ if (!/(32)/.test(e.keyCode.toString(10))) e.preventDefault();
1092
+ if (!that.options.liveSearch) {
1093
+ $(':focus').click();
1094
+ } else if (!/(32)/.test(e.keyCode.toString(10))) {
1095
+ that.$menu.find('.active a').click();
1096
+ $this.focus();
1116
1097
  }
1098
+ $(document).data('keycount', 0);
1099
+ }
1100
+
1101
+ if ((/(^9$|27)/.test(e.keyCode.toString(10)) && isActive && (that.multiple || that.options.liveSearch)) || (/(27)/.test(e.keyCode.toString(10)) && !isActive)) {
1102
+ that.$menu.parent().removeClass('open');
1103
+ that.$button.focus();
1104
+ }
1105
+ },
1106
+
1107
+ mobile: function () {
1108
+ this.$element.addClass('mobile-device').appendTo(this.$newElement);
1109
+ if (this.options.container) this.$menu.hide();
1110
+ },
1111
+
1112
+ refresh: function () {
1113
+ this.$lis = null;
1114
+ this.reloadLi();
1115
+ this.render();
1116
+ this.setWidth();
1117
+ this.setStyle();
1118
+ this.checkDisabled();
1119
+ this.liHeight();
1120
+ },
1121
+
1122
+ hide: function () {
1123
+ this.$newElement.hide();
1124
+ },
1125
+
1126
+ show: function () {
1127
+ this.$newElement.show();
1128
+ },
1129
+
1130
+ remove: function () {
1131
+ this.$newElement.remove();
1132
+ this.$element.remove();
1133
+ }
1134
+ };
1135
+
1136
+ // SELECTPICKER PLUGIN DEFINITION
1137
+ // ==============================
1138
+ function Plugin(option, event) {
1139
+ // get the args of the outer function..
1140
+ var args = arguments;
1141
+ // The arguments of the function are explicitly re-defined from the argument list, because the shift causes them
1142
+ // to get lost
1143
+ //noinspection JSDuplicatedDeclaration
1144
+ var _option = option,
1145
+ option = args[0],
1146
+ event = args[1];
1147
+ [].shift.apply(args);
1148
+
1149
+ // This fixes a bug in the js implementation on android 2.3 #715
1150
+ if (typeof option == 'undefined') {
1151
+ option = _option;
1117
1152
  }
1118
1153
 
1119
- var old = $.fn.selectpicker;
1120
- $.fn.selectpicker = Plugin;
1121
- $.fn.selectpicker.Constructor = Selectpicker;
1122
-
1123
- // SELECTPICKER NO CONFLICT
1124
- // ========================
1125
- $.fn.selectpicker.noConflict = function () {
1126
- $.fn.selectpicker = old;
1127
- return this;
1128
- };
1129
-
1130
- $(document)
1131
- .data('keycount', 0)
1132
- .on('keydown', '.bootstrap-select [data-toggle=dropdown], .bootstrap-select [role=menu], .bs-searchbox input', Selectpicker.prototype.keydown)
1133
- .on('focusin.modal', '.bootstrap-select [data-toggle=dropdown], .bootstrap-select [role=menu], .bs-searchbox input', function (e) {
1134
- e.stopPropagation();
1135
- });
1154
+ var value;
1155
+ var chain = this.each(function () {
1156
+ var $this = $(this);
1157
+ if ($this.is('select')) {
1158
+ var data = $this.data('selectpicker'),
1159
+ options = typeof option == 'object' && option;
1160
+
1161
+ if (!data) {
1162
+ var config = $.extend({}, Selectpicker.DEFAULTS, $.fn.selectpicker.defaults || {}, $this.data(), options);
1163
+ $this.data('selectpicker', (data = new Selectpicker(this, config, event)));
1164
+ } else if (options) {
1165
+ for (var i in options) {
1166
+ if (options.hasOwnProperty(i)) {
1167
+ data.options[i] = options[i];
1168
+ }
1169
+ }
1170
+ }
1136
1171
 
1137
- // SELECTPICKER DATA-API
1138
- // =====================
1139
- $(window).on('load.bs.select.data-api', function () {
1140
- $('.selectpicker').each(function () {
1141
- var $selectpicker = $(this);
1142
- Plugin.call($selectpicker, $selectpicker.data());
1143
- })
1172
+ if (typeof option == 'string') {
1173
+ if (data[option] instanceof Function) {
1174
+ value = data[option].apply(data, args);
1175
+ } else {
1176
+ value = data.options[option];
1177
+ }
1178
+ }
1179
+ }
1144
1180
  });
1181
+
1182
+ if (typeof value !== 'undefined') {
1183
+ //noinspection JSUnusedAssignment
1184
+ return value;
1185
+ } else {
1186
+ return chain;
1187
+ }
1188
+ }
1189
+
1190
+ var old = $.fn.selectpicker;
1191
+ $.fn.selectpicker = Plugin;
1192
+ $.fn.selectpicker.Constructor = Selectpicker;
1193
+
1194
+ // SELECTPICKER NO CONFLICT
1195
+ // ========================
1196
+ $.fn.selectpicker.noConflict = function () {
1197
+ $.fn.selectpicker = old;
1198
+ return this;
1199
+ };
1200
+
1201
+ $(document)
1202
+ .data('keycount', 0)
1203
+ .on('keydown', '.bootstrap-select [data-toggle=dropdown], .bootstrap-select [role=menu], .bs-searchbox input', Selectpicker.prototype.keydown)
1204
+ .on('focusin.modal', '.bootstrap-select [data-toggle=dropdown], .bootstrap-select [role=menu], .bs-searchbox input', function (e) {
1205
+ e.stopPropagation();
1206
+ });
1207
+
1208
+ // SELECTPICKER DATA-API
1209
+ // =====================
1210
+ $(window).on('load.bs.select.data-api', function () {
1211
+ $('.selectpicker').each(function () {
1212
+ var $selectpicker = $(this);
1213
+ Plugin.call($selectpicker, $selectpicker.data());
1214
+ })
1215
+ });
1145
1216
  })(jQuery);