diff --git a/bower.json b/bower.json index e96bb7f5..e7c40b63 100644 --- a/bower.json +++ b/bower.json @@ -18,7 +18,7 @@ ], "dependencies": { "jquery": ">= 1.11.0", - "bootstrap": ">= 2.3.2" + "bootstrap": ">= 4.5.2" }, "ignore": [ "docs/.*", diff --git a/dist/css/bootstrap-multiselect.css b/dist/css/bootstrap-multiselect.css index 6a6b68a2..f623d090 100644 --- a/dist/css/bootstrap-multiselect.css +++ b/dist/css/bootstrap-multiselect.css @@ -1 +1,87 @@ -span.multiselect-native-select{position:relative}span.multiselect-native-select select{border:0!important;clip:rect(0 0 0 0)!important;height:1px!important;margin:-1px -1px -1px -3px!important;overflow:hidden!important;padding:0!important;position:absolute!important;width:1px!important;left:50%;top:30px}.multiselect-container{position:absolute;list-style-type:none;margin:0;padding:0}.multiselect-container .input-group{margin:5px}.multiselect-container .multiselect-reset .input-group{width:93%}.multiselect-container>li{padding:0}.multiselect-container>li>a.multiselect-all label{font-weight:700}.multiselect-container>li.multiselect-group label{margin:0;padding:3px 20px;height:100%;font-weight:700}.multiselect-container>li.multiselect-group-clickable label{cursor:pointer}.multiselect-container>li>a{padding:0}.multiselect-container>li>a>label{margin:0;height:100%;cursor:pointer;font-weight:400;padding:3px 20px 3px 40px}.multiselect-container>li>a>label.checkbox,.multiselect-container>li>a>label.radio{margin:0}.multiselect-container>li>a>label>input[type=checkbox]{margin-bottom:5px}.btn-group>.btn-group:nth-child(2)>.multiselect.btn{border-top-left-radius:4px;border-bottom-left-radius:4px}.form-inline .multiselect-container label.checkbox,.form-inline .multiselect-container label.radio{padding:3px 20px 3px 40px}.form-inline .multiselect-container li a label.checkbox input[type=checkbox],.form-inline .multiselect-container li a label.radio input[type=radio]{margin-left:-20px;margin-right:0} \ No newline at end of file +/** + * Bootstrap Multiselect (http://davidstutz.de/bootstrap-multiselect/) + * + * Apache License, Version 2.0: + * Copyright (c) 2012 - 2020 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 - 2020 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. + */ +span.multiselect-native-select { + position: relative; +} +span.multiselect-native-select select { + border: 0 !important; + clip: rect(0 0 0 0) !important; + height: 1px !important; + margin: -1px -1px -1px -3px !important; + overflow: hidden !important; + padding: 0 !important; + position: absolute !important; + width: 1px !important; + left: 50%; + top: 30px; +} +.multiselect.dropdown-toggle:after { + display: none; +} +.multiselect-container { + position: absolute; + list-style-type: none; + margin: 0; + padding: 0; +} +.multiselect-container .multiselect-reset .input-group { + width: 93%; +} +.multiselect-container > .multiselect-option.dropdown-item, +.multiselect-container .multiselect-group.dropdown-item, +.multiselect-container > .multiselect-option.dropdown-toggle, +.multiselect-container .multiselect-group.dropdown-toggle { + cursor: pointer; +} +.multiselect-container > .multiselect-option > span, +.multiselect-container .multiselect-group > span { + padding: 3px 20px; +} +.multiselect-container > .multiselect-option > span > .form-check-label, +.multiselect-container .multiselect-group > span > .form-check-label { + cursor: pointer; +} +.form-inline .multiselect-container span.form-check { + padding: 3px 20px 3px 40px; +} diff --git a/dist/css/bootstrap-multiselect.min.css b/dist/css/bootstrap-multiselect.min.css new file mode 100644 index 00000000..beb7bf63 --- /dev/null +++ b/dist/css/bootstrap-multiselect.min.css @@ -0,0 +1 @@ +span.multiselect-native-select{position:relative}span.multiselect-native-select select{border:0!important;clip:rect(0 0 0 0)!important;height:1px!important;margin:-1px -1px -1px -3px!important;overflow:hidden!important;padding:0!important;position:absolute!important;width:1px!important;left:50%;top:30px}.multiselect.dropdown-toggle:after{display:none}.multiselect-container{position:absolute;list-style-type:none;margin:0;padding:0}.multiselect-container .multiselect-reset .input-group{width:93%}.multiselect-container .multiselect-group.dropdown-item,.multiselect-container .multiselect-group.dropdown-toggle,.multiselect-container>.multiselect-option.dropdown-item,.multiselect-container>.multiselect-option.dropdown-toggle{cursor:pointer}.multiselect-container .multiselect-group>span,.multiselect-container>.multiselect-option>span{padding:3px 20px}.multiselect-container .multiselect-group>span>.form-check-label,.multiselect-container>.multiselect-option>span>.form-check-label{cursor:pointer}.form-inline .multiselect-container span.form-check{padding:3px 20px 3px 40px} \ No newline at end of file diff --git a/dist/js/bootstrap-multiselect.js b/dist/js/bootstrap-multiselect.js index 2a028b77..50a6d8fa 100644 --- a/dist/js/bootstrap-multiselect.js +++ b/dist/js/bootstrap-multiselect.js @@ -59,7 +59,7 @@ ko.bindingHandlers.multiselect = { after: ['options', 'value', 'selectedOptions', 'enable', 'disable'], - init: function(element, valueAccessor, allBindings, viewModel, bindingContext) { + init: function (element, valueAccessor, allBindings, viewModel, bindingContext) { var $element = $(element); var config = ko.toJS(valueAccessor()); @@ -69,9 +69,9 @@ var options = allBindings.get('options'); if (ko.isObservable(options)) { ko.computed({ - read: function() { + read: function () { options(); - setTimeout(function() { + setTimeout(function () { var ms = $element.data('multiselect'); if (ms) ms.updateOriginalOptions();//Not sure how beneficial this is. @@ -90,9 +90,9 @@ var value = allBindings.get('value'); if (ko.isObservable(value)) { ko.computed({ - read: function() { + read: function () { value(); - setTimeout(function() { + setTimeout(function () { $element.multiselect('refresh'); }, 1); }, @@ -107,9 +107,9 @@ var selectedOptions = allBindings.get('selectedOptions'); if (ko.isObservable(selectedOptions)) { ko.computed({ - read: function() { + read: function () { selectedOptions(); - setTimeout(function() { + setTimeout(function () { $element.multiselect('refresh'); }, 1); }, @@ -155,12 +155,12 @@ } } - ko.utils.domNodeDisposal.addDisposeCallback(element, function() { + ko.utils.domNodeDisposal.addDisposeCallback(element, function () { $element.multiselect('destroy'); }); }, - update: function(element, valueAccessor, allBindings, viewModel, bindingContext) { + update: function (element, valueAccessor, allBindings, viewModel, bindingContext) { var $element = $(element); var config = ko.toJS(valueAccessor()); @@ -248,9 +248,9 @@ * @param {jQuery} select * @returns {String} */ - buttonText: function(options, select) { + buttonText: function (options, select) { if (this.disabledText.length > 0 - && (select.prop('disabled') || (options.length == 0 && this.disableIfEmpty))) { + && (select.prop('disabled') || (options.length == 0 && this.disableIfEmpty))) { return this.disabledText; } @@ -258,9 +258,9 @@ return this.nonSelectedText; } else if (this.allSelectedText - && options.length === $('option', $(select)).length - && $('option', $(select)).length !== 1 - && this.multiple) { + && options.length === $('option', $(select)).length + && $('option', $(select)).length !== 1 + && this.multiple) { if (this.selectAllNumber) { return this.allSelectedText + ' (' + options.length + ')'; @@ -276,7 +276,7 @@ var selected = ''; var delimiter = this.delimiterText; - options.each(function() { + options.each(function () { var label = ($(this).attr('label') !== undefined) ? $(this).attr('label') : $(this).text(); selected += label + delimiter; }); @@ -291,7 +291,7 @@ * @param {jQuery} select * @returns {@exp;selected@call;substr} */ - buttonTitle: function(options, select) { + buttonTitle: function (options, select) { if (options.length === 0) { return this.nonSelectedText; } @@ -306,7 +306,7 @@ return selected.substr(0, selected.length - this.delimiterText.length); } }, - checkboxName: function(option) { + checkboxName: function (option) { return false; // no checkbox name }, /** @@ -315,7 +315,7 @@ * @param {jQuery} element * @returns {String} */ - optionLabel: function(element){ + optionLabel: function (element) { return $(element).attr('label') || $(element).text(); }, /** @@ -324,7 +324,7 @@ * @param {jQuery} element * @returns {String} */ - optionClass: function(element) { + optionClass: function (element) { return $(element).attr('class') || ''; }, /** @@ -335,7 +335,7 @@ * @param {jQuery} option * @param {Boolean} checked */ - onChange : function(option, checked) { + onChange: function (option, checked) { }, /** @@ -343,7 +343,7 @@ * * @param {jQuery} event */ - onDropdownShow: function(event) { + onDropdownShow: function (event) { }, /** @@ -351,7 +351,7 @@ * * @param {jQuery} event */ - onDropdownHide: function(event) { + onDropdownHide: function (event) { }, /** @@ -359,7 +359,7 @@ * * @param {jQuery} event */ - onDropdownShown: function(event) { + onDropdownShown: function (event) { }, /** @@ -367,19 +367,19 @@ * * @param {jQuery} event */ - onDropdownHidden: function(event) { + onDropdownHidden: function (event) { }, /** * Triggered on select all. */ - onSelectAll: function() { + onSelectAll: function () { }, /** * Triggered on deselect all. */ - onDeselectAll: function() { + onDeselectAll: function () { }, /** @@ -388,7 +388,7 @@ * @param {jQuery} $select * @param {jQuery} $container */ - onInitialized: function($select, $container) { + onInitialized: function ($select, $container) { }, /** @@ -396,11 +396,11 @@ * * @param {jQuery} $filter */ - onFiltering: function($filter) { + onFiltering: function ($filter) { }, enableHTML: false, - buttonClass: 'btn btn-default', + buttonClass: 'custom-select', inheritClass: false, buttonWidth: 'auto', buttonContainer: '
', @@ -439,14 +439,14 @@ includeResetDivider: false, resetText: 'Reset', templates: { - button: '', - ul: '', - filter: '
  • ', - filterClearBtn: '', - li: '
  • ', - divider: '
  • ', - liGroup: '
  • ', - resetButton: '
  • ' + button: '', + popupContainer: '', + filter: '
    ', + filterClearBtn: '
    ', + option: '', + divider: '', + optionGroup: '', + resetButton: '
    ' } }, @@ -455,7 +455,7 @@ /** * Builds the container of the multiselect. */ - buildContainer: function() { + 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); @@ -466,7 +466,7 @@ /** * Builds the button of the multiselect. */ - buildButton: function() { + 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')); @@ -482,9 +482,9 @@ // Manually add button width if set. if (this.options.buttonWidth && this.options.buttonWidth !== 'auto') { this.$button.css({ - 'width' : '100%', //this.options.buttonWidth, - 'overflow' : 'hidden', - 'text-overflow' : 'ellipsis' + 'width': '100%', //this.options.buttonWidth, + 'overflow': 'hidden', + 'text-overflow': 'ellipsis' }); this.$container.css({ 'width': this.options.buttonWidth @@ -501,41 +501,35 @@ }, /** - * Builds the ul representing the dropdown menu. + * Builds the popup container representing the dropdown menu. */ - buildDropdown: function() { + buildDropdown: function () { - // Build ul. - this.$ul = $(this.options.templates.ul); + // Build popup container. + this.$popupContainer = $(this.options.templates.popupContainer); if (this.options.dropRight) { - this.$ul.addClass('pull-right'); + this.$container.addClass('dropright'); + } + else if (this.options.dropUp) { + this.$container.addClass("dropup"); } // 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({ + this.$popupContainer.css({ 'max-height': this.options.maxHeight + 'px', 'overflow-y': 'auto', 'overflow-x': 'hidden' }); } - if (this.options.dropUp) { - - var height = Math.min(this.options.maxHeight, $('option[data-role!="divider"]', this.$select).length*26 + $('option[data-role="divider"]', this.$select).length*19 + (this.options.includeSelectAllOption ? 26 : 0) + (this.options.enableFiltering || this.options.enableCaseInsensitiveFiltering ? 44 : 0)); - var moveCalc = height + 34; - - this.$ul.css({ - 'max-height': height + 'px', - 'overflow-y': 'auto', - 'overflow-x': 'hidden', - 'margin-top': "-" + moveCalc + 'px' - }); - } + this.$popupContainer.on("touchstart click", function (e) { + e.stopPropagation(); + }); - this.$container.append(this.$ul); + this.$container.append(this.$popupContainer); }, /** @@ -543,9 +537,9 @@ * * Uses createDivider and createOptionValue to create the necessary options. */ - buildDropdownOptions: function() { + buildDropdownOptions: function () { - this.$select.children().each($.proxy(function(index, element) { + this.$select.children().each($.proxy(function (index, element) { var $element = $(element); // Support optgroups and options without a group simultaneously. @@ -574,8 +568,8 @@ }, this)); // Bind the change event on the dropdown elements. - $(this.$ul).off('change', 'li:not(.multiselect-group) input[type="checkbox"], li:not(.multiselect-group) input[type="radio"]'); - $(this.$ul).on('change', 'li:not(.multiselect-group) input[type="checkbox"], li:not(.multiselect-group) input[type="radio"]', $.proxy(function(event) { + $(this.$popupContainer).off('change', '> *:not(.multiselect-group) input[type="checkbox"], > *:not(.multiselect-group) input[type="radio"]'); + $(this.$popupContainer).on('change', '> *:not(.multiselect-group) input[type="checkbox"], > *:not(.multiselect-group) input[type="radio"]', $.proxy(function (event) { var $target = $(event.target); var checked = $target.prop('checked') || false; @@ -584,11 +578,11 @@ // Apply or unapply the configured selected class. if (this.options.selectedClass) { if (checked) { - $target.closest('li') + $target.closest('.multiselect-option') .addClass(this.options.selectedClass); } else { - $target.closest('li') + $target.closest('.multiselect-option') .removeClass(this.options.selectedClass); } } @@ -620,7 +614,7 @@ else { // Unselect all other options and corresponding checkboxes. if (this.options.selectedClass) { - $($checkboxesNotThis).closest('li').removeClass(this.options.selectedClass); + $($checkboxesNotThis).closest('.dropdown-item').removeClass(this.options.selectedClass); } $($checkboxesNotThis).prop('checked', false); @@ -631,7 +625,7 @@ } if (this.options.selectedClass === "active") { - $optionsNotThis.closest("a").css("outline", ""); + $optionsNotThis.closest(".dropdown-item").css("outline", ""); } } else { @@ -653,34 +647,36 @@ this.$select.change(); this.updateButtonText(); - if(this.options.preventInputChangeEvent) { + if (this.options.preventInputChangeEvent) { return false; } }, this)); - $('li a', this.$ul).on('mousedown', function(e) { + $('.multiselect-option', this.$popupContainer).off('mousedown'); + $('.multiselect-option', this.$popupContainer).on('mousedown', function (e) { if (e.shiftKey) { // Prevent selecting text by Shift+click return false; } }); - $(this.$ul).on('touchstart click', 'li a', $.proxy(function(event) { + $(this.$popupContainer).off('touchstart click', '.multiselect-option, .multiselect-all, .multiselect-group'); + $(this.$popupContainer).on('touchstart click', '.multiselect-option, .multiselect-all, .multiselect-group', $.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) + if (!$target.is("input")) { // Handles checkbox selection manually (see https://github.com/davidstutz/bootstrap-multiselect/issues/431) event.preventDefault(); - $target = $target.find("input"); + $target = $target.closest(".multiselect-option").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 = this.$ul.find("li:visible").index($target.parents("li")); - var to = this.$ul.find("li:visible").index(this.lastToggledInput.parents("li")); + var from = this.$popupContainer.find(".multiselect-option:visible").index($target.closest(".multiselect-option")); + var to = this.$popupContainer.find(".multiselect-option:visible").index(this.lastToggledInput.closest(".multiselect-option")); if (from > to) { // Swap the indices var tmp = to; @@ -692,12 +688,12 @@ ++to; // Change the checkboxes and underlying options - var range = this.$ul.find("li").not(".multiselect-filter-hidden").slice(from, to).find("input"); + var range = this.$popupContainer.find(".multiselect-option:not(.multiselect-filter-hidden)").slice(from, to).find("input"); range.prop('checked', checked); if (this.options.selectedClass) { - range.closest('li') + range.closest('.multiselect-option') .toggleClass(this.options.selectedClass, checked); } @@ -713,100 +709,120 @@ // Trigger the select "change" event $target.trigger("change"); } + else if (!$target.is('input')) { + var $checkbox = $target.closest('.multiselect-option, .multiselect-all').find('.form-check-input'); + if($checkbox.length > 0) { + $checkbox.prop('checked', !$checkbox.prop('checked')); + $checkbox.change(); + } + else if(this.options.enableClickableOptGroups && this.options.multiple && !$target.hasClass("caret-container")) { + var groupItem = $target; + if(!groupItem.hasClass("multiselect-group")){ + groupItem = $target.closest('.multiselect-group'); + } + $checkbox = groupItem.find(".form-check-input"); + if($checkbox.length > 0) { + $checkbox.prop('checked', !$checkbox.prop('checked')); + $checkbox.change(); + } + } + + event.preventDefault(); + } // Remembers last clicked option - if($target.is("input") && !$target.closest("li").is(".multiselect-item")){ + var $input = $target.closest(".multiselect-option").find("input[type='checkbox'], input[type='radio']"); + if ($input.length > 0) { this.lastToggledInput = $target; } + else { + this.lastToggledInput = null; + } $target.blur(); }, this)); - // Keyboard support. - this.$container.off('keydown.multiselect').on('keydown.multiselect', $.proxy(function(event) { + //Keyboard support. + this.$container.off('keydown.multiselect').on('keydown.multiselect', $.proxy(function (event) { if ($('input[type="text"]', this.$container).is(':focus')) { return; } - if (event.keyCode === 9 && this.$container.hasClass('open')) { + // keyCode 9 == Tab + if (event.keyCode === 9 && this.$container.hasClass('show')) { this.$button.click(); } else { - var $items = $(this.$container).find("li:not(.divider):not(.disabled) a").filter(":visible"); + var $items = $(this.$container).find(".multiselect-option:not(.disabled), .multiselect-group:not(.disabled), .multiselect-all").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) { + // keyCode 32 = Space + if (event.keyCode === 32) { var $checkbox = $current.find('input'); $checkbox.prop("checked", !$checkbox.prop("checked")); $checkbox.change(); + + event.preventDefault(); } - event.stopPropagation(); - event.preventDefault(); + // keyCode 13 = Enter + if(event.keyCode === 13) { + setTimeout(function() { + $current.focus(); + }, 0); + } } }, this)); if (this.options.enableClickableOptGroups && this.options.multiple) { - $("li.multiselect-group input", this.$ul).on("change", $.proxy(function(event) { + $(".multiselect-group input", this.$popupContainer).off("change"); + $(".multiselect-group input", this.$popupContainer).on("change", $.proxy(function (event) { event.stopPropagation(); var $target = $(event.target); var checked = $target.prop('checked') || false; - var $li = $(event.target).closest('li'); - var $group = $li.nextUntil("li.multiselect-group") + var $item = $(event.target).closest('.dropdown-item'); + var $group = $item.nextUntil(".multiselect-group") .not('.multiselect-filter-hidden') .not('.disabled'); var $inputs = $group.find("input"); - var values = []; var $options = []; if (this.options.selectedClass) { if (checked) { - $li.addClass(this.options.selectedClass); + $item.addClass(this.options.selectedClass); } else { - $li.removeClass(this.options.selectedClass); + $item.removeClass(this.options.selectedClass); } } - $.each($inputs, $.proxy(function(index, input) { - var value = $(input).val(); + $.each($inputs, $.proxy(function (index, input) { + var $input = $(input); + var value = $input.val(); var $option = this.getOptionByValue(value); if (checked) { - $(input).prop('checked', true); - $(input).closest('li') + $input.prop('checked', true); + $input.closest('.dropdown-item') .addClass(this.options.selectedClass); $option.prop('selected', true); } else { - $(input).prop('checked', false); - $(input).closest('li') + $input.prop('checked', false); + $input.closest('.dropdown-item') .removeClass(this.options.selectedClass); $option.prop('selected', false); @@ -826,13 +842,14 @@ } if (this.options.enableCollapsibleOptGroups && this.options.multiple) { - $("li.multiselect-group .caret-container", this.$ul).on("click", $.proxy(function(event) { - var $li = $(event.target).closest('li'); - var $inputs = $li.nextUntil("li.multiselect-group") - .not('.multiselect-filter-hidden'); + $(".multiselect-group .caret-container", this.$popupContainer).off("click"); + $(".multiselect-group .caret-container", this.$popupContainer).on("click", $.proxy(function (event) { + var $group = $(event.target).closest('.multiselect-group'); + var $inputs = $group.nextUntil(".multiselect-group") + .not('.multiselect-filter-hidden'); var visible = true; - $inputs.each(function() { + $inputs.each(function () { visible = visible && !$(this).hasClass('multiselect-collapsible-hidden'); }); @@ -845,11 +862,43 @@ .removeClass('multiselect-collapsible-hidden'); } }, this)); + } + }, + + /** + * Create a checkbox container with input and label based on given values + * @param {JQuery} $item + * @param {String} label + * @param {String} name + * @param {String} value + * @param {String} inputType + * @returns {JQuery} + */ + createCheckbox: function ($item, label, name, value, title, inputType) { + var $wrapper = $(''); + $wrapper.addClass("form-check"); - $("li.multiselect-all", this.$ul).css('background', '#f3f3f3').css('border-bottom', '1px solid #eaeaea'); - $("li.multiselect-all > a > label.checkbox", this.$ul).css('padding', '3px 20px 3px 35px'); - $("li.multiselect-group > a > input", this.$ul).css('margin', '4px 0px 5px -20px'); + if (this.options.enableHTML && $(label).length > 0) { + $wrapper.append($(label)); } + else { + var $checkboxLabel = $('