diff --git a/dist/js/bootstrap-multiselect.js b/dist/js/bootstrap-multiselect.js
index b5ac66d6..48d2728f 100644
--- a/dist/js/bootstrap-multiselect.js
+++ b/dist/js/bootstrap-multiselect.js
@@ -1378,6 +1378,58 @@
}
},
+ /**
+ * Set the current selection
+ *
+ * Helper function to set which options are currently selected by invoking
+ * 'select' for all unselected values that appear in the given list and
+ * invoking 'deselect' for all selected values that do NOT appear in the
+ * given list
+ *
+ * @param {Array} selection
+ * @param {Boolean} triggerOnChange
+ */
+ setSelected: function (selection, triggerOnChange) {
+ if (!$.isArray(selection)) {
+ selection = [selection];
+ }
+
+ // Get all of the enabled options
+ var opts = $("option:enabled", this.$select);
+ var selectedOpts = opts.filter(":selected");
+ var notSelectedOpts = opts.not(":selected");
+ var values;
+ var val;
+
+ // Find all the not-selected options
+ values = notSelectedOpts.map(function () {
+ // If their value is in the array, it should be selected so
+ // return that value (otherwise, return null to omit it from the result)
+ val = $(this).val();
+ return ($.inArray(val, selection) > -1) ? val : null;
+ }).get();
+
+ if ( values.length )
+ {
+ // Select all that need to be selected
+ this.select(values, triggerOnChange);
+ }
+
+ // Find all the selected options
+ values = selectedOpts.map(function () {
+ // If their value is NOT in the array, it should be deselected so
+ // return that value (otherwise, return null to omit it from the result)
+ val = $(this).val();
+ return ($.inArray(val, selection) == -1) ? val : null;
+ }).get();
+
+ if ( values.length )
+ {
+ // Deselect all that should not be selected
+ this.deselect(values, triggerOnChange);
+ }
+ },
+
/**
* Rebuild the plugin.
*
diff --git a/index.html b/index.html
index 66143e2b..83fa0dda 100644
--- a/index.html
+++ b/index.html
@@ -3750,6 +3750,160 @@
Methods
});
});
</script>
+
+
+
+
+
+
+ .multiselect('setSelected', selection)
+
+
+
+ Explicitly sets which options are selected (also works with an array of values). Any currently selected options
+ that do not appear in the given array will be deselected. Any deselected options that do appear in the given array
+ will be selected.
+
+
+
+
+
+
+
+ Option 1
+ Option 2
+ Option 3
+ Option 4
+ Option 5
+ Option 6
+
+ Set the Selection...
+
+
+
+
+
+<script type="text/javascript">
+ $(document).ready(function() {
+ $('#example-setSelected').multiselect();
+
+ $('#example-setSelected-button').on('click', function() {
+ $('#example-setSelected').multiselect('setSelected', ['1', '2', '4']);
+
+ alert('Selected 1, 2 and 4. Deselected 3, 5, and 6.');
+ });
+ });
+</script>
+
+
+
+
+ The method provides an additional parameter: .multiselect('setSelected', selection, triggerOnChange). If the third parameter is set to true, the method will manually trigger the onChange option.
+
+
+
+
+
+
+
+ Option 1
+ Option 2
+ Option 3
+ Option 4
+ Option 5
+ Option 6
+
+ Set Selected
+
+
+
+
+
+<script type="text/javascript">
+ $(document).ready(function() {
+ $('#example-setSelected-onChange').multiselect({
+ onChange: function(option, checked, select) {
+ alert('onChange triggered: ' + $(option).val() + ' was ' + (checked ? '' : 'de') + 'selected.');
+ }
+ });
+
+ $('#example-setSelected-onChange-button').on('click', function() {
+ $('#example-setSelected-onChange').multiselect('setSelected', '1', true);
+ });
+ });
+</script>
+
+
+
+
+ The above parameter also works when multiple options change (selected or deselected). Note that onChange is called for each selected and deselected option individually.
+
+
+
+
+
+
+
+ Option 1
+ Option 2
+ Option 3
+ Option 4
+ Option 5
+ Option 6
+
+ Change Multiple Selections
+
+
+
+
+
+<script type="text/javascript">
+ $(document).ready(function() {
+ $('#example-setSelected-onChange-array').multiselect({
+ onChange: function(option, checked, select) {
+ alert('onChange triggered: ' + $(option).val() + ' was ' + (checked ? '' : 'de') + 'selected.');
+ }
+ });
+
+ $('#example-setSelected-onChange-array-button').on('click', function() {
+ $('#example-setSelected-onChange-array').multiselect('setSelected', ['2','4'], true);
+ });
+ });
+</script>
diff --git a/tests/spec/bootstrap-multiselect.js b/tests/spec/bootstrap-multiselect.js
index 280b5d20..4e003933 100644
--- a/tests/spec/bootstrap-multiselect.js
+++ b/tests/spec/bootstrap-multiselect.js
@@ -3,19 +3,19 @@ describe('Bootstrap Multiselect "Core".', function() {
beforeEach(function() {
var $select = $(' ');
-
+
for (var i = 1; i < 100; i++) {
var $option = $('' + i + ' ');
-
+
if (i < 10) {
$option.prop('selected', true);
}
-
+
$select.append($option);
}
-
+
$('body').append($select);
-
+
$select.multiselect({
buttonContainer: '
',
onInitialized: function($select) {
@@ -26,182 +26,182 @@ describe('Bootstrap Multiselect "Core".', function() {
}
});
});
-
+
it('Should add the container after the select.', function() {
expect($('#multiselect-container').length).toBe(1);
});
-
+
it('Should add the multiselect button.', function() {
expect($('#multiselect-container .multiselect').length).toBe(1);
});
-
+
it('Should add the dropdown menu.', function() {
expect($('#multiselect-container .dropdown-menu').length).toBe(1);
});
-
+
it('Should add an li element with checkbox and label for each option.', function() {
expect($('#multiselect-container li').length).toBe(99);
expect($('#multiselect-container label').length).toBe(99);
expect($('#multiselect-container input[type="checkbox"]').length).toBe(99);
});
-
+
it('Should preserve selected options.', function() {
expect($('#multiselect-container input[type="checkbox"]:checked').length).toBe(9);
expect($('#multiselect option:selected').length).toBe(9);
});
-
+
it('Should be able to select options by value.', function() {
$('#multiselect').multiselect('select', '10');
-
+
expect($('#multiselect option[value="10"]').prop('selected')).toBe(true);
expect($('#multiselect-container input[value="10"]').prop('checked')).toBe(true);
});
-
+
it('Select method should handle "null" and "undefined" correctly.', function() {
expect($('#multiselect option:selected').length).toBe(9);
-
+
$('#multiselect').multiselect('select', null);
expect($('#multiselect option:selected').length).toBe(9);
-
+
$('#multiselect').multiselect('select', undefined);
expect($('#multiselect option:selected').length).toBe(9);
});
-
+
it('Should be able to deselect options by value.', function() {
$('#multiselect').multiselect('select', '10');
$('#multiselect').multiselect('deselect', '10');
-
+
expect($('#multiselect option[value="10"]').prop('selected')).toBe(false);
expect($('#multiselect-container input[value="10"]').prop('checked')).toBe(false);
});
-
+
it('Deselect method should handle "null" and "undefined" correctly.', function() {
expect($('#multiselect option:selected').length).toBe(9);
-
+
$('#multiselect').multiselect('deselect', null);
expect($('#multiselect option:selected').length).toBe(9);
-
+
$('#multiselect').multiselect('deselect', undefined);
expect($('#multiselect option:selected').length).toBe(9);
});
-
+
it('Should be able to select options using an array of values.', function() {
$('#multiselect').multiselect('select', ['10', '11']);
-
+
expect($('#multiselect option[value="10"]').prop('selected')).toBe(true);
expect($('#multiselect-container input[value="10"]').prop('checked')).toBe(true);
-
+
expect($('#multiselect option[value="11"]').prop('selected')).toBe(true);
expect($('#multiselect-container input[value="11"]').prop('checked')).toBe(true);
});
-
+
it('Should be able to deselect options using an array of values.', function() {
$('#multiselect').multiselect('select', ['10', '11']);
$('#multiselect').multiselect('deselect', ['10', '11']);
-
+
expect($('#multiselect option[value="10"]').prop('selected')).toBe(false);
expect($('#multiselect-container input[value="10"]').prop('checked')).toBe(false);
-
+
expect($('#multiselect option[value="11"]').prop('selected')).toBe(false);
expect($('#multiselect-container input[value="11"]').prop('checked')).toBe(false);
});
-
+
it('Should be able to disable the multiselect', function() {
$('#multiselect').multiselect('disable');
-
+
expect($('#multiselect').prop('disabled')).toBe(true);
});
-
+
it('Should be able to enable the multiselect', function() {
$('#multiselect').multiselect('disable');
$('#multiselect').multiselect('enable');
-
+
expect($('#multiselect').prop('disabled')).toBe(false);
});
-
+
it('Should be able to select all options.', function() {
$('#multiselect').multiselect('selectAll');
-
+
for (var i = 1; i < 100; i++) {
expect($('#multiselect option[value="' + i.toString() + '"]').prop('selected')).toBe(true);
expect($('#multiselect-container input[value="' + i.toString() + '"]').prop('checked')).toBe(true);
}
});
-
+
it('Should be able to deselect all options.', function() {
$('#multiselect').multiselect('selectAll');
-
+
for (var i = 1; i < 100; i++) {
expect($('#multiselect option[value="' + i.toString() + '"]').prop('selected')).toBe(true);
expect($('#multiselect-container input[value="' + i.toString() + '"]').prop('checked')).toBe(true);
}
-
+
$('#multiselect').multiselect('deselectAll');
-
+
for (var i = 1; i < 100; i++) {
expect($('#multiselect option[value="' + i.toString() + '"]').prop('selected')).toBe(false);
expect($('#multiselect-container input[value="' + i.toString() + '"]').prop('checked')).toBe(false);
}
});
-
+
it('Should update the checkboxes according to the selected options after using refresh.', function() {
for (var i = 10; i < 20; i++) {
$('#multiselect option[value="' + i + '"]').prop('selected', true);
}
-
+
expect($('#multiselect option:selected').length).toBe(19);
expect($('#multiselect-container input[type="checkbox"]:checked').length).toBe(9);
-
+
$('#multiselect').multiselect('refresh');
-
+
expect($('#multiselect-container input[type="checkbox"]:checked').length).toBe(19);
-
+
for (var i = 10; i < 20; i++) {
expect($('#multiselect option[value="' + i + '"]').prop('selected')).toBe(true);
}
});
-
+
it('Should remove container, button and ul after destroy.', function() {
$('#multiselect').multiselect('destroy');
-
+
// Destroy should remove container, button and ul.
expect($('#multiselect-container.multiselect-container').length).toBe(0);
expect($('#multiselect-container .multiselect').length).toBe(0);
expect($('#multiselect-container .dropdown-menu').length).toBe(0);
});
-
+
it('Should select an option when checkbox is changed (change event).', function() {
$('#multiselect-container li input[value="10"]').prop('checked', true);
$('#multiselect-container li input[value="10"]').trigger('change');
-
+
expect($('#multiselect-container input[value="10"]').prop('checked')).toBe(true);
expect($('#multiselect option[value="10"]').prop('selected')).toBe(true);
});
-
+
it('Should deselect an option when checkbox is changed (change event).', function() {
$('#multiselect-container li input[value="10"]').prop('checked', true);
$('#multiselect-container li input[value="10"]').trigger('change');
-
+
// Already checked above.
-
+
$('#multiselect-container li input[value="10"]').prop('checked', false);
$('#multiselect-container li input[value="10"]').trigger('change');
-
+
expect($('#multiselect-container input[value="10"]').prop('checked')).toBe(false);
expect($('#multiselect option[value="10"]').prop('selected')).toBe(false);
});
-
+
it('Should select an option when checkbox is clicked.', function() {
$('#multiselect-container li input[value="10"]').click();
-
+
expect($('#multiselect-container input[value="10"]').prop('checked')).toBe(true);
expect($('#multiselect option[value="10"]').prop('selected')).toBe(true);
});
-
+
it('Should deselect an option when checkbox is clicked.', function() {
$('#multiselect-container li input[value="10"]').click();
$('#multiselect-container li input[value="10"]').click();
-
+
expect($('#multiselect-container input[value="10"]').prop('checked')).toBe(false);
expect($('#multiselect option[value="10"]').prop('selected')).toBe(false);
});
@@ -225,29 +225,29 @@ describe('Bootstrap Multiselect "Core".', function() {
describe('Bootstrap Multiselect "Single Selection"', function() {
beforeEach(function() {
var $select = $(' ');
-
+
for (var i = 1; i < 100; i++) {
$select.append('Option ' + i + ' ');
}
-
+
$('body').append($select);
-
+
$select.multiselect({
buttonContainer: '
'
});
});
-
+
it('Should create radio buttons instead of checkboxes.', function() {
expect($('#multiselect-container input[type="radio"]').length).toBe(99);
expect($('#multiselect-container input[type="checkbox"]').length).toBe(0);
-
+
// Browser selects one option per default.
expect($('#multiselect option:selected').length).toBe(1);
});
-
+
it('Only one option at a time can be selected.', function() {
expect($('#multiselect option:selected').length).toBe(1);
-
+
var i = 0;
$('#multiselect-container input').each(function() {
if (i === 0) {
@@ -257,18 +257,18 @@ describe('Bootstrap Multiselect "Single Selection"', function() {
else {
expect($(this).prop('checked')).toBe(false);
$(this).click();
-
+
expect($('#multiselect option:selected').length).toBe(1);
expect($(this).prop('checked')).toBe(true);
i++;
}
});
});
-
+
it('Deselect all should work.', function() {
expect($('#multiselect option:selected').length).toBe(1);
});
-
+
afterEach(function() {
$('#multiselect').multiselect('destroy');
$('#multiselect').remove();
@@ -276,16 +276,16 @@ describe('Bootstrap Multiselect "Single Selection"', function() {
});
describe('Bootstrap Multiselect "Clickable Optgroups"', function() {
-
+
// Count the number of onChanges fired.
var fired = 0;
-
+
beforeEach(function() {
var $select = $(' ');
-
+
for (var i = 1; i < 11; i++) {
var $optgroup = $(' ');
-
+
for (var j = 1; j < 11; j++) {
if (i == 1) {
$optgroup.append('Option ' + i + '.' + j + ' ');
@@ -294,12 +294,12 @@ describe('Bootstrap Multiselect "Clickable Optgroups"', function() {
$optgroup.append('Option ' + i + '.' + j + ' ');
}
}
-
+
$select.append($optgroup);
}
-
+
$('body').append($select);
-
+
$select.multiselect({
buttonContainer: '
',
enableClickableOptGroups: true,
@@ -309,20 +309,20 @@ describe('Bootstrap Multiselect "Clickable Optgroups"', function() {
}
});
});
-
+
it('Should correctly create inputs for optgroups.', function() {
expect($('#multiselect-container li.multiselect-group').length).toBe(10);
expect($('#multiselect-container li.multiselect-group input').length).toBe(10);
-
+
$('#multiselect-container label.multiselect-group').each(function() {
expect($('input', $(this)).length).toBe(10);
});
});
-
+
it('Groups should be clickable and correctly initialized.', function() {
expect($('#multiselect option:selected').length).toBe(10);
expect(fired).toBe(0);
-
+
var i = 0;
$('#multiselect-container li.multiselect-group').each(function() {
if (i == 0) {
@@ -338,7 +338,7 @@ describe('Bootstrap Multiselect "Clickable Optgroups"', function() {
}
else {
$('label', $(this)).click();
-
+
expect($('option:selected', $('#multiselect optgroup')[i]).length).toBe(10);
expect($('#multiselect option:selected').length).toBe(20);
@@ -348,27 +348,27 @@ describe('Bootstrap Multiselect "Clickable Optgroups"', function() {
i++;
});
});
-
+
it('Clickable groups should fire onChange only once.', function() {
expect($('#multiselect option:selected').length).toBe(10);
-
+
fired = 0;
expect(fired).toBe(0);
-
+
var i = 0;
$('#multiselect-container li.multiselect-group').each(function() {
$('label', $(this)).click();
-
+
// Selected
expect(fired).toBe(1);
fired = 0;
-
+
$('label', $(this)).click();
-
+
// Deselected
expect(fired).toBe(1);
fired = 0;
-
+
i++;
});
});
@@ -457,7 +457,7 @@ describe('Bootstrap Multiselect "Clickable Optgroups"', function() {
$('#multiselect').multiselect('select', values);
expect($('input', $group).prop('checked')).toBe(true);
});
-
+
afterEach(function() {
$('#multiselect').multiselect('destroy');
$('#multiselect').remove();
@@ -465,25 +465,25 @@ describe('Bootstrap Multiselect "Clickable Optgroups"', function() {
});
describe('Bootstrap Multiselect "Collapsible Optgroups"', function() {
-
+
// Count the number of onChanges fired.
var fired = 0;
-
+
beforeEach(function() {
var $select = $(' ');
-
+
for (var i = 1; i < 11; i++) {
var $optgroup = $(' ');
-
+
for (var j = 1; j < 11; j++) {
$optgroup.append('Option ' + i + '.' + j + ' ');
}
-
+
$select.append($optgroup);
}
-
+
$('body').append($select);
-
+
$select.multiselect({
buttonContainer: '
',
enableCollapsibleOptGroups: true,
@@ -492,52 +492,52 @@ describe('Bootstrap Multiselect "Collapsible Optgroups"', function() {
}
});
});
-
+
it('Should correctly create headers for optgroups.', function() {
expect($('#multiselect-container li.multiselect-group').length).toBe(10);
-
+
$('#multiselect-container label.multiselect-group').each(function() {
expect($('input', $(this)).length).toBe(10);
});
});
-
+
if ('Should not create inputs.', function() {
expect($('#multiselect-container li.multiselect-group input').length).toBe(0);
});
-
+
it('Groups should not be clickable.', function() {
expect($('#multiselect option:selected').length).toBe(0);
-
+
var i = 0;
$('#multiselect-container li.multiselect-group').each(function() {
$('label', $(this)).click();
expect($('option:selected', $('#multiselect optgroup')[i]).length).toBe(0);
expect($('#multiselect option:selected').length).toBe(0);
-
+
$('label', $(this)).click();
i++;
});
});
-
+
it('Should be collapsible.', function() {
var $group = $('#multiselect-container li.multiselect-group:first');
$('.caret-container', $group).click();
-
+
var $lis = $group.nextUntil('li.multiselect-group');
$lis.each(function() {
expect($(this).hasClass('multiselect-collapsible-hidden')).toBe(true);
expect($(this).hasClass('multiselect-collapsible-hidden')).toBe($(this).is(':hidden'));
});
-
+
$('.caret-container', $group).click();
-
+
var $lis = $group.nextUntil('li.multiselect-group');
$lis.each(function() {
expect($(this).hasClass('multiselect-collapsible-hidden')).toBe(false);
expect($(this).hasClass('multiselect-collapsible-hidden')).toBe($(this).is(':hidden'));
});
});
-
+
afterEach(function() {
$('#multiselect').multiselect('destroy');
$('#multiselect').remove();
@@ -545,25 +545,25 @@ describe('Bootstrap Multiselect "Collapsible Optgroups"', function() {
});
describe('Bootstrap Multiselect "Clickable+Collapsible Optgroups"', function() {
-
+
// Count the number of onChanges fired.
var fired = 0;
-
+
beforeEach(function() {
var $select = $(' ');
-
+
for (var i = 1; i < 11; i++) {
var $optgroup = $(' ');
-
+
for (var j = 1; j < 11; j++) {
$optgroup.append('Option ' + i + '.' + j + ' ');
}
-
+
$select.append($optgroup);
}
-
+
$('body').append($select);
-
+
$select.multiselect({
buttonContainer: '
',
enableClickableOptGroups: true,
@@ -573,73 +573,73 @@ describe('Bootstrap Multiselect "Clickable+Collapsible Optgroups"', function() {
}
});
});
-
+
it('Should correctly create inputs for optgroups.', function() {
expect($('#multiselect-container li.multiselect-group').length).toBe(10);
expect($('#multiselect-container li.multiselect-group input').length).toBe(10);
-
+
$('#multiselect-container label.multiselect-group').each(function() {
expect($('input', $(this)).length).toBe(10);
});
});
-
+
it('Groups should be clickable.', function() {
expect($('#multiselect option:selected').length).toBe(0);
-
+
var i = 0;
$('#multiselect-container li.multiselect-group').each(function() {
$('label', $(this)).click();
expect($('option:selected', $('#multiselect optgroup')[i]).length).toBe(10);
expect($('#multiselect option:selected').length).toBe(10);
-
+
$('label', $(this)).click();
i++;
});
});
-
+
it('Clickable groups should fire onChange only once.', function() {
expect($('#multiselect option:selected').length).toBe(0);
-
+
fired = 0;
expect(fired).toBe(0);
-
+
var i = 0;
$('#multiselect-container li.multiselect-group').each(function() {
$('label', $(this)).click();
-
+
// Selected
expect(fired).toBe(1);
fired = 0;
-
+
$('label', $(this)).click();
-
+
// Deselected
expect(fired).toBe(1);
fired = 0;
-
+
i++;
});
});
-
+
it('Should be collapsible.', function() {
var $group = $('#multiselect-container li.multiselect-group:first');
$('.caret-container', $group).click();
-
+
var $lis = $group.nextUntil('li.multiselect-group');
$lis.each(function() {
expect($(this).hasClass('multiselect-collapsible-hidden')).toBe(true);
expect($(this).hasClass('multiselect-collapsible-hidden')).toBe($(this).is(':hidden'));
});
-
+
$('.caret-container', $group).click();
-
+
var $lis = $group.nextUntil('li.multiselect-group');
$lis.each(function() {
expect($(this).hasClass('multiselect-collapsible-hidden')).toBe(false);
expect($(this).hasClass('multiselect-collapsible-hidden')).toBe($(this).is(':hidden'));
});
});
-
+
afterEach(function() {
$('#multiselect').multiselect('destroy');
$('#multiselect').remove();
@@ -647,25 +647,25 @@ describe('Bootstrap Multiselect "Clickable+Collapsible Optgroups"', function() {
});
describe('Bootstrap Multiselect "Clickable+Collapsible+SelectAll Optgroups"', function() {
-
+
// Count the number of onChanges fired.
var fired = 0;
-
+
beforeEach(function() {
var $select = $(' ');
-
+
for (var i = 1; i < 11; i++) {
var $optgroup = $(' ');
-
+
for (var j = 1; j < 11; j++) {
$optgroup.append('Option ' + i + '.' + j + ' ');
}
-
+
$select.append($optgroup);
}
-
+
$('body').append($select);
-
+
$select.multiselect({
buttonContainer: '
',
enableClickableOptGroups: true,
@@ -674,26 +674,26 @@ describe('Bootstrap Multiselect "Clickable+Collapsible+SelectAll Optgroups"', fu
selectAllValue: 'multiselect-all'
});
});
-
+
it('Should handle option groups differently, i.e. not set class to active.', function() {
// Otherwise they are hidden.
$('#multiselect-container input[value="multiselect-all"]').click();
-
+
var $groups = $('#multiselect-container li.multiselect-group');
$groups.each(function() {
expect($(this).hasClass('active')).toBe(false);
});
-
+
var $lis = $('#multiselect-container li:not(.multiselect-group)');
$lis.each(function() {
expect($(this).hasClass('active')).toBe(true);
});
});
-
+
it('Should select all options (including option groups).', function() {
//$('#multiselect-container li.multiselect-group .caret-container').click();
$('#multiselect-container input[value="multiselect-all"]').click();
-
+
var $lis = $('#multiselect-container li');
$lis.each(function() {
expect($('input', this).prop('checked')).toBe(true);
@@ -712,7 +712,7 @@ describe('Bootstrap Multiselect "Clickable+Collapsible+SelectAll Optgroups"', fu
expect($('#multiselect-container li input[value="multiselect-all"]').prop('checked')).toBe(true);
});
-
+
afterEach(function() {
$('#multiselect').multiselect('destroy');
$('#multiselect').remove();
@@ -722,14 +722,14 @@ describe('Bootstrap Multiselect "Clickable+Collapsible+SelectAll Optgroups"', fu
describe('Bootstrap Multiselect "Dataprovider"', function() {
beforeEach(function() {
var $select = $(' ');
-
+
$('body').append($select);
-
+
$select.multiselect({
buttonContainer: '
'
});
});
-
+
var options = [
{label: 'Option 1', value: '1', selected: true, title: 'Option 1 Title'},
{label: 'Option 2', value: '2', title: 'Option 2 Title'},
@@ -738,51 +738,51 @@ describe('Bootstrap Multiselect "Dataprovider"', function() {
{label: 'Option 5', value: '5', title: 'Option 5 Title'},
{label: 'Option 6', value: '6', title: 'Option 6 Title'}
];
-
+
var options_attributes = [
{label: 'Option 1', value: '1', attributes: {'some-attribute': 'test'}}
];
-
+
it("Should be able to add options.", function() {
$('#multiselect').multiselect('dataprovider', options);
expect($('#multiselect option').length).toBe(6);
expect($('#multiselect-container input').length).toBe(6);
-
+
expect($('#multiselect option[value="1"]').length).toBe(1);
expect($('#multiselect option[value="1"]').prop('selected')).toBe(true);
expect($('#multiselect-container input[value="1"]').prop('checked')).toBe(true);
-
+
expect($('#multiselect option[value="2"]').length).toBe(1);
expect($('#multiselect option[value="2"]').prop('selected')).toBe(false);
expect($('#multiselect-container input[value="2"]').prop('checked')).toBe(false);
-
+
expect($('#multiselect option[value="3"]').length).toBe(1);
expect($('#multiselect option[value="3"]').prop('selected')).toBe(true);
expect($('#multiselect-container input[value="3"]').prop('checked')).toBe(true);
-
+
expect($('#multiselect option[value="4"]').length).toBe(1);
expect($('#multiselect option[value="4"]').prop('selected')).toBe(false);
expect($('#multiselect-container input[value="4"]').prop('checked')).toBe(false);
-
+
expect($('#multiselect option[value="5"]').length).toBe(1);
expect($('#multiselect option[value="5"]').prop('selected')).toBe(false);
expect($('#multiselect-container input[value="5"]').prop('checked')).toBe(false);
-
+
expect($('#multiselect option[value="6"]').length).toBe(1);
expect($('#multiselect option[value="6"]').prop('selected')).toBe(false);
expect($('#multiselect-container input[value="6"]').prop('checked')).toBe(false);
});
-
+
it("Should be able to define title.", function() {
$('#multiselect').multiselect('dataprovider', options);
-
+
expect($('#multiselect option[value="1"]').attr('title')).toBe('Option 1 Title');
expect($('#multiselect option[value="2"]').attr('title')).toBe('Option 2 Title');
expect($('#multiselect option[value="3"]').attr('title')).toBe('Option 3 Title');
expect($('#multiselect option[value="4"]').attr('title')).toBe('Option 4 Title');
expect($('#multiselect option[value="5"]').attr('title')).toBe('Option 5 Title');
expect($('#multiselect option[value="6"]').attr('title')).toBe('Option 6 Title');
-
+
expect($('#multiselect-container input[value="1"]').closest('label').attr('title')).toBe('Option 1 Title');
expect($('#multiselect-container input[value="2"]').closest('label').attr('title')).toBe('Option 2 Title');
expect($('#multiselect-container input[value="3"]').closest('label').attr('title')).toBe('Option 3 Title');
@@ -790,13 +790,13 @@ describe('Bootstrap Multiselect "Dataprovider"', function() {
expect($('#multiselect-container input[value="5"]').closest('label').attr('title')).toBe('Option 5 Title');
expect($('#multiselect-container input[value="6"]').closest('label').attr('title')).toBe('Option 6 Title');
});
-
+
it("Should be able to define data attributes.", function() {
$('#multiselect').multiselect('dataprovider', options_attributes)
expect($('#multiselect option[value="1"]').attr('value')).toBe('1');
expect($('#multiselect option[value="1"]').attr('data-some-attribute')).toBe('test');
});
-
+
var optgroups = [
{
label: 'Group 1', children: [
@@ -813,18 +813,18 @@ describe('Bootstrap Multiselect "Dataprovider"', function() {
]
}
];
-
+
it('Should be able to handle optgroups.', function() {
$('#multiselect').multiselect('dataprovider', optgroups);
-
+
expect($('#multiselect optgroup').length).toBe(2);
expect($('#multiselect option').length).toBe(6);
expect($('#multiselect-container input').length).toBe(6);
-
+
expect($('#multiselect optgroup[label="Group 1"] option').length).toBe(3);
expect($('#multiselect optgroup[label="Group 2"] option').length).toBe(3);
});
-
+
afterEach(function() {
$('#multiselect').multiselect('destroy');
$('#multiselect').remove();
@@ -832,21 +832,21 @@ describe('Bootstrap Multiselect "Dataprovider"', function() {
});
describe('Bootstrap Multiselect "Select All".', function() {
-
+
var onSelectAllTriggered = false;
var onDeselectAllTriggered = false;
-
+
var fired = 0;
-
+
beforeEach(function() {
var $select = $(' ');
-
+
for (var i = 1; i < 100; i++) {
$select.append('1 ');
}
-
+
$('body').append($select);
-
+
$select.multiselect({
buttonContainer: '
',
includeSelectAllOption: true,
@@ -862,48 +862,48 @@ describe('Bootstrap Multiselect "Select All".', function() {
}
});
});
-
+
it('Should not add an additional option to the select.', function() {
expect($('#multiselect option[value="multiselect-all"]').length).toBe(0);
expect($('#multiselect-container input[value="multiselect-all"]').length).toBe(1);
expect($('#multiselect option').length).toBe(99);
expect($('#multiselect-container input').length).toBe(100);
});
-
+
it('Should update the select all when all options are selected by the "select" method.', function() {
expect($('#multiselect option:selected').length).toBe(0);
expect($('#multiselect-container input[value="multiselect-all"]').prop('checked')).toBe(false);
-
+
for (var i = 1; i < 100; i++) {
$('#multiselect').multiselect('select', i.toString());
expect($('#multiselect option[value="' + i.toString() + '"]').prop('selected')).toBe(true);
}
-
+
expect($('#multiselect option:selected').length).toBe(99);
expect($('#multiselect-container input').length).toBe(100);
expect($('#multiselect-container input[value="multiselect-all"]').prop('checked')).toBe(true);
});
-
+
it('Should update the select all when all options are deselected by the "deselect" method (first all options are selected as before).', function() {
expect($('#multiselect option:selected').length).toBe(0);
expect($('#multiselect-container input[value="multiselect-all"]').prop('checked')).toBe(false);
-
+
for (var i = 1; i < 100; i++) {
$('#multiselect').multiselect('select', i.toString());
}
-
+
expect($('#multiselect option:selected').length).toBe(99);
expect($('#multiselect-container input:checked').length).toBe(100);
expect($('#multiselect-container input[value="multiselect-all"]').prop('checked')).toBe(true);
-
+
for (var i = 1; i < 100; i++) {
$('#multiselect').multiselect('deselect', i.toString());
}
-
+
expect($('#multiselect option:selected').length).toBe(0);
expect($('#multiselect-container input[value="multiselect-all"]').prop('checked')).toBe(false);
});
-
+
it('Should update the select all option when all options are selected by the change event.', function() {
expect($('#multiselect option:selected').length).toBe(0);
expect($('#multiselect-container input[value="multiselect-all"]').prop('checked')).toBe(false);
@@ -992,9 +992,9 @@ describe('Bootstrap Multiselect "Select All".', function() {
it('Should trigger onSelectAll/onDeselectAll based on the click event.', function() {
expect($('#multiselect option:selected').length).toBe(0);
expect($('#multiselect-container input[value="multiselect-all"]').prop('checked')).toBe(false);
-
+
$('#multiselect-container input[value!="multiselect-all"]').click();
-
+
expect($('#multiselect option:selected').length).toBe(99);
expect($('#multiselect-container input[value="multiselect-all"]').prop('checked')).toBe(true);
@@ -1015,53 +1015,221 @@ describe('Bootstrap Multiselect "Select All".', function() {
$('#multiselect').multiselect('deselectAll', true, true);
expect(onDeselectAllTriggered).toBe(true);
});
-
+
afterEach(function() {
$('#multiselect').multiselect('destroy');
$('#multiselect').remove();
});
});
+describe('Bootstrap Multiselect "setSelection".', function () {
+
+ var onChangeSelected = [];
+ var onChangeDeselected = [];
+ var onChangeFired = 0;
+ var $select;
+
+ beforeEach(function () {
+ $select = $(' ');
+
+ for (var i = 1; i < 100; i++) {
+ $select.append('1 ');
+ }
+
+ $('body').append($select);
+
+ $select.multiselect({
+ onChange: function (option, checked) {
+ ++onChangeFired;
+
+ (checked ? onChangeSelected : onChangeDeselected).push($(option).val());
+ }
+ });
+
+ onChangeFired = 0;
+ onChangeSelected = [];
+ onChangeDeselected = [];
+ });
+
+ var VALS_A = [3, 25, 19, 76];
+ var VALS_B = [11, 23, 92];
+ var VALS_C = [37, 69, 40];
+ var VALS_AB = VALS_A.concat(VALS_B);
+ var VALS_BC = VALS_B.concat(VALS_C);
+ var VALS_ABC = VALS_A.concat(VALS_B).concat(VALS_C);
+
+ function sortInt(x, y) { return (x - y); }
+
+ VALS_A = VALS_A.sort(sortInt).map(function (n) { return n.toString(); });
+ VALS_B = VALS_B.sort(sortInt).map(function (n) { return n.toString(); });
+ VALS_C = VALS_C.sort(sortInt).map(function (n) { return n.toString(); });
+ VALS_AB = VALS_AB.sort(sortInt).map(function (n) { return n.toString(); });
+ VALS_BC = VALS_BC.sort(sortInt).map(function (n) { return n.toString(); });
+ VALS_ABC = VALS_ABC.sort(sortInt).map(function (n) { return n.toString(); });
+
+ it('Should be able to set selected values', function () {
+ var values = VALS_AB;
+
+ expect($('option:selected', $select).length).toBe(0);
+ expect($select.val()).toBeNull();
+
+ $select.multiselect("setSelected", values);
+ for (var i = 0; i < values.length; ++i) {
+ expect($('option[value="' + values[i].toString() + '"]').prop('selected')).toBe(true);
+ }
+ expect($select.val()).toEqual(values);
+ });
+
+ it('Should be able to deselect values', function () {
+ var values = VALS_AB;
+ var i;
+
+ // Verify initial state
+ expect($('option:selected', $select).length).toBe(0);
+ expect($select.val()).toBeNull();
+
+ // Select some values and test the state
+ $select.multiselect("select", values);
+ expect($select.val()).toEqual(values);
+ for (i = 0; i < VALS_C.length; ++i) {
+ expect($('option[value="' + VALS_C[i].toString() + '"]').prop('selected')).toBe(false);
+ }
+ for (i = 0; i < values.length; ++i) {
+ expect($('option[value="' + values[i].toString() + '"]').prop('selected')).toBe(true);
+ }
+
+ // Set the selection to a different set of values
+ $select.multiselect("setSelected", VALS_C);
+ expect($select.val()).toEqual(VALS_C);
+ for (i = 0; i < VALS_C.length; ++i) {
+ expect($('option[value="' + VALS_C[i].toString() + '"]').prop('selected')).toBe(true);
+ }
+ for (i = 0; i < values.lengths; ++i) {
+ expect($('option[value="' + values[i].toString() + '"]').prop('selected')).toBe(false);
+ }
+ });
+
+ it('Should be able to receive onChange notifications for only the values that changed', function () {
+ var initVals = VALS_AB;
+ var setVals = VALS_BC;
+ var i;
+
+ expect(onChangeFired).toBe(0);
+ expect(onChangeSelected.length).toBe(0);
+ expect(onChangeDeselected.length).toBe(0);
+
+ $select.multiselect("setSelected", initVals, true);
+ expect(onChangeSelected).toEqual(initVals);
+ expect($select.val()).toEqual(initVals);
+ expect(onChangeSelected).toEqual($select.val());
+ expect(onChangeDeselected.length).toBe(0);
+ expect(onChangeFired).toBe(initVals.length);
+ for (i = 0; i < VALS_A.length; ++i) {
+ expect($('option[value="' + VALS_A[i].toString() + '"]').prop('selected')).toBe(true);
+ }
+ for (i = 0; i < VALS_B.length; ++i) {
+ expect($('option[value="' + VALS_B[i].toString() + '"]').prop('selected')).toBe(true);
+ }
+ for (i = 0; i < VALS_C.length; ++i) {
+ expect($('option[value="' + VALS_C[i].toString() + '"]').prop('selected')).toBe(false);
+ }
+
+ onChangeSelected = [];
+ onChangeFired = 0;
+ $select.multiselect("setSelected", setVals, true); // Unselect "A", Select "C", Leave "B" Selected
+ expect($select.val()).toEqual(setVals);
+ expect(onChangeSelected).toEqual(VALS_C);
+ expect(onChangeDeselected).toEqual(VALS_A);
+ expect(onChangeFired).toBe(VALS_C.length + VALS_A.length);
+ for (i = 0; i < VALS_A.length; ++i) {
+ expect($('option[value="' + VALS_A[i].toString() + '"]').prop('selected')).toBe(false);
+ }
+ for (i = 0; i < VALS_B.length; ++i) {
+ expect($('option[value="' + VALS_B[i].toString() + '"]').prop('selected')).toBe(true);
+ }
+ for (i = 0; i < VALS_C.length; ++i) {
+ expect($('option[value="' + VALS_C[i].toString() + '"]').prop('selected')).toBe(true);
+ }
+ });
+
+ it('Should not fire onChange notifications if they\'re not requested', function () {
+ expect(onChangeFired).toBe(0);
+ expect(onChangeSelected.length).toBe(0);
+ expect(onChangeDeselected.length).toBe(0);
+
+ // Set a new selection
+ $select.multiselect('setSelected', VALS_AB, false);
+
+ // Verify the selection changed but events did not fire
+ expect($select.val()).toEqual(VALS_AB);
+ expect(onChangeFired).toBe(0);
+ expect(onChangeSelected.length).toBe(0);
+ expect(onChangeDeselected.length).toBe(0);
+
+ // Set a new selection
+ $select.multiselect('setSelected', VALS_BC, false);
+
+ // Verify the selection changed but events did not fire
+ expect($select.val()).toEqual(VALS_BC);
+ expect(onChangeFired).toBe(0);
+ expect(onChangeSelected.length).toBe(0);
+ expect(onChangeDeselected.length).toBe(0);
+
+ // Set a new selection
+ $select.multiselect('setSelected', VALS_ABC, false);
+
+ // Verify the selection changed but events did not fire
+ expect($select.val()).toEqual(VALS_ABC);
+ expect(onChangeFired).toBe(0);
+ expect(onChangeSelected.length).toBe(0);
+ expect(onChangeDeselected.length).toBe(0);
+ });
+
+ afterEach(function () {
+ $select.multiselect('destroy');
+ $select.remove();
+ });
+});
describe('Bootstrap Multiselect Specific Issues.', function() {
-
+
it('#393', function() {
var $select = $(' ');
-
+
for (var i = 1; i < 100; i++) {
$select.append('1 ');
}
-
+
$('body').append($select);
-
+
$select.multiselect({
buttonContainer: '
',
includeSelectAllOption: true,
selectAllValue: 0
});
-
+
expect($('#multiselect-container input[value="0"]').length).toBe(1);
expect($('#multiselect-container input[value="0"]').prop('checked')).toBe(false);
-
+
$('#multiselect').multiselect('selectAll');
-
+
expect($('#multiselect option:selected').length).toBe(99);
expect($('#multiselect-container input[value="0"]').prop('checked')).toBe(true);
-
+
$('#multiselect').multiselect('deselectAll');
-
+
expect($('#multiselect option:selected').length).toBe(0);
expect($('#multiselect-container input[value="0"]').prop('checked')).toBe(false);
-
+
$('#multiselect-container input[value="0"]').click();
-
+
expect($('#multiselect option:selected').length).toBe(99);
expect($('#multiselect-container input[value="0"]').prop('checked')).toBe(true);
-
+
$('#multiselect-container input[value="0"]').click();
-
+
expect($('#multiselect option:selected').length).toBe(0);
expect($('#multiselect-container input[value="0"]').prop('checked')).toBe(false);
-
+
$('#multiselect').multiselect('destroy');
$('#multiselect').remove();
});
@@ -1096,22 +1264,22 @@ describe('Bootstrap Multiselect Specific Issues.', function() {
$('#multiselect').remove();
$selection.remove();
});
-
+
it('#679', function() {
var $select = $(' ');
-
+
for (var i = 1; i < 11; i++) {
var $optgroup = $(' ');
-
+
for (var j = 1; j < 11; j++) {
$optgroup.append('Option ' + i + '.' + j + ' ');
}
-
+
$select.append($optgroup);
}
-
+
$('body').append($select);
-
+
var fired = 0;
$select.multiselect({
buttonContainer: '
',
@@ -1121,27 +1289,27 @@ describe('Bootstrap Multiselect Specific Issues.', function() {
fired++;
}
});
-
+
expect($('#multiselect option:selected').length).toBe(0);
expect(fired).toBe(0);
-
+
var i = 0;
$('#multiselect-container li.multiselect-group').each(function() {
$('label', $(this)).click();
-
+
// Selected
expect(fired).toBe(1);
fired = 0;
-
+
$('label', $(this)).click();
-
+
// Deselected
expect(fired).toBe(1);
fired = 0;
-
+
i++;
});
-
+
$('#multiselect').multiselect('destroy');
$('#multiselect').remove();
});
@@ -1204,7 +1372,7 @@ describe('Knockout Binding.', function() {
expect($testArea.find('option:checked').length).toEqual(2);
expect($testArea.find('option:checked').map(function() { return $(this).text().trim() }).toArray()).toEqual(['option1', 'option2']);
- expect($testArea.next().find('button.multiselect').text().trim()).toEqual('All selected (2)');
+ expect($testArea.next().find('button.multiselect').text().trim()).toEqual('All selected (2)');
// add another option
viewModel.myOptions.push('wacky option');
@@ -1213,6 +1381,6 @@ describe('Knockout Binding.', function() {
expect($testArea.find('option:checked').length).toEqual(2);
expect($testArea.find('option:checked').map(function() { return $(this).text().trim() }).toArray()).toEqual(['option1', 'option2']);
expect($testArea.find('option').map(function() { return $(this).text().trim() }).toArray()).toEqual(['option1', 'option2', 'wacky option']);
- expect($testArea.next().find('button.multiselect').text().trim()).toEqual('2 selected');
+ expect($testArea.next().find('button.multiselect').text().trim()).toEqual('2 selected');
});
});