Multiselect Dropdown z-index在滚动容器div中不起作用。它显示滚动而不是像另一个下拉菜单一样打开它。
示例代码:“http://jsfiddle.net/rousseauo/acg2Lco8/”
// Helped by the code of : pete-experimenter
// Due to bootstrap-multiselect.js not being available on CDN, it's included first below.
// My code begins on line 570
/**
* bootstrap-multiselect.js 1.0.0
* https://github.com/davidstutz/bootstrap-multiselect
*
* Copyright 2012, 2013 David Stutz
*
* Dual licensed under the BSD-3-Clause and the Apache License, Version 2.0.
* See the README.
*/! function ($) {
"use strict"; // jshint ;_;
if (typeof ko != 'undefined' && ko.bindingHandlers && !ko.bindingHandlers.multiselect) {
ko.bindingHandlers.multiselect = {
init: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {},
update: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
var ms = $(element).data('multiselect');
if (!ms) {
$(element).multiselect(ko.utils.unwrapObservable(valueAccessor()));
} else if (allBindingsAccessor().options && allBindingsAccessor().options().length !== ms.originalOptions.length) {
ms.updateOriginalOptions();
$(element).multiselect('rebuild');
}
}
};
}
function Multiselect(select, options) {
this.options = this.getOptions(options);
this.$select = $(select);
this.originalOptions = this.$select.clone()[0].options;
//we have to clone to create a new reference
this.query = '';
this.searchTimeout = null;
this.options.multiple = this.$select.attr('multiple') == "multiple";
this.$container = $(this.options.buttonContainer).append('<button type="button" class="multiselect dropdown-toggle ' + this.options.buttonClass + '" data-toggle="dropdown">' + this.options.buttonText(this.getSelected(), this.$select) + '</button>')
.append('<ul class="multiselect-container dropdown-menu' + (this.options.dropRight ? ' pull-right' : '') + '"></ul>');
// Manually add button width if set.
if (this.options.buttonWidth) {
$('button', this.$container).css({
'width': this.options.buttonWidth
});
}
// Keep the tab index from the select.
var tabindex = this.$select.attr('tabindex');
if (tabindex) {
$('button', this.$container).attr('tabindex', tabindex);
}
// 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.
$('.multiselect-container', this.$container).css({
'max-height': this.options.maxHeight + 'px',
'overflow-y': 'auto',
'overflow-x': 'hidden'
});
}
// Enable filtering.
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.buildFilter();
}
}
// Build select all if enabled.
this.buildSelectAll();
this.buildDropdown();
this.updateButtonText();
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.
// If more than 3 options are selected, the number of selected options is printed.
buttonText: function (options, select) {
if (options.length == 0) {
return this.nonSelectedText + '<b class="caret"></b>';
} else if (options.length > 3) {
return options.length + ' ' + this.nSelectedText + ' <b class="caret"></b>';
} else {
var selected = '';
options.each(function () {
var label = ($(this).attr('label') !== undefined) ? $(this).attr('label') : $(this).html();
selected += label + ', ';
});
return selected.substr(0, selected.length - 2) + ' <b class="caret"></b>';
}
},
// Like the buttonText option to update the title of the button.
buttonTitle: function (options, select) {
var selected = '';
options.each(function () {
selected += $(this).text() + ', ';
});
return selected.substr(0, selected.length - 2);
},
// Is triggered on change of the selected options.
onChange: function (option, checked) {
},
buttonClass: 'btn',
dropRight: false,
selectedClass: 'active',
buttonWidth: 'auto',
buttonContainer: '<div class="btn-group" />',
// Maximum height of the dropdown menu.
// If maximum height is exceeded a scrollbar will be displayed.
maxHeight: false,
includeSelectAllOption: false,
selectAllText: ' Select all',
selectAllValue: 'multiselect-all',
enableFiltering: false,
enableCaseInsensitiveFiltering: false,
filterPlaceholder: 'Search',
// possible options: 'text', 'value', 'both'
filterBehavior: 'text',
preventInputChangeEvent: false,
nonSelectedText: 'None selected',
nSelectedText: 'selected'
},
constructor: Multiselect,
// Will build an dropdown element for the given option.
createOptionValue: function (element) {
if ($(element).is(':selected')) {
$(element).attr('selected', 'selected').prop('selected', true);
}
// Support the label attribute on options.
var label = $(element).attr('label') || $(element).html();
var value = $(element).val();
var inputType = this.options.multiple ? "checkbox" : "radio";
var $li = $('<li><a href="javascript:void(0);"><label class="' + inputType + '"><input type="' + inputType + '" /></label></a></li>');
var selected = $(element).prop('selected') || false;
var $checkbox = $('input', $li);
$checkbox.val(value);
if (value == this.options.selectAllValue) {
$checkbox.parent().parent().addClass('multiselect-all');
}
$('label', $li).append(" " + label);
$('.multiselect-container', this.$container).append($li);
if ($(element).is(':disabled')) {
$checkbox.attr('disabled', 'disabled').prop('disabled', true).parents('li').addClass('disabled');
}
$checkbox.prop('checked', selected);
if (selected && this.options.selectedClass) {
$checkbox.parents('li').addClass(this.options.selectedClass);
}
},
toggleActiveState: function (shouldBeActive) {
if (this.$select.attr('disabled') == undefined) {
$('button.multiselect.dropdown-toggle', this.$container).removeClass('disabled');
} else {
$('button.multiselect.dropdown-toggle', this.$container).addClass('disabled');
}
},
// Add the select all option to the select.
buildSelectAll: function () {
var alreadyHasSelectAll = this.$select[0][0] ? this.$select[0][0].value == this.options.selectAllValue : false;
// If options.includeSelectAllOption === true, add the include all checkbox.
if (this.options.includeSelectAllOption && this.options.multiple && !alreadyHasSelectAll) {
this.$select.prepend('<option value="' + this.options.selectAllValue + '">' + this.options.selectAllText + '</option>');
}
},
// Build the dropdown and bind event handling.
buildDropdown: function () {
this.toggleActiveState();
this.$select.children().each($.proxy(function (index, element) {
// Support optgroups and options without a group simultaneously.
var tag = $(element).prop('tagName').toLowerCase();
if (tag == 'optgroup') {
var group = element;
var groupName = $(group).prop('label');
// Add a header for the group.
var $li = $('<li><label class="multiselect-group"></label></li>');
$('label', $li).text(groupName);
$('.multiselect-container', this.$container).append($li);
// Add the options of the group.
$('option', group).each($.proxy(function (index, element) {
this.createOptionValue(element);
}, this));
} else if (tag == 'option') {
this.createOptionValue(element);
} else {
// Ignore illegal tags.
}
}, this));
// Bind the change event on the dropdown elements.
$('.multiselect-container li input', this.$container).on('change', $.proxy(function (event) {
var checked = $(event.target).prop('checked') || false;
var isSelectAllOption = $(event.target).val() == this.options.selectAllValue;
// Apply or unapply the configured selected class.
if (this.options.selectedClass) {
if (checked) {
$(event.target).parents('li').addClass(this.options.selectedClass);
} else {
$(event.target).parents('li').removeClass(this.options.selectedClass);
}
}
var $option = $('option', this.$select).filter(function () {
return $(this).val() == $(event.target).val();
});
var $optionsNotThis = $('option', this.$select).not($option);
var $checkboxesNotThis = $('input', this.$container).not($(event.target));
// Toggle all options if the select all option was changed.
if (isSelectAllOption) {
$checkboxesNotThis.filter(function () {
return $(this).is(':checked') != checked;
}).trigger('click');
}
if (checked) {
$option.prop('selected', true);
if (this.options.multiple) {
$option.attr('selected', 'selected');
} else {
if (this.options.selectedClass) {
$($checkboxesNotThis).parents('li').removeClass(this.options.selectedClass);
}
$($checkboxesNotThis).prop('checked', false);
$optionsNotThis.removeAttr('selected').prop('selected', false);
// It's a single selection, so close.
$(this.$container).find(".multiselect.dropdown-toggle").click();
}
if (this.options.selectedClass == "active") {
$optionsNotThis.parents("a").css("outline", "");
}
} else {
$option.removeAttr('selected').prop('selected', false);
}
this.updateButtonText();
this.options.onChange($option, checked);
this.$select.change();
if (this.options.preventInputChangeEvent) {
return false;
}
}, this));
$('.multiselect-container li a', this.$container).on('touchstart click', function (event) {
event.stopPropagation();
$(event.target).blur();
});
// Keyboard support.
this.$container.on('keydown', $.proxy(function (event) {
if ($('input[type="text"]', this.$container).is(':focus')) return;
if ((event.keyCode == 9 || event.keyCode == 27) && this.$container.hasClass('open')) {
// Close on tab or escape.
$(this.$container).find(".multiselect.dropdown-toggle").click();
} else {
var $items = $(this.$container).find("li:not(.divider):visible a");
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();
// Override style for items in li:active.
if (this.options.selectedClass == "active") {
$current.css("outline", "thin dotted #333").css("outline", "5px auto -webkit-focus-ring-color");
$items.not($current).css("outline", "");
}
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));
},
// Build and bind filter.
buildFilter: function () {
$('.multiselect-container', this.$container).prepend('<div class="input-prepend"><span class="add-on"><i class="icon-search"></i></span><input class="multiselect-search" type="text" placeholder="' + this.options.filterPlaceholder + '"></div>');
$('.multiselect-search', this.$container).val(this.query).on('click', function (event) {
event.stopPropagation();
}).on('keydown', $.proxy(function (event) {
// This is useful to catch "keydown" events after the browser has
// updated the control.
clearTimeout(this.searchTimeout);
this.searchTimeout = this.asyncFunction($.proxy(function () {
if (this.query != event.target.value) {
this.query = event.target.value;
$.each($('.multiselect-container li', this.$container), $.proxy(function (index, element) {
var value = $('input', element).val();
if (value != this.options.selectAllValue) {
var text = $('label', element).text();
var value = $('input', element).val();
if (value && text && value != this.options.selectAllValue) {
// by default lets assume that element is not
// interesting for this search
var showElement = false;
var filterCandidate = '';
if ((this.options.filterBehavior == 'text' || this.options.filterBehavior == 'both')) {
filterCandidate = text;
}
if ((this.options.filterBehavior == 'value' || this.options.filterBehavior == 'both')) {
filterCandidate = value;
}
if (this.options.enableCaseInsensitiveFiltering && filterCandidate.toLowerCase().indexOf(this.query.toLowerCase()) > -1) {
showElement = true;
} else if (filterCandidate.indexOf(this.query) > -1) {
showElement = true;
}
if (showElement) {
$(element).show();
} else {
$(element).hide();
}
}
}
}, this));
}
}, this), 300, this);
}, this));
},
// Destroy - unbind - the plugin.
destroy: function () {
this.$container.remove();
this.$select.show();
},
// Refreshs the checked options based on the current state of the select.
refresh: function () {
$('option', this.$select).each($.proxy(function (index, element) {
var $input = $('.multiselect-container li input', this.$container).filter(function () {
return $(this).val() == $(element).val();
});
if ($(element).is(':selected')) {
$input.prop('checked', true);
if (this.options.selectedClass) {
$input.parents('li').addClass(this.options.selectedClass);
}
} else {
$input.prop('checked', false);
if (this.options.selectedClass) {
$input.parents('li').removeClass(this.options.selectedClass);
}
}
if ($(element).is(":disabled")) {
$input.attr('disabled', 'disabled').prop('disabled', true).parents('li').addClass('disabled');
} else {
$input.removeAttr('disabled').prop('disabled', false).parents('li').removeClass('disabled');
}
}, this));
this.updateButtonText();
},
// Select an option by its value.
select: function (value) {
var $option = $('option', this.$select).filter(function () {
return $(this).val() == value;
});
var $checkbox = $('.multiselect-container li input', this.$container).filter(function () {
return $(this).val() == value;
});
if (this.options.selectedClass) {
$checkbox.parents('li').addClass(this.options.selectedClass);
}
$checkbox.prop('checked', true);
$option.attr('selected', 'selected').prop('selected', true);
this.updateButtonText();
this.options.onChange($option, true);
},
// Deselect an option by its value.
deselect: function (value) {
var $option = $('option', this.$select).filter(function () {
return $(this).val() == value;
});
var $checkbox = $('.multiselect-container li input', this.$container).filter(function () {
return $(this).val() == value;
});
if (this.options.selectedClass) {
$checkbox.parents('li').removeClass(this.options.selectedClass);
}
$checkbox.prop('checked', false);
$option.removeAttr('selected').prop('selected', false);
this.updateButtonText();
this.options.onChange($option, false);
},
// Rebuild the whole dropdown menu.
rebuild: function () {
$('.multiselect-container', this.$container).html('');
this.buildSelectAll();
this.buildDropdown(this.$select, this.options);
this.updateButtonText();
// Enable filtering.
if (this.options.enableFiltering || this.options.enableCaseInsensitiveFiltering) {
this.buildFilter();
}
},
// Get options by merging defaults and given options.
getOptions: function (options) {
return $.extend({}, this.defaults, options);
},
updateButtonText: function () {
var options = this.getSelected();
// First update the displayed button text.
$('button', this.$container).html(this.options.buttonText(options, this.$select));
// Now update the title attribute of the button.
$('button', this.$container).attr('title', this.options.buttonTitle(options, this.$select));
},
// Get all selected options.
getSelected: function () {
return $('option:selected[value!="' + this.options.selectAllValue + '"]', this.$select);
},
updateOriginalOptions: function () {
this.originalOptions = this.$select.clone()[0].options;
},
asyncFunction: function (callback, timeout, self) {
var args = Array.prototype.slice.call(arguments, 3);
return setTimeout(function () {
callback.apply(self || window, args);
}, timeout);
}
};
$.fn.multiselect = function (option, parameter) {
return this.each(function () {
var data = $(this).data('multiselect'),
options = typeof option == 'object' && option;
// Initialize the multiselect.
if (!data) {
$(this).data('multiselect', (data = new Multiselect(this, options)));
}
// Call multiselect method.
if (typeof option == 'string') {
data[option](parameter);
}
});
};
$.fn.multiselect.Constructor = Multiselect;
$(function () {
$("select[data-role=multiselect]").multiselect();
});
}(window.jQuery);
/**
* MY CODE --------------------------------------------------
* ----------------------------------------------------------
*/
$('#multiSelect').multiselect({
includeSelectAllOption: true,
buttonWidth: '200px',
});
#scrollMe {
height:150px;
background-color:yellow;
overflow-y: auto;
overflow-x:hidden;
padding:20px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<link href="http://netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css" rel="stylesheet"/>
<script src="http://netdna.bootstrapcdn.com/bootstrap/3.0.0/js/bootstrap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/2.3.0/knockout-min.js"></script>
<div class="container">
<!-- Content Table -->
<div class="content">
<div class="row">
<div id="scrollMe" class="col-md-12">
<select id="multiSelect" class="form-control multiselect" multiple="multiple">
<option value="volvo">Volvo</option>
<option value="saab">Saab</option>
<option value="opel">Opel</option>
<option value="audi">Audi</option>
<option value="volvo">Volvo</option>
<option value="saab">Saab</option>
<option value="opel">Opel</option>
<option value="audi">Audi</option>
<option value="volvo">Volvo</option>
<option value="saab">Saab</option>
<option value="opel">Opel</option>
<option value="audi">Audi</option>
</select>
<br>
<br>
<select class="form-control">
<option value="volvo">Volvo</option>
<option value="saab">Saab</option>
<option value="opel">Opel</option>
<option value="audi">Audi</option>
<option value="volvo">Volvo</option>
<option value="saab">Saab</option>
<option value="opel">Opel</option>
<option value="audi">Audi</option>
<option value="volvo">Volvo</option>
<option value="saab">Saab</option>
<option value="opel">Opel</option>
<option value="audi">Audi</option>
</select>
</div>
</div>
</div>
<!-- /content -->
</div>
下拉列表在div中打开,并创建一个不必要的滚动。
答案 0 :(得分:2)
您只需要设置:overflow: inherit !important;
您更新的小提琴:http://jsfiddle.net/kLn28n63/
答案 1 :(得分:1)
您已将css应用于#scrollMe div。只需改变它
#scrollMe {
height: auto;
background-color: yellow;
/* overflow-y: auto; */
/* overflow-x: hidden; */
padding: 20px;
}
请注意我已评论
`/* overflow-y: auto; */`
`/* overflow-x: hidden; */`
答案 2 :(得分:-1)
从.ms-options-wrap > .ms-options
类中删除利润。
.ms-options-wrap > .ms-options{margin-bottom: 0;}