23

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 を使用しています。それとも、これは私のコードを修正することで対処できるものですか?

ありがとうございました。

4

1 に答える 1

1

これは確かに、select 要素の幅と要素の scrollHeight に関係するある種のバグだと思います。

オプションが多ければ多いほど、幅が広くなり、それでも問題なく機能します。39 個のオプションを持つ選択タグがある場合、混乱する前の最大値は約 510px のようです。

平均して、select が処理できる最大幅は、オプションごとに約 13px のようです。したがって、13 個のオプションを持つセレクターがある場合、最大値は約 169px (13 * 13) です。

2 番目のオプションまでスクロールすると、scrollTop は 14px になり、3 番目のオプションまでスクロールすると 28px になります。したがって、スクロール先の各要素は 14px です。したがって、幅がscrollHeightから特定のピクセル数を引いたものよりも小さい限り、機能します...オプションごとに13ピクセルを使用すると、正常に機能するようです。

したがって、2 つのオプションがあります。

  1. 選択の幅が 13 * オプションの数未満であることを確認してください

また

  1. JavaScriptを使用して、目的の動作を取得します...動作するJsFiddleを思いつきました。jQuery の使用が好きな方は、このJsFiddleをお試しください

keydown イベントをリッスンし、スクロールを調整して、選択した要素が選択される前に表示されるようにするだけです。

また、スクロール要素で scrollByLines(numberOfLines) メソッドを機能させるには、次のスタイルが必要です。

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>
于 2015-05-24T00:04:01.810 に答える