2013-11-14 29 views
16

按照標題,是否有辦法強制select2始終創建下拉菜單而不是drop-up?防止select2向上翻轉下拉菜單

似乎還有一些JavaScript會導致翻頁,當您在下拉菜單上方滾動時,添加一個新的CSS類「select2-drop-above」或兩者。

編輯:我應該指定我通過select2-rails拉圖書館。我希望有一種方法可以解決這個問題,它不涉及在我自己內部提取整個select2庫並直接編輯select2.js文件。

回答

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); 
     } 
    }); 

此代碼確定是否有足夠的空間來放置下拉列表的底部,如果不通過增加下邊距到頁面上的某些元素創建它。然後滾動到select2上方,以便下拉不會翻轉。

+0

這似乎並不適用於我:http://jsfiddle.net/brunodd/jEADR/2006/ – brunodd

+0

我不確定你的意思,它適用於我的Chrome – shanabus

+1

我使用的版本是4.0和這一個仍然是3.我已經修好了。 http://jsfiddle.net/brunodd/jEADR/2009 – brunodd

18

您只需編輯select2.js


凡說

enoughRoomBelow = dropTop + dropHeight <= viewportBottom, 
enoughRoomAbove = (offset.top - dropHeight) >= this.body().scrollTop(), 

只是將其更改爲

enoughRoomBelow = true, 
enoughRoomAbove = false, 
+10

但是這意味着您在考慮將來升級select2時需要記住這一點。所以要小心這個。 – MarkoHiel

+1

你永遠不應該修改源腳本,否則你會遇到問題。 – cmfolio

+0

不幸的是,這是唯一能夠解決這個問題的方法(使用ajax查詢並關閉select)。一個公共關係已被創建來解決這個問題,但尚未合併:https://github.com/select2/select2/pull/4560 –

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); 
      } 
     }); 
+0

什麼是$(「。aLwrElmntOrCntntWrppr」) – Jaskey

3

我用來尋找,一個更容易/更快的解決方案:

 $("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:open)。

它只會在該事件下工作,並且可以有許多其他方式來執行它,只是在打開選擇時更改類。

ps。如果您嘗試使用jquery填充您的選擇,它將不起作用。

+0

不起作用,因爲select2增加了一些頂級值的內聯css – Ben

+0

嗯,它對我來說很有用。乾杯。 – 2016-01-02 21:19:51

+0

不知道如何可能與關聯元素的內聯最大值 – Ben

2

您可以通過覆蓋CSS像這樣做:

.select-dropdown { 
    position: static; 
} 
.select-dropdown .select-dropdown--above { 
     margin-top: 336px; 
} 
2

由於修改源代碼是不是一種選擇,並增加了鉤到select2:open事件是不是很優雅,尤其是當你有多個選擇2實例在同一頁面中,我爲Select2插件寫了一個小擴展。

我的實現靈感來自尚未合併的插件存儲庫(https://github.com/select2/select2/pull/4618)中的PR。

基本上,下面的代碼覆蓋了處理下拉定位的原始插件函數,並添加了一個新選項(dropdownPosition)來強制上/下的下拉定位。

新的dropdownPosition選項可以取下列值: - below - 下拉總是顯示在輸入的底部; - above - 下拉總是顯示在輸入的頂部; - auto(默認) - 它使用舊的行爲。

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

有如下初始化插件:

$(document).ready(function() { 
    $(".select-el").select2({ 
    dropdownPosition: 'below' 
    }); 
}); 

小提琴這裏: https://jsfiddle.net/byxj73ov/

Github上庫: https://github.com/andreivictor/select2-dropdownPosition

select2.js文件只需插入下面的代碼