bootstrap-multiselect.0.9.13.js revision 9f5d362439ba3ff6d3ac9019482b117474d8b20b
/**
* Bootstrap Multiselect (https://github.com/davidstutz/bootstrap-multiselect)
*
* Apache License, Version 2.0:
* Copyright (c) 2012 - 2015 David Stutz
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a
* copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
* BSD 3-Clause License:
* Copyright (c) 2012 - 2015 David Stutz
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* - Neither the name of David Stutz nor the names of its contributors may be
* used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
!function ($) {
"use strict";// jshint ;_;
read: function() {
options();
setTimeout(function() {
if (ms)
}, 1);
},
});
}
}
//value and selectedOptions are two-way, so these will be triggered even by our own actions.
//It needs some way to tell if they are triggered because of us or because of outside change.
//It doesn't loop but it's a waste of processing.
read: function() {
value();
setTimeout(function() {
}, 1);
},
}
}
//Switched from arrayChange subscription to general subscription using 'refresh'.
//Not sure performance is any better using 'select' and 'deselect'.
read: function() {
setTimeout(function() {
}, 1);
},
}
}
});
},
}
};
}
}
}
/**
* Constructor to create a new multiselect using the given select.
*
* @param {jQuery} select
* @param {Object} options
* @returns {Multiselect}
*/
// Placeholder via data attributes
}
// Initialization.
// We have to clone to create a new reference.
this.query = '';
this.searchTimeout = null;
this.lastToggledInput = null
// Build select all if enabled.
this.buildContainer();
this.buildButton();
this.buildDropdown();
this.buildSelectAll();
this.buildDropdownOptions();
this.buildFilter();
this.updateButtonText();
this.updateSelectAll();
this.disable();
}
};
Multiselect.prototype = {
defaults: {
/**
* 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.
*
* @param {jQuery} options
* @param {jQuery} select
* @returns {String}
*/
return this.nonSelectedText;
}
else if (this.allSelectedText
&& this.multiple) {
if (this.selectAllNumber) {
}
else {
return this.allSelectedText;
}
}
}
else {
var selected = '';
var delimiter = this.delimiterText;
});
}
},
/**
* Updates the title of the button similar to the buttonText function.
*
* @param {jQuery} options
* @param {jQuery} select
* @returns {@exp;selected@call;substr}
*/
return this.nonSelectedText;
}
else {
var selected = '';
var delimiter = this.delimiterText;
});
}
},
/**
* Create a label.
*
* @param {jQuery} element
* @returns {String}
*/
optionLabel: function(element){
},
/**
* Triggered on change of the multiselect.
*
* Not triggered when selecting/deselecting options manually.
*
* @param {jQuery} option
* @param {Boolean} checked
*/
},
/**
* Triggered when the dropdown is shown.
*
* @param {jQuery} event
*/
onDropdownShow: function(event) {
},
/**
* Triggered when the dropdown is hidden.
*
* @param {jQuery} event
*/
onDropdownHide: function(event) {
},
/**
* Triggered after the dropdown is shown.
*
* @param {jQuery} event
*/
onDropdownShown: function(event) {
},
/**
* Triggered after the dropdown is hidden.
*
* @param {jQuery} event
*/
onDropdownHidden: function(event) {
},
/**
* Triggered on select all.
*/
onSelectAll: function() {
},
enableHTML: false,
buttonClass: 'btn btn-default',
inheritClass: false,
buttonWidth: 'auto',
buttonContainer: '<div class="btn-group" />',
dropRight: false,
selectedClass: 'active',
// Maximum height of the dropdown menu.
// If maximum height is exceeded a scrollbar will be displayed.
maxHeight: false,
checkboxName: false,
includeSelectAllOption: false,
selectAllText: ' Select all',
selectAllValue: 'multiselect-all',
selectAllName: false,
selectAllNumber: true,
enableFiltering: false,
enableCaseInsensitiveFiltering: false,
enableClickableOptGroups: false,
filterPlaceholder: 'Search',
// possible options: 'text', 'value', 'both'
filterBehavior: 'text',
includeFilterClearBtn: true,
preventInputChangeEvent: false,
nonSelectedText: 'None selected',
nSelectedText: 'selected',
allSelectedText: 'All selected',
numberDisplayed: 3,
disableIfEmpty: false,
delimiterText: ', ',
templates: {
button: '<button type="button" class="multiselect dropdown-toggle" data-toggle="dropdown"><span class="multiselect-selected-text"></span> <b class="caret"></b></button>',
ul: '<ul class="multiselect-container dropdown-menu"></ul>',
filter: '<li class="multiselect-item filter"><div class="input-group"><span class="input-group-addon"><i class="glyphicon glyphicon-search"></i></span><input class="form-control multiselect-search" type="text"></div></li>',
filterClearBtn: '<span class="input-group-btn"><button class="btn btn-default multiselect-clear-filter" type="button"><i class="glyphicon glyphicon-remove-circle"></i></button></span>',
li: '<li><a tabindex="0"><label></label></a></li>',
divider: '<li class="multiselect-item divider"></li>',
liGroup: '<li class="multiselect-item multiselect-group"><label></label></li>'
}
},
/**
* Builds the container of the multiselect.
*/
buildContainer: function() {
},
/**
* Builds the button of the multiselect.
*/
buildButton: function() {
}
// Adopt active state.
this.disable();
}
else {
this.enable();
}
// Manually add button width if set.
'overflow' : 'hidden',
'text-overflow' : 'ellipsis'
});
this.$container.css({
});
}
// Keep the tab index from the select.
if (tabindex) {
}
},
/**
* Builds the ul representing the dropdown menu.
*/
buildDropdown: function() {
// Build ul.
}
// Set max height of dropdown menu to activate auto scrollbar.
// TODO: Add a class for this option to move the css declarations.
'overflow-y': 'auto',
'overflow-x': 'hidden'
});
}
},
/**
* Build the dropdown options and binds all nessecary events.
*
* Uses createDivider and createOptionValue to create the necessary options.
*/
buildDropdownOptions: function() {
// Support optgroups and options without a group simultaneously.
.toLowerCase();
return;
}
if (tag === 'optgroup') {
this.createOptgroup(element);
}
else if (tag === 'option') {
this.createDivider();
}
else {
this.createOptionValue(element);
}
}
// Other illegal tags will be ignored.
}, this));
// Bind the change event on the dropdown elements.
// Apply or unapply the configured selected class.
if (this.options.selectedClass) {
if (checked) {
}
else {
}
}
// Get the corresponding option.
if (isSelectAllOption) {
if (checked) {
this.selectAll();
}
else {
this.deselectAll();
}
}
if(!isSelectAllOption){
if (checked) {
// Simply select additional option.
}
else {
// Unselect all other options and corresponding checkboxes.
if (this.options.selectedClass) {
}
// It's a single selection, so close.
}
}
}
else {
// Unselect option.
}
}
this.updateButtonText();
this.updateSelectAll();
if(this.options.preventInputChangeEvent) {
return false;
}
}, this));
if (e.shiftKey) {
// Prevent selecting text by Shift+click
return false;
}
});
if($target.is("label")){ // Handles checkbox selection manually (see https://github.com/davidstutz/bootstrap-multiselect/issues/431)
}
if (this.lastToggledInput !== null && this.lastToggledInput !== $target) { // Make sure we actually have a range
}
// Make sure we grab all elements since slice excludes the last index
++to;
// Change the checkboxes and underlying options
if (this.options.selectedClass) {
}
}
}
// Trigger the select "change" event
}
// Remembers last clicked option
this.lastToggledInput = $target;
}
}, this));
// Keyboard support.
return;
}
}
else {
return;
}
// Navigation up.
index--;
}
// Navigate down.
index++;
}
else if (!~index) {
index = 0;
}
}
}
}, this));
// Search all option in optgroup
// check or uncheck items
var allChecked = true;
optionInputs.each(function() {
});
}, this));
}
},
/**
* Create an option using the given select option.
*
* @param {jQuery} element
*/
createOptionValue: function(element) {
}
// Support the label attribute on options.
if (this.options.enableHTML) {
}
else {
}
if (this.options.checkboxName) {
}
.addClass('multiselect-all');
}
.prop('disabled', true)
.closest('a')
.closest('li')
.addClass('disabled');
}
}
},
/**
* Creates a divider using the given select option.
*
* @param {jQuery} element
*/
createDivider: function(element) {
},
/**
* Creates an optgroup.
*
* @param {jQuery} group
*/
createOptgroup: function(group) {
// Add a header for the group.
if (this.options.enableHTML) {
}
else {
}
if (this.options.enableClickableOptGroups) {
}
}
// Add the options of the group.
this.createOptionValue(element);
}, this));
},
/**
* Build the selct all.
*
* Checks if a select all has already been created.
*/
buildSelectAll: function() {
}
var alreadyHasSelectAll = this.hasSelectAll();
// Check whether to add a divider after the select all.
if (this.options.includeSelectAllDivider) {
}
if (this.options.enableHTML) {
}
else {
}
if (this.options.selectAllName) {
}
else {
}
.addClass('multiselect-all');
}
},
/**
* Builds the filter.
*/
buildFilter: function() {
// Build filter if filtering OR case insensitive filtering is enabled and the number of options exceeds (or equals) enableFilterLength.
var enableFilterLength = Math.max(this.options.enableFiltering, this.options.enableCaseInsensitiveFiltering);
// Adds optional filter clear button
if(this.options.includeFilterClearBtn){
clearTimeout(this.searchTimeout);
this.updateSelectAll();
}, this));
}
// Cancel enter key default behaviour
}
// This is useful to catch "keydown" events after the browser has updated the control.
clearTimeout(this.searchTimeout);
var filterCandidate = '';
}
}
}
// By default lets assume that element is not
// interesting for this search.
var showElement = false;
if (this.options.enableCaseInsensitiveFiltering && filterCandidate.toLowerCase().indexOf(this.query.toLowerCase()) > -1) {
showElement = true;
}
showElement = true;
}
// Toggle current element (group or group item) according to showElement boolean.
// Differentiate groups and group items.
// Remember group status.
}
else {
// Show group name when at least one of its items is visible.
if (showElement) {
}
// Show all group items when group name satisfies filter.
if (!showElement && currentGroupVisible) {
}
}
}
}, this));
}
this.updateSelectAll();
}, this), 300, this);
}, this));
}
}
},
/**
* Unbinds the whole plugin.
*/
destroy: function() {
this.$container.remove();
},
/**
* Refreshs the multiselect based on the selected options of the select.
*/
refresh: function() {
});
if (this.options.selectedClass) {
}
}
else {
if (this.options.selectedClass) {
}
}
.prop('disabled', true)
.closest('li')
.addClass('disabled');
}
else {
.closest('li')
.removeClass('disabled');
}
}, this));
this.updateButtonText();
this.updateSelectAll();
},
/**
* Select all options of the given values.
*
* If triggerOnChange is set to true, the on change event is triggered if
* and only if one value is passed.
*
* @param {Array} selectValues
* @param {Boolean} triggerOnChange
*/
if(!$.isArray(selectValues)) {
selectValues = [selectValues];
}
var value = selectValues[i];
continue;
}
continue;
}
this.deselectAll(false);
}
if (this.options.selectedClass) {
}
if (triggerOnChange) {
}
}
this.updateButtonText();
this.updateSelectAll();
},
/**
* Clears all selected items.
*/
clearSelection: function () {
this.deselectAll(false);
this.updateButtonText();
this.updateSelectAll();
},
/**
* Deselects all options of the given values.
*
* If triggerOnChange is set to true, the on change event is triggered, if
* and only if one value is passed.
*
* @param {Array} deselectValues
* @param {Boolean} triggerOnChange
*/
if(!$.isArray(deselectValues)) {
}
var value = deselectValues[i];
continue;
}
continue;
}
if (this.options.selectedClass) {
}
if (triggerOnChange) {
}
}
this.updateButtonText();
this.updateSelectAll();
},
/**
* Selects all enabled & visible options.
*
* If justVisible is true or not specified, only visible options are selected.
*
* @param {Boolean} justVisible
* @param {Boolean} triggerOnSelectAll
*/
if(justVisible) {
$("li:not(.divider):not(.disabled)", this.$ul).filter(":visible").addClass(this.options.selectedClass);
}
else {
}
}
else {
return $(this).val();
}).get();
}).prop('selected', true);
}
if (triggerOnSelectAll) {
this.options.onSelectAll();
}
},
/**
* Deselects all options.
*
* If justVisible is true or not specified, only visible options are deselected.
*
* @param {Boolean} justVisible
*/
deselectAll: function (justVisible) {
if(justVisible) {
return $(this).val();
}).get();
}).prop('selected', false);
if (this.options.selectedClass) {
$("li:not(.divider):not(.disabled)", this.$ul).filter(":visible").removeClass(this.options.selectedClass);
}
}
else {
if (this.options.selectedClass) {
}
}
},
/**
* Rebuild the plugin.
*
* Rebuilds the dropdown, the filter and the select all option.
*/
rebuild: function() {
// Important to distinguish between radios and checkboxes.
this.buildSelectAll();
this.buildDropdownOptions();
this.buildFilter();
this.updateButtonText();
this.updateSelectAll();
this.disable();
}
else {
this.enable();
}
}
},
/**
* The provided data will be used to build the dropdown.
*/
dataprovider: function(dataprovider) {
var groupCounter = 0;
var $tag;
groupCounter++;
});
}));
});
}
else {
});
}
});
this.rebuild();
},
/**
* Enable the multiselect.
*/
enable: function() {
.removeClass('disabled');
},
/**
* Disable the multiselect.
*/
disable: function() {
.addClass('disabled');
},
/**
* Set the options.
*
* @param {Array} options
*/
setOptions: function(options) {
},
/**
* Merges the given options with the default options.
*
* @param {Array} options
* @returns {Array}
*/
mergeOptions: function(options) {
},
/**
* Checks whether a select all checkbox is present.
*
* @returns {Boolean}
*/
hasSelectAll: function() {
},
/**
* Updates the select all checkbox based on the currently displayed and selected checkboxes.
*/
updateSelectAll: function() {
if (this.hasSelectAll()) {
this.options.onSelectAll();
}
else {
}
}
},
/**
* Update the button text and its title based on the currently selected options.
*/
updateButtonText: function() {
var options = this.getSelected();
// First update the displayed button text.
if (this.options.enableHTML) {
$('.multiselect .multiselect-selected-text', this.$container).html(this.options.buttonText(options, this.$select));
}
else {
$('.multiselect .multiselect-selected-text', this.$container).text(this.options.buttonText(options, this.$select));
}
// Now update the title attribute of the button.
},
/**
* Get all selected options.
*
* @returns {jQUery}
*/
getSelected: function() {
},
/**
* Gets a select option by its value.
*
* @param {String} value
* @returns {jQuery}
*/
getOptionByValue: function (value) {
return $(option);
}
}
},
/**
*
* @param {String} value
* @returns {jQuery}
*/
getInputByValue: function (value) {
var checkbox = checkboxes[i];
return $(checkbox);
}
}
},
/**
* Used for knockout integration.
*/
updateOriginalOptions: function() {
},
return setTimeout(function() {
}, timeout);
},
setAllSelectedText: function(allSelectedText) {
this.updateButtonText();
}
};
return this.each(function() {
// Initialize the multiselect.
if (!data) {
}
// Call multiselect method.
if (typeof option === 'string') {
if (option === 'destroy') {
$(this).data('multiselect', false);
}
}
});
};
$(function() {
$("select[data-role=multiselect]").multiselect();
});