I was wondering if any of you has what I am asking for ready, to save me from the trouble. What I am looking for is for a dropdown menu to have the dropup class automatically added according to its position on the screen - and also change automatically when the user scrolls or resizes window.
What I am looking for is already implemented in the bootstrap-select plugin, but the plugin is too 'heavy' to use.
Use data-offset or data-reference to change the location of the dropdown.
Wrap a <div> element around the elements to position the dropdown content correctly with CSS. CSS) The . dropdown class uses position:relative , which is needed when we want the dropdown content to be placed right below the dropdown button (using position:absolute ).
Just wrap the contents of the menu in a form tag. That's it.
dropdown class indicates a dropdown menu. To open the dropdown menu, use a button or a link with a class of . dropdown-toggle and the data-toggle="dropdown" attribute.
A bit late, but because is quite different from others, here is my solution for bootstrap 3. It applies globally to all dropdowns on the page, also those created or loaded dynamically.
Note that I had to use the shown.bs.dropdown
event because the dimensions are ready only at that point.
$(document).on("shown.bs.dropdown", ".dropdown", function () { // calculate the required sizes, spaces var $ul = $(this).children(".dropdown-menu"); var $button = $(this).children(".dropdown-toggle"); var ulOffset = $ul.offset(); // how much space would be left on the top if the dropdown opened that direction var spaceUp = (ulOffset.top - $button.height() - $ul.height()) - $(window).scrollTop(); // how much space is left at the bottom var spaceDown = $(window).scrollTop() + $(window).height() - (ulOffset.top + $ul.height()); // switch to dropup only if there is no space at the bottom AND there is space at the top, or there isn't either but it would be still better fit if (spaceDown < 0 && (spaceUp >= 0 || spaceUp > spaceDown)) $(this).addClass("dropup"); }).on("hidden.bs.dropdown", ".dropdown", function() { // always reset after close $(this).removeClass("dropup"); });
One could easily improve it with @PeterWone's app height wizardry if needed, currently this was working well enough for me.
UPDATE
Here is a fiddle representing this solution: http://jsfiddle.net/3s2efe9u/
I had performance issues with the provided answer on large pages.
I've "improved" it by using getBoundingClientRect()
, and adding a new class to specific .btn-group
's that contain dropdows., eg. btn-group-dropup
.
Your mileage may vary.
(function() {
// require menu height + margin, otherwise convert to drop-up
var dropUpMarginBottom = 100;
function dropUp() {
var windowHeight = $(window).height();
$(".btn-group-dropup").each(function() {
var dropDownMenuHeight,
rect = this.getBoundingClientRect();
// only toggle menu's that are visible on the current page
if (rect.top > windowHeight) {
return;
}
// if you know height of menu - set on parent, eg. `data-menu="100"`
dropDownMenuHeight = $(this).data('menu');
if (dropDownMenuHeight == null) {
dropDownMenuHeight = $(this).children('.dropdown-menu').height();
}
$(this).toggleClass("dropup", ((windowHeight - rect.bottom) < (dropDownMenuHeight + dropUpMarginBottom)) && (rect.top > dropDownMenuHeight));
});
};
// bind to load & scroll - but debounce scroll with `underscorejs`
$(window).bind({
"resize scroll touchstart touchmove mousewheel": _.debounce(dropUp, 100),
"load": dropUp
});
}).call(this);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With