Commit 0a857a08 authored by David Stutz's avatar David Stutz

Fixed #109, #113.

Moved CSS declarations into separate LESS file. Filter will now be
rebuild, too.
parent 29f1ab30
This source diff could not be displayed because it is too large. You can view the blob instead.
.multiselect-container{position:absolute;list-style-type:none;margin:0;padding:0}.multiselect-container input[type="text"]{width:70%}.multiselect-container .input-prepend{padding:3px}.multiselect-container>li{padding:0}.multiselect-container>li>label{margin:0;padding:3px 20px 3px 20px;height:100%;cursor:pointer}.multiselect-container>li>label.multiselect-header{margin:0;padding:3px 20px 3px 20px;height:100%}.multiselect-container>li>label>input[type="checkbox"]{margin-bottom:5px}
\ No newline at end of file
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
<meta name="copyright" content="David Stutz" /> <meta name="copyright" content="David Stutz" />
<link rel="stylesheet" href="css/bootstrap-2.3.2.min.css" type="text/css"> <link rel="stylesheet" href="css/bootstrap-2.3.2.min.css" type="text/css">
<link rel="stylesheet" href="css/bootstrap-multiselect.css" type="text/css">
<link rel="stylesheet" href="css/prettify.css" type="text/css"> <link rel="stylesheet" href="css/prettify.css" type="text/css">
<script type="text/javascript" src="js/jquery-2.0.1.min.js"></script> <script type="text/javascript" src="js/jquery-2.0.1.min.js"></script>
...@@ -587,7 +588,8 @@ ...@@ -587,7 +588,8 @@
}); });
$('#example12').multiselect({ $('#example12').multiselect({
buttonContainer: '<span />' buttonContainer: '<span />',
enableFiltering: true
}); });
$('#example12-rebuild').on('click', function() { $('#example12-rebuild').on('click', function() {
$('#example12').multiselect('rebuild'); $('#example12').multiselect('rebuild');
...@@ -1297,7 +1299,7 @@ ...@@ -1297,7 +1299,7 @@
<div class="add-styling"> <div class="add-styling">
<table class="table table-striped"> <table class="table table-striped">
<tr> <tr>
<td> <td width="30%">
<select id="example15" multiple="multiple"> <select id="example15" multiple="multiple">
<optgroup label="Mathematics"> <optgroup label="Mathematics">
<option value="analysis">Analysis</option> <option value="analysis">Analysis</option>
...@@ -1314,10 +1316,10 @@ ...@@ -1314,10 +1316,10 @@
</optgroup> </optgroup>
</select> </select>
</td> </td>
<td> <td width="30%">
Text alignment combined with fixed width and bold, underlined text for option group headers. Text alignment combined with fixed width and bold, underlined text for option group headers.
</td> </td>
<td> <td width="40%">
<pre class="prettyprint linenums"> <pre class="prettyprint linenums">
.multiselect { .multiselect {
text-align: left; text-align: left;
......
...@@ -16,494 +16,515 @@ ...@@ -16,494 +16,515 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
!function ($) { !function($) {"use strict";// jshint ;_;
"use strict"; // jshint ;_; if ( typeof ko != 'undefined' && ko.bindingHandlers && !ko.bindingHandlers.multiselect) {
ko.bindingHandlers.multiselect = {
if(typeof ko != 'undefined' && ko.bindingHandlers && !ko.bindingHandlers.multiselect){ init : function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
ko.bindingHandlers.multiselect = { },
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');
} }
} }
}; };
} }
function Multiselect(select, options) { function Multiselect(select, options) {
this.options = this.getOptions(options); this.options = this.getOptions(options);
this.$select = $(select); this.$select = $(select);
this.originalOptions = this.$select.clone()[0].options; //we have to clone to create a new reference this.originalOptions = this.$select.clone()[0].options;
this.query = ''; //we have to clone to create a new reference
this.searchTimeout = null; this.query = '';
this.searchTimeout = null;
this.options.multiple = this.$select.attr('multiple') == "multiple";
this.options.multiple = this.$select.attr('multiple') == "multiple";
this.$container = $(this.options.buttonContainer)
.append('<button type="button" class="multiselect dropdown-toggle ' + this.options.buttonClass + '" data-toggle="dropdown">' + this.options.buttonText(this.getSelected(), this.$select) + '</button>') this.$container = $(this.options.buttonContainer).append('<button type="button" class="multiselect dropdown-toggle ' + this.options.buttonClass + '" data-toggle="dropdown">' + this.options.buttonText(this.getSelected(), this.$select) + '</button>')
.append('<ul class="multiselect-container dropdown-menu' + (this.options.dropRight ? ' pull-right' : '') + '" style="position:absolute; list-style-type: none;margin:0;padding:0;"></ul>'); .append('<ul class="multiselect-container dropdown-menu' + (this.options.dropRight ? ' pull-right' : '') + '"></ul>');
if (this.options.buttonWidth) { if (this.options.buttonWidth) {
$('button', this.$container).css({ $('button', this.$container).css({
'width': this.options.buttonWidth 'width' : this.options.buttonWidth
}); });
} }
// Set max height of dropdown menu to activate auto scrollbar. // Set max height of dropdown menu to activate auto scrollbar.
if (this.options.maxHeight) { if (this.options.maxHeight) {
$('.multiselect-container', this.$container).css({ // TODO: Add a class for this option to move the css declarations.
'max-height': this.options.maxHeight + 'px', $('.multiselect-container', this.$container).css({
'overflow-y': 'auto', 'max-height' : this.options.maxHeight + 'px',
'overflow-x': 'hidden' 'overflow-y' : 'auto',
}); 'overflow-x' : 'hidden'
});
$('input[type="text"]', this.$container).width('75%'); }
}
// Enable filtering.
// Enable filtering. if (this.options.enableFiltering || this.options.enableCaseInsensitiveFiltering) {
if (this.options.enableFiltering || this.options.enableCaseInsensitiveFiltering) { this.buildFilter();
$('.multiselect-container', this.$container).prepend('<div class="input-prepend" style="padding:3px;"><span class="add-on"><i class="icon-search"></i></span><input class="multiselect-search" type="text" placeholder="' + this.options.filterPlaceholder + '"></div>'); }
$('.multiselect-search', this.$container).val(this.query).on('click', function (event) { this.buildDropdown();
event.stopPropagation(); this.updateButtonText();
}).on('keydown', $.proxy(function (event) {
// This is useful to catch "keydown" events after the browser has updated the control. this.$select.hide().after(this.$container);
clearTimeout(this.searchTimeout); };
this.searchTimeout = this.asyncFunction($.proxy(function () { Multiselect.prototype = {
if (this.query != event.target.value) { defaults : {
this.query = event.target.value; // Default text function will either print 'None selected' in case no
// option is selected, or a list of the selected options up to a length of 3 selected options.
$.each($('.multiselect-container li', this.$container), $.proxy(function(index, element) { // If more than 3 options are selected, the number of selected options is printed.
var value = $('input', element).val(); buttonText : function(options, select) {
if (value != this.options.selectAllValue) { if (options.length == 0) {
var text = $('label', element).text(); return 'None selected <b class="caret"></b>';
var value = $('input', element).val(); }
if (value && text && value != this.options.selectAllValue ) { else
// by default lets assume that element is not interesting for this search if (options.length > 3) {
var showElement = false; return options.length + ' selected <b class="caret"></b>';
var filterCandidate = ''; }
if ( (this.options.filterBehavior == 'text' || this.options.filterBehavior == 'both')) { else {
filterCandidate = text; var selected = '';
} options.each(function() {
if ( (this.options.filterBehavior == 'value' || this.options.filterBehavior == 'both')) { var label = ($(this).attr('label') !== undefined) ? $(this).attr('label') : $(this).text();
filterCandidate = value;
} selected += label + ', ';
if(this.options.enableCaseInsensitiveFiltering && filterCandidate.toLowerCase().indexOf(this.query.toLowerCase()) > -1) { });
showElement = true; return selected.substr(0, selected.length - 2) + ' <b class="caret"></b>';
} else if(filterCandidate.indexOf(this.query) > -1) { }
showElement = true; },
} // Is triggered on change of the selected options.
if (showElement) { onChange : function(option, checked) {
$(element).show();
} else { },
$(element).hide(); buttonClass : 'btn',
} dropRight : false,
} selectedClass : 'active',
} buttonWidth : 'auto',
}, this)); buttonContainer : '<div class="btn-group" />',
} // Maximum height of the dropdown menu.
}, this), 300, this); // If maximum height is exceeded a scrollbar will be displayed.
}, this)); maxHeight : false,
} includeSelectAllOption : false,
selectAllText : ' Select all',
this.buildDropdown(); selectAllValue : 'multiselect-all',
enableFiltering : false,
this.updateButtonText(); enableCaseInsensitiveFiltering : false,
filterPlaceholder : 'Search',
this.$select // possible options: 'text', 'value', 'both'
.hide() filterBehavior : 'text'
.after(this.$container); },
};
constructor : Multiselect,
Multiselect.prototype = {
// Will build an dropdown element for the given option.
defaults: { createOptionValue : function(element) {
// Default text function will either print 'None selected' in case no option is selected, if ($(element).is(':selected')) {
// or a list of the selected options up to a length of 3 selected options. $(element).attr('selected', 'selected').prop('selected', true);
// If more than 3 options are selected, the number of selected options is printed. }
buttonText: function(options, select) {
if (options.length == 0) { // Support the label attribute on options.
return 'None selected <b class="caret"></b>'; var label = $(element).attr('label') || $(element).text();
} var value = $(element).val();
else if (options.length > 3) { var inputType = this.options.multiple ? "checkbox" : "radio";
return options.length + ' selected <b class="caret"></b>';
} var $li = $('<li><a href="javascript:void(0);"><label><input type="' + inputType + '" /></label></a></li>');
else {
var selected = ''; var selected = $(element).prop('selected') || false;
options.each(function() { var $checkbox = $('input', $li);
var label = ($(this).attr('label') !== undefined) ? $(this).attr('label') : $(this).text(); $checkbox.val(value);
selected += label + ', '; if (value == this.options.selectAllValue) {
}); $checkbox.parent().parent().addClass('multiselect-all');
return selected.substr(0, selected.length -2) + ' <b class="caret"></b>'; }
}
}, $('label', $li).append(" " + label);
// Is triggered on change of the selected options.
onChange: function(option, checked) { $('.multiselect-container', this.$container).append($li);
}, if ($(element).is(':disabled')) {
buttonClass: 'btn', $checkbox.attr('disabled', 'disabled').prop('disabled', true).parents('li').addClass('disabled');
dropRight: false, }
selectedClass: 'active',
buttonWidth: 'auto', $checkbox.prop('checked', selected);
buttonContainer: '<div class="btn-group" />',
// Maximum height of the dropdown menu. if (selected && this.options.selectedClass) {
// If maximum height is exceeded a scrollbar will be displayed. $checkbox.parents('li').addClass(this.options.selectedClass);
maxHeight: false, }
includeSelectAllOption: false, },
selectAllText: ' Select all',
selectAllValue: 'multiselect-all', toggleActiveState : function(shouldBeActive) {
enableFiltering: false, if (this.$select.attr('disabled') == undefined) {
enableCaseInsensitiveFiltering: false, $('button.multiselect.dropdown-toggle', this.$container).removeClass('disabled');
filterPlaceholder: 'Search', }
filterBehavior: 'text' // possible options: 'text', 'value', 'both' else {
}, $('button.multiselect.dropdown-toggle', this.$container).addClass('disabled');
}
constructor: Multiselect, },
// Will build an dropdown element for the given option. // Build the dropdown and bind event handling.
createOptionValue: function(element) { buildDropdown : function() {
if ($(element).is(':selected')) { var alreadyHasSelectAll = this.$select[0][0] ? this.$select[0][0].value == this.options.selectAllValue : false;
$(element).attr('selected', 'selected').prop('selected', true);
} // If options.includeSelectAllOption === true, add the include all
// checkbox.
// Support the label attribute on options. if (this.options.includeSelectAllOption && this.options.multiple && !alreadyHasSelectAll) {
var label = $(element).attr('label') || $(element).text(); this.$select.prepend('<option value="' + this.options.selectAllValue + '">' + this.options.selectAllText + '</option>');
var value = $(element).val(); }
var inputType = this.options.multiple ? "checkbox" : "radio";
this.toggleActiveState();
var $li = $('<li><a href="javascript:void(0);" style="padding:0;"><label style="margin:0;padding:3px 20px 3px 20px;height:100%;cursor:pointer;"><input style="margin-bottom:5px;" type="' + inputType + '" /></label></a></li>');
this.$select.children().each($.proxy(function(index, element) {
var selected = $(element).prop('selected') || false; // Support optgroups and options without a group simultaneously.
var $checkbox = $('input', $li); var tag = $(element).prop('tagName').toLowerCase();
$checkbox.val(value); if (tag == 'optgroup') {
var group = element;
if (value == this.options.selectAllValue) { var groupName = $(group).prop('label');
$checkbox.parent().parent().addClass('multiselect-all');
} // Add a header for the group.
var $li = $('<li><label class="multiselect-group"></label></li>');
$('label', $li).append(" " + label); $('label', $li).text(groupName);
$('.multiselect-container', this.$container).append($li);
$('.multiselect-container', this.$container).append($li);
// Add the options of the group.
if ($(element).is(':disabled')) { $('option', group).each($.proxy(function(index, element) {
$checkbox.attr('disabled', 'disabled').prop('disabled', true).parents('li').addClass('disabled'); this.createOptionValue(element);
} }, this));
}
$checkbox.prop('checked', selected); else
if (tag == 'option') {
if (selected && this.options.selectedClass) { this.createOptionValue(element);
$checkbox.parents('li').addClass(this.options.selectedClass); }
} else {
}, // Ignore illegal tags.
}
toggleActiveState: function (shouldBeActive) { }, this));
if (this.$select.attr('disabled') == undefined) {
$('button.multiselect.dropdown-toggle', this.$container).removeClass('disabled'); // Bind the change event on the dropdown elements.
} $('.multiselect-container li input', this.$container).on('change', $.proxy(function(event) {
else { var checked = $(event.target).prop('checked') || false;
$('button.multiselect.dropdown-toggle', this.$container).addClass('disabled'); var isSelectAllOption = $(event.target).val() == this.options.selectAllValue;
}
}, // Apply or unapply the configured selected class.
if (this.options.selectedClass) {
// Build the dropdown and bind event handling. if (checked) {
buildDropdown: function () { $(event.target).parents('li').addClass(this.options.selectedClass);
var alreadyHasSelectAll = this.$select[0][0] ? this.$select[0][0].value == this.options.selectAllValue : false; }
else {
// If options.includeSelectAllOption === true, add the include all checkbox. $(event.target).parents('li').removeClass(this.options.selectedClass);
if (this.options.includeSelectAllOption && this.options.multiple && !alreadyHasSelectAll) { }
this.$select.prepend('<option value="' + this.options.selectAllValue + '">' + this.options.selectAllText + '</option>'); }
}
var $option = $('option', this.$select).filter(function() {
this.toggleActiveState(); return $(this).val() == $(event.target).val();
});
this.$select.children().each($.proxy(function (index, element) {
// Support optgroups and options without a group simultaneously. var $optionsNotThis = $('option', this.$select).not($option);
var tag = $(element).prop('tagName').toLowerCase(); var $checkboxesNotThis = $('input', this.$container).not($(event.target));
if (tag == 'optgroup') {
var group = element; // Toggle all options if the select all option was changed.
var groupName = $(group).prop('label'); if (isSelectAllOption) {
$checkboxesNotThis.filter(function() {
// Add a header for the group. return $(this).is(':checked') != checked;
var $li = $('<li><label style="margin:0;padding:3px 20px 3px 20px;height:100%;" class="multiselect-group"></label></li>'); }).trigger('click');
$('label', $li).text(groupName); }
$('.multiselect-container', this.$container).append($li);
if (checked) {
// Add the options of the group. $option.prop('selected', true);
$('option', group).each($.proxy(function (index, element) {
this.createOptionValue(element); if (this.options.multiple) {
}, this)); $option.attr('selected', 'selected');
} }
else if (tag == 'option') { else {
this.createOptionValue(element); if (this.options.selectedClass) {
} $($checkboxesNotThis).parents('li').removeClass(this.options.selectedClass);
else { }
// Ignore illegal tags.
} $($checkboxesNotThis).prop('checked', false);
}, this));
$optionsNotThis.removeAttr('selected').prop('selected', false);
// Bind the change event on the dropdown elements.
$('.multiselect-container li input', this.$container).on('change', $.proxy(function (event) { // It's a single selection, so close.
var checked = $(event.target).prop('checked') || false; $(this.$container).find(".multiselect.dropdown-toggle").click();
var isSelectAllOption = $(event.target).val() == this.options.selectAllValue; }
// Apply or unapply the configured selected class. if (this.options.selectedClass == "active") {
if (this.options.selectedClass) { $optionsNotThis.parents("a").css("outline", "");
if (checked) { }
$(event.target).parents('li').addClass(this.options.selectedClass);
} }
else { else {
$(event.target).parents('li').removeClass(this.options.selectedClass); $option.removeAttr('selected').prop('selected', false);
} }
}
this.updateButtonText();
var $option = $('option', this.$select).filter(function() {
return $(this).val() == $(event.target).val(); this.options.onChange($option, checked);
});
this.$select.change();
var $optionsNotThis = $('option', this.$select).not($option); }, this));
var $checkboxesNotThis = $('input', this.$container).not($(event.target));
$('.multiselect-container li a', this.$container).on('touchstart click', function(event) {
// Toggle all options if the select all option was changed. event.stopPropagation();
if (isSelectAllOption) { $(event.target).blur();
$checkboxesNotThis.filter(function () { return $(this).is(':checked') != checked; }).trigger('click'); });
}
// Keyboard support.
if (checked) { this.$container.on('keydown', $.proxy(function(event) {
$option.prop('selected', true); if ($('input[type="text"]', this.$container).is(':focus'))
return;
if (this.options.multiple) { if ((event.keyCode == 9 || event.keyCode == 27) && this.$container.hasClass('open')) {
$option.attr('selected', 'selected'); // Close on tab or escape.
} $(this.$container).find(".multiselect.dropdown-toggle").click();
else { }
if (this.options.selectedClass) { else {
$($checkboxesNotThis).parents('li').removeClass(this.options.selectedClass); var $items = $(this.$container).find("li:not(.divider):visible a");
}
if (!$items.length) {
$($checkboxesNotThis).prop('checked', false); return;
}
$optionsNotThis.removeAttr('selected').prop('selected', false);
var index = $items.index($items.filter(':focus'));
// It's a single selection, so close.
$(this.$container).find(".multiselect.dropdown-toggle").click(); // Navigation up.
} if (event.keyCode == 38 && index > 0) {
index--;
if (this.options.selectedClass == "active") { }
$optionsNotThis.parents("a").css("outline", ""); // Navigate down.
} else
if (event.keyCode == 40 && index < $items.length - 1) {
} index++;
else { }
$option.removeAttr('selected').prop('selected', false); else
} if (!~index) {
index = 0;
this.updateButtonText(); }
this.options.onChange($option, checked); var $current = $items.eq(index);
$current.focus();
this.$select.change();
}, this)); // Override style for items in li:active.
if (this.options.selectedClass == "active") {
$('.multiselect-container li a', this.$container).on('touchstart click', function (event) { $current.css("outline", "thin dotted #333").css("outline", "5px auto -webkit-focus-ring-color");
event.stopPropagation();
$(event.target).blur(); $items.not($current).css("outline", "");
}); }
// Keyboard support. if (event.keyCode == 32 || event.keyCode == 13) {
this.$container.on('keydown', $.proxy(function (event) { var $checkbox = $current.find('input');
if ($('input[type="text"]', this.$container).is(':focus')) return;
if ((event.keyCode == 9 || event.keyCode == 27) && this.$container.hasClass('open')) { $checkbox.prop("checked", !$checkbox.prop("checked"));
// Close on tab or escape. $checkbox.change();
$(this.$container).find(".multiselect.dropdown-toggle").click(); }
}
else { event.stopPropagation();
var $items = $(this.$container).find("li:not(.divider):visible a"); event.preventDefault();
}
if (!$items.length) { }, this));
return; },
}
// Build and bind filter.
var index = $items.index($items.filter(':focus')); buildFilter: function() {
$('.multiselect-container', this.$container).prepend('<div class="input-prepend"><span class="add-on"><i class="icon-search"></i></span><input class="multiselect-search" type="text" placeholder="' + this.options.filterPlaceholder + '"></div>');
// Navigation up.
if (event.keyCode == 38 && index > 0) { $('.multiselect-search', this.$container).val(this.query).on('click', function(event) {
index--; event.stopPropagation();
} }).on('keydown', $.proxy(function(event) {
// Navigate down. // This is useful to catch "keydown" events after the browser has
else if (event.keyCode == 40 && index < $items.length - 1) { // updated the control.
index++; clearTimeout(this.searchTimeout);
}
else if (!~index) { this.searchTimeout = this.asyncFunction($.proxy(function() {
index = 0;
} if (this.query != event.target.value) {
this.query = event.target.value;
var $current = $items.eq(index);
$current.focus(); $.each($('.multiselect-container li', this.$container), $.proxy(function(index, element) {
var value = $('input', element).val();
// Override style for items in li:active. if (value != this.options.selectAllValue) {
if (this.options.selectedClass == "active") { var text = $('label', element).text();
$current.css("outline", "thin dotted #333").css("outline", "5px auto -webkit-focus-ring-color"); var value = $('input', element).val();
if (value && text && value != this.options.selectAllValue) {
$items.not($current).css("outline", ""); // by default lets assume that element is not
} // interesting for this search
var showElement = false;
if (event.keyCode == 32 || event.keyCode == 13) {
var $checkbox = $current.find('input'); var filterCandidate = '';
if ((this.options.filterBehavior == 'text' || this.options.filterBehavior == 'both')) {
$checkbox.prop("checked", !$checkbox.prop("checked")); filterCandidate = text;
$checkbox.change(); }
} if ((this.options.filterBehavior == 'value' || this.options.filterBehavior == 'both')) {
filterCandidate = value;
event.stopPropagation(); }
event.preventDefault();
} if (this.options.enableCaseInsensitiveFiltering && filterCandidate.toLowerCase().indexOf(this.query.toLowerCase()) > -1) {
}, this)); showElement = true;
}, }
else if (filterCandidate.indexOf(this.query) > -1) {
// Destroy - unbind - the plugin. showElement = true;
destroy: function() { }
this.$container.remove();
this.$select.show(); if (showElement) {
}, $(element).show();
}
// Refreshs the checked options based on the current state of the select. else {
refresh: function() { $(element).hide();
$('option', this.$select).each($.proxy(function(index, element) { }
var $input = $('.multiselect-container li input', this.$container).filter(function () { }
return $(this).val() == $(element).val(); }
}); }, this));
}
if ($(element).is(':selected')) { }, this), 300, this);
$input.prop('checked', true); }, this));
},
if (this.options.selectedClass) {
$input.parents('li').addClass(this.options.selectedClass); // Destroy - unbind - the plugin.
} destroy : function() {
} this.$container.remove();
else { this.$select.show();
$input.prop('checked', false); },
if (this.options.selectedClass) { // Refreshs the checked options based on the current state of the select.
$input.parents('li').removeClass(this.options.selectedClass); refresh : function() {
} $('option', this.$select).each($.proxy(function(index, element) {
} var $input = $('.multiselect-container li input', this.$container).filter(function() {
return $(this).val() == $(element).val();
if ($(element).is(":disabled")) { });
$input.attr('disabled', 'disabled').prop('disabled', true).parents('li').addClass('disabled');
} if ($(element).is(':selected')) {
else { $input.prop('checked', true);
$input.removeAttr('disabled').prop('disabled', false).parents('li').removeClass('disabled');
} if (this.options.selectedClass) {
}, this)); $input.parents('li').addClass(this.options.selectedClass);
}
this.updateButtonText(); }
}, else {
$input.prop('checked', false);
// Select an option by its value.
select: function(value) { if (this.options.selectedClass) {
var $option = $('option', this.$select).filter(function () { $input.parents('li').removeClass(this.options.selectedClass);
return $(this).val() == value; }
}); }
var $checkbox = $('.multiselect-container li input', this.$container).filter(function () {
return $(this).val() == value; if ($(element).is(":disabled")) {
}); $input.attr('disabled', 'disabled').prop('disabled', true).parents('li').addClass('disabled');
}
if (this.options.selectedClass) { else {
$checkbox.parents('li').addClass(this.options.selectedClass); $input.removeAttr('disabled').prop('disabled', false).parents('li').removeClass('disabled');
} }
}, this));
$checkbox.prop('checked', true);
this.updateButtonText();
$option.attr('selected', 'selected').prop('selected', true); },
this.updateButtonText(); // Select an option by its value.
this.options.onChange($option, checked); select : function(value) {
}, var $option = $('option', this.$select).filter(function() {
return $(this).val() == value;
// Deselect an option by its value. });
deselect: function(value) { var $checkbox = $('.multiselect-container li input', this.$container).filter(function() {
var $option = $('option', this.$select).filter(function () { return $(this).val() == value;
return $(this).val() == value; });
});
var $checkbox = $('.multiselect-container li input', this.$container).filter(function () { if (this.options.selectedClass) {
return $(this).val() == value; $checkbox.parents('li').addClass(this.options.selectedClass);
}); }
if (this.options.selectedClass) { $checkbox.prop('checked', true);
$checkbox.parents('li').removeClass(this.options.selectedClass);
} $option.attr('selected', 'selected').prop('selected', true);
$checkbox.prop('checked', false); this.updateButtonText();
this.options.onChange($option, checked);
$option.removeAttr('selected').prop('selected', false); },
this.updateButtonText(); // Deselect an option by its value.
}, deselect : function(value) {
var $option = $('option', this.$select).filter(function() {
// Rebuild the whole dropdown menu. return $(this).val() == value;
rebuild: function() { });
$('.multiselect-container', this.$container).html(''); var $checkbox = $('.multiselect-container li input', this.$container).filter(function() {
this.buildDropdown(this.$select, this.options); return $(this).val() == value;
this.updateButtonText(); });
},
if (this.options.selectedClass) {
// Get options by merging defaults and given options. $checkbox.parents('li').removeClass(this.options.selectedClass);
getOptions: function(options) { }
return $.extend({}, this.defaults, options);
}, $checkbox.prop('checked', false);
updateButtonText: function() { $option.removeAttr('selected').prop('selected', false);
var options = this.getSelected();
$('button', this.$container).html(this.options.buttonText(options, this.$select)); this.updateButtonText();
}, },
// Get all selected options. // Rebuild the whole dropdown menu.
getSelected: function () { rebuild : function() {
return $('option:selected[value!="' + this.options.selectAllValue + '"]', this.$select); $('.multiselect-container', this.$container).html('');
}, this.buildDropdown(this.$select, this.options);
this.updateButtonText();
updateOriginalOptions: function() {
this.originalOptions = this.$select.clone()[0].options; // Enable filtering.
}, if (this.options.enableFiltering || this.options.enableCaseInsensitiveFiltering) {
this.buildFilter();
asyncFunction: function (callback, timeout, self) { }
var args = Array.prototype.slice.call(arguments, 3); },
return setTimeout(function () {
callback.apply(self || window, args); // Get options by merging defaults and given options.
}, timeout); getOptions : function(options) {
} return $.extend({}, this.defaults, options);
}; },
updateButtonText : function() {
var options = this.getSelected();
$('button', this.$container).html(this.options.buttonText(options, this.$select));
},
// Get all selected options.
getSelected : function() {
return $('option:selected[value!="' + this.options.selectAllValue + '"]', this.$select);
},
updateOriginalOptions : function() {
this.originalOptions = this.$select.clone()[0].options;
},
asyncFunction : function(callback, timeout, self) {
var args = Array.prototype.slice.call(arguments, 3);
return setTimeout(function() {
callback.apply(self || window, args);
}, timeout);
}
};
$.fn.multiselect = function(option, parameter) { $.fn.multiselect = function(option, parameter) {
return this.each(function() { return this.each(function() {
var data = $(this).data('multiselect'), var data = $(this).data('multiselect'), options = typeof option == 'object' && option;
options = typeof option == 'object' && option;
// Initialize the multiselect. // Initialize the multiselect.
if (!data) { if (!data) {
$(this).data('multiselect', (data = new Multiselect(this, options))); $(this).data('multiselect', ( data = new Multiselect(this, options)));
} }
// Call multiselect method. // Call multiselect method.
if (typeof option == 'string') { if ( typeof option == 'string') {
data[option](parameter); data[option](parameter);
} }
}); });
}; };
$.fn.multiselect.Constructor = Multiselect; $.fn.multiselect.Constructor = Multiselect;
$(function() { $(function() {
$("select[data-role=multiselect]").multiselect(); $("select[data-role=multiselect]").multiselect();
}); });
}(window.jQuery); }(window.jQuery);
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
<meta name="copyright" content="David Stutz" /> <meta name="copyright" content="David Stutz" />
<link rel="stylesheet" href="css/bootstrap-3.3.2.min.css" type="text/css"> <link rel="stylesheet" href="css/bootstrap-3.3.2.min.css" type="text/css">
<link rel="stylesheet" href="css/bootstrap-multiselect.css" type="text/css">
<link rel="stylesheet" href="css/prettify.css" type="text/css"> <link rel="stylesheet" href="css/prettify.css" type="text/css">
<script type="text/javascript" src="js/jquery-2.0.1.min.js"></script> <script type="text/javascript" src="js/jquery-2.0.1.min.js"></script>
......
.multiselect-container {
position: absolute;
list-style-type: none;
margin: 0;
padding: 0;
input[type="text"] {
width: 70%;
}
.input-prepend {
padding: 3px;
}
> li {
padding: 0;
> label {
margin: 0;
padding: 3px 20px 3px 20px;
height: 100%;
cursor: pointer;
&.multiselect-header {
margin: 0;
padding: 3px 20px 3px 20px;
height: 100%;
}
> input[type="checkbox"] {
margin-bottom:5px;
}
}
}
}
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