2014-01-20 36 views
12

我想知道你們中的任何一個人是否有我要求準備的東西,以免我的麻煩。我在尋找的是一個下拉菜單,根據它在屏幕上的位置自動添加dropup類,並且當用戶滾動窗口或調整窗口大小時也會自動更改。引導下拉菜單根據屏幕位置自動上傳?

我在找的東西已經在bootstrap-select插件中實現了,但是插件太「重」了。

+0

您是否要求我們推薦或找到工具庫? – pbenard

+0

我在問,但我一直在這個工作在過去一個小時,所以我想我可能接近 – scooterlord

回答

6

編輯:用正確的解決方案替換:

dropup = function() { 
$(".dropdown-toggle").each(function(){ 
par=$(this).parents('.btn-group'); 
dropl=par.find('ul'); 
otop=$(this).offset().top+$(this).height()-$(window).scrollTop(); 
ulh=dropl.height(); 
obot=$(window).height()-$(this).height()-$(this).offset().top+$(window).scrollTop(); 

if ((obot < ulh) && (otop > ulh)) { 
par.addClass('dropup'); 
} else { 
par.removeClass('dropup'); 
} 

}); 
} 

$(window).load(dropup); 
$(window).bind('resize scroll touchstart touchmove mousewheel', dropup); 
+1

我認爲你應該對你的第一個問題做一個完整的編輯,並將這個(你的評論)答案整合到你編輯的問題中。也許downvote是因爲你只是要求找到一個沒有代碼或其他東西的工具... – pbenard

+0

不得不根據我的需求做一些修改就像一個魅力! :) – LegendaryAks

10

我曾與大型網頁所提供的答案的性能問題。

我通過使用getBoundingClientRect()「增強」了它,併爲包含陰影的特定.btn-group添加了一個新類。 btn-group-dropup

您的里程可能會有所不同。

(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); 
2

不是每次菜單中的每個菜單都會改變裁切邊界,爲什麼不採取JIT方法呢?

<body> 
    <div id="viewport-proxy" style="visibility:hidden; 
    position:absolute; height:100%; width:100%; margin:0; padding:0; 
    top:0; left: 0; right:0; bottom:0;"></div> 
... 

var w = window, d = document, e = d.documentElement; 
var g = d.getElementsByTagName('body')[0]; 
function appHeight() { 
    var a = w.innerHeight || e.clientHeight || g.clientHeight; 
    var b = $("#viewport-proxy").height(); 
    return a < b ? a : b; 
}; 

$(".dropdown").on('show.bs.dropdown', function() { 
    var windowHeight = appHeight(); 
    var rect = this.getBoundingClientRect(); 
    if (rect.top > windowHeight) return; 
    var menuHeight = $(this).children('.dropdown-menu').height(); 
    $(this).toggleClass("dropup", 
     ((windowHeight - rect.bottom) < menuHeight) && 
     (rect.top > menuHeight)); 
    }); 

很明顯,您必須在菜單進出時管理事件綁定。在Nathan的答案變成上述的Durandal應用程序中,每個代表數據的行都有一個上下文菜單。我在數據加載時創建綁定,將它們保留在視圖模型中並在停用時銷燬它們。我不需要在激活時重新創建它們,因爲它會調用數據加載例程,然後創建綁定。所以它的早期加載,並且影響到所有的意見

$(window).on("scroll resize", function() { $(".dropdown.open").dropdown("toggle"); }); 

你把這個在shell.js:

我還添加了這一點。如果它不是很明顯,那麼當窗口滾動或調整大小時,關閉所有打開的dropup。這符合Windows約定,並且在發生調整大小或滾動事件時不必重新計算定位。

請注意appHeight函數。即使jQuery未能準確地報告手機窗口高度,但appHeight在我迄今爲止測試過的每個平臺和瀏覽器(IE,Ch,FF桌面,IE,Ch,Sa mobile)上都能正常工作。

在其當前版本中,它測量了一個絕對定位的隱藏div集合以填充視口。這適用於Android Chrome,但不適用IE,而代碼中顯示的其他方法適用於IE,但不適用於Android Chrome,因此我使用這兩種方法並使用較低的數字。

在我的Durandal應用程序中,該功能是作爲應用程序對象的高度方法實現的,但爲了簡潔明瞭,我展示了示例代碼。

+0

+1我正在考慮類似的東西,海事組織是比靜態處理菜單更好,更優雅的方法。 –

14

有點晚,但因爲與其他人不太一樣,下面是我的bootstrap 3的解決方案。它適用於頁面上的所有下拉菜單,也可以是動態創建或加載的下拉菜單。

請注意,我必須使用shown.bs.dropdown事件,因爲尺寸僅在該點準備就緒。如果需要的話

$(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"); 
}); 

一個可以很容易地@PeterWone's app height巫術改進,目前這是工作不夠好,對我來說。

UPDATE

這裏是代表該解決方案小提琴:http://jsfiddle.net/3s2efe9u/

+0

你能舉一個小提琴的例子嗎?這似乎不適用於我的案件。 – bard

+0

@bard在這裏你是http://jsfiddle.net/3s2efe9u/ –

+0

這對我來說工作得很好。 –

1

我知道這是一個老問題,但它是在谷歌高了結果,因此這裏的另一個簡單的解決方案爲我工作。請在if聲明中調整150,以確保您的下拉列表需要多大的空間。

var dropUp = function() { 
    var windowHeight = $(window).innerHeight(); 
    var pageScroll = $('body').scrollTop(); 

    $(".your-dropdown").each(function() { 
     var offset = $(this).offset().top; 
     var space = windowHeight - (offset - pageScroll); 

     if(space < 150) { 
      $(this).addClass("dropup"); 
     } else { 
      $(this).removeClass("dropup"); 
     } 
    }); 
} 

$(window).load(dropUp); 
$(window).bind('resize scroll mousewheel', dropUp); 
0

我發現從佐爾坦陶馬希的答案是一個很好的起點,但還不夠,當下拉應該用垂直滾動條一個div內出現。我需要該div的高度(下面代碼中的scrollHeight變量)來確定下拉菜單是否會佔用底部的很多空間。

jquery(document).on("show.bs.dropdown", ".dropdown", function() { 
    var $ul = jquery(this).children(".dropdown-menu"); 
    var menuHeight = $ul.height() 
    var buttonHeight = jquery(this).children(".dropdown-toggle").height(); 
    var scrollHeight = $ul.parent().offsetParent().height(); 
    var menuAnchorTop = $ul.parent().position().top + buttonHeight; 

    // how much space would be left at the top 
    var spaceUp = (menuAnchorTop - buttonHeight - menuHeight); 
    // how much space would be left at the bottom 
    var spaceDown = scrollHeight - (menuAnchorTop + menuHeight); 
    // Switch to dropup if more space there 
    if (spaceDown < 0 && (spaceUp >= 0 || spaceUp > spaceDown)) 
    jquery(this).addClass("dropup"); 
}).on("hidden.bs.dropdown", ".dropdown", function() { 
    // always reset after close 
    jquery(this).removeClass("dropup"); 
});