Многократная выборка прокрутки Safari 8

Я столкнулся с проблемой при использовании нескольких полей выбора select в Safari 8 в OS X Yosemite. Если поле выбора имеет применяемую ширину, как в строке, так и в классе, я не могу использовать клавиши со стрелками клавиатуры для прокрутки вниз по выбору в соответствии с обычным поведением.

<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

Я думаю, что это действительно какая-то ошибка, связанная с шириной элемента select vs scrollHeight элемента.

Чем больше вариантов у вас есть, тем шире он может быть и до сих пор отлично работает. Если у меня есть тэг select с 39 опциями, то max, кажется, составляет около 510 пикселей, прежде чем он испортится.

В среднем максимальная ширина, которую может обрабатывать элемент выбора, составляет приблизительно 13 пикселей на выбор. Так что, если у вас есть селектор с 13 параметрами, то max составляет около 169px (13 * 13)

Когда вы переходите ко второму параметру, scrollTop имеет 14px и третий вариант, 28px. Таким образом, каждый элемент, который вы прокручиваете, составляет 14 пикселей. Таким образом, пока ширина меньше, чем 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 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 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>