From 82b3ef8448078af0f08c3a6bd234768cd87bb019 Mon Sep 17 00:00:00 2001 From: lindski Date: Fri, 25 Sep 2015 11:05:38 +0100 Subject: [PATCH] Updated widget so jquery and associated plug ins play nice with other widgets --- dist/BootstrapMultiSelectForMendix.mpk | Bin 152072 -> 154307 bytes .../lib/bootstrap-multiselect.js | 2671 +++++------ .../lib/bootstrap.js | 4138 +++++++++-------- .../lib/jqwrapper.js | 6 + .../widget/BootstrapMultiSelect.js | 33 +- .../widgets/BootstrapMultiSelectForMendix.mpk | Bin 152072 -> 154307 bytes 6 files changed, 3446 insertions(+), 3402 deletions(-) create mode 100644 src/BootstrapMultiSelectForMendix/lib/jqwrapper.js diff --git a/dist/BootstrapMultiSelectForMendix.mpk b/dist/BootstrapMultiSelectForMendix.mpk index 735664ac2d5ccaa5775dbb2ff95a96792e0d6988..fdf6ee568ad01216588c090c59ac8b187394f011 100644 GIT binary patch delta 38127 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 V`c{L0fbzOh5MO`RhXbyy{{gT{g3|y1 delta 35961 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 F>_1(e^>_dP diff --git a/src/BootstrapMultiSelectForMendix/lib/bootstrap-multiselect.js b/src/BootstrapMultiSelectForMendix/lib/bootstrap-multiselect.js index 5fb4c18..08b8887 100644 --- a/src/BootstrapMultiSelectForMendix/lib/bootstrap-multiselect.js +++ b/src/BootstrapMultiSelectForMendix/lib/bootstrap-multiselect.js @@ -1,1416 +1,1427 @@ -/** - * 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 - * and/or other materials provided with the distribution. - * - 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 ;_; - - if (typeof ko !== 'undefined' && ko.bindingHandlers && !ko.bindingHandlers.multiselect) { - ko.bindingHandlers.multiselect = { - after: ['options', 'value', 'selectedOptions'], - - init: function(element, valueAccessor, allBindings, viewModel, bindingContext) { - var $element = $(element); - var config = ko.toJS(valueAccessor()); - - $element.multiselect(config); - - if (allBindings.has('options')) { - var options = allBindings.get('options'); - if (ko.isObservable(options)) { - ko.computed({ - read: function() { - options(); - setTimeout(function() { - var ms = $element.data('multiselect'); - if (ms) - ms.updateOriginalOptions();//Not sure how beneficial this is. - $element.multiselect('rebuild'); - }, 1); - }, - disposeWhenNodeIsRemoved: element - }); - } - } - - //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. - if (allBindings.has('value')) { - var value = allBindings.get('value'); - if (ko.isObservable(value)) { - ko.computed({ - read: function() { - value(); - setTimeout(function() { - $element.multiselect('refresh'); - }, 1); - }, - disposeWhenNodeIsRemoved: element - }).extend({ rateLimit: 100, notifyWhenChangesStop: true }); - } - } +define([], function () { - //Switched from arrayChange subscription to general subscription using 'refresh'. - //Not sure performance is any better using 'select' and 'deselect'. - if (allBindings.has('selectedOptions')) { - var selectedOptions = allBindings.get('selectedOptions'); - if (ko.isObservable(selectedOptions)) { - ko.computed({ - read: function() { - selectedOptions(); - setTimeout(function() { - $element.multiselect('refresh'); - }, 1); - }, - disposeWhenNodeIsRemoved: element - }).extend({ rateLimit: 100, notifyWhenChangesStop: true }); - } - } + return { + createInstance: function (jQuery) { - ko.utils.domNodeDisposal.addDisposeCallback(element, function() { - $element.multiselect('destroy'); - }); - }, - - update: function(element, valueAccessor, allBindings, viewModel, bindingContext) { - var $element = $(element); - var config = ko.toJS(valueAccessor()); - - $element.multiselect('setOptions', config); - $element.multiselect('rebuild'); - } - }; - } - - function forEach(array, callback) { - for (var index = 0; index < array.length; ++index) { - callback(array[index], index); - } - } - - /** - * Constructor to create a new multiselect using the given select. - * - * @param {jQuery} select - * @param {Object} options - * @returns {Multiselect} - */ - function Multiselect(select, options) { - - this.$select = $(select); - - // Placeholder via data attributes - if (this.$select.attr("data-placeholder")) { - options.nonSelectedText = this.$select.data("placeholder"); - } - - this.options = this.mergeOptions($.extend({}, options, this.$select.data())); - - // Initialization. - // We have to clone to create a new reference. - this.originalOptions = this.$select.clone()[0].options; - this.query = ''; - this.searchTimeout = null; - this.lastToggledInput = null - - this.options.multiple = this.$select.attr('multiple') === "multiple"; - this.options.onChange = $.proxy(this.options.onChange, this); - this.options.onDropdownShow = $.proxy(this.options.onDropdownShow, this); - this.options.onDropdownHide = $.proxy(this.options.onDropdownHide, this); - this.options.onDropdownShown = $.proxy(this.options.onDropdownShown, this); - this.options.onDropdownHidden = $.proxy(this.options.onDropdownHidden, this); - - // Build select all if enabled. - this.buildContainer(); - this.buildButton(); - this.buildDropdown(); - this.buildSelectAll(); - this.buildDropdownOptions(); - this.buildFilter(); - - this.updateButtonText(); - this.updateSelectAll(); - - if (this.options.disableIfEmpty && $('option', this.$select).length <= 0) { - this.disable(); - } - - this.$select.hide().after(this.$container); - }; - - 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. + * Bootstrap Multiselect (https://github.com/davidstutz/bootstrap-multiselect) * - * @param {jQuery} options - * @param {jQuery} select - * @returns {String} - */ - buttonText: function(options, select) { - if (options.length === 0) { - return this.nonSelectedText; - } - else if (this.allSelectedText - && options.length === $('option', $(select)).length - && $('option', $(select)).length !== 1 - && this.multiple) { - - if (this.selectAllNumber) { - return this.allSelectedText + ' (' + options.length + ')'; - } - else { - return this.allSelectedText; - } - } - else if (options.length > this.numberDisplayed) { - return options.length + ' ' + this.nSelectedText; - } - else { - var selected = ''; - var delimiter = this.delimiterText; - - options.each(function() { - var label = ($(this).attr('label') !== undefined) ? $(this).attr('label') : $(this).text(); - selected += label + delimiter; - }); - - return selected.substr(0, selected.length - 2); - } - }, - /** - * Updates the title of the button similar to the buttonText function. + * Apache License, Version 2.0: + * Copyright (c) 2012 - 2015 David Stutz * - * @param {jQuery} options - * @param {jQuery} select - * @returns {@exp;selected@call;substr} - */ - buttonTitle: function(options, select) { - if (options.length === 0) { - return this.nonSelectedText; - } - else { - var selected = ''; - var delimiter = this.delimiterText; - - options.each(function () { - var label = ($(this).attr('label') !== undefined) ? $(this).attr('label') : $(this).text(); - selected += label + delimiter; - }); - return selected.substr(0, selected.length - 2); - } - }, - /** - * Create a label. - * - * @param {jQuery} element - * @returns {String} - */ - optionLabel: function(element){ - return $(element).attr('label') || $(element).text(); - }, - /** - * Triggered on change of the multiselect. + * 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. * - * Not triggered when selecting/deselecting options manually. + * 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 + * and/or other materials provided with the distribution. + * - 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. * - * @param {jQuery} option - * @param {Boolean} checked + * 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. */ - onChange : function(option, checked) { + !function ($) { + "use strict";// jshint ;_; + + if (typeof ko !== 'undefined' && ko.bindingHandlers && !ko.bindingHandlers.multiselect) { + ko.bindingHandlers.multiselect = { + after: ['options', 'value', 'selectedOptions'], + + init: function(element, valueAccessor, allBindings, viewModel, bindingContext) { + var $element = $(element); + var config = ko.toJS(valueAccessor()); + + $element.multiselect(config); + + if (allBindings.has('options')) { + var options = allBindings.get('options'); + if (ko.isObservable(options)) { + ko.computed({ + read: function() { + options(); + setTimeout(function() { + var ms = $element.data('multiselect'); + if (ms) + ms.updateOriginalOptions();//Not sure how beneficial this is. + $element.multiselect('rebuild'); + }, 1); + }, + disposeWhenNodeIsRemoved: element + }); + } + } - }, - /** - * Triggered when the dropdown is shown. - * - * @param {jQuery} event - */ - onDropdownShow: function(event) { + //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. + if (allBindings.has('value')) { + var value = allBindings.get('value'); + if (ko.isObservable(value)) { + ko.computed({ + read: function() { + value(); + setTimeout(function() { + $element.multiselect('refresh'); + }, 1); + }, + disposeWhenNodeIsRemoved: element + }).extend({ rateLimit: 100, notifyWhenChangesStop: true }); + } + } - }, - /** - * Triggered when the dropdown is hidden. - * - * @param {jQuery} event - */ - onDropdownHide: function(event) { + //Switched from arrayChange subscription to general subscription using 'refresh'. + //Not sure performance is any better using 'select' and 'deselect'. + if (allBindings.has('selectedOptions')) { + var selectedOptions = allBindings.get('selectedOptions'); + if (ko.isObservable(selectedOptions)) { + ko.computed({ + read: function() { + selectedOptions(); + setTimeout(function() { + $element.multiselect('refresh'); + }, 1); + }, + disposeWhenNodeIsRemoved: element + }).extend({ rateLimit: 100, notifyWhenChangesStop: true }); + } + } - }, - /** - * 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: '
', - 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, - includeSelectAllIfMoreThan: 0, - 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: '', - ul: '', - filter: '
  • ', - filterClearBtn: '', - li: '
  • ', - divider: '
  • ', - liGroup: '
  • ' - } - }, - - constructor: Multiselect, - - /** - * Builds the container of the multiselect. - */ - buildContainer: function() { - this.$container = $(this.options.buttonContainer); - this.$container.on('show.bs.dropdown', this.options.onDropdownShow); - this.$container.on('hide.bs.dropdown', this.options.onDropdownHide); - this.$container.on('shown.bs.dropdown', this.options.onDropdownShown); - this.$container.on('hidden.bs.dropdown', this.options.onDropdownHidden); - }, - - /** - * Builds the button of the multiselect. - */ - buildButton: function() { - this.$button = $(this.options.templates.button).addClass(this.options.buttonClass); - if (this.$select.attr('class') && this.options.inheritClass) { - this.$button.addClass(this.$select.attr('class')); - } - // Adopt active state. - if (this.$select.prop('disabled')) { - this.disable(); - } - else { - this.enable(); - } - - // Manually add button width if set. - if (this.options.buttonWidth && this.options.buttonWidth !== 'auto') { - this.$button.css({ - 'width' : this.options.buttonWidth, - 'overflow' : 'hidden', - 'text-overflow' : 'ellipsis' - }); - this.$container.css({ - 'width': this.options.buttonWidth - }); - } - - // Keep the tab index from the select. - var tabindex = this.$select.attr('tabindex'); - if (tabindex) { - this.$button.attr('tabindex', tabindex); - } - - this.$container.prepend(this.$button); - }, - - /** - * Builds the ul representing the dropdown menu. - */ - buildDropdown: function() { - - // Build ul. - this.$ul = $(this.options.templates.ul); - - if (this.options.dropRight) { - this.$ul.addClass('pull-right'); - } - - // Set max height of dropdown menu to activate auto scrollbar. - if (this.options.maxHeight) { - // TODO: Add a class for this option to move the css declarations. - this.$ul.css({ - 'max-height': this.options.maxHeight + 'px', - 'overflow-y': 'auto', - 'overflow-x': 'hidden' - }); - } - - this.$container.append(this.$ul); - }, - - /** - * Build the dropdown options and binds all nessecary events. - * - * Uses createDivider and createOptionValue to create the necessary options. - */ - buildDropdownOptions: function() { - - this.$select.children().each($.proxy(function(index, element) { - - var $element = $(element); - // Support optgroups and options without a group simultaneously. - var tag = $element.prop('tagName') - .toLowerCase(); - - if ($element.prop('value') === this.options.selectAllValue) { - return; + ko.utils.domNodeDisposal.addDisposeCallback(element, function() { + $element.multiselect('destroy'); + }); + }, + + update: function(element, valueAccessor, allBindings, viewModel, bindingContext) { + var $element = $(element); + var config = ko.toJS(valueAccessor()); + + $element.multiselect('setOptions', config); + $element.multiselect('rebuild'); + } + }; } - if (tag === 'optgroup') { - this.createOptgroup(element); + function forEach(array, callback) { + for (var index = 0; index < array.length; ++index) { + callback(array[index], index); + } } - else if (tag === 'option') { - if ($element.data('role') === 'divider') { - this.createDivider(); + /** + * Constructor to create a new multiselect using the given select. + * + * @param {jQuery} select + * @param {Object} options + * @returns {Multiselect} + */ + function Multiselect(select, options) { + + this.$select = $(select); + + // Placeholder via data attributes + if (this.$select.attr("data-placeholder")) { + options.nonSelectedText = this.$select.data("placeholder"); } - else { - this.createOptionValue(element); + + this.options = this.mergeOptions($.extend({}, options, this.$select.data())); + + // Initialization. + // We have to clone to create a new reference. + this.originalOptions = this.$select.clone()[0].options; + this.query = ''; + this.searchTimeout = null; + this.lastToggledInput = null + + this.options.multiple = this.$select.attr('multiple') === "multiple"; + this.options.onChange = $.proxy(this.options.onChange, this); + this.options.onDropdownShow = $.proxy(this.options.onDropdownShow, this); + this.options.onDropdownHide = $.proxy(this.options.onDropdownHide, this); + this.options.onDropdownShown = $.proxy(this.options.onDropdownShown, this); + this.options.onDropdownHidden = $.proxy(this.options.onDropdownHidden, this); + + // Build select all if enabled. + this.buildContainer(); + this.buildButton(); + this.buildDropdown(); + this.buildSelectAll(); + this.buildDropdownOptions(); + this.buildFilter(); + + this.updateButtonText(); + this.updateSelectAll(); + + if (this.options.disableIfEmpty && $('option', this.$select).length <= 0) { + this.disable(); } - } + this.$select.hide().after(this.$container); + }; + + 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} + */ + buttonText: function(options, select) { + if (options.length === 0) { + return this.nonSelectedText; + } + else if (this.allSelectedText + && options.length === $('option', $(select)).length + && $('option', $(select)).length !== 1 + && this.multiple) { + + if (this.selectAllNumber) { + return this.allSelectedText + ' (' + options.length + ')'; + } + else { + return this.allSelectedText; + } + } + else if (options.length > this.numberDisplayed) { + return options.length + ' ' + this.nSelectedText; + } + else { + var selected = ''; + var delimiter = this.delimiterText; - // Other illegal tags will be ignored. - }, this)); + options.each(function() { + var label = ($(this).attr('label') !== undefined) ? $(this).attr('label') : $(this).text(); + selected += label + delimiter; + }); - // Bind the change event on the dropdown elements. - $('li input', this.$ul).on('change', $.proxy(function(event) { - var $target = $(event.target); + return selected.substr(0, selected.length - 2); + } + }, + /** + * Updates the title of the button similar to the buttonText function. + * + * @param {jQuery} options + * @param {jQuery} select + * @returns {@exp;selected@call;substr} + */ + buttonTitle: function(options, select) { + if (options.length === 0) { + return this.nonSelectedText; + } + else { + var selected = ''; + var delimiter = this.delimiterText; + + options.each(function () { + var label = ($(this).attr('label') !== undefined) ? $(this).attr('label') : $(this).text(); + selected += label + delimiter; + }); + return selected.substr(0, selected.length - 2); + } + }, + /** + * Create a label. + * + * @param {jQuery} element + * @returns {String} + */ + optionLabel: function(element){ + return $(element).attr('label') || $(element).text(); + }, + /** + * Triggered on change of the multiselect. + * + * Not triggered when selecting/deselecting options manually. + * + * @param {jQuery} option + * @param {Boolean} checked + */ + onChange : function(option, 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: '
    ', + 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, + includeSelectAllIfMoreThan: 0, + 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: '', + ul: '', + filter: '
  • ', + filterClearBtn: '', + li: '
  • ', + divider: '
  • ', + liGroup: '
  • ' + } + }, + + constructor: Multiselect, + + /** + * Builds the container of the multiselect. + */ + buildContainer: function() { + this.$container = $(this.options.buttonContainer); + this.$container.on('show.bs.dropdown', this.options.onDropdownShow); + this.$container.on('hide.bs.dropdown', this.options.onDropdownHide); + this.$container.on('shown.bs.dropdown', this.options.onDropdownShown); + this.$container.on('hidden.bs.dropdown', this.options.onDropdownHidden); + }, + + /** + * Builds the button of the multiselect. + */ + buildButton: function() { + this.$button = $(this.options.templates.button).addClass(this.options.buttonClass); + if (this.$select.attr('class') && this.options.inheritClass) { + this.$button.addClass(this.$select.attr('class')); + } + // Adopt active state. + if (this.$select.prop('disabled')) { + this.disable(); + } + else { + this.enable(); + } - var checked = $target.prop('checked') || false; - var isSelectAllOption = $target.val() === this.options.selectAllValue; + // Manually add button width if set. + if (this.options.buttonWidth && this.options.buttonWidth !== 'auto') { + this.$button.css({ + 'width' : this.options.buttonWidth, + 'overflow' : 'hidden', + 'text-overflow' : 'ellipsis' + }); + this.$container.css({ + 'width': this.options.buttonWidth + }); + } - // Apply or unapply the configured selected class. - if (this.options.selectedClass) { - if (checked) { - $target.closest('li') - .addClass(this.options.selectedClass); - } - else { - $target.closest('li') - .removeClass(this.options.selectedClass); - } - } + // Keep the tab index from the select. + var tabindex = this.$select.attr('tabindex'); + if (tabindex) { + this.$button.attr('tabindex', tabindex); + } - // Get the corresponding option. - var value = $target.val(); - var $option = this.getOptionByValue(value); + this.$container.prepend(this.$button); + }, - var $optionsNotThis = $('option', this.$select).not($option); - var $checkboxesNotThis = $('input', this.$container).not($target); + /** + * Builds the ul representing the dropdown menu. + */ + buildDropdown: function() { - if (isSelectAllOption) { - if (checked) { - this.selectAll(); - } - else { - this.deselectAll(); - } - } + // Build ul. + this.$ul = $(this.options.templates.ul); - if(!isSelectAllOption){ - if (checked) { - $option.prop('selected', true); + if (this.options.dropRight) { + this.$ul.addClass('pull-right'); + } - if (this.options.multiple) { - // Simply select additional option. - $option.prop('selected', true); + // Set max height of dropdown menu to activate auto scrollbar. + if (this.options.maxHeight) { + // TODO: Add a class for this option to move the css declarations. + this.$ul.css({ + 'max-height': this.options.maxHeight + 'px', + 'overflow-y': 'auto', + 'overflow-x': 'hidden' + }); } - else { - // Unselect all other options and corresponding checkboxes. + + this.$container.append(this.$ul); + }, + + /** + * Build the dropdown options and binds all nessecary events. + * + * Uses createDivider and createOptionValue to create the necessary options. + */ + buildDropdownOptions: function() { + + this.$select.children().each($.proxy(function(index, element) { + + var $element = $(element); + // Support optgroups and options without a group simultaneously. + var tag = $element.prop('tagName') + .toLowerCase(); + + if ($element.prop('value') === this.options.selectAllValue) { + return; + } + + if (tag === 'optgroup') { + this.createOptgroup(element); + } + else if (tag === 'option') { + + if ($element.data('role') === 'divider') { + this.createDivider(); + } + else { + this.createOptionValue(element); + } + + } + + // Other illegal tags will be ignored. + }, this)); + + // Bind the change event on the dropdown elements. + $('li input', this.$ul).on('change', $.proxy(function(event) { + var $target = $(event.target); + + var checked = $target.prop('checked') || false; + var isSelectAllOption = $target.val() === this.options.selectAllValue; + + // Apply or unapply the configured selected class. if (this.options.selectedClass) { - $($checkboxesNotThis).closest('li').removeClass(this.options.selectedClass); + if (checked) { + $target.closest('li') + .addClass(this.options.selectedClass); + } + else { + $target.closest('li') + .removeClass(this.options.selectedClass); + } + } + + // Get the corresponding option. + var value = $target.val(); + var $option = this.getOptionByValue(value); + + var $optionsNotThis = $('option', this.$select).not($option); + var $checkboxesNotThis = $('input', this.$container).not($target); + + if (isSelectAllOption) { + if (checked) { + this.selectAll(); + } + else { + this.deselectAll(); + } + } + + if(!isSelectAllOption){ + if (checked) { + $option.prop('selected', true); + + if (this.options.multiple) { + // Simply select additional option. + $option.prop('selected', true); + } + else { + // Unselect all other options and corresponding checkboxes. + if (this.options.selectedClass) { + $($checkboxesNotThis).closest('li').removeClass(this.options.selectedClass); + } + + $($checkboxesNotThis).prop('checked', false); + $optionsNotThis.prop('selected', false); + + // It's a single selection, so close. + this.$button.click(); + } + + if (this.options.selectedClass === "active") { + $optionsNotThis.closest("a").css("outline", ""); + } + } + else { + // Unselect option. + $option.prop('selected', false); + } + } + + this.$select.change(); + + this.updateButtonText(); + this.updateSelectAll(); + + this.options.onChange($option, checked); + + if(this.options.preventInputChangeEvent) { + return false; + } + }, this)); + + $('li a', this.$ul).on('mousedown', function(e) { + if (e.shiftKey) { + // Prevent selecting text by Shift+click + return false; + } + }); + + $('li a', this.$ul).on('touchstart click', $.proxy(function(event) { + event.stopPropagation(); + + var $target = $(event.target); + + if (event.shiftKey && this.options.multiple) { + if($target.is("label")){ // Handles checkbox selection manually (see https://github.com/davidstutz/bootstrap-multiselect/issues/431) + event.preventDefault(); + $target = $target.find("input"); + $target.prop("checked", !$target.prop("checked")); + } + var checked = $target.prop('checked') || false; + + if (this.lastToggledInput !== null && this.lastToggledInput !== $target) { // Make sure we actually have a range + var from = $target.closest("li").index(); + var to = this.lastToggledInput.closest("li").index(); + + if (from > to) { // Swap the indices + var tmp = to; + to = from; + from = tmp; + } + + // Make sure we grab all elements since slice excludes the last index + ++to; + + // Change the checkboxes and underlying options + var range = this.$ul.find("li").slice(from, to).find("input"); + + range.prop('checked', checked); + + if (this.options.selectedClass) { + range.closest('li') + .toggleClass(this.options.selectedClass, checked); + } + + for (var i = 0, j = range.length; i < j; i++) { + var $checkbox = $(range[i]); + + var $option = this.getOptionByValue($checkbox.val()); + + $option.prop('selected', checked); + } + } + + // Trigger the select "change" event + $target.trigger("change"); } - $($checkboxesNotThis).prop('checked', false); - $optionsNotThis.prop('selected', false); + // Remembers last clicked option + if($target.is("input") && !$target.closest("li").is(".multiselect-item")){ + this.lastToggledInput = $target; + } + + $target.blur(); + }, this)); + + // Keyboard support. + this.$container.off('keydown.multiselect').on('keydown.multiselect', $.proxy(function(event) { + if ($('input[type="text"]', this.$container).is(':focus')) { + return; + } - // It's a single selection, so close. - this.$button.click(); + if (event.keyCode === 9 && this.$container.hasClass('open')) { + this.$button.click(); + } + else { + var $items = $(this.$container).find("li:not(.divider):not(.disabled) a").filter(":visible"); + + if (!$items.length) { + return; + } + + var index = $items.index($items.filter(':focus')); + + // Navigation up. + if (event.keyCode === 38 && index > 0) { + index--; + } + // Navigate down. + else if (event.keyCode === 40 && index < $items.length - 1) { + index++; + } + else if (!~index) { + index = 0; + } + + var $current = $items.eq(index); + $current.focus(); + + if (event.keyCode === 32 || event.keyCode === 13) { + var $checkbox = $current.find('input'); + + $checkbox.prop("checked", !$checkbox.prop("checked")); + $checkbox.change(); + } + + event.stopPropagation(); + event.preventDefault(); + } + }, this)); + + if(this.options.enableClickableOptGroups && this.options.multiple) { + $('li.multiselect-group', this.$ul).on('click', $.proxy(function(event) { + event.stopPropagation(); + + var group = $(event.target).parent(); + + // Search all option in optgroup + var $options = group.nextUntil('li.multiselect-group'); + var $visibleOptions = $options.filter(":visible:not(.disabled)"); + + // check or uncheck items + var allChecked = true; + var optionInputs = $visibleOptions.find('input'); + optionInputs.each(function() { + allChecked = allChecked && $(this).prop('checked'); + }); + + optionInputs.prop('checked', !allChecked).trigger('change'); + }, this)); } + }, + + /** + * Create an option using the given select option. + * + * @param {jQuery} element + */ + createOptionValue: function(element) { + var $element = $(element); + if ($element.is(':selected')) { + $element.prop('selected', true); + } + + // Support the label attribute on options. + var label = this.options.optionLabel(element); + var value = $element.val(); + var inputType = this.options.multiple ? "checkbox" : "radio"; - if (this.options.selectedClass === "active") { - $optionsNotThis.closest("a").css("outline", ""); + var $li = $(this.options.templates.li); + var $label = $('label', $li); + $label.addClass(inputType); + + if (this.options.enableHTML) { + $label.html(" " + label); + } + else { + $label.text(" " + label); } - } - else { - // Unselect option. - $option.prop('selected', false); - } - } - this.$select.change(); + var $checkbox = $('').attr('type', inputType); - this.updateButtonText(); - this.updateSelectAll(); + if (this.options.checkboxName) { + $checkbox.attr('name', this.options.checkboxName); + } + $label.prepend($checkbox); - this.options.onChange($option, checked); + var selected = $element.prop('selected') || false; + $checkbox.val(value); - if(this.options.preventInputChangeEvent) { - return false; - } - }, this)); + if (value === this.options.selectAllValue) { + $li.addClass("multiselect-item multiselect-all"); + $checkbox.parent().parent() + .addClass('multiselect-all'); + } - $('li a', this.$ul).on('mousedown', function(e) { - if (e.shiftKey) { - // Prevent selecting text by Shift+click - return false; - } - }); - - $('li a', this.$ul).on('touchstart click', $.proxy(function(event) { - event.stopPropagation(); - - var $target = $(event.target); - - if (event.shiftKey && this.options.multiple) { - if($target.is("label")){ // Handles checkbox selection manually (see https://github.com/davidstutz/bootstrap-multiselect/issues/431) - event.preventDefault(); - $target = $target.find("input"); - $target.prop("checked", !$target.prop("checked")); - } - var checked = $target.prop('checked') || false; - - if (this.lastToggledInput !== null && this.lastToggledInput !== $target) { // Make sure we actually have a range - var from = $target.closest("li").index(); - var to = this.lastToggledInput.closest("li").index(); - - if (from > to) { // Swap the indices - var tmp = to; - to = from; - from = tmp; + $label.attr('title', $element.attr('title')); + + this.$ul.append($li); + + if ($element.is(':disabled')) { + $checkbox.attr('disabled', 'disabled') + .prop('disabled', true) + .closest('a') + .attr("tabindex", "-1") + .closest('li') + .addClass('disabled'); + } + + $checkbox.prop('checked', selected); + + if (selected && this.options.selectedClass) { + $checkbox.closest('li') + .addClass(this.options.selectedClass); } - - // Make sure we grab all elements since slice excludes the last index - ++to; - - // Change the checkboxes and underlying options - var range = this.$ul.find("li").slice(from, to).find("input"); - - range.prop('checked', checked); - - if (this.options.selectedClass) { - range.closest('li') - .toggleClass(this.options.selectedClass, checked); + }, + + /** + * Creates a divider using the given select option. + * + * @param {jQuery} element + */ + createDivider: function(element) { + var $divider = $(this.options.templates.divider); + this.$ul.append($divider); + }, + + /** + * Creates an optgroup. + * + * @param {jQuery} group + */ + createOptgroup: function(group) { + var groupName = $(group).prop('label'); + + // Add a header for the group. + var $li = $(this.options.templates.liGroup); + + if (this.options.enableHTML) { + $('label', $li).html(groupName); + } + else { + $('label', $li).text(groupName); } - - for (var i = 0, j = range.length; i < j; i++) { - var $checkbox = $(range[i]); - var $option = this.getOptionByValue($checkbox.val()); + if (this.options.enableClickableOptGroups) { + $li.addClass('multiselect-group-clickable'); + } - $option.prop('selected', checked); - } - } - - // Trigger the select "change" event - $target.trigger("change"); - } - - // Remembers last clicked option - if($target.is("input") && !$target.closest("li").is(".multiselect-item")){ - this.lastToggledInput = $target; - } + this.$ul.append($li); - $target.blur(); - }, this)); + if ($(group).is(':disabled')) { + $li.addClass('disabled'); + } - // Keyboard support. - this.$container.off('keydown.multiselect').on('keydown.multiselect', $.proxy(function(event) { - if ($('input[type="text"]', this.$container).is(':focus')) { - return; - } + // Add the options of the group. + $('option', group).each($.proxy(function(index, element) { + this.createOptionValue(element); + }, this)); + }, + + /** + * Build the selct all. + * + * Checks if a select all has already been created. + */ + buildSelectAll: function() { + if (typeof this.options.selectAllValue === 'number') { + this.options.selectAllValue = this.options.selectAllValue.toString(); + } - if (event.keyCode === 9 && this.$container.hasClass('open')) { - this.$button.click(); - } - else { - var $items = $(this.$container).find("li:not(.divider):not(.disabled) a").filter(":visible"); + var alreadyHasSelectAll = this.hasSelectAll(); - if (!$items.length) { - return; - } + if (!alreadyHasSelectAll && this.options.includeSelectAllOption && this.options.multiple + && $('option', this.$select).length > this.options.includeSelectAllIfMoreThan) { - var index = $items.index($items.filter(':focus')); + // Check whether to add a divider after the select all. + if (this.options.includeSelectAllDivider) { + this.$ul.prepend($(this.options.templates.divider)); + } - // Navigation up. - if (event.keyCode === 38 && index > 0) { - index--; - } - // Navigate down. - else if (event.keyCode === 40 && index < $items.length - 1) { - index++; - } - else if (!~index) { - index = 0; - } + var $li = $(this.options.templates.li); + $('label', $li).addClass("checkbox"); - var $current = $items.eq(index); - $current.focus(); + if (this.options.enableHTML) { + $('label', $li).html(" " + this.options.selectAllText); + } + else { + $('label', $li).text(" " + this.options.selectAllText); + } - if (event.keyCode === 32 || event.keyCode === 13) { - var $checkbox = $current.find('input'); + if (this.options.selectAllName) { + $('label', $li).prepend(''); + } + else { + $('label', $li).prepend(''); + } - $checkbox.prop("checked", !$checkbox.prop("checked")); - $checkbox.change(); - } + var $checkbox = $('input', $li); + $checkbox.val(this.options.selectAllValue); - event.stopPropagation(); - event.preventDefault(); - } - }, this)); + $li.addClass("multiselect-item multiselect-all"); + $checkbox.parent().parent() + .addClass('multiselect-all'); - if(this.options.enableClickableOptGroups && this.options.multiple) { - $('li.multiselect-group', this.$ul).on('click', $.proxy(function(event) { - event.stopPropagation(); + this.$ul.prepend($li); - var group = $(event.target).parent(); + $checkbox.prop('checked', false); + } + }, + + /** + * Builds the filter. + */ + buildFilter: function() { + + // Build filter if filtering OR case insensitive filtering is enabled and the number of options exceeds (or equals) enableFilterLength. + if (this.options.enableFiltering || this.options.enableCaseInsensitiveFiltering) { + var enableFilterLength = Math.max(this.options.enableFiltering, this.options.enableCaseInsensitiveFiltering); + + if (this.$select.find('option').length >= enableFilterLength) { + + this.$filter = $(this.options.templates.filter); + $('input', this.$filter).attr('placeholder', this.options.filterPlaceholder); + + // Adds optional filter clear button + if(this.options.includeFilterClearBtn){ + var clearBtn = $(this.options.templates.filterClearBtn); + clearBtn.on('click', $.proxy(function(event){ + clearTimeout(this.searchTimeout); + this.$filter.find('.multiselect-search').val(''); + $('li', this.$ul).show().removeClass("filter-hidden"); + this.updateSelectAll(); + }, this)); + this.$filter.find('.input-group').append(clearBtn); + } + + this.$ul.prepend(this.$filter); + + this.$filter.val(this.query).on('click', function(event) { + event.stopPropagation(); + }).on('input keydown', $.proxy(function(event) { + // Cancel enter key default behaviour + if (event.which === 13) { + event.preventDefault(); + } - // Search all option in optgroup - var $options = group.nextUntil('li.multiselect-group'); - var $visibleOptions = $options.filter(":visible:not(.disabled)"); + // This is useful to catch "keydown" events after the browser has updated the control. + clearTimeout(this.searchTimeout); + + this.searchTimeout = this.asyncFunction($.proxy(function() { + + if (this.query !== event.target.value) { + this.query = event.target.value; + + var currentGroup, currentGroupVisible; + $.each($('li', this.$ul), $.proxy(function(index, element) { + var value = $('input', element).length > 0 ? $('input', element).val() : ""; + var text = $('label', element).text(); + + var filterCandidate = ''; + if ((this.options.filterBehavior === 'text')) { + filterCandidate = text; + } + else if ((this.options.filterBehavior === 'value')) { + filterCandidate = value; + } + else if (this.options.filterBehavior === 'both') { + filterCandidate = text + '\n' + value; + } + + if (value !== this.options.selectAllValue && text) { + // 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; + } + else if (filterCandidate.indexOf(this.query) > -1) { + showElement = true; + } + + // Toggle current element (group or group item) according to showElement boolean. + $(element).toggle(showElement).toggleClass('filter-hidden', !showElement); + + // Differentiate groups and group items. + if ($(element).hasClass('multiselect-group')) { + // Remember group status. + currentGroup = element; + currentGroupVisible = showElement; + } + else { + // Show group name when at least one of its items is visible. + if (showElement) { + $(currentGroup).show().removeClass('filter-hidden'); + } + + // Show all group items when group name satisfies filter. + if (!showElement && currentGroupVisible) { + $(element).show().removeClass('filter-hidden'); + } + } + } + }, this)); + } - // check or uncheck items - var allChecked = true; - var optionInputs = $visibleOptions.find('input'); - optionInputs.each(function() { - allChecked = allChecked && $(this).prop('checked'); - }); + this.updateSelectAll(); + }, this), 300, this); + }, this)); + } + } + }, + + /** + * Unbinds the whole plugin. + */ + destroy: function() { + this.$container.remove(); + this.$select.show(); + this.$select.data('multiselect', null); + }, + + /** + * Refreshs the multiselect based on the selected options of the select. + */ + refresh: function() { + $('option', this.$select).each($.proxy(function(index, element) { + var $input = $('li input', this.$ul).filter(function() { + return $(this).val() === $(element).val(); + }); + + if ($(element).is(':selected')) { + $input.prop('checked', true); + + if (this.options.selectedClass) { + $input.closest('li') + .addClass(this.options.selectedClass); + } + } + else { + $input.prop('checked', false); - optionInputs.prop('checked', !allChecked).trigger('change'); - }, this)); - } - }, - - /** - * Create an option using the given select option. - * - * @param {jQuery} element - */ - createOptionValue: function(element) { - var $element = $(element); - if ($element.is(':selected')) { - $element.prop('selected', true); - } - - // Support the label attribute on options. - var label = this.options.optionLabel(element); - var value = $element.val(); - var inputType = this.options.multiple ? "checkbox" : "radio"; - - var $li = $(this.options.templates.li); - var $label = $('label', $li); - $label.addClass(inputType); - - if (this.options.enableHTML) { - $label.html(" " + label); - } - else { - $label.text(" " + label); - } - - var $checkbox = $('').attr('type', inputType); - - if (this.options.checkboxName) { - $checkbox.attr('name', this.options.checkboxName); - } - $label.prepend($checkbox); - - var selected = $element.prop('selected') || false; - $checkbox.val(value); - - if (value === this.options.selectAllValue) { - $li.addClass("multiselect-item multiselect-all"); - $checkbox.parent().parent() - .addClass('multiselect-all'); - } - - $label.attr('title', $element.attr('title')); - - this.$ul.append($li); - - if ($element.is(':disabled')) { - $checkbox.attr('disabled', 'disabled') - .prop('disabled', true) - .closest('a') - .attr("tabindex", "-1") - .closest('li') - .addClass('disabled'); - } - - $checkbox.prop('checked', selected); - - if (selected && this.options.selectedClass) { - $checkbox.closest('li') - .addClass(this.options.selectedClass); - } - }, - - /** - * Creates a divider using the given select option. - * - * @param {jQuery} element - */ - createDivider: function(element) { - var $divider = $(this.options.templates.divider); - this.$ul.append($divider); - }, - - /** - * Creates an optgroup. - * - * @param {jQuery} group - */ - createOptgroup: function(group) { - var groupName = $(group).prop('label'); - - // Add a header for the group. - var $li = $(this.options.templates.liGroup); - - if (this.options.enableHTML) { - $('label', $li).html(groupName); - } - else { - $('label', $li).text(groupName); - } - - if (this.options.enableClickableOptGroups) { - $li.addClass('multiselect-group-clickable'); - } - - this.$ul.append($li); - - if ($(group).is(':disabled')) { - $li.addClass('disabled'); - } - - // Add the options of the group. - $('option', group).each($.proxy(function(index, element) { - this.createOptionValue(element); - }, this)); - }, - - /** - * Build the selct all. - * - * Checks if a select all has already been created. - */ - buildSelectAll: function() { - if (typeof this.options.selectAllValue === 'number') { - this.options.selectAllValue = this.options.selectAllValue.toString(); - } - - var alreadyHasSelectAll = this.hasSelectAll(); - - if (!alreadyHasSelectAll && this.options.includeSelectAllOption && this.options.multiple - && $('option', this.$select).length > this.options.includeSelectAllIfMoreThan) { - - // Check whether to add a divider after the select all. - if (this.options.includeSelectAllDivider) { - this.$ul.prepend($(this.options.templates.divider)); - } + if (this.options.selectedClass) { + $input.closest('li') + .removeClass(this.options.selectedClass); + } + } - var $li = $(this.options.templates.li); - $('label', $li).addClass("checkbox"); - - if (this.options.enableHTML) { - $('label', $li).html(" " + this.options.selectAllText); - } - else { - $('label', $li).text(" " + this.options.selectAllText); - } - - if (this.options.selectAllName) { - $('label', $li).prepend(''); - } - else { - $('label', $li).prepend(''); - } - - var $checkbox = $('input', $li); - $checkbox.val(this.options.selectAllValue); - - $li.addClass("multiselect-item multiselect-all"); - $checkbox.parent().parent() - .addClass('multiselect-all'); - - this.$ul.prepend($li); - - $checkbox.prop('checked', false); - } - }, - - /** - * Builds the filter. - */ - buildFilter: function() { - - // Build filter if filtering OR case insensitive filtering is enabled and the number of options exceeds (or equals) enableFilterLength. - if (this.options.enableFiltering || this.options.enableCaseInsensitiveFiltering) { - var enableFilterLength = Math.max(this.options.enableFiltering, this.options.enableCaseInsensitiveFiltering); - - if (this.$select.find('option').length >= enableFilterLength) { - - this.$filter = $(this.options.templates.filter); - $('input', this.$filter).attr('placeholder', this.options.filterPlaceholder); - - // Adds optional filter clear button - if(this.options.includeFilterClearBtn){ - var clearBtn = $(this.options.templates.filterClearBtn); - clearBtn.on('click', $.proxy(function(event){ - clearTimeout(this.searchTimeout); - this.$filter.find('.multiselect-search').val(''); - $('li', this.$ul).show().removeClass("filter-hidden"); - this.updateSelectAll(); + if ($(element).is(":disabled")) { + $input.attr('disabled', 'disabled') + .prop('disabled', true) + .closest('li') + .addClass('disabled'); + } + else { + $input.prop('disabled', false) + .closest('li') + .removeClass('disabled'); + } }, this)); - this.$filter.find('.input-group').append(clearBtn); - } - - this.$ul.prepend(this.$filter); - - this.$filter.val(this.query).on('click', function(event) { - event.stopPropagation(); - }).on('input keydown', $.proxy(function(event) { - // Cancel enter key default behaviour - if (event.which === 13) { - event.preventDefault(); + + 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 + */ + select: function(selectValues, triggerOnChange) { + if(!$.isArray(selectValues)) { + selectValues = [selectValues]; } - - // This is useful to catch "keydown" events after the browser has updated the control. - clearTimeout(this.searchTimeout); - this.searchTimeout = this.asyncFunction($.proxy(function() { + for (var i = 0; i < selectValues.length; i++) { + var value = selectValues[i]; - if (this.query !== event.target.value) { - this.query = event.target.value; + if (value === null || value === undefined) { + continue; + } - var currentGroup, currentGroupVisible; - $.each($('li', this.$ul), $.proxy(function(index, element) { - var value = $('input', element).length > 0 ? $('input', element).val() : ""; - var text = $('label', element).text(); + var $option = this.getOptionByValue(value); + var $checkbox = this.getInputByValue(value); - var filterCandidate = ''; - if ((this.options.filterBehavior === 'text')) { - filterCandidate = text; - } - else if ((this.options.filterBehavior === 'value')) { - filterCandidate = value; - } - else if (this.options.filterBehavior === 'both') { - filterCandidate = text + '\n' + value; - } + if($option === undefined || $checkbox === undefined) { + continue; + } - if (value !== this.options.selectAllValue && text) { - // By default lets assume that element is not - // interesting for this search. - var showElement = false; + if (!this.options.multiple) { + this.deselectAll(false); + } - if (this.options.enableCaseInsensitiveFiltering && filterCandidate.toLowerCase().indexOf(this.query.toLowerCase()) > -1) { - showElement = true; - } - else if (filterCandidate.indexOf(this.query) > -1) { - showElement = true; - } + if (this.options.selectedClass) { + $checkbox.closest('li') + .addClass(this.options.selectedClass); + } - // Toggle current element (group or group item) according to showElement boolean. - $(element).toggle(showElement).toggleClass('filter-hidden', !showElement); - - // Differentiate groups and group items. - if ($(element).hasClass('multiselect-group')) { - // Remember group status. - currentGroup = element; - currentGroupVisible = showElement; - } - else { - // Show group name when at least one of its items is visible. - if (showElement) { - $(currentGroup).show().removeClass('filter-hidden'); - } - - // Show all group items when group name satisfies filter. - if (!showElement && currentGroupVisible) { - $(element).show().removeClass('filter-hidden'); - } - } - } - }, this)); + $checkbox.prop('checked', true); + $option.prop('selected', true); + + if (triggerOnChange) { + this.options.onChange($option, true); } + } - this.updateSelectAll(); - }, this), 300, this); - }, this)); - } - } - }, - - /** - * Unbinds the whole plugin. - */ - destroy: function() { - this.$container.remove(); - this.$select.show(); - this.$select.data('multiselect', null); - }, - - /** - * Refreshs the multiselect based on the selected options of the select. - */ - refresh: function() { - $('option', this.$select).each($.proxy(function(index, element) { - var $input = $('li input', this.$ul).filter(function() { - return $(this).val() === $(element).val(); - }); + 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 + */ + deselect: function(deselectValues, triggerOnChange) { + if(!$.isArray(deselectValues)) { + deselectValues = [deselectValues]; + } - if ($(element).is(':selected')) { - $input.prop('checked', true); + for (var i = 0; i < deselectValues.length; i++) { + var value = deselectValues[i]; - if (this.options.selectedClass) { - $input.closest('li') - .addClass(this.options.selectedClass); - } - } - else { - $input.prop('checked', false); + if (value === null || value === undefined) { + continue; + } - if (this.options.selectedClass) { - $input.closest('li') - .removeClass(this.options.selectedClass); - } - } + var $option = this.getOptionByValue(value); + var $checkbox = this.getInputByValue(value); - if ($(element).is(":disabled")) { - $input.attr('disabled', 'disabled') - .prop('disabled', true) - .closest('li') - .addClass('disabled'); - } - else { - $input.prop('disabled', false) - .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 - */ - select: function(selectValues, triggerOnChange) { - if(!$.isArray(selectValues)) { - selectValues = [selectValues]; - } - - for (var i = 0; i < selectValues.length; i++) { - var value = selectValues[i]; - - if (value === null || value === undefined) { - continue; - } + if($option === undefined || $checkbox === undefined) { + continue; + } - var $option = this.getOptionByValue(value); - var $checkbox = this.getInputByValue(value); + if (this.options.selectedClass) { + $checkbox.closest('li') + .removeClass(this.options.selectedClass); + } - if($option === undefined || $checkbox === undefined) { - continue; - } - - if (!this.options.multiple) { - this.deselectAll(false); - } - - if (this.options.selectedClass) { - $checkbox.closest('li') - .addClass(this.options.selectedClass); - } + $checkbox.prop('checked', false); + $option.prop('selected', false); - $checkbox.prop('checked', true); - $option.prop('selected', true); - - if (triggerOnChange) { - this.options.onChange($option, true); - } - } - - 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 - */ - deselect: function(deselectValues, triggerOnChange) { - if(!$.isArray(deselectValues)) { - deselectValues = [deselectValues]; - } - - for (var i = 0; i < deselectValues.length; i++) { - var value = deselectValues[i]; - - if (value === null || value === undefined) { - continue; - } + if (triggerOnChange) { + this.options.onChange($option, false); + } + } - var $option = this.getOptionByValue(value); - var $checkbox = this.getInputByValue(value); + 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 + */ + selectAll: function (justVisible, triggerOnSelectAll) { + var justVisible = typeof justVisible === 'undefined' ? true : justVisible; + var allCheckboxes = $("li input[type='checkbox']:enabled", this.$ul); + var visibleCheckboxes = allCheckboxes.filter(":visible"); + var allCheckboxesCount = allCheckboxes.length; + var visibleCheckboxesCount = visibleCheckboxes.length; + + if(justVisible) { + visibleCheckboxes.prop('checked', true); + $("li:not(.divider):not(.disabled)", this.$ul).filter(":visible").addClass(this.options.selectedClass); + } + else { + allCheckboxes.prop('checked', true); + $("li:not(.divider):not(.disabled)", this.$ul).addClass(this.options.selectedClass); + } - if($option === undefined || $checkbox === undefined) { - continue; - } + if (allCheckboxesCount === visibleCheckboxesCount || justVisible === false) { + $("option:enabled", this.$select).prop('selected', true); + } + else { + var values = visibleCheckboxes.map(function() { + return $(this).val(); + }).get(); - if (this.options.selectedClass) { - $checkbox.closest('li') - .removeClass(this.options.selectedClass); - } + $("option:enabled", this.$select).filter(function(index) { + return $.inArray($(this).val(), values) !== -1; + }).prop('selected', true); + } - $checkbox.prop('checked', false); - $option.prop('selected', false); - - if (triggerOnChange) { - this.options.onChange($option, false); - } - } - - 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 - */ - selectAll: function (justVisible, triggerOnSelectAll) { - var justVisible = typeof justVisible === 'undefined' ? true : justVisible; - var allCheckboxes = $("li input[type='checkbox']:enabled", this.$ul); - var visibleCheckboxes = allCheckboxes.filter(":visible"); - var allCheckboxesCount = allCheckboxes.length; - var visibleCheckboxesCount = visibleCheckboxes.length; - - if(justVisible) { - visibleCheckboxes.prop('checked', true); - $("li:not(.divider):not(.disabled)", this.$ul).filter(":visible").addClass(this.options.selectedClass); - } - else { - allCheckboxes.prop('checked', true); - $("li:not(.divider):not(.disabled)", this.$ul).addClass(this.options.selectedClass); - } - - if (allCheckboxesCount === visibleCheckboxesCount || justVisible === false) { - $("option:enabled", this.$select).prop('selected', true); - } - else { - var values = visibleCheckboxes.map(function() { - return $(this).val(); - }).get(); - - $("option:enabled", this.$select).filter(function(index) { - return $.inArray($(this).val(), values) !== -1; - }).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) { - var justVisible = typeof justVisible === 'undefined' ? true : justVisible; - - if(justVisible) { - var visibleCheckboxes = $("li input[type='checkbox']:not(:disabled)", this.$ul).filter(":visible"); - visibleCheckboxes.prop('checked', false); - - var values = visibleCheckboxes.map(function() { - return $(this).val(); - }).get(); - - $("option:enabled", this.$select).filter(function(index) { - return $.inArray($(this).val(), values) !== -1; - }).prop('selected', false); - - if (this.options.selectedClass) { - $("li:not(.divider):not(.disabled)", this.$ul).filter(":visible").removeClass(this.options.selectedClass); - } - } - else { - $("li input[type='checkbox']:enabled", this.$ul).prop('checked', false); - $("option:enabled", this.$select).prop('selected', false); - - if (this.options.selectedClass) { - $("li:not(.divider):not(.disabled)", this.$ul).removeClass(this.options.selectedClass); - } - } - }, - - /** - * Rebuild the plugin. - * - * Rebuilds the dropdown, the filter and the select all option. - */ - rebuild: function() { - this.$ul.html(''); - - // Important to distinguish between radios and checkboxes. - this.options.multiple = this.$select.attr('multiple') === "multiple"; - - this.buildSelectAll(); - this.buildDropdownOptions(); - this.buildFilter(); - - this.updateButtonText(); - this.updateSelectAll(); - - if (this.options.disableIfEmpty && $('option', this.$select).length <= 0) { - this.disable(); - } - else { - this.enable(); - } - - if (this.options.dropRight) { - this.$ul.addClass('pull-right'); - } - }, - - /** - * The provided data will be used to build the dropdown. - */ - dataprovider: function(dataprovider) { - - var groupCounter = 0; - var $select = this.$select.empty(); - - $.each(dataprovider, function (index, option) { - var $tag; - - if ($.isArray(option.children)) { // create optiongroup tag - groupCounter++; - - $tag = $('').attr({ - label: option.label || 'Group ' + groupCounter, - disabled: !!option.disabled - }); - - forEach(option.children, function(subOption) { // add children option tags - $tag.append($('').attr({ + label: option.label || 'Group ' + groupCounter, + disabled: !!option.disabled + }); + + forEach(option.children, function(subOption) { // add children option tags + $tag.append($('