2017-07-19 79 views
0

Multiselect下拉z-index在滾動容器div內不起作用。它顯示滾動而不是像另一個下拉菜單那樣打開它。Multiselect Dropdown z-index在滾動容器div內不起作用

樣品的編號: 「http://jsfiddle.net/rousseauo/acg2Lco8/

// Helped by the code of : pete-experimenter 
 
// Due to bootstrap-multiselect.js not being available on CDN, it's included first below. 
 
// My code begins on line 570 
 

 

 
/** 
 
* bootstrap-multiselect.js 1.0.0 
 
* https://github.com/davidstutz/bootstrap-multiselect 
 
* 
 
* Copyright 2012, 2013 David Stutz 
 
* 
 
* Dual licensed under the BSD-3-Clause and the Apache License, Version 2.0. 
 
* See the README. 
 
*/! function ($) { 
 
    "use strict"; // jshint ;_; 
 

 
    if (typeof ko != 'undefined' && ko.bindingHandlers && !ko.bindingHandlers.multiselect) { 
 
     ko.bindingHandlers.multiselect = { 
 
      init: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {}, 
 
      update: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) { 
 
       var ms = $(element).data('multiselect'); 
 
       if (!ms) { 
 
        $(element).multiselect(ko.utils.unwrapObservable(valueAccessor())); 
 
       } else if (allBindingsAccessor().options && allBindingsAccessor().options().length !== ms.originalOptions.length) { 
 
        ms.updateOriginalOptions(); 
 
        $(element).multiselect('rebuild'); 
 
       } 
 
      } 
 
     }; 
 
    } 
 

 
    function Multiselect(select, options) { 
 

 
     this.options = this.getOptions(options); 
 
     this.$select = $(select); 
 
     this.originalOptions = this.$select.clone()[0].options; 
 
     //we have to clone to create a new reference 
 
     this.query = ''; 
 
     this.searchTimeout = null; 
 

 
     this.options.multiple = this.$select.attr('multiple') == "multiple"; 
 

 
     this.$container = $(this.options.buttonContainer).append('<button type="button" class="multiselect dropdown-toggle ' + this.options.buttonClass + '" data-toggle="dropdown">' + this.options.buttonText(this.getSelected(), this.$select) + '</button>') 
 
      .append('<ul class="multiselect-container dropdown-menu' + (this.options.dropRight ? ' pull-right' : '') + '"></ul>'); 
 

 
     // Manually add button width if set. 
 
     if (this.options.buttonWidth) { 
 
      $('button', this.$container).css({ 
 
       'width': this.options.buttonWidth 
 
      }); 
 
     } 
 

 
     // Keep the tab index from the select. 
 
     var tabindex = this.$select.attr('tabindex'); 
 
     if (tabindex) { 
 
      $('button', this.$container).attr('tabindex', tabindex); 
 
     } 
 

 
     // Set max height of dropdown menu to activate auto scrollbar. 
 
     if (this.options.maxHeight) { 
 
      // TODO: Add a class for this option to move the css declarations. 
 
      $('.multiselect-container', this.$container).css({ 
 
       'max-height': this.options.maxHeight + 'px', 
 
        'overflow-y': 'auto', 
 
        'overflow-x': 'hidden' 
 
      }); 
 
     } 
 

 
     // Enable filtering. 
 
     if (this.options.enableFiltering || this.options.enableCaseInsensitiveFiltering) { 
 
      var enableFilterLength = Math.max(this.options.enableFiltering, this.options.enableCaseInsensitiveFiltering); 
 
      if (this.$select.find('option').length >= enableFilterLength) { 
 
       this.buildFilter(); 
 
      } 
 
     } 
 

 
     // Build select all if enabled. 
 
     this.buildSelectAll(); 
 
     this.buildDropdown(); 
 
     this.updateButtonText(); 
 

 
     this.$select.hide().after(this.$container); 
 
    }; 
 

 
    Multiselect.prototype = { 
 

 
     defaults: { 
 
      // Default text function will either print 'None selected' in case no 
 
      // option is selected, or a list of the selected options up to a length of 3 selected options. 
 
      // If more than 3 options are selected, the number of selected options is printed. 
 
      buttonText: function (options, select) { 
 
       if (options.length == 0) { 
 
        return this.nonSelectedText + '<b class="caret"></b>'; 
 
       } else if (options.length > 3) { 
 
        return options.length + ' ' + this.nSelectedText + ' <b class="caret"></b>'; 
 
       } else { 
 
        var selected = ''; 
 
        options.each(function() { 
 
         var label = ($(this).attr('label') !== undefined) ? $(this).attr('label') : $(this).html(); 
 

 
         selected += label + ', '; 
 
        }); 
 
        return selected.substr(0, selected.length - 2) + ' <b class="caret"></b>'; 
 
       } 
 
      }, 
 
      // Like the buttonText option to update the title of the button. 
 
      buttonTitle: function (options, select) { 
 
       var selected = ''; 
 
       options.each(function() { 
 
        selected += $(this).text() + ', '; 
 
       }); 
 
       return selected.substr(0, selected.length - 2); 
 
      }, 
 
      // Is triggered on change of the selected options. 
 
      onChange: function (option, checked) { 
 

 
      }, 
 
      buttonClass: 'btn', 
 
      dropRight: false, 
 
      selectedClass: 'active', 
 
      buttonWidth: 'auto', 
 
      buttonContainer: '<div class="btn-group" />', 
 
      // Maximum height of the dropdown menu. 
 
      // If maximum height is exceeded a scrollbar will be displayed. 
 
      maxHeight: false, 
 
      includeSelectAllOption: false, 
 
      selectAllText: ' Select all', 
 
      selectAllValue: 'multiselect-all', 
 
      enableFiltering: false, 
 
      enableCaseInsensitiveFiltering: false, 
 
      filterPlaceholder: 'Search', 
 
      // possible options: 'text', 'value', 'both' 
 
      filterBehavior: 'text', 
 
      preventInputChangeEvent: false, 
 
      nonSelectedText: 'None selected', 
 
      nSelectedText: 'selected' 
 
     }, 
 

 
     constructor: Multiselect, 
 

 
     // Will build an dropdown element for the given option. 
 
     createOptionValue: function (element) { 
 
      if ($(element).is(':selected')) { 
 
       $(element).attr('selected', 'selected').prop('selected', true); 
 
      } 
 

 
      // Support the label attribute on options. 
 
      var label = $(element).attr('label') || $(element).html(); 
 
      var value = $(element).val(); 
 
      var inputType = this.options.multiple ? "checkbox" : "radio"; 
 

 
      var $li = $('<li><a href="javascript:void(0);"><label class="' + inputType + '"><input type="' + inputType + '" /></label></a></li>'); 
 

 
      var selected = $(element).prop('selected') || false; 
 
      var $checkbox = $('input', $li); 
 
      $checkbox.val(value); 
 

 
      if (value == this.options.selectAllValue) { 
 
       $checkbox.parent().parent().addClass('multiselect-all'); 
 
      } 
 

 
      $('label', $li).append(" " + label); 
 

 
      $('.multiselect-container', this.$container).append($li); 
 

 
      if ($(element).is(':disabled')) { 
 
       $checkbox.attr('disabled', 'disabled').prop('disabled', true).parents('li').addClass('disabled'); 
 
      } 
 

 
      $checkbox.prop('checked', selected); 
 

 
      if (selected && this.options.selectedClass) { 
 
       $checkbox.parents('li').addClass(this.options.selectedClass); 
 
      } 
 
     }, 
 

 
     toggleActiveState: function (shouldBeActive) { 
 
      if (this.$select.attr('disabled') == undefined) { 
 
       $('button.multiselect.dropdown-toggle', this.$container).removeClass('disabled'); 
 
      } else { 
 
       $('button.multiselect.dropdown-toggle', this.$container).addClass('disabled'); 
 
      } 
 
     }, 
 

 
     // Add the select all option to the select. 
 
     buildSelectAll: function() { 
 
      var alreadyHasSelectAll = this.$select[0][0] ? this.$select[0][0].value == this.options.selectAllValue : false; 
 

 
      // If options.includeSelectAllOption === true, add the include all checkbox. 
 
      if (this.options.includeSelectAllOption && this.options.multiple && !alreadyHasSelectAll) { 
 
       this.$select.prepend('<option value="' + this.options.selectAllValue + '">' + this.options.selectAllText + '</option>'); 
 
      } 
 
     }, 
 

 
     // Build the dropdown and bind event handling. 
 
     buildDropdown: function() { 
 
      this.toggleActiveState(); 
 

 
      this.$select.children().each($.proxy(function (index, element) { 
 
       // Support optgroups and options without a group simultaneously. 
 
       var tag = $(element).prop('tagName').toLowerCase(); 
 
       if (tag == 'optgroup') { 
 
        var group = element; 
 
        var groupName = $(group).prop('label'); 
 

 
        // Add a header for the group. 
 
        var $li = $('<li><label class="multiselect-group"></label></li>'); 
 
        $('label', $li).text(groupName); 
 
        $('.multiselect-container', this.$container).append($li); 
 

 
        // Add the options of the group. 
 
        $('option', group).each($.proxy(function (index, element) { 
 
         this.createOptionValue(element); 
 
        }, this)); 
 
       } else if (tag == 'option') { 
 
        this.createOptionValue(element); 
 
       } else { 
 
        // Ignore illegal tags. 
 
       } 
 
      }, this)); 
 

 
      // Bind the change event on the dropdown elements. 
 
      $('.multiselect-container li input', this.$container).on('change', $.proxy(function (event) { 
 
       var checked = $(event.target).prop('checked') || false; 
 
       var isSelectAllOption = $(event.target).val() == this.options.selectAllValue; 
 

 
       // Apply or unapply the configured selected class. 
 
       if (this.options.selectedClass) { 
 
        if (checked) { 
 
         $(event.target).parents('li').addClass(this.options.selectedClass); 
 
        } else { 
 
         $(event.target).parents('li').removeClass(this.options.selectedClass); 
 
        } 
 
       } 
 

 
       var $option = $('option', this.$select).filter(function() { 
 
        return $(this).val() == $(event.target).val(); 
 
       }); 
 

 
       var $optionsNotThis = $('option', this.$select).not($option); 
 
       var $checkboxesNotThis = $('input', this.$container).not($(event.target)); 
 

 
       // Toggle all options if the select all option was changed. 
 
       if (isSelectAllOption) { 
 
        $checkboxesNotThis.filter(function() { 
 
         return $(this).is(':checked') != checked; 
 
        }).trigger('click'); 
 
       } 
 

 
       if (checked) { 
 
        $option.prop('selected', true); 
 

 
        if (this.options.multiple) { 
 
         $option.attr('selected', 'selected'); 
 
        } else { 
 
         if (this.options.selectedClass) { 
 
          $($checkboxesNotThis).parents('li').removeClass(this.options.selectedClass); 
 
         } 
 

 
         $($checkboxesNotThis).prop('checked', false); 
 

 
         $optionsNotThis.removeAttr('selected').prop('selected', false); 
 

 
         // It's a single selection, so close. 
 
         $(this.$container).find(".multiselect.dropdown-toggle").click(); 
 
        } 
 

 
        if (this.options.selectedClass == "active") { 
 
         $optionsNotThis.parents("a").css("outline", ""); 
 
        } 
 

 
       } else { 
 
        $option.removeAttr('selected').prop('selected', false); 
 
       } 
 

 
       this.updateButtonText(); 
 

 
       this.options.onChange($option, checked); 
 

 
       this.$select.change(); 
 

 
       if (this.options.preventInputChangeEvent) { 
 
        return false; 
 
       } 
 
      }, this)); 
 

 
      $('.multiselect-container li a', this.$container).on('touchstart click', function (event) { 
 
       event.stopPropagation(); 
 
       $(event.target).blur(); 
 
      }); 
 

 
      // Keyboard support. 
 
      this.$container.on('keydown', $.proxy(function (event) { 
 
       if ($('input[type="text"]', this.$container).is(':focus')) return; 
 
       if ((event.keyCode == 9 || event.keyCode == 27) && this.$container.hasClass('open')) { 
 
        // Close on tab or escape. 
 
        $(this.$container).find(".multiselect.dropdown-toggle").click(); 
 
       } else { 
 
        var $items = $(this.$container).find("li:not(.divider):visible a"); 
 

 
        if (!$items.length) { 
 
         return; 
 
        } 
 

 
        var index = $items.index($items.filter(':focus')); 
 

 
        // Navigation up. 
 
        if (event.keyCode == 38 && index > 0) { 
 
         index--; 
 
        } 
 
        // Navigate down. 
 
        else if (event.keyCode == 40 && index < $items.length - 1) { 
 
         index++; 
 
        } else if (!~index) { 
 
         index = 0; 
 
        } 
 

 
        var $current = $items.eq(index); 
 
        $current.focus(); 
 

 
        // Override style for items in li:active. 
 
        if (this.options.selectedClass == "active") { 
 
         $current.css("outline", "thin dotted #333").css("outline", "5px auto -webkit-focus-ring-color"); 
 

 
         $items.not($current).css("outline", ""); 
 
        } 
 

 
        if (event.keyCode == 32 || event.keyCode == 13) { 
 
         var $checkbox = $current.find('input'); 
 

 
         $checkbox.prop("checked", !$checkbox.prop("checked")); 
 
         $checkbox.change(); 
 
        } 
 

 
        event.stopPropagation(); 
 
        event.preventDefault(); 
 
       } 
 
      }, this)); 
 
     }, 
 

 
     // Build and bind filter. 
 
     buildFilter: function() { 
 
      $('.multiselect-container', this.$container).prepend('<div class="input-prepend"><span class="add-on"><i class="icon-search"></i></span><input class="multiselect-search" type="text" placeholder="' + this.options.filterPlaceholder + '"></div>'); 
 

 
      $('.multiselect-search', this.$container).val(this.query).on('click', function (event) { 
 
       event.stopPropagation(); 
 
      }).on('keydown', $.proxy(function (event) { 
 
       // This is useful to catch "keydown" events after the browser has 
 
       // updated the control. 
 
       clearTimeout(this.searchTimeout); 
 

 
       this.searchTimeout = this.asyncFunction($.proxy(function() { 
 

 
        if (this.query != event.target.value) { 
 
         this.query = event.target.value; 
 

 
         $.each($('.multiselect-container li', this.$container), $.proxy(function (index, element) { 
 
          var value = $('input', element).val(); 
 
          if (value != this.options.selectAllValue) { 
 
           var text = $('label', element).text(); 
 
           var value = $('input', element).val(); 
 
           if (value && text && value != this.options.selectAllValue) { 
 
            // by default lets assume that element is not 
 
            // interesting for this search 
 
            var showElement = false; 
 

 
            var filterCandidate = ''; 
 
            if ((this.options.filterBehavior == 'text' || this.options.filterBehavior == 'both')) { 
 
             filterCandidate = text; 
 
            } 
 
            if ((this.options.filterBehavior == 'value' || this.options.filterBehavior == 'both')) { 
 
             filterCandidate = value; 
 
            } 
 

 
            if (this.options.enableCaseInsensitiveFiltering && filterCandidate.toLowerCase().indexOf(this.query.toLowerCase()) > -1) { 
 
             showElement = true; 
 
            } else if (filterCandidate.indexOf(this.query) > -1) { 
 
             showElement = true; 
 
            } 
 

 
            if (showElement) { 
 
             $(element).show(); 
 
            } else { 
 
             $(element).hide(); 
 
            } 
 
           } 
 
          } 
 
         }, this)); 
 
        } 
 
       }, this), 300, this); 
 
      }, this)); 
 
     }, 
 

 
     // Destroy - unbind - the plugin. 
 
     destroy: function() { 
 
      this.$container.remove(); 
 
      this.$select.show(); 
 
     }, 
 

 
     // Refreshs the checked options based on the current state of the select. 
 
     refresh: function() { 
 
      $('option', this.$select).each($.proxy(function (index, element) { 
 
       var $input = $('.multiselect-container li input', this.$container).filter(function() { 
 
        return $(this).val() == $(element).val(); 
 
       }); 
 

 
       if ($(element).is(':selected')) { 
 
        $input.prop('checked', true); 
 

 
        if (this.options.selectedClass) { 
 
         $input.parents('li').addClass(this.options.selectedClass); 
 
        } 
 
       } else { 
 
        $input.prop('checked', false); 
 

 
        if (this.options.selectedClass) { 
 
         $input.parents('li').removeClass(this.options.selectedClass); 
 
        } 
 
       } 
 

 
       if ($(element).is(":disabled")) { 
 
        $input.attr('disabled', 'disabled').prop('disabled', true).parents('li').addClass('disabled'); 
 
       } else { 
 
        $input.removeAttr('disabled').prop('disabled', false).parents('li').removeClass('disabled'); 
 
       } 
 
      }, this)); 
 

 
      this.updateButtonText(); 
 
     }, 
 

 
     // Select an option by its value. 
 
     select: function (value) { 
 
      var $option = $('option', this.$select).filter(function() { 
 
       return $(this).val() == value; 
 
      }); 
 
      var $checkbox = $('.multiselect-container li input', this.$container).filter(function() { 
 
       return $(this).val() == value; 
 
      }); 
 

 
      if (this.options.selectedClass) { 
 
       $checkbox.parents('li').addClass(this.options.selectedClass); 
 
      } 
 

 
      $checkbox.prop('checked', true); 
 

 
      $option.attr('selected', 'selected').prop('selected', true); 
 

 
      this.updateButtonText(); 
 
      this.options.onChange($option, true); 
 
     }, 
 

 
     // Deselect an option by its value. 
 
     deselect: function (value) { 
 
      var $option = $('option', this.$select).filter(function() { 
 
       return $(this).val() == value; 
 
      }); 
 
      var $checkbox = $('.multiselect-container li input', this.$container).filter(function() { 
 
       return $(this).val() == value; 
 
      }); 
 

 
      if (this.options.selectedClass) { 
 
       $checkbox.parents('li').removeClass(this.options.selectedClass); 
 
      } 
 

 
      $checkbox.prop('checked', false); 
 

 
      $option.removeAttr('selected').prop('selected', false); 
 

 
      this.updateButtonText(); 
 
      this.options.onChange($option, false); 
 
     }, 
 

 
     // Rebuild the whole dropdown menu. 
 
     rebuild: function() { 
 
      $('.multiselect-container', this.$container).html(''); 
 

 
      this.buildSelectAll(); 
 
      this.buildDropdown(this.$select, this.options); 
 
      this.updateButtonText(); 
 

 
      // Enable filtering. 
 
      if (this.options.enableFiltering || this.options.enableCaseInsensitiveFiltering) { 
 
       this.buildFilter(); 
 
      } 
 
     }, 
 

 
     // Get options by merging defaults and given options. 
 
     getOptions: function (options) { 
 
      return $.extend({}, this.defaults, options); 
 
     }, 
 

 
     updateButtonText: function() { 
 
      var options = this.getSelected(); 
 

 
      // First update the displayed button text. 
 
      $('button', this.$container).html(this.options.buttonText(options, this.$select)); 
 

 
      // Now update the title attribute of the button. 
 
      $('button', this.$container).attr('title', this.options.buttonTitle(options, this.$select)); 
 

 
     }, 
 

 
     // Get all selected options. 
 
     getSelected: function() { 
 
      return $('option:selected[value!="' + this.options.selectAllValue + '"]', this.$select); 
 
     }, 
 

 
     updateOriginalOptions: function() { 
 
      this.originalOptions = this.$select.clone()[0].options; 
 
     }, 
 

 
     asyncFunction: function (callback, timeout, self) { 
 
      var args = Array.prototype.slice.call(arguments, 3); 
 
      return setTimeout(function() { 
 
       callback.apply(self || window, args); 
 
      }, timeout); 
 
     } 
 
    }; 
 

 
    $.fn.multiselect = function (option, parameter) { 
 
     return this.each(function() { 
 
      var data = $(this).data('multiselect'), 
 
       options = typeof option == 'object' && option; 
 

 
      // Initialize the multiselect. 
 
      if (!data) { 
 
       $(this).data('multiselect', (data = new Multiselect(this, options))); 
 
      } 
 

 
      // Call multiselect method. 
 
      if (typeof option == 'string') { 
 
       data[option](parameter); 
 
      } 
 
     }); 
 
    }; 
 

 
    $.fn.multiselect.Constructor = Multiselect; 
 

 
    $(function() { 
 
     $("select[data-role=multiselect]").multiselect(); 
 
    }); 
 

 
}(window.jQuery); 
 

 

 

 
/** 
 
* MY CODE -------------------------------------------------- 
 
* ---------------------------------------------------------- 
 
*/ 
 

 

 
$('#multiSelect').multiselect({ 
 
    includeSelectAllOption: true, 
 
    buttonWidth: '200px', 
 
});
#scrollMe { 
 
    height:150px; 
 
    background-color:yellow; 
 
    overflow-y: auto; 
 
    overflow-x:hidden; 
 
    padding:20px; 
 
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 
 
<link href="http://netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css" rel="stylesheet"/> 
 
<script src="http://netdna.bootstrapcdn.com/bootstrap/3.0.0/js/bootstrap.min.js"></script> 
 
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/2.3.0/knockout-min.js"></script> 
 
<div class="container"> 
 
    <!-- Content Table --> 
 
    <div class="content"> 
 
     <div class="row"> 
 
      <div id="scrollMe" class="col-md-12"> 
 
       <select id="multiSelect" class="form-control multiselect" multiple="multiple"> 
 
        <option value="volvo">Volvo</option> 
 
        <option value="saab">Saab</option> 
 
        <option value="opel">Opel</option> 
 
        <option value="audi">Audi</option> 
 
        <option value="volvo">Volvo</option> 
 
        <option value="saab">Saab</option> 
 
        <option value="opel">Opel</option> 
 
        <option value="audi">Audi</option> 
 
        <option value="volvo">Volvo</option> 
 
        <option value="saab">Saab</option> 
 
        <option value="opel">Opel</option> 
 
        <option value="audi">Audi</option> 
 
       </select> 
 
       <br> 
 
       <br> 
 
       <select class="form-control"> 
 
        <option value="volvo">Volvo</option> 
 
        <option value="saab">Saab</option> 
 
        <option value="opel">Opel</option> 
 
        <option value="audi">Audi</option> 
 
        <option value="volvo">Volvo</option> 
 
        <option value="saab">Saab</option> 
 
        <option value="opel">Opel</option> 
 
        <option value="audi">Audi</option> 
 
        <option value="volvo">Volvo</option> 
 
        <option value="saab">Saab</option> 
 
        <option value="opel">Opel</option> 
 
        <option value="audi">Audi</option> 
 
       </select> 
 
      </div> 
 
     </div> 
 
    </div> 
 
    <!-- /content --> 
 
</div>

下拉被內部格打開和創建不必要的渦旋。

+0

哪裏是'樣品code'? –

+0

@HimanshuUpadhyay代碼附帶的問題,也有一個鏈接到jsfiddle –

回答

1

您已將CSS應用於#scrollMe div。只要改變它

#scrollMe { 
    height: auto; 
    background-color: yellow; 
    /* overflow-y: auto; */ 
    /* overflow-x: hidden; */ 
    padding: 20px; 
} 

通知我評論

`/* overflow-y: auto; */` 
    `/* overflow-x: hidden; */` 
+0

希望這解決了你的問題。 –

+0

是的,它正在工作,但爲此我需要使高度自動。我想要div的固定高度 –