bootstrap-select-rails 1.6.2 → 1.6.3

Sign up to get free protection for your applications and to get access to all the features.
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);