Safari 8 множественный выбор прокрутки проблема

Я столкнулся с проблемой при использовании полей множественного выбора в 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 против scrollHeight элемента.

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

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

При прокрутке до 2-го варианта, scrollTop составляет 14px, а до 3-го варианта, 28px. Таким образом, каждый элемент, к которому вы прокручиваете, имеет размер 14 пикселей. Так что, пока ширина меньше scrollHeight минус определенное количество пикселей, это работает... Если вы используете 13 пикселей для каждого параметра, кажется, что он работает нормально.

Итак, у вас есть 2 варианта.

  1. Убедитесь, что ширина вашего выбора меньше 13 * количество вариантов

ИЛИ ЖЕ

  1. Используйте javascript, чтобы получить желаемое поведение... Я придумал JsFiddle, который работает. А для тех, кто любит использовать jQuery, попробуйте этот JsFiddle

Вам просто нужно прослушать событие нажатия клавиш и отрегулировать прокрутку так, чтобы выбранный элемент был виден до его выбора.

Кроме того, чтобы метод 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>
Другие вопросы по тегам