Search code examples
javascriptbrowser-bugs

Setting focus on select element with Javascript scrolls first item out of view


I'm having a problem where I want to have an input box above a select box (multi). The select box has more items in it than the height of the box. (I am setting the size of the box lower than the number of items).

<select id="multiSelect" size="3" multiple>
  <option value="item1">Item 1</option>
  <option value="item2">Item 2</option>
  <option value="item3">Item 3</option>
  <option value="item4">Item 4</option>
  <option value="item5">Item 5</option>
  <option value="item6">Item 6</option>
</select>

I want to allow the user to enter values in the above text input, then use their "down arrow" to move to the results that would appear in the select box.

inputField.addEventListener("keydown", function(e) {
  if (e.keyCode == 40) {
    multiSelect.focus();
    multiSelect.selectedIndex = 0;
  }
});

When the user does this, the first item in the multi select box gets scrolled out of view. This problem happens in both Chrome and Firefox (on a Mac [Safari is fine]).

You can see the problem here.

https://jsfiddle.net/rsturim/ops9q3xk/


Solution

  • Add preventDefault to your keyevent. I have noticed that in Safari, for example, it scrolls down the page a little if it can. That means that the keyevent is actually being passed around to a couple of things, which might include your select:

    var inputField = document.getElementById("inputField");
    var multiSelect = document.getElementById("multiSelect");
    
    inputField.addEventListener("keydown", function(e) {
      if (e.keyCode == 40) {
        e.preventDefault();
        multiSelect.focus();
        multiSelect.selectedIndex = 0;
      }
    });
    
    multiSelect.addEventListener("keydown", function(e) {
      if (e.keyCode == 38 && multiSelect.selectedIndex == 0) {
        inputField.focus();
      }
    });
    <div>
      <input id="inputField" type="text" placeholder="start here" /> => use down arrow to move to multi-select box
    </div>
    <div>
      <select id="multiSelect" size="5" multiple>
        <option value="item1">Item 1</option>
        <option value="item2">Item 2</option>
        <option value="item3">Item 3</option>
        <option value="item4">Item 4</option>
        <option value="item5">Item 5</option>
        <option value="item6">Item 6</option>
        <option value="item7">Item 7</option>
        <option value="item8">Item 8</option>
        <option value="item9">Item 9</option>
        <option value="item10">Item 10</option>
      </select> => use up arrow to move to input box
    </div>

    Aslo, please note that you input element is a self closing element, so <input /> and not <input></input> (sorry, the SO Snippet editor showed me there was a semantic error) (Tested in Safari and Chrome)