Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

bootstrap drop-down menu auto dropup according to screen position?

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.

like image 915
scooterlord Avatar asked Jan 20 '14 11:01

scooterlord


People also ask

How do I change the position of a drop down menu in Bootstrap?

Use data-offset or data-reference to change the location of the dropdown.

How do I change position in drop down?

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 ).

How do I keep my Bootstrap dropdown open?

Just wrap the contents of the menu in a form tag. That's it.

How do I toggle a drop down menu?

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.


2 Answers

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/

like image 105
Zoltán Tamási Avatar answered Sep 16 '22 15:09

Zoltán Tamási


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);
like image 38
nathan-m Avatar answered Sep 16 '22 15:09

nathan-m