I have been encountering an issue when using multiple select select fields within Safari 8 on OS X Yosemite. If the select field has an applied width, either in-line or as a class, I am unable to use the keyboards arrow keys to scroll down through the select as per normal behaviour.
<select size="5" name="selectMultiple" multiple="multiple">
Multiple select JSFiddle.
<select size="5" name="selectMultiple" multiple="multiple" style="width:100%;">
with style tag JSFiddle.
When the select has style the selection moves out of view instead of scrolling the list downwards keeping the selected item in view.
Is this a bug in the version of Safari (Version 8.0 (10600.1.25)) I am using. I am using BrowserStack for my testing. Or is this something I can address with a fix through my code?
Thank you.
I think this is indeed some type of bug that has to do with the width of the select element vs the scrollHeight of the element.
The more options you have, the wider it can be and still work fine. If I have a select tag with 39 options, the max seems to be around 510px before it messes up.
On average, the max width that a select can handle seems to be approx 13px per option. So if you have a selector with 13 options, then the max is about 169px (13 * 13)
When you scroll to the 2nd option, the scrollTop is 14px and to the 3rd option, 28px. So each element that you scroll to is 14px. So as long as the width is less than the scrollHeight minus a certain number of pixels, it works... If you use the 13 pixels per option, it seems to work fine.
So, you have 2 options.
OR
You just have to listen to the keydown event and adjust the scroll so that the selected element is in view before it is selected.
Also, in order to make the scrollByLines(numberOfLines) method work on the scroll element, it has to have the following style:
overflow-y: scroll;
Here is a quick HTML document that works
<!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>
And here is the jQuery version:
<!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>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With