Commit 8d43ff18 authored by David Stutz's avatar David Stutz

#162 and tests.

parent 03e9818a
/** /**
* bootstrap-multiselect.js 1.0.0 * bootstrap-multiselect.js
* https://github.com/davidstutz/bootstrap-multiselect * https://github.com/davidstutz/bootstrap-multiselect
* *
* Copyright 2012, 2013 David Stutz * Copyright 2012, 2013 David Stutz
...@@ -9,17 +9,15 @@ ...@@ -9,17 +9,15 @@
*/ */
!function($) {"use strict";// jshint ;_; !function($) {"use strict";// jshint ;_;
if ( typeof ko != 'undefined' && ko.bindingHandlers && !ko.bindingHandlers.multiselect) { if (typeof ko != 'undefined' && ko.bindingHandlers && !ko.bindingHandlers.multiselect) {
ko.bindingHandlers.multiselect = { ko.bindingHandlers.multiselect = {
init : function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) { init : function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {},
},
update : function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) { update : function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
var ms = $(element).data('multiselect'); var ms = $(element).data('multiselect');
if (!ms) { if (!ms) {
$(element).multiselect(ko.utils.unwrapObservable(valueAccessor())); $(element).multiselect(ko.utils.unwrapObservable(valueAccessor()));
} }
else else if (allBindingsAccessor().options && allBindingsAccessor().options().length !== ms.originalOptions.length) {
if (allBindingsAccessor().options && allBindingsAccessor().options().length !== ms.originalOptions.length) {
ms.updateOriginalOptions(); ms.updateOriginalOptions();
$(element).multiselect('rebuild'); $(element).multiselect('rebuild');
} }
...@@ -90,9 +88,9 @@ ...@@ -90,9 +88,9 @@
if (options.length == 0) { if (options.length == 0) {
return this.nonSelectedText + ' <b class="caret"></b>'; return this.nonSelectedText + ' <b class="caret"></b>';
} }
else else {
if (options.length > 3) { if (options.length > 3) {
return options.length + ' ' + this.nonSelectedText + ' <b class="caret"></b>'; return options.length + ' ' + this.nSelectedText + ' <b class="caret"></b>';
} }
else { else {
var selected = ''; var selected = '';
...@@ -103,6 +101,7 @@ ...@@ -103,6 +101,7 @@
}); });
return selected.substr(0, selected.length - 2) + ' <b class="caret"></b>'; return selected.substr(0, selected.length - 2) + ' <b class="caret"></b>';
} }
}
}, },
// Like the buttonText option to update the title of the button. // Like the buttonText option to update the title of the button.
buttonTitle: function(options, select) { buttonTitle: function(options, select) {
...@@ -175,7 +174,22 @@ ...@@ -175,7 +174,22 @@
} }
}, },
toggleActiveState: function(shouldBeActive) { // Create optgroup.
createOptgroup: function(group) {
var groupName = $(group).prop('label');
// Add a header for the group.
var $li = $('<li><label class="multiselect-group"></label></li>');
$('label', $li).text(groupName);
$('.multiselect-container', this.$container).append($li);
// Add the options of the group.
$('option', group).each($.proxy(function(index, element) {
this.createOptionValue(element);
}, this));
},
toggleActiveState: function() {
if (this.$select.attr('disabled') == undefined) { if (this.$select.attr('disabled') == undefined) {
$('button.multiselect.dropdown-toggle', this.$container).removeClass('disabled'); $('button.multiselect.dropdown-toggle', this.$container).removeClass('disabled');
} }
...@@ -202,26 +216,12 @@ ...@@ -202,26 +216,12 @@
// Support optgroups and options without a group simultaneously. // Support optgroups and options without a group simultaneously.
var tag = $(element).prop('tagName').toLowerCase(); var tag = $(element).prop('tagName').toLowerCase();
if (tag == 'optgroup') { if (tag == 'optgroup') {
var group = element; this.createOptgroup(element);
var groupName = $(group).prop('label');
// Add a header for the group.
var $li = $('<li><label class="multiselect-group"></label></li>');
$('label', $li).text(groupName);
$('.multiselect-container', this.$container).append($li);
// Add the options of the group.
$('option', group).each($.proxy(function(index, element) {
this.createOptionValue(element);
}, this));
} }
else else if (tag == 'option') {
if (tag == 'option') {
this.createOptionValue(element); this.createOptionValue(element);
} }
else { // Other illegal tags will be ignored.
// Ignore illegal tags.
}
}, this)); }, this));
// Bind the change event on the dropdown elements. // Bind the change event on the dropdown elements.
...@@ -239,6 +239,7 @@ ...@@ -239,6 +239,7 @@
} }
} }
// Get the corresponding option.
var $option = $('option', this.$select).filter(function() { var $option = $('option', this.$select).filter(function() {
return $(this).val() == $(event.target).val(); return $(this).val() == $(event.target).val();
}); });
...@@ -257,15 +258,16 @@ ...@@ -257,15 +258,16 @@
$option.prop('selected', true); $option.prop('selected', true);
if (this.options.multiple) { if (this.options.multiple) {
// Simply select additional option.
$option.attr('selected', 'selected'); $option.attr('selected', 'selected');
} }
else { else {
// Unselect all other options and corresponding checkboxes.
if (this.options.selectedClass) { if (this.options.selectedClass) {
$($checkboxesNotThis).parents('li').removeClass(this.options.selectedClass); $($checkboxesNotThis).parents('li').removeClass(this.options.selectedClass);
} }
$($checkboxesNotThis).prop('checked', false); $($checkboxesNotThis).prop('checked', false);
$optionsNotThis.removeAttr('selected').prop('selected', false); $optionsNotThis.removeAttr('selected').prop('selected', false);
// It's a single selection, so close. // It's a single selection, so close.
...@@ -275,9 +277,9 @@ ...@@ -275,9 +277,9 @@
if (this.options.selectedClass == "active") { if (this.options.selectedClass == "active") {
$optionsNotThis.parents("a").css("outline", ""); $optionsNotThis.parents("a").css("outline", "");
} }
} }
else { else {
// Unselect option.
$option.removeAttr('selected').prop('selected', false); $option.removeAttr('selected').prop('selected', false);
} }
...@@ -319,12 +321,10 @@ ...@@ -319,12 +321,10 @@
index--; index--;
} }
// Navigate down. // Navigate down.
else else if (event.keyCode == 40 && index < $items.length - 1) {
if (event.keyCode == 40 && index < $items.length - 1) {
index++; index++;
} }
else else if (!~index) {
if (!~index) {
index = 0; index = 0;
} }
...@@ -358,8 +358,7 @@ ...@@ -358,8 +358,7 @@
$('.multiselect-search', this.$container).val(this.query).on('click', function(event) { $('.multiselect-search', this.$container).val(this.query).on('click', function(event) {
event.stopPropagation(); event.stopPropagation();
}).on('keydown', $.proxy(function(event) { }).on('keydown', $.proxy(function(event) {
// This is useful to catch "keydown" events after the browser has // This is useful to catch "keydown" events after the browser has updated the control.
// updated the control.
clearTimeout(this.searchTimeout); clearTimeout(this.searchTimeout);
this.searchTimeout = this.asyncFunction($.proxy(function() { this.searchTimeout = this.asyncFunction($.proxy(function() {
...@@ -445,18 +444,21 @@ ...@@ -445,18 +444,21 @@
this.updateButtonText(); this.updateButtonText();
}, },
// Select an option by its value. // Select an option by its value or multiple options using an array of values.
select: function(selectValues) { select: function(selectValues) {
if(selectValues && !$.isArray(selectValues)) { if(selectValues && !$.isArray(selectValues)) {
selectValues = [selectValues]; selectValues = [selectValues];
} }
for(var i = 0; i < selectValues.length; i ++) { for (var i = 0; i < selectValues.length; i++) {
var value = selectValues[i]; var value = selectValues[i];
// Find corresponding option.
var $option = $('option', this.$select).filter(function() { var $option = $('option', this.$select).filter(function() {
return $(this).val() == value; return $(this).val() == value;
}); });
// Find corresponding checkbox.
var $checkbox = $('.multiselect-container li input', this.$container).filter(function() { var $checkbox = $('.multiselect-container li input', this.$container).filter(function() {
return $(this).val() == value; return $(this).val() == value;
}); });
...@@ -474,15 +476,17 @@ ...@@ -474,15 +476,17 @@
this.updateButtonText(); this.updateButtonText();
}, },
// Deselect an option by its value. // Deselect an option by its value or using an array of values.
deselect: function(deselectValues) { deselect: function(deselectValues) {
if(deselectValues && !$.isArray(deselectValues)) { if(deselectValues && !$.isArray(deselectValues)) {
deselectValues = [deselectValues]; deselectValues = [deselectValues];
} }
for(var i = 0; i < deselectValues.length; i ++) { for (var i = 0; i < deselectValues.length; i++) {
var value = deselectValues[i]; var value = deselectValues[i];
// Find option and corresponding checkbox.
var $option = $('option', this.$select).filter(function() { var $option = $('option', this.$select).filter(function() {
return $(this).val() == value; return $(this).val() == value;
}); });
...@@ -508,7 +512,7 @@ ...@@ -508,7 +512,7 @@
$('.multiselect-container', this.$container).html(''); $('.multiselect-container', this.$container).html('');
this.buildSelectAll(); this.buildSelectAll();
this.buildDropdown(this.$select, this.options); this.buildDropdown();
this.updateButtonText(); this.updateButtonText();
// Enable filtering. // Enable filtering.
...@@ -520,7 +524,6 @@ ...@@ -520,7 +524,6 @@
// Build select using the given data as options. // Build select using the given data as options.
dataprovider: function(dataprovider) { dataprovider: function(dataprovider) {
var optionDOM = ""; var optionDOM = "";
dataprovider.forEach(function (option) { dataprovider.forEach(function (option) {
optionDOM += '<option value="' + option.value + '">' + option.label + '</option>'; optionDOM += '<option value="' + option.value + '">' + option.label + '</option>';
}); });
...@@ -534,6 +537,7 @@ ...@@ -534,6 +537,7 @@
return $.extend({}, this.defaults, options); return $.extend({}, this.defaults, options);
}, },
// Update button text and button title.
updateButtonText: function() { updateButtonText: function() {
var options = this.getSelected(); var options = this.getSelected();
...@@ -580,6 +584,7 @@ ...@@ -580,6 +584,7 @@
$.fn.multiselect.Constructor = Multiselect; $.fn.multiselect.Constructor = Multiselect;
// Automatically init selects by their data-role.
$(function() { $(function() {
$("select[data-role=multiselect]").multiselect(); $("select[data-role=multiselect]").multiselect();
}); });
......
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment