bootstrap-multiselect-rails 0.0.2 → 0.0.4
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
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 209905ce2f3ed58adb2a4b612d313c503c66ec42
|
4
|
+
data.tar.gz: 8471b006251914b1e32056fb5052f64bfa07a0df
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: ebb318bd3d83fd0aedcdead2a0f38e57463958c7dc120286482913a4c00c68ba4ce8972398c4db442b4da77a77bd77d58f56c2b769a260d4a4a2added9bd3747
|
7
|
+
data.tar.gz: e672577800668d926e952739f5b71433fe3df2ac04f590aa9e1cfdf0c26102ebb46d772ba89748b152522532c5922435df2448debe395861f7e4948f1344b102
|
data/README.md
CHANGED
@@ -16,11 +16,11 @@ And then execute:
|
|
16
16
|
|
17
17
|
In `application.js`:
|
18
18
|
|
19
|
-
//= require bootstrap-multiselect
|
19
|
+
//= require bootstrap-multiselect
|
20
20
|
|
21
21
|
In `application.css`:
|
22
22
|
|
23
|
-
*= require bootstrap-multiselect
|
23
|
+
*= require bootstrap-multiselect
|
24
24
|
|
25
25
|
## License
|
26
26
|
|
@@ -1,296 +1,452 @@
|
|
1
1
|
/**
|
2
|
-
* bootstrap-multiselect.js
|
2
|
+
* bootstrap-multiselect.js
|
3
3
|
* https://github.com/davidstutz/bootstrap-multiselect
|
4
4
|
*
|
5
|
-
* Copyright 2012 David Stutz
|
5
|
+
* Copyright 2012 - 2014 David Stutz
|
6
6
|
*
|
7
|
-
*
|
8
|
-
* you may not use this file except in compliance with the License.
|
9
|
-
* You may obtain a copy of the License at
|
10
|
-
*
|
11
|
-
* http://www.apache.org/licenses/LICENSE-2.0
|
12
|
-
*
|
13
|
-
* Unless required by applicable law or agreed to in writing, software
|
14
|
-
* distributed under the License is distributed on an "AS IS" BASIS,
|
15
|
-
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
16
|
-
* See the License for the specific language governing permissions and
|
17
|
-
* limitations under the License.
|
7
|
+
* Dual licensed under the BSD-3-Clause and the Apache License, Version 2.0.
|
18
8
|
*/
|
19
|
-
!function($) {
|
9
|
+
!function($) {
|
20
10
|
|
21
|
-
|
11
|
+
"use strict";// jshint ;_;
|
12
|
+
|
13
|
+
if (typeof ko !== 'undefined' && ko.bindingHandlers && !ko.bindingHandlers.multiselect) {
|
22
14
|
ko.bindingHandlers.multiselect = {
|
23
|
-
|
15
|
+
|
16
|
+
init: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
|
17
|
+
|
18
|
+
var listOfSelectedItems = allBindingsAccessor().selectedOptions,
|
19
|
+
config = ko.utils.unwrapObservable(valueAccessor());
|
20
|
+
|
21
|
+
$(element).multiselect(config);
|
22
|
+
|
23
|
+
if (isObservableArray(listOfSelectedItems)) {
|
24
|
+
// Subscribe to the selectedOptions: ko.observableArray
|
25
|
+
listOfSelectedItems.subscribe(function (changes) {
|
26
|
+
var addedArray = [], deletedArray = [];
|
27
|
+
changes.forEach(function (change) {
|
28
|
+
switch (change.status) {
|
29
|
+
case 'added':
|
30
|
+
addedArray.push(change.value);
|
31
|
+
break;
|
32
|
+
case 'deleted':
|
33
|
+
deletedArray.push(change.value);
|
34
|
+
break;
|
35
|
+
}
|
36
|
+
});
|
37
|
+
if (addedArray.length > 0) {
|
38
|
+
$(element).multiselect('select', addedArray);
|
39
|
+
};
|
40
|
+
if (deletedArray.length > 0) {
|
41
|
+
$(element).multiselect('deselect', deletedArray);
|
42
|
+
};
|
43
|
+
}, null, "arrayChange");
|
44
|
+
}
|
24
45
|
},
|
25
|
-
|
26
|
-
|
46
|
+
|
47
|
+
update: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
|
48
|
+
|
49
|
+
var listOfItems = allBindingsAccessor().options,
|
50
|
+
ms = $(element).data('multiselect'),
|
51
|
+
config = ko.utils.unwrapObservable(valueAccessor());
|
52
|
+
|
53
|
+
if (isObservableArray(listOfItems)) {
|
54
|
+
// Subscribe to the options: ko.observableArray incase it changes later
|
55
|
+
listOfItems.subscribe(function (theArray) {
|
56
|
+
$(element).multiselect('rebuild');
|
57
|
+
});
|
58
|
+
}
|
59
|
+
|
27
60
|
if (!ms) {
|
28
|
-
$(element).multiselect(
|
61
|
+
$(element).multiselect(config);
|
29
62
|
}
|
30
|
-
else
|
31
|
-
if (allBindingsAccessor().options && allBindingsAccessor().options().length !== ms.originalOptions.length) {
|
63
|
+
else {
|
32
64
|
ms.updateOriginalOptions();
|
33
|
-
$(element).multiselect('rebuild');
|
34
65
|
}
|
35
66
|
}
|
36
67
|
};
|
37
68
|
}
|
38
69
|
|
70
|
+
function isObservableArray(obj) {
|
71
|
+
return ko.isObservable(obj) && !(obj.destroyAll === undefined);
|
72
|
+
}
|
73
|
+
|
74
|
+
/**
|
75
|
+
* Constructor to create a new multiselect using the given select.
|
76
|
+
*
|
77
|
+
* @param {jQuery} select
|
78
|
+
* @param {Object} options
|
79
|
+
* @returns {Multiselect}
|
80
|
+
*/
|
39
81
|
function Multiselect(select, options) {
|
40
82
|
|
41
|
-
this.options = this.
|
83
|
+
this.options = this.mergeOptions(options);
|
42
84
|
this.$select = $(select);
|
85
|
+
|
86
|
+
// Initialization.
|
87
|
+
// We have to clone to create a new reference.
|
43
88
|
this.originalOptions = this.$select.clone()[0].options;
|
44
|
-
//we have to clone to create a new reference
|
45
89
|
this.query = '';
|
46
90
|
this.searchTimeout = null;
|
47
91
|
|
48
|
-
this.options.multiple = this.$select.attr('multiple')
|
49
|
-
|
50
|
-
this
|
51
|
-
|
52
|
-
|
53
|
-
if (this.options.buttonWidth) {
|
54
|
-
$('button', this.$container).css({
|
55
|
-
'width' : this.options.buttonWidth
|
56
|
-
});
|
57
|
-
}
|
58
|
-
|
59
|
-
// Set max height of dropdown menu to activate auto scrollbar.
|
60
|
-
if (this.options.maxHeight) {
|
61
|
-
// TODO: Add a class for this option to move the css declarations.
|
62
|
-
$('.multiselect-container', this.$container).css({
|
63
|
-
'max-height' : this.options.maxHeight + 'px',
|
64
|
-
'overflow-y' : 'auto',
|
65
|
-
'overflow-x' : 'hidden'
|
66
|
-
});
|
67
|
-
}
|
68
|
-
|
69
|
-
// Enable filtering.
|
70
|
-
if (this.options.enableFiltering || this.options.enableCaseInsensitiveFiltering) {
|
71
|
-
this.buildFilter();
|
72
|
-
}
|
92
|
+
this.options.multiple = this.$select.attr('multiple') === "multiple";
|
93
|
+
this.options.onChange = $.proxy(this.options.onChange, this);
|
94
|
+
this.options.onDropdownShow = $.proxy(this.options.onDropdownShow, this);
|
95
|
+
this.options.onDropdownHide = $.proxy(this.options.onDropdownHide, this);
|
73
96
|
|
97
|
+
// Build select all if enabled.
|
98
|
+
this.buildContainer();
|
99
|
+
this.buildButton();
|
100
|
+
this.buildSelectAll();
|
74
101
|
this.buildDropdown();
|
102
|
+
this.buildDropdownOptions();
|
103
|
+
this.buildFilter();
|
104
|
+
|
75
105
|
this.updateButtonText();
|
106
|
+
this.updateSelectAll();
|
76
107
|
|
77
108
|
this.$select.hide().after(this.$container);
|
78
109
|
};
|
79
110
|
|
80
111
|
Multiselect.prototype = {
|
81
112
|
|
82
|
-
defaults
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
113
|
+
defaults: {
|
114
|
+
/**
|
115
|
+
* Default text function will either print 'None selected' in case no
|
116
|
+
* option is selected or a list of the selected options up to a length of 3 selected options.
|
117
|
+
*
|
118
|
+
* @param {jQuery} options
|
119
|
+
* @param {jQuery} select
|
120
|
+
* @returns {String}
|
121
|
+
*/
|
122
|
+
buttonText: function(options, select) {
|
123
|
+
if (options.length === 0) {
|
124
|
+
return this.nonSelectedText + ' <b class="caret"></b>';
|
89
125
|
}
|
90
|
-
else
|
91
|
-
|
92
|
-
|
126
|
+
else {
|
127
|
+
if (options.length > this.numberDisplayed) {
|
128
|
+
return options.length + ' ' + this.nSelectedText + ' <b class="caret"></b>';
|
129
|
+
}
|
130
|
+
else {
|
131
|
+
var selected = '';
|
132
|
+
options.each(function() {
|
133
|
+
var label = ($(this).attr('label') !== undefined) ? $(this).attr('label') : $(this).html();
|
134
|
+
|
135
|
+
selected += label + ', ';
|
136
|
+
});
|
137
|
+
return selected.substr(0, selected.length - 2) + ' <b class="caret"></b>';
|
138
|
+
}
|
139
|
+
}
|
140
|
+
},
|
141
|
+
/**
|
142
|
+
* Updates the title of the button similar to the buttonText function.
|
143
|
+
* @param {jQuery} options
|
144
|
+
* @param {jQuery} select
|
145
|
+
* @returns {@exp;selected@call;substr}
|
146
|
+
*/
|
147
|
+
buttonTitle: function(options, select) {
|
148
|
+
if (options.length === 0) {
|
149
|
+
return this.nonSelectedText;
|
93
150
|
}
|
94
151
|
else {
|
95
152
|
var selected = '';
|
96
|
-
options.each(function() {
|
97
|
-
|
98
|
-
|
99
|
-
selected += label + ', ';
|
153
|
+
options.each(function () {
|
154
|
+
selected += $(this).text() + ', ';
|
100
155
|
});
|
101
|
-
return selected.substr(0, selected.length - 2)
|
156
|
+
return selected.substr(0, selected.length - 2);
|
102
157
|
}
|
103
158
|
},
|
104
|
-
|
159
|
+
/**
|
160
|
+
* Create a label.
|
161
|
+
*
|
162
|
+
* @param {jQuery} element
|
163
|
+
* @returns {String}
|
164
|
+
*/
|
165
|
+
label: function(element){
|
166
|
+
return $(element).attr('label') || $(element).html();
|
167
|
+
},
|
168
|
+
/**
|
169
|
+
* Triggered on change of the multiselect.
|
170
|
+
* Not triggered when selecting/deselecting options manually.
|
171
|
+
*
|
172
|
+
* @param {jQuery} option
|
173
|
+
* @param {Boolean} checked
|
174
|
+
*/
|
105
175
|
onChange : function(option, checked) {
|
106
176
|
|
107
177
|
},
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
178
|
+
/**
|
179
|
+
* Triggered when the dropdown is shown.
|
180
|
+
*
|
181
|
+
* @param {jQuery} event
|
182
|
+
*/
|
183
|
+
onDropdownShow: function(event) {
|
184
|
+
|
185
|
+
},
|
186
|
+
/**
|
187
|
+
* Triggered when the dropdown is hidden.
|
188
|
+
*
|
189
|
+
* @param {jQuery} event
|
190
|
+
*/
|
191
|
+
onDropdownHide: function(event) {
|
192
|
+
|
193
|
+
},
|
194
|
+
buttonClass: 'btn btn-default',
|
195
|
+
dropRight: false,
|
196
|
+
selectedClass: 'active',
|
197
|
+
buttonWidth: 'auto',
|
198
|
+
buttonContainer: '<div class="btn-group" />',
|
113
199
|
// Maximum height of the dropdown menu.
|
114
200
|
// If maximum height is exceeded a scrollbar will be displayed.
|
115
|
-
maxHeight
|
116
|
-
includeSelectAllOption
|
117
|
-
selectAllText
|
118
|
-
selectAllValue
|
119
|
-
enableFiltering
|
120
|
-
enableCaseInsensitiveFiltering
|
121
|
-
filterPlaceholder
|
201
|
+
maxHeight: false,
|
202
|
+
includeSelectAllOption: false,
|
203
|
+
selectAllText: ' Select all',
|
204
|
+
selectAllValue: 'multiselect-all',
|
205
|
+
enableFiltering: false,
|
206
|
+
enableCaseInsensitiveFiltering: false,
|
207
|
+
filterPlaceholder: 'Search',
|
122
208
|
// possible options: 'text', 'value', 'both'
|
123
|
-
filterBehavior
|
209
|
+
filterBehavior: 'text',
|
124
210
|
preventInputChangeEvent: false,
|
125
211
|
nonSelectedText: 'None selected',
|
126
|
-
nSelectedText: 'selected'
|
212
|
+
nSelectedText: 'selected',
|
213
|
+
numberDisplayed: 3
|
127
214
|
},
|
128
215
|
|
129
|
-
|
216
|
+
templates: {
|
217
|
+
button: '<button type="button" class="multiselect dropdown-toggle" data-toggle="dropdown"></button>',
|
218
|
+
ul: '<ul class="multiselect-container dropdown-menu"></ul>',
|
219
|
+
filter: '<div class="input-group"><span class="input-group-addon"><i class="glyphicon glyphicon-search"></i></span><input class="form-control multiselect-search" type="text"></div>',
|
220
|
+
li: '<li><a href="javascript:void(0);"><label></label></a></li>',
|
221
|
+
divider: '<li class="divider"></li>',
|
222
|
+
liGroup: '<li><label class="multiselect-group"></label></li>'
|
223
|
+
},
|
130
224
|
|
131
|
-
|
132
|
-
createOptionValue : function(element) {
|
133
|
-
if ($(element).is(':selected')) {
|
134
|
-
$(element).attr('selected', 'selected').prop('selected', true);
|
135
|
-
}
|
225
|
+
constructor: Multiselect,
|
136
226
|
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
227
|
+
/**
|
228
|
+
* Builds the container of the multiselect.
|
229
|
+
*/
|
230
|
+
buildContainer: function() {
|
231
|
+
this.$container = $(this.options.buttonContainer);
|
232
|
+
this.$container.on('show.bs.dropdown', this.options.onDropdownShow);
|
233
|
+
this.$container.on('hide.bs.dropdown', this.options.onDropdownHide);
|
234
|
+
},
|
141
235
|
|
142
|
-
|
236
|
+
/**
|
237
|
+
* Builds the button of the multiselect.
|
238
|
+
*/
|
239
|
+
buildButton: function() {
|
240
|
+
this.$button = $(this.templates.button).addClass(this.options.buttonClass);
|
143
241
|
|
144
|
-
|
145
|
-
|
146
|
-
|
242
|
+
// Adopt active state.
|
243
|
+
if (this.$select.prop('disabled')) {
|
244
|
+
this.disable();
|
245
|
+
}
|
246
|
+
else {
|
247
|
+
this.enable();
|
248
|
+
}
|
147
249
|
|
148
|
-
|
149
|
-
|
250
|
+
// Manually add button width if set.
|
251
|
+
if (this.options.buttonWidth && this.options.buttonWidth != 'auto') {
|
252
|
+
this.$button.css({
|
253
|
+
'width' : this.options.buttonWidth
|
254
|
+
});
|
150
255
|
}
|
151
256
|
|
152
|
-
|
257
|
+
// Keep the tab index from the select.
|
258
|
+
var tabindex = this.$select.attr('tabindex');
|
259
|
+
if (tabindex) {
|
260
|
+
this.$button.attr('tabindex', tabindex);
|
261
|
+
}
|
153
262
|
|
154
|
-
|
263
|
+
this.$container.prepend(this.$button);
|
264
|
+
},
|
155
265
|
|
156
|
-
|
157
|
-
|
158
|
-
|
266
|
+
/**
|
267
|
+
* Builds the ul representing the dropdown menu.
|
268
|
+
*/
|
269
|
+
buildDropdown: function() {
|
159
270
|
|
160
|
-
|
271
|
+
// Build ul.
|
272
|
+
this.$ul = $(this.templates.ul);
|
161
273
|
|
162
|
-
if (
|
163
|
-
|
274
|
+
if (this.options.dropRight) {
|
275
|
+
this.$ul.addClass('pull-right');
|
164
276
|
}
|
165
|
-
},
|
166
277
|
|
167
|
-
|
168
|
-
if (this
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
278
|
+
// Set max height of dropdown menu to activate auto scrollbar.
|
279
|
+
if (this.options.maxHeight) {
|
280
|
+
// TODO: Add a class for this option to move the css declarations.
|
281
|
+
this.$ul.css({
|
282
|
+
'max-height': this.options.maxHeight + 'px',
|
283
|
+
'overflow-y': 'auto',
|
284
|
+
'overflow-x': 'hidden'
|
285
|
+
});
|
173
286
|
}
|
174
|
-
},
|
175
|
-
|
176
|
-
// Build the dropdown and bind event handling.
|
177
|
-
buildDropdown : function() {
|
178
|
-
var alreadyHasSelectAll = this.$select[0][0] ? this.$select[0][0].value == this.options.selectAllValue : false;
|
179
287
|
|
180
|
-
|
181
|
-
|
182
|
-
if (this.options.includeSelectAllOption && this.options.multiple && !alreadyHasSelectAll) {
|
183
|
-
this.$select.prepend('<option value="' + this.options.selectAllValue + '">' + this.options.selectAllText + '</option>');
|
184
|
-
}
|
288
|
+
this.$container.append(this.$ul);
|
289
|
+
},
|
185
290
|
|
186
|
-
|
291
|
+
/**
|
292
|
+
* Build the dropdown options and binds all nessecary events.
|
293
|
+
* Uses createDivider and createOptionValue to create the necessary options.
|
294
|
+
*/
|
295
|
+
buildDropdownOptions: function() {
|
187
296
|
|
188
297
|
this.$select.children().each($.proxy(function(index, element) {
|
298
|
+
|
189
299
|
// Support optgroups and options without a group simultaneously.
|
190
|
-
var tag = $(element).prop('tagName')
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
// Add a header for the group.
|
196
|
-
var $li = $('<li><label class="multiselect-group"></label></li>');
|
197
|
-
$('label', $li).text(groupName);
|
198
|
-
$('.multiselect-container', this.$container).append($li);
|
199
|
-
|
200
|
-
// Add the options of the group.
|
201
|
-
$('option', group).each($.proxy(function(index, element) {
|
202
|
-
this.createOptionValue(element);
|
203
|
-
}, this));
|
204
|
-
}
|
205
|
-
else
|
206
|
-
if (tag == 'option') {
|
207
|
-
this.createOptionValue(element);
|
300
|
+
var tag = $(element).prop('tagName')
|
301
|
+
.toLowerCase();
|
302
|
+
|
303
|
+
if (tag === 'optgroup') {
|
304
|
+
this.createOptgroup(element);
|
208
305
|
}
|
209
|
-
else {
|
210
|
-
|
306
|
+
else if (tag === 'option') {
|
307
|
+
|
308
|
+
if ($(element).data('role') === 'divider') {
|
309
|
+
this.createDivider();
|
310
|
+
}
|
311
|
+
else {
|
312
|
+
this.createOptionValue(element);
|
313
|
+
}
|
314
|
+
|
211
315
|
}
|
316
|
+
|
317
|
+
// Other illegal tags will be ignored.
|
212
318
|
}, this));
|
213
319
|
|
214
320
|
// Bind the change event on the dropdown elements.
|
215
|
-
$('
|
321
|
+
$('li input', this.$ul).on('change', $.proxy(function(event) {
|
216
322
|
var checked = $(event.target).prop('checked') || false;
|
217
|
-
var isSelectAllOption = $(event.target).val()
|
323
|
+
var isSelectAllOption = $(event.target).val() === this.options.selectAllValue;
|
218
324
|
|
219
325
|
// Apply or unapply the configured selected class.
|
220
326
|
if (this.options.selectedClass) {
|
221
327
|
if (checked) {
|
222
|
-
$(event.target).parents('li')
|
328
|
+
$(event.target).parents('li')
|
329
|
+
.addClass(this.options.selectedClass);
|
223
330
|
}
|
224
331
|
else {
|
225
|
-
$(event.target).parents('li')
|
332
|
+
$(event.target).parents('li')
|
333
|
+
.removeClass(this.options.selectedClass);
|
226
334
|
}
|
227
335
|
}
|
228
336
|
|
229
|
-
|
230
|
-
|
231
|
-
|
337
|
+
// Get the corresponding option.
|
338
|
+
var value = $(event.target).val();
|
339
|
+
var $option = this.getOptionByValue(value);
|
232
340
|
|
233
341
|
var $optionsNotThis = $('option', this.$select).not($option);
|
234
342
|
var $checkboxesNotThis = $('input', this.$container).not($(event.target));
|
235
343
|
|
236
|
-
// Toggle all options if the select all option was changed.
|
237
344
|
if (isSelectAllOption) {
|
238
|
-
|
239
|
-
|
240
|
-
|
345
|
+
if (this.$select[0][0].value === this.options.selectAllValue) {
|
346
|
+
var values = [];
|
347
|
+
var options = $('option[value!="' + this.options.selectAllValue + '"]', this.$select);
|
348
|
+
for (var i = 0; i < options.length; i++) {
|
349
|
+
// Additionally check whether the option is visible within the dropcown.
|
350
|
+
if (options[i].value !== this.options.selectAllValue && this.getInputByValue(options[i].value).is(':visible')) {
|
351
|
+
values.push(options[i].value);
|
352
|
+
}
|
353
|
+
}
|
354
|
+
|
355
|
+
if (checked) {
|
356
|
+
this.select(values);
|
357
|
+
}
|
358
|
+
else {
|
359
|
+
this.deselect(values);
|
360
|
+
}
|
361
|
+
}
|
241
362
|
}
|
242
363
|
|
243
364
|
if (checked) {
|
244
365
|
$option.prop('selected', true);
|
245
366
|
|
246
367
|
if (this.options.multiple) {
|
247
|
-
|
368
|
+
// Simply select additional option.
|
369
|
+
$option.prop('selected', true);
|
248
370
|
}
|
249
371
|
else {
|
372
|
+
// Unselect all other options and corresponding checkboxes.
|
250
373
|
if (this.options.selectedClass) {
|
251
374
|
$($checkboxesNotThis).parents('li').removeClass(this.options.selectedClass);
|
252
375
|
}
|
253
376
|
|
254
377
|
$($checkboxesNotThis).prop('checked', false);
|
255
|
-
|
256
|
-
$optionsNotThis.removeAttr('selected').prop('selected', false);
|
378
|
+
$optionsNotThis.prop('selected', false);
|
257
379
|
|
258
380
|
// It's a single selection, so close.
|
259
|
-
|
381
|
+
this.$button.click();
|
260
382
|
}
|
261
383
|
|
262
|
-
if (this.options.selectedClass
|
384
|
+
if (this.options.selectedClass === "active") {
|
263
385
|
$optionsNotThis.parents("a").css("outline", "");
|
264
386
|
}
|
265
|
-
|
266
387
|
}
|
267
388
|
else {
|
268
|
-
|
389
|
+
// Unselect option.
|
390
|
+
$option.prop('selected', false);
|
269
391
|
}
|
270
392
|
|
271
|
-
this.
|
272
|
-
|
393
|
+
this.$select.change();
|
273
394
|
this.options.onChange($option, checked);
|
274
395
|
|
275
|
-
this
|
396
|
+
this.updateButtonText();
|
397
|
+
this.updateSelectAll();
|
276
398
|
|
277
399
|
if(this.options.preventInputChangeEvent) {
|
278
400
|
return false;
|
279
401
|
}
|
280
402
|
}, this));
|
281
403
|
|
282
|
-
$('
|
404
|
+
$('li a', this.$ul).on('touchstart click', function(event) {
|
283
405
|
event.stopPropagation();
|
406
|
+
|
407
|
+
if (event.shiftKey) {
|
408
|
+
var checked = $(event.target).prop('checked') || false;
|
409
|
+
|
410
|
+
if (checked) {
|
411
|
+
var prev = $(event.target).parents('li:last')
|
412
|
+
.siblings('li[class="active"]:first');
|
413
|
+
|
414
|
+
var currentIdx = $(event.target).parents('li')
|
415
|
+
.index();
|
416
|
+
var prevIdx = prev.index();
|
417
|
+
|
418
|
+
if (currentIdx > prevIdx) {
|
419
|
+
$(event.target).parents("li:last").prevUntil(prev).each(
|
420
|
+
function() {
|
421
|
+
$(this).find("input:first").prop("checked", true)
|
422
|
+
.trigger("change");
|
423
|
+
}
|
424
|
+
);
|
425
|
+
}
|
426
|
+
else {
|
427
|
+
$(event.target).parents("li:last").nextUntil(prev).each(
|
428
|
+
function() {
|
429
|
+
$(this).find("input:first").prop("checked", true)
|
430
|
+
.trigger("change");
|
431
|
+
}
|
432
|
+
);
|
433
|
+
}
|
434
|
+
}
|
435
|
+
}
|
436
|
+
|
284
437
|
$(event.target).blur();
|
285
438
|
});
|
286
439
|
|
287
440
|
// Keyboard support.
|
288
441
|
this.$container.on('keydown', $.proxy(function(event) {
|
289
|
-
if ($('input[type="text"]', this.$container).is(':focus'))
|
442
|
+
if ($('input[type="text"]', this.$container).is(':focus')) {
|
290
443
|
return;
|
291
|
-
|
444
|
+
}
|
445
|
+
if ((event.keyCode === 9 || event.keyCode === 27)
|
446
|
+
&& this.$container.hasClass('open')) {
|
447
|
+
|
292
448
|
// Close on tab or escape.
|
293
|
-
|
449
|
+
this.$button.click();
|
294
450
|
}
|
295
451
|
else {
|
296
452
|
var $items = $(this.$container).find("li:not(.divider):visible a");
|
@@ -302,30 +458,21 @@
|
|
302
458
|
var index = $items.index($items.filter(':focus'));
|
303
459
|
|
304
460
|
// Navigation up.
|
305
|
-
if (event.keyCode
|
461
|
+
if (event.keyCode === 38 && index > 0) {
|
306
462
|
index--;
|
307
463
|
}
|
308
464
|
// Navigate down.
|
309
|
-
else
|
310
|
-
if (event.keyCode == 40 && index < $items.length - 1) {
|
465
|
+
else if (event.keyCode === 40 && index < $items.length - 1) {
|
311
466
|
index++;
|
312
467
|
}
|
313
|
-
else
|
314
|
-
if (!~index) {
|
468
|
+
else if (!~index) {
|
315
469
|
index = 0;
|
316
470
|
}
|
317
471
|
|
318
472
|
var $current = $items.eq(index);
|
319
473
|
$current.focus();
|
320
474
|
|
321
|
-
|
322
|
-
if (this.options.selectedClass == "active") {
|
323
|
-
$current.css("outline", "thin dotted #333").css("outline", "5px auto -webkit-focus-ring-color");
|
324
|
-
|
325
|
-
$items.not($current).css("outline", "");
|
326
|
-
}
|
327
|
-
|
328
|
-
if (event.keyCode == 32 || event.keyCode == 13) {
|
475
|
+
if (event.keyCode === 32 || event.keyCode === 13) {
|
329
476
|
var $checkbox = $current.find('input');
|
330
477
|
|
331
478
|
$checkbox.prop("checked", !$checkbox.prop("checked"));
|
@@ -338,174 +485,468 @@
|
|
338
485
|
}, this));
|
339
486
|
},
|
340
487
|
|
341
|
-
|
342
|
-
|
343
|
-
|
488
|
+
/**
|
489
|
+
* Create an option using the given select option.
|
490
|
+
*
|
491
|
+
* @param {jQuery} element
|
492
|
+
*/
|
493
|
+
createOptionValue: function(element) {
|
494
|
+
if ($(element).is(':selected')) {
|
495
|
+
$(element).prop('selected', true);
|
496
|
+
}
|
344
497
|
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
// updated the control.
|
350
|
-
clearTimeout(this.searchTimeout);
|
351
|
-
|
352
|
-
this.searchTimeout = this.asyncFunction($.proxy(function() {
|
353
|
-
|
354
|
-
if (this.query != event.target.value) {
|
355
|
-
this.query = event.target.value;
|
356
|
-
|
357
|
-
$.each($('.multiselect-container li', this.$container), $.proxy(function(index, element) {
|
358
|
-
var value = $('input', element).val();
|
359
|
-
if (value != this.options.selectAllValue) {
|
360
|
-
var text = $('label', element).text();
|
361
|
-
var value = $('input', element).val();
|
362
|
-
if (value && text && value != this.options.selectAllValue) {
|
363
|
-
// by default lets assume that element is not
|
364
|
-
// interesting for this search
|
365
|
-
var showElement = false;
|
366
|
-
|
367
|
-
var filterCandidate = '';
|
368
|
-
if ((this.options.filterBehavior == 'text' || this.options.filterBehavior == 'both')) {
|
369
|
-
filterCandidate = text;
|
370
|
-
}
|
371
|
-
if ((this.options.filterBehavior == 'value' || this.options.filterBehavior == 'both')) {
|
372
|
-
filterCandidate = value;
|
373
|
-
}
|
498
|
+
// Support the label attribute on options.
|
499
|
+
var label = this.options.label(element);
|
500
|
+
var value = $(element).val();
|
501
|
+
var inputType = this.options.multiple ? "checkbox" : "radio";
|
374
502
|
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
else if (filterCandidate.indexOf(this.query) > -1) {
|
379
|
-
showElement = true;
|
380
|
-
}
|
503
|
+
var $li = $(this.templates.li);
|
504
|
+
$('label', $li).addClass(inputType);
|
505
|
+
$('label', $li).append('<input type="' + inputType + '" />');
|
381
506
|
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
507
|
+
var selected = $(element).prop('selected') || false;
|
508
|
+
var $checkbox = $('input', $li);
|
509
|
+
$checkbox.val(value);
|
510
|
+
|
511
|
+
if (value === this.options.selectAllValue) {
|
512
|
+
$checkbox.parent().parent()
|
513
|
+
.addClass('multiselect-all');
|
514
|
+
}
|
515
|
+
|
516
|
+
$('label', $li).append(" " + label);
|
517
|
+
|
518
|
+
this.$ul.append($li);
|
519
|
+
|
520
|
+
if ($(element).is(':disabled')) {
|
521
|
+
$checkbox.attr('disabled', 'disabled')
|
522
|
+
.prop('disabled', true)
|
523
|
+
.parents('li')
|
524
|
+
.addClass('disabled');
|
525
|
+
}
|
526
|
+
|
527
|
+
$checkbox.prop('checked', selected);
|
528
|
+
|
529
|
+
if (selected && this.options.selectedClass) {
|
530
|
+
$checkbox.parents('li')
|
531
|
+
.addClass(this.options.selectedClass);
|
532
|
+
}
|
533
|
+
},
|
534
|
+
|
535
|
+
/**
|
536
|
+
* Creates a divider using the given select option.
|
537
|
+
*
|
538
|
+
* @param {jQuery} element
|
539
|
+
*/
|
540
|
+
createDivider: function(element) {
|
541
|
+
var $divider = $(this.templates.divider);
|
542
|
+
this.$ul.append($divider);
|
543
|
+
},
|
544
|
+
|
545
|
+
/**
|
546
|
+
* Creates an optgroup.
|
547
|
+
*
|
548
|
+
* @param {jQuery} group
|
549
|
+
*/
|
550
|
+
createOptgroup: function(group) {
|
551
|
+
var groupName = $(group).prop('label');
|
552
|
+
|
553
|
+
// Add a header for the group.
|
554
|
+
var $li = $(this.templates.liGroup);
|
555
|
+
$('label', $li).text(groupName);
|
556
|
+
|
557
|
+
this.$ul.append($li);
|
558
|
+
|
559
|
+
if ($(group).is(':disabled')) {
|
560
|
+
$li.addClass('disabled');
|
561
|
+
}
|
562
|
+
|
563
|
+
// Add the options of the group.
|
564
|
+
$('option', group).each($.proxy(function(index, element) {
|
565
|
+
this.createOptionValue(element);
|
566
|
+
}, this));
|
567
|
+
},
|
568
|
+
|
569
|
+
/**
|
570
|
+
* Build the selct all.
|
571
|
+
* Checks if a select all ahs already been created.
|
572
|
+
*/
|
573
|
+
buildSelectAll: function() {
|
574
|
+
var alreadyHasSelectAll = this.hasSelectAll();
|
575
|
+
|
576
|
+
// If options.includeSelectAllOption === true, add the include all checkbox.
|
577
|
+
if (this.options.includeSelectAllOption && this.options.multiple && !alreadyHasSelectAll) {
|
578
|
+
if (this.options.includeSelectAllDivider) {
|
579
|
+
this.$select.prepend('<option value="" disabled="disabled" data-role="divider">');
|
580
|
+
}
|
581
|
+
this.$select.prepend('<option value="' + this.options.selectAllValue + '">' + this.options.selectAllText + '</option>');
|
582
|
+
}
|
583
|
+
},
|
584
|
+
|
585
|
+
/**
|
586
|
+
* Builds the filter.
|
587
|
+
*/
|
588
|
+
buildFilter: function() {
|
589
|
+
|
590
|
+
// Build filter if filtering OR case insensitive filtering is enabled and the number of options exceeds (or equals) enableFilterLength.
|
591
|
+
if (this.options.enableFiltering || this.options.enableCaseInsensitiveFiltering) {
|
592
|
+
var enableFilterLength = Math.max(this.options.enableFiltering, this.options.enableCaseInsensitiveFiltering);
|
593
|
+
|
594
|
+
if (this.$select.find('option').length >= enableFilterLength) {
|
595
|
+
|
596
|
+
this.$filter = $(this.templates.filter);
|
597
|
+
$('input', this.$filter).attr('placeholder', this.options.filterPlaceholder);
|
598
|
+
this.$ul.prepend(this.$filter);
|
599
|
+
|
600
|
+
this.$filter.val(this.query).on('click', function(event) {
|
601
|
+
event.stopPropagation();
|
602
|
+
}).on('input keydown', $.proxy(function(event) {
|
603
|
+
// This is useful to catch "keydown" events after the browser has updated the control.
|
604
|
+
clearTimeout(this.searchTimeout);
|
605
|
+
|
606
|
+
this.searchTimeout = this.asyncFunction($.proxy(function() {
|
607
|
+
|
608
|
+
if (this.query !== event.target.value) {
|
609
|
+
this.query = event.target.value;
|
610
|
+
|
611
|
+
$.each($('li', this.$ul), $.proxy(function(index, element) {
|
612
|
+
var value = $('input', element).val();
|
613
|
+
var text = $('label', element).text();
|
614
|
+
|
615
|
+
if (value !== this.options.selectAllValue && text) {
|
616
|
+
// by default lets assume that element is not
|
617
|
+
// interesting for this search
|
618
|
+
var showElement = false;
|
619
|
+
|
620
|
+
var filterCandidate = '';
|
621
|
+
if ((this.options.filterBehavior === 'text' || this.options.filterBehavior === 'both')) {
|
622
|
+
filterCandidate = text;
|
623
|
+
}
|
624
|
+
if ((this.options.filterBehavior === 'value' || this.options.filterBehavior === 'both')) {
|
625
|
+
filterCandidate = value;
|
626
|
+
}
|
627
|
+
|
628
|
+
if (this.options.enableCaseInsensitiveFiltering && filterCandidate.toLowerCase().indexOf(this.query.toLowerCase()) > -1) {
|
629
|
+
showElement = true;
|
630
|
+
}
|
631
|
+
else if (filterCandidate.indexOf(this.query) > -1) {
|
632
|
+
showElement = true;
|
633
|
+
}
|
634
|
+
|
635
|
+
if (showElement) {
|
636
|
+
$(element).show();
|
637
|
+
}
|
638
|
+
else {
|
639
|
+
$(element).hide();
|
640
|
+
}
|
387
641
|
}
|
388
|
-
}
|
642
|
+
}, this));
|
389
643
|
}
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
644
|
+
|
645
|
+
// TODO: check whether select all option needs to be updated.
|
646
|
+
}, this), 300, this);
|
647
|
+
}, this));
|
648
|
+
}
|
649
|
+
}
|
394
650
|
},
|
395
651
|
|
396
|
-
|
397
|
-
|
652
|
+
/**
|
653
|
+
* Unbinds the whole plugin.
|
654
|
+
*/
|
655
|
+
destroy: function() {
|
398
656
|
this.$container.remove();
|
399
657
|
this.$select.show();
|
400
658
|
},
|
401
659
|
|
402
|
-
|
403
|
-
|
660
|
+
/**
|
661
|
+
* Refreshs the multiselect based on the selected options of the select.
|
662
|
+
*/
|
663
|
+
refresh: function() {
|
404
664
|
$('option', this.$select).each($.proxy(function(index, element) {
|
405
|
-
var $input = $('
|
406
|
-
return $(this).val()
|
665
|
+
var $input = $('li input', this.$ul).filter(function() {
|
666
|
+
return $(this).val() === $(element).val();
|
407
667
|
});
|
408
668
|
|
409
669
|
if ($(element).is(':selected')) {
|
410
670
|
$input.prop('checked', true);
|
411
671
|
|
412
672
|
if (this.options.selectedClass) {
|
413
|
-
$input.parents('li')
|
673
|
+
$input.parents('li')
|
674
|
+
.addClass(this.options.selectedClass);
|
414
675
|
}
|
415
676
|
}
|
416
677
|
else {
|
417
678
|
$input.prop('checked', false);
|
418
679
|
|
419
680
|
if (this.options.selectedClass) {
|
420
|
-
$input.parents('li')
|
681
|
+
$input.parents('li')
|
682
|
+
.removeClass(this.options.selectedClass);
|
421
683
|
}
|
422
684
|
}
|
423
685
|
|
424
686
|
if ($(element).is(":disabled")) {
|
425
|
-
$input.attr('disabled', 'disabled')
|
687
|
+
$input.attr('disabled', 'disabled')
|
688
|
+
.prop('disabled', true)
|
689
|
+
.parents('li')
|
690
|
+
.addClass('disabled');
|
426
691
|
}
|
427
692
|
else {
|
428
|
-
$input.
|
693
|
+
$input.prop('disabled', false)
|
694
|
+
.parents('li')
|
695
|
+
.removeClass('disabled');
|
429
696
|
}
|
430
697
|
}, this));
|
431
698
|
|
432
699
|
this.updateButtonText();
|
700
|
+
this.updateSelectAll();
|
433
701
|
},
|
434
702
|
|
435
|
-
|
436
|
-
|
437
|
-
|
438
|
-
|
439
|
-
|
440
|
-
|
441
|
-
|
442
|
-
|
443
|
-
|
444
|
-
if (this.options.selectedClass) {
|
445
|
-
$checkbox.parents('li').addClass(this.options.selectedClass);
|
703
|
+
/**
|
704
|
+
* Select all options of the given values.
|
705
|
+
*
|
706
|
+
* @param {Array} selectValues
|
707
|
+
*/
|
708
|
+
select: function(selectValues) {
|
709
|
+
if(selectValues && !$.isArray(selectValues)) {
|
710
|
+
selectValues = [selectValues];
|
446
711
|
}
|
447
712
|
|
448
|
-
|
713
|
+
for (var i = 0; i < selectValues.length; i++) {
|
714
|
+
var value = selectValues[i];
|
449
715
|
|
450
|
-
|
716
|
+
var $option = this.getOptionByValue(value);
|
717
|
+
var $checkbox = this.getInputByValue(value);
|
718
|
+
|
719
|
+
if (this.options.selectedClass) {
|
720
|
+
$checkbox.parents('li')
|
721
|
+
.addClass(this.options.selectedClass);
|
722
|
+
}
|
723
|
+
|
724
|
+
$checkbox.prop('checked', true);
|
725
|
+
$option.prop('selected', true);
|
726
|
+
}
|
451
727
|
|
452
728
|
this.updateButtonText();
|
453
|
-
this.options.onChange($option, true);
|
454
729
|
},
|
455
730
|
|
456
|
-
|
457
|
-
|
458
|
-
|
459
|
-
|
460
|
-
|
461
|
-
var $checkbox = $('.multiselect-container li input', this.$container).filter(function() {
|
462
|
-
return $(this).val() == value;
|
463
|
-
});
|
731
|
+
/**
|
732
|
+
* Clears all selected items
|
733
|
+
*
|
734
|
+
*/
|
735
|
+
clearSelection: function () {
|
464
736
|
|
465
|
-
|
466
|
-
|
737
|
+
var selected = this.getSelected();
|
738
|
+
|
739
|
+
if (selected.length) {
|
740
|
+
|
741
|
+
var arry = [];
|
742
|
+
|
743
|
+
for (var i = 0; i < selected.length; i = i + 1) {
|
744
|
+
arry.push(selected[i].value);
|
745
|
+
}
|
746
|
+
|
747
|
+
this.deselect(arry);
|
748
|
+
this.$select.change();
|
467
749
|
}
|
750
|
+
},
|
468
751
|
|
469
|
-
|
752
|
+
/**
|
753
|
+
* Deselects all options of the given values.
|
754
|
+
*
|
755
|
+
* @param {Array} deselectValues
|
756
|
+
*/
|
757
|
+
deselect: function(deselectValues) {
|
758
|
+
if(deselectValues && !$.isArray(deselectValues)) {
|
759
|
+
deselectValues = [deselectValues];
|
760
|
+
}
|
470
761
|
|
471
|
-
|
762
|
+
for (var i = 0; i < deselectValues.length; i++) {
|
763
|
+
|
764
|
+
var value = deselectValues[i];
|
765
|
+
|
766
|
+
var $option = this.getOptionByValue(value);
|
767
|
+
var $checkbox = this.getInputByValue(value);
|
768
|
+
|
769
|
+
if (this.options.selectedClass) {
|
770
|
+
$checkbox.parents('li')
|
771
|
+
.removeClass(this.options.selectedClass);
|
772
|
+
}
|
773
|
+
|
774
|
+
$checkbox.prop('checked', false);
|
775
|
+
$option.prop('selected', false);
|
776
|
+
}
|
472
777
|
|
473
778
|
this.updateButtonText();
|
474
|
-
this.options.onChange($option, false);
|
475
779
|
},
|
476
780
|
|
477
|
-
|
478
|
-
|
479
|
-
|
480
|
-
|
781
|
+
/**
|
782
|
+
* Rebuild the plugin.
|
783
|
+
* Rebuilds the dropdown, the filter and the select all option.
|
784
|
+
*/
|
785
|
+
rebuild: function() {
|
786
|
+
this.$ul.html('');
|
787
|
+
|
788
|
+
// Remove select all option in select.
|
789
|
+
$('option[value="' + this.options.selectAllValue + '"]', this.$select).remove();
|
790
|
+
|
791
|
+
// Important to distinguish between radios and checkboxes.
|
792
|
+
this.options.multiple = this.$select.attr('multiple') === "multiple";
|
793
|
+
|
794
|
+
this.buildSelectAll();
|
795
|
+
this.buildDropdownOptions();
|
796
|
+
this.buildFilter();
|
797
|
+
|
481
798
|
this.updateButtonText();
|
799
|
+
this.updateSelectAll();
|
800
|
+
},
|
482
801
|
|
483
|
-
|
484
|
-
|
485
|
-
|
486
|
-
|
802
|
+
/**
|
803
|
+
* The provided data will be used to build the dropdown.
|
804
|
+
*
|
805
|
+
* @param {Array} dataprovider
|
806
|
+
*/
|
807
|
+
dataprovider: function(dataprovider) {
|
808
|
+
var optionDOM = "";
|
809
|
+
dataprovider.forEach(function (option) {
|
810
|
+
optionDOM += '<option value="' + option.value + '">' + option.label + '</option>';
|
811
|
+
});
|
812
|
+
|
813
|
+
this.$select.html(optionDOM);
|
814
|
+
this.rebuild();
|
487
815
|
},
|
488
816
|
|
489
|
-
|
490
|
-
|
491
|
-
|
817
|
+
/**
|
818
|
+
* Enable the multiselect.
|
819
|
+
*/
|
820
|
+
enable: function() {
|
821
|
+
this.$select.prop('disabled', false);
|
822
|
+
this.$button.prop('disabled', false)
|
823
|
+
.removeClass('disabled');
|
492
824
|
},
|
493
825
|
|
494
|
-
|
826
|
+
/**
|
827
|
+
* Disable the multiselect.
|
828
|
+
*/
|
829
|
+
disable: function() {
|
830
|
+
this.$select.prop('disabled', true);
|
831
|
+
this.$button.prop('disabled', true)
|
832
|
+
.addClass('disabled');
|
833
|
+
},
|
834
|
+
|
835
|
+
/**
|
836
|
+
* Set the options.
|
837
|
+
*
|
838
|
+
* @param {Array} options
|
839
|
+
*/
|
840
|
+
setOptions: function(options) {
|
841
|
+
this.options = this.mergeOptions(options);
|
842
|
+
},
|
843
|
+
|
844
|
+
/**
|
845
|
+
* Merges the given options with the default options.
|
846
|
+
*
|
847
|
+
* @param {Array} options
|
848
|
+
* @returns {Array}
|
849
|
+
*/
|
850
|
+
mergeOptions: function(options) {
|
851
|
+
return $.extend({}, this.defaults, this.options, options);
|
852
|
+
},
|
853
|
+
|
854
|
+
/**
|
855
|
+
* Checks whether a select all option is present.
|
856
|
+
*
|
857
|
+
* @returns {Boolean}
|
858
|
+
*/
|
859
|
+
hasSelectAll: function() {
|
860
|
+
return this.$select[0][0] ? this.$select[0][0].value === this.options.selectAllValue : false;
|
861
|
+
},
|
862
|
+
|
863
|
+
/**
|
864
|
+
* Updates the select all option based on the currently selected options.
|
865
|
+
*/
|
866
|
+
updateSelectAll: function() {
|
867
|
+
if (this.hasSelectAll()) {
|
868
|
+
var selected = this.getSelected();
|
869
|
+
|
870
|
+
if (selected.length === $('option:not([data-role=divider])', this.$select).length - 1) {
|
871
|
+
this.select(this.options.selectAllValue);
|
872
|
+
}
|
873
|
+
else {
|
874
|
+
this.deselect(this.options.selectAllValue);
|
875
|
+
}
|
876
|
+
}
|
877
|
+
},
|
878
|
+
|
879
|
+
/**
|
880
|
+
* Update the button text and its title based on the currently selected options.
|
881
|
+
*/
|
882
|
+
updateButtonText: function() {
|
495
883
|
var options = this.getSelected();
|
884
|
+
|
885
|
+
// First update the displayed button text.
|
496
886
|
$('button', this.$container).html(this.options.buttonText(options, this.$select));
|
887
|
+
|
888
|
+
// Now update the title attribute of the button.
|
889
|
+
$('button', this.$container).attr('title', this.options.buttonTitle(options, this.$select));
|
890
|
+
|
891
|
+
},
|
892
|
+
|
893
|
+
/**
|
894
|
+
* Get all selected options.
|
895
|
+
*
|
896
|
+
* @returns {jQUery}
|
897
|
+
*/
|
898
|
+
getSelected: function() {
|
899
|
+
return $('option[value!="' + this.options.selectAllValue + '"]:selected', this.$select).filter(function() {
|
900
|
+
return $(this).prop('selected');
|
901
|
+
});
|
902
|
+
},
|
903
|
+
|
904
|
+
/**
|
905
|
+
* Gets a select option by its value.
|
906
|
+
*
|
907
|
+
* @param {String} value
|
908
|
+
* @returns {jQuery}
|
909
|
+
*/
|
910
|
+
getOptionByValue: function (value) {
|
911
|
+
|
912
|
+
var options = $('option', this.$select);
|
913
|
+
var valueToCompare = value.toString();
|
914
|
+
|
915
|
+
for (var i = 0; i < options.length; i = i + 1) {
|
916
|
+
var option = options[i];
|
917
|
+
if (option.value == valueToCompare) {
|
918
|
+
return $(option);
|
919
|
+
}
|
920
|
+
}
|
497
921
|
},
|
498
922
|
|
499
|
-
|
500
|
-
|
501
|
-
|
923
|
+
/**
|
924
|
+
* Get the input (radio/checkbox) by its value.
|
925
|
+
*
|
926
|
+
* @param {String} value
|
927
|
+
* @returns {jQuery}
|
928
|
+
*/
|
929
|
+
getInputByValue: function (value) {
|
930
|
+
|
931
|
+
var checkboxes = $('li input', this.$ul);
|
932
|
+
var valueToCompare = value.toString();
|
933
|
+
|
934
|
+
for (var i = 0; i < checkboxes.length; i = i + 1) {
|
935
|
+
var checkbox = checkboxes[i];
|
936
|
+
if (checkbox.value == valueToCompare) {
|
937
|
+
return $(checkbox);
|
938
|
+
}
|
939
|
+
}
|
502
940
|
},
|
503
941
|
|
504
|
-
|
942
|
+
/**
|
943
|
+
* Used for knockout integration.
|
944
|
+
*/
|
945
|
+
updateOriginalOptions: function() {
|
505
946
|
this.originalOptions = this.$select.clone()[0].options;
|
506
947
|
},
|
507
948
|
|
508
|
-
asyncFunction
|
949
|
+
asyncFunction: function(callback, timeout, self) {
|
509
950
|
var args = Array.prototype.slice.call(arguments, 3);
|
510
951
|
return setTimeout(function() {
|
511
952
|
callback.apply(self || window, args);
|
@@ -515,16 +956,22 @@
|
|
515
956
|
|
516
957
|
$.fn.multiselect = function(option, parameter) {
|
517
958
|
return this.each(function() {
|
518
|
-
var data = $(this).data('multiselect')
|
959
|
+
var data = $(this).data('multiselect');
|
960
|
+
var options = typeof option === 'object' && option;
|
519
961
|
|
520
962
|
// Initialize the multiselect.
|
521
963
|
if (!data) {
|
522
|
-
|
964
|
+
data = new Multiselect(this, options);
|
965
|
+
$(this).data('multiselect', data);
|
523
966
|
}
|
524
967
|
|
525
968
|
// Call multiselect method.
|
526
|
-
if (
|
969
|
+
if (typeof option === 'string') {
|
527
970
|
data[option](parameter);
|
971
|
+
|
972
|
+
if (option === 'destroy') {
|
973
|
+
$(this).data('multiselect', false);
|
974
|
+
}
|
528
975
|
}
|
529
976
|
});
|
530
977
|
};
|