根据标题,有没有办法强制select2始终创建下拉菜单而不是下拉?
当您在下拉列表上方滚动,添加新的CSS类“select2-drop-above”或两者兼而有之时,似乎还有一些javascript导致翻转。
编辑:我应该指定我通过select2-rails拉动库。我希望有一种解决方法,不涉及在我自己拉动整个select2 lib并直接编辑select2.js文件。
答案 0 :(得分:24)
您只需修改select2.js
即可
在哪里说
enoughRoomBelow = dropTop + dropHeight <= viewportBottom,
enoughRoomAbove = (offset.top - dropHeight) >= this.body().scrollTop(),
将其更改为
enoughRoomBelow = true,
enoughRoomAbove = false,
答案 1 :(得分:12)
由于修改源代码不是一个选项,并且为select2:open
事件添加一个钩子不是很优雅,特别是当你在同一个页面中有多个select2实例时,我为{编写了一个小扩展名{1}}插件。
我的实现受到插件存储库(https://github.com/select2/select2/pull/4618)中尚未合并的PR的启发。
基本上,以下代码会覆盖处理下拉列表定位的原始插件函数,并添加一个新选项(Select2
)以强制下拉/下方定位下拉列表。
新的dropdownPosition
选项可以采用以下值:
- dropdownPosition
- 下拉列表始终显示在输入的底部;
- below
- 下拉列表始终显示在输入的顶部;
- above
(默认值) - 它使用旧行为。
只需在auto
文件后插入以下代码:
select2.js
使用以下内容初始化插件:
(function($) {
var Defaults = $.fn.select2.amd.require('select2/defaults');
$.extend(Defaults.defaults, {
dropdownPosition: 'auto'
});
var AttachBody = $.fn.select2.amd.require('select2/dropdown/attachBody');
var _positionDropdown = AttachBody.prototype._positionDropdown;
AttachBody.prototype._positionDropdown = function() {
var $window = $(window);
var isCurrentlyAbove = this.$dropdown.hasClass('select2-dropdown--above');
var isCurrentlyBelow = this.$dropdown.hasClass('select2-dropdown--below');
var newDirection = null;
var offset = this.$container.offset();
offset.bottom = offset.top + this.$container.outerHeight(false);
var container = {
height: this.$container.outerHeight(false)
};
container.top = offset.top;
container.bottom = offset.top + container.height;
var dropdown = {
height: this.$dropdown.outerHeight(false)
};
var viewport = {
top: $window.scrollTop(),
bottom: $window.scrollTop() + $window.height()
};
var enoughRoomAbove = viewport.top < (offset.top - dropdown.height);
var enoughRoomBelow = viewport.bottom > (offset.bottom + dropdown.height);
var css = {
left: offset.left,
top: container.bottom
};
// Determine what the parent element is to use for calciulating the offset
var $offsetParent = this.$dropdownParent;
// For statically positoned elements, we need to get the element
// that is determining the offset
if ($offsetParent.css('position') === 'static') {
$offsetParent = $offsetParent.offsetParent();
}
var parentOffset = $offsetParent.offset();
css.top -= parentOffset.top
css.left -= parentOffset.left;
var dropdownPositionOption = this.options.get('dropdownPosition');
if (dropdownPositionOption === 'above' || dropdownPositionOption === 'below') {
newDirection = dropdownPositionOption;
} else {
if (!isCurrentlyAbove && !isCurrentlyBelow) {
newDirection = 'below';
}
if (!enoughRoomBelow && enoughRoomAbove && !isCurrentlyAbove) {
newDirection = 'above';
} else if (!enoughRoomAbove && enoughRoomBelow && isCurrentlyAbove) {
newDirection = 'below';
}
}
if (newDirection == 'above' ||
(isCurrentlyAbove && newDirection !== 'below')) {
css.top = container.top - parentOffset.top - dropdown.height;
}
if (newDirection != null) {
this.$dropdown
.removeClass('select2-dropdown--below select2-dropdown--above')
.addClass('select2-dropdown--' + newDirection);
this.$container
.removeClass('select2-container--below select2-container--above')
.addClass('select2-container--' + newDirection);
}
this.$dropdownContainer.css(css);
};
})(window.jQuery);
这里小提琴: https://jsfiddle.net/byxj73ov/
Github存储库: https://github.com/andreivictor/select2-dropdownPosition
答案 2 :(得分:5)
您可以通过覆盖CSS来实现:
.select-dropdown {
position: static;
}
.select-dropdown .select-dropdown--above {
margin-top: 336px;
}
答案 3 :(得分:4)
我曾经为此找到一个更简单/更快的解决方案:
$("select").select2({
// Options
}).on('select2:open',function(){
$('.select2-dropdown--above').attr('id','fix');
$('#fix').removeClass('select2-dropdown--above');
$('#fix').addClass('select2-dropdown--below');
});
很简单,你只需将 .select2-dropdown - 上面更改为打开事件中 .select2-dropdown - 下面 (SELECT2:打开)。
它只能在事件下工作,并且可以有许多其他方法来执行它只是在打开选择时更改类。
PS。如果您尝试使用jquery填充select,它将无法工作。
答案 4 :(得分:3)
如您所述,不首选修改插件。我有一个类似的问题,无法找到使用select2
选项强制下拉列表保持在下方的方法。我最终得到的解决方案如下:
$("#mySelect2").select2({ ...options... })
.on('select2-open', function() {
// however much room you determine you need to prevent jumping
var requireHeight = 600;
var viewportBottom = $(window).scrollTop() + $(window).height();
// figure out if we need to make changes
if (viewportBottom < requireHeight)
{
// determine how much padding we should add (via marginBottom)
var marginBottom = requireHeight - viewportBottom;
// adding padding so we can scroll down
$(".aLwrElmntOrCntntWrppr").css("marginBottom", marginBottom + "px");
// animate to just above the select2, now with plenty of room below
$('html, body').animate({
scrollTop: $("#mySelect2").offset().top - 10
}, 1000);
}
});
此代码确定是否有足够的空间将下拉列表放在底部,如果没有,则通过向页面上的某个元素添加margin-bottom来创建它。然后它滚动到select2的正上方,这样下拉列表就不会翻转。
答案 5 :(得分:1)
从[shanabus]回复
更新jQuery("#line_item").select2({
formatResult: Invoice.formatLineItem
})
.on('select2-open', function() {
// however much room you determine you need to prevent jumping
var requireHeight = $("#select2-drop").height()+10;
var viewportBottom = $(window).height() - $("#line_item").offset().top;
// figure out if we need to make changes
if (viewportBottom < requireHeight)
{
// determine how much padding we should add (via marginBottom)
var marginBottom = requireHeight - viewportBottom;
// adding padding so we can scroll down
$(".aLwrElmntOrCntntWrppr").css("marginBottom", marginBottom + "px");
// animate to just above the select2, now with plenty of room below
$('html, body').animate({
scrollTop: $("#select2-drop").offset().top - 10
}, 1000);
}
});
答案 6 :(得分:0)
看起来在 CSS 中强制使底部值自动也可以做到这一点。我使用了以下代码,它对我来说很好用。
.my_select_picker_trigger.dropup .dropdown-menu {
bottom: auto !important;
}