arrow keys navigation through li (no jquery) arrow keys navigation through li (no jquery) ajax ajax

arrow keys navigation through li (no jquery)


This turned out to be simpler than I expected, and I've came up with the following code which appearently does the job quite well.

Things to take in account are:

  • the HTML attribute 'tabindex' must be specified on each element for the .focus() to be applied
  • to have a ENTER->submit feeling, you MUST target a link element within the li (still, I'm achieving this with onclick events not included here)
  • this works with an extremely simple list structure, so far I haven't tested it with nested dropdown menus
  • Note: this is most likely not suitable for a copy/paste situation, but as far as I can tell this method is procedurally currect, and can get you started developing more complex solutions

This is the basic HTML:

<input type="text" name="main_input" id="input" /><ul id="list"> <li class="listElement"><a href="#" tabindex="1">li content</a></li> <li class="listElement"><a href="#" tabindex="1">li content</a></li> <li class="listElement"><a href="#" tabindex="1">li content</a></li></ul>

And here's the JS function, triggered when the list above is populated and shown:

    function scrollList() {      var list = document.getElementById('list'); // targets the <ul>      var first = list.firstChild; // targets the first <li>      var maininput = document.getElementById('input');  // targets the input, which triggers the functions populating the list      document.onkeydown = function(e) { // listen to keyboard events        switch (e.keyCode) {          case 38: // if the UP key is pressed            if (document.activeElement == (maininput || first)) { break; } // stop the script if the focus is on the input or first element            else { document.activeElement.parentNode.previousSibling.firstChild.focus(); } // select the element before the current, and focus it            break;          case 40: // if the DOWN key is pressed            if (document.activeElement == maininput) { first.firstChild.focus(); } // if the currently focused element is the main input --> focus the first <li>            else { document.activeElement.parentNode.nextSibling.firstChild.focus(); } // target the currently focused element -> <a>, go up a node -> <li>, select the next node, go down a node and focus it          break;        }      }    }

Apologies in advance for the kinda chaotic layout of the code, the function I came up with is a bit more complex and I've stripped out most of it for explaination purposes.

Needless to say, I'm looking forward any comment about the solution above, in regard of errors, improvements or known compatibility issues.


you wrote

tabindex="1"

Why not just tabindex="0"?Using a positive umber greater than 0 is only needed if you want to cahnge the default order of navigation.