Commit 92d46ae3 authored by David Stutz's avatar David Stutz

Merge pull request #68 from luisrudge/filtering

Added filtering capability.
parents 726d4702 9b88602f
...@@ -196,6 +196,14 @@ Define if the menu should drop to the right of the button or not, by adding `pul ...@@ -196,6 +196,14 @@ Define if the menu should drop to the right of the button or not, by adding `pul
Define if a `<option value="select-all-option"> Select all</option>` should be appended at the beginning of the options list. When this item is clicked, it will check/uncheck other items. This only works when `multiple="multiple"` is enabled. Default is false. Define if a `<option value="select-all-option"> Select all</option>` should be appended at the beginning of the options list. When this item is clicked, it will check/uncheck other items. This only works when `multiple="multiple"` is enabled. Default is false.
**enableFiltering**
Define if a text input should be created to filter results. Note that 'select all' option will select all **FILTERED** options. Default is false.
**filterPlaceholder**
Define the placeholder for the text input above. Note that 'select all' option will select all **FILTERED** options. Default is false.
**onChange** **onChange**
Assign an event handler to the change event: Assign an event handler to the change event:
......
This diff is collapsed.
...@@ -47,12 +47,55 @@ ...@@ -47,12 +47,55 @@
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.getFilteredOptions = function () {
if (this.query == '') return this.originalOptions;
var query = this.query;
return $(this.originalOptions).filter(function () {
return this.text.substring(0, query.length) == query
});
};
this.query = '';
this.searchTimeout = null;
this.asyncFunction = function (callback, timeout, self) {
var args = Array.prototype.slice.call(arguments, 3);
return setTimeout(function () {
callback.apply(self || window, args);
}, timeout);
};
this.options.multiple = this.$select.attr('multiple') == "multiple"; this.options.multiple = this.$select.attr('multiple') == "multiple";
this.$container = $(this.options.buttonContainer) 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('<button type="button" class="multiselect dropdown-toggle ' + this.options.buttonClass + '" data-toggle="dropdown">' + this.options.buttonText(this.getSelected(), this.$select) + '</button>')
.append('<ul class="dropdown-menu' + (this.options.dropRight ? ' pull-right' : '') + '"></ul>'); .append('<div id="dropdown-container" class="dropdown-menu" style="position:absolute;"><ul style="list-style-type: none;margin:0;padding:0;"></ul></div>');
if (this.options.enableFiltering) {
$('#dropdown-container', this.$container).prepend('<div class="input-prepend" style="padding:3px;"><span class="add-on"><i class="icon-search"></i></span><input id="multiselect-default-search" type="text" placeholder="' + this.options.filterPlaceholder + '"></div>');
$('#multiselect-default-search', this.$container).val(this.query).click(function (event) {
event.stopPropagation();
}).keydown($.proxy(function (event) {
// This is useful to catch "keydown" events after the browser has updated the control
clearTimeout(this.searchTimeout);
this.searchTimeout = this.asyncFunction($.proxy(function () {
var inputValue = event.target.value;
if (inputValue != this.query) {
this.query = inputValue;
this.$select.empty();
var filteredValues = this.getFilteredOptions();
var newOptions = '';
for (var i = 0; i < filteredValues.length; i++) {
var option = filteredValues[i];
newOptions += '<option value="'+option.value+'">'+option.text+'</option>';
}
this.$select.html(newOptions);
this.rebuild();
}
}, this), 300, this);
}, this));
}
if (this.options.buttonWidth) { if (this.options.buttonWidth) {
$('button', this.$container).css({ $('button', this.$container).css({
...@@ -62,11 +105,13 @@ ...@@ -62,11 +105,13 @@
// 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) {
$('ul', this.$container).css({ $('#dropdown-container ul', this.$container).css({
'max-height': this.options.maxHeight + 'px', 'max-height': this.options.maxHeight + 'px',
'overflow-y': 'auto', 'overflow-y': 'auto',
'overflow-x': 'hidden' 'overflow-x': 'hidden'
}); });
$('input[type="text"]', this.$container).width('75%');
} }
this.buildDropdown(); this.buildDropdown();
...@@ -114,7 +159,9 @@ ...@@ -114,7 +159,9 @@
// If maximum height is exceeded a scrollbar will be displayed. // If maximum height is exceeded a scrollbar will be displayed.
maxHeight: false, maxHeight: false,
includeSelectAllOption: false, includeSelectAllOption: false,
selectAllText: ' Select all' selectAllText: ' Select all',
enableFiltering: false,
filterPlaceholder: 'Search'
}, },
constructor: Multiselect, constructor: Multiselect,
...@@ -138,7 +185,7 @@ ...@@ -138,7 +185,7 @@
if (value == 'select-all-option') $checkbox.parent().parent().addClass('select-all-option'); if (value == 'select-all-option') $checkbox.parent().parent().addClass('select-all-option');
$('label', $li).append(" " + label); $('label', $li).append(" " + label);
$('ul', this.$container).append($li); $('#dropdown-container ul', this.$container).append($li);
if ($(element).is(':disabled')) { if ($(element).is(':disabled')) {
$checkbox.attr('disabled', 'disabled').prop('disabled', true).parents('li').addClass('disabled'); $checkbox.attr('disabled', 'disabled').prop('disabled', true).parents('li').addClass('disabled');
...@@ -169,7 +216,7 @@ ...@@ -169,7 +216,7 @@
// Add a header for the group. // Add a header for the group.
var $li = $('<li><label style="margin:0;padding:3px 20px 3px 20px;height:100%;" class="multiselect-group"></label></li>'); var $li = $('<li><label style="margin:0;padding:3px 20px 3px 20px;height:100%;" class="multiselect-group"></label></li>');
$('label', $li).text(groupName); $('label', $li).text(groupName);
$('ul', this.$container).append($li); $('#dropdown-container ul', this.$container).append($li);
// Add the options of the group. // Add the options of the group.
$('option', group).each($.proxy(function (index, element) { $('option', group).each($.proxy(function (index, element) {
...@@ -185,7 +232,7 @@ ...@@ -185,7 +232,7 @@
}, this)); }, this));
// Bind the change event on the dropdown elements. // Bind the change event on the dropdown elements.
$('ul li input', this.$container).on('change', $.proxy(function(event) { $('#dropdown-container ul li input', this.$container).on('change', $.proxy(function (event) {
var checked = $(event.target).prop('checked') || false; var checked = $(event.target).prop('checked') || false;
var isSelectAllOption = $(event.target).val() == 'select-all-option'; var isSelectAllOption = $(event.target).val() == 'select-all-option';
...@@ -243,12 +290,13 @@ ...@@ -243,12 +290,13 @@
this.$select.change(); this.$select.change();
}, this)); }, this));
$('ul li a', this.$container).on('touchstart click', function(event) { $('#dropdown-container ul li a', this.$container).on('touchstart click', function (event) {
event.stopPropagation(); event.stopPropagation();
}); });
// Keyboard support. // Keyboard support.
this.$container.on('keydown', $.proxy(function(event) { this.$container.on('keydown', $.proxy(function (event) {
if ($('input[type="text"]', this.$container).is(':focus')) return;
if ((event.keyCode == 9 || event.keyCode == 27) && this.$container.hasClass('open')) { if ((event.keyCode == 9 || event.keyCode == 27) && this.$container.hasClass('open')) {
// Close on tab or escape. // Close on tab or escape.
$(this.$container).find(".multiselect.dropdown-toggle").click(); $(this.$container).find(".multiselect.dropdown-toggle").click();
...@@ -306,7 +354,7 @@ ...@@ -306,7 +354,7 @@
// Refreshs the checked options based on the current state of the select. // Refreshs the checked options based on the current state of the select.
refresh: function() { refresh: function() {
$('option', this.$select).each($.proxy(function(index, element) { $('option', this.$select).each($.proxy(function(index, element) {
var $input = $('ul li input', this.$container).filter(function () { var $input = $('#dropdown-container ul li input', this.$container).filter(function () {
return $(this).val() == $(element).val(); return $(this).val() == $(element).val();
}); });
...@@ -339,7 +387,7 @@ ...@@ -339,7 +387,7 @@
// Select an option by its value. // Select an option by its value.
select: function(value) { select: function(value) {
var $option = $('option', this.$select).filter(function () { return $(this).val() == value; }); var $option = $('option', this.$select).filter(function () { return $(this).val() == value; });
var $checkbox = $('ul li input', this.$container).filter(function () { return $(this).val() == value; }); var $checkbox = $('#dropdown-container ul li input', this.$container).filter(function () { return $(this).val() == value; });
if (this.options.selectedClass) { if (this.options.selectedClass) {
$checkbox.parents('li').addClass(this.options.selectedClass); $checkbox.parents('li').addClass(this.options.selectedClass);
...@@ -355,7 +403,7 @@ ...@@ -355,7 +403,7 @@
// Deselect an option by its value. // Deselect an option by its value.
deselect: function(value) { deselect: function(value) {
var $option = $('option', this.$select).filter(function () { return $(this).val() == value; }); var $option = $('option', this.$select).filter(function () { return $(this).val() == value; });
var $checkbox = $('ul li input', this.$container).filter(function () { return $(this).val() == value; }); var $checkbox = $('#dropdown-container ul li input', this.$container).filter(function () { return $(this).val() == value; });
if (this.options.selectedClass) { if (this.options.selectedClass) {
$checkbox.parents('li').removeClass(this.options.selectedClass); $checkbox.parents('li').removeClass(this.options.selectedClass);
...@@ -370,7 +418,7 @@ ...@@ -370,7 +418,7 @@
// Rebuild the whole dropdown menu. // Rebuild the whole dropdown menu.
rebuild: function() { rebuild: function() {
$('ul', this.$container).html(''); $('#dropdown-container ul', this.$container).html('');
this.buildDropdown(this.$select, this.options); this.buildDropdown(this.$select, this.options);
this.updateButtonText(); this.updateButtonText();
}, },
......
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