Safari 8多选滚动问题

时间:2014-11-24 16:12:43

标签: html css osx-yosemite browserstack safari8

在OS X Yosemite 上的 Safari 8中使用多个选择选择字段时,我遇到了一个问题。如果选择字段具有应用的宽度,无论是内联还是作为类,我都无法使用键盘箭头键按照正常行为向下滚动选择。

<select size="5" name="selectMultiple" multiple="multiple">

多重选择JSFiddle

<select size="5" name="selectMultiple" multiple="multiple" style="width:100%;">

样式标记 JSFiddle

当选择具有样式时,选择移出视图而不是向下滚动列表,保持所选项目在视图中。

这是我正在使用的Safari版本(版本8.0(10600.1.25))中的错误。我正在使用BrowserStack进行测试。或者这是我可以通过我的代码修复解决的问题吗?

谢谢。

1 个答案:

答案 0 :(得分:1)

我认为这确实是某种类型的bug,它与select元素的宽度和元素的scrollHeight有关。

您拥有的选项越多,它就越宽,并且仍然可以正常工作。如果我有一个包含39个选项的select标签,那么最大值似乎大约是510px,然后才会混乱。

平均而言,select可以处理的最大宽度似乎是每个选项大约13px。因此,如果您有一个包含13个选项的选择器,则最大值约为169px(13 * 13)

滚动到第二个选项时,scrollTop为14px,第三个选项为28px。因此,您滚动到的每个元素是14px。因此,只要宽度小于scrollHeight减去一定数量的像素,它就可以工作......如果你使用每个选项13个像素,它似乎工作正常。

所以,你有2个选择。

  1. 确保您选择的宽度小于13 *选项数
  2. OR

    1. 使用javascript来获得您想要的行为......我想出了一个有效的JsFiddle。对于那些喜欢使用jQuery的人来说,试试这个JsFiddle
    2. 您只需要监听keydown事件并调整滚动,以便在选中之前所选元素处于视图中。

      此外,为了使scrollByLines(numberOfLines)方法适用于scroll元素,它必须具有以下样式:

      overflow-y: scroll;
      

      这是一个有效的快速HTML文档

      <!DOCTYPE html>
      <html>
      <head lang="en">
          <meta charset="UTF-8">
          <title></title>
          <script type="text/javascript">
      
              // This happens on document load
              function myOnLoad() {
      
                  // Get the selector element
                  var mySelector = document.getElementById('mySelector');
      
                  // If the selector is doomed to glitch out on us because it's wider than the max allowed width, we need to fix it
                  if (mySelector.offsetWidth > 13 * mySelector.options.length) {
      
                      // Figure out the pixels for a single scroll line
                      mySelector.scrollByLines(1);
                      var scrollLineHeight = mySelector.scrollTop;
      
                      // Scroll back to the top
                      mySelector.scrollTop = 0;
      
                      // Add a keydown event listener so that we can scroll programatically before it messes up
                      mySelector.addEventListener('keydown', function (e) {
      
                          // Only listen to up and down arrows
                          if (e.keyCode !== 38 && e.keyCode !== 40) {
                              return;
                          }
      
                          // Figure out where the selector is scrolled to
                          var scrollTop = this.scrollTop;
                          var scrolledToLine = parseInt(scrollTop / scrollLineHeight);
      
                          // If we hit the up arrow and the selected index is equal to the scrolled line, simply move us up by one
                          if (e.keyCode === 38 && this.selectedIndex === scrolledToLine) {
                              this.scrollByLines(-1);
                          }
      
                          // If we hit the down arrow and the selected index is equal to the scrolled line + the number of visible lines - 1, move us down by one
                          if (e.keyCode === 40 && this.selectedIndex === scrolledToLine + (this.size - 1)) {
                              this.scrollByLines(1);
                          }
                      });
                  }
              }
          </script>
      </head>
      <body onload="myOnLoad();">
      <select size="5" name="selectMultiple" multiple="multiple" style="width:100%; overflow-y: scroll;" id="mySelector">
          <option value="0">line 0</option>
          <option value="1">line 1</option>
          <option value="2">line 2</option>
          <option value="3">line 3</option>
          <option value="4">line 4</option>
          <option value="5">line 5</option>
          <option value="6">line 6</option>
          <option value="7">line 7</option>
          <option value="8">line 8</option>
          <option value="9">line 9</option>
          <option value="10">line 10</option>
          <option value="11">line 11</option>
          <option value="12">line 12</option>
      </select>
      </body>
      </html>
      

      这是jQuery版本:

      <!DOCTYPE html>
      <html>
      <head lang="en">
          <meta charset="UTF-8">
          <title></title>
          <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
          <script type="text/javascript">
      
              $( document ).ready(function() {
      
                  // Get the selector element
                  var mySelectorObj = $('#mySelector');
                  var mySelector = mySelectorObj[0];
      
                  // If the selector is doomed to glitch out on us because it's wider than the max allowed width, we need to fix it
                  if (mySelector.offsetWidth > 13 * mySelector.options.length) {
      
                      // Figure out the pixels for a single scroll line
                      mySelector.scrollByLines(1);
                      var scrollLineHeight = mySelector.scrollTop;
      
                      // Scroll back to the top
                      mySelector.scrollTop = 0;
      
                      // Add a keydown event listener so that we can scroll programatically before it messes up
                      mySelectorObj.on('keydown', function(e) {
      
                          // Only listen to up and down arrows
                          if (e.keyCode !== 38 && e.keyCode !== 40) {
                              return;
                          }
      
                          // Figure out where the selector is scrolled to
                          var scrollTop = this.scrollTop;
                          var scrolledToLine = parseInt(scrollTop / scrollLineHeight);
      
                          // If we hit the up arrow and the selected index is equal to the scrolled line, simply move us up by one
                          if (e.keyCode === 38 && this.selectedIndex === scrolledToLine) {
                              this.scrollByLines(-1);
                          }
      
                          // If we hit the down arrow and the selected index is equal to the scrolled line + the number of visible lines - 1, move us down by one
                          if (e.keyCode === 40 && this.selectedIndex === scrolledToLine + (this.size - 1)) {
                              this.scrollByLines(1);
                          }
                      });
                  }
              });
          </script>
      </head>
      <body>
      <select size="5" name="selectMultiple" multiple="multiple" style="width:100%; overflow-y: scroll;" id="mySelector">
          <option value="0">line 0</option>
          <option value="1">line 1</option>
          <option value="2">line 2</option>
          <option value="3">line 3</option>
          <option value="4">line 4</option>
          <option value="5">line 5</option>
          <option value="6">line 6</option>
          <option value="7">line 7</option>
          <option value="8">line 8</option>
          <option value="9">line 9</option>
          <option value="10">line 10</option>
          <option value="11">line 11</option>
          <option value="12">line 12</option>
      </select>
      </body>
      </html>