Фокусировка по элементам списка клавиатурными стрелками (по аналогии с tab)

Нужно добавить функционал, позволяющий фокусировать элементы списка стрелками (по аналогии с использованием клавиши tab, только нужно использовать стрелки, чтобы переключаться по элементам списка вверх и вниз по аналогии с поиском в гугле, когда при вводе поискового запроса появляется список с возможными вариантами поиска)

Уже и не знаю как мне взаимодействовать с дом элементами и фокусить их в зависимости от нажатой кнопки. В идеале было бы круто дополнить возможностью вернуться к первому элементу списка, поле того как долистали до конца

$(document).keyup(function(e) {
      //Arrow up
      if (e.keyCode === 38) {
        if ($('ul li').is(":focus")) {
          $(':focus')[0].closest('div').nextSibling.focus() // нет фокуса :(
          //do something
        }
        
      }

      //Arrow down
      if (e.keyCode === 40) {
        if ($('ul li').is(":focus")) {
          //do something
        }
      }
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script><a href="#">useless link</a> <br>
<a href="#">useless link</a> <br>
<ul>
<li tabindex="0">elem 1</li>
<li tabindex="0">elem 2</li>
<li tabindex="0">elem 3</li>
<li tabindex="0">elem 4</li>
<li tabindex="0">elem 5</li>
<li tabindex="0">elem 5</li>
</ul>
<a href="#">useless link</a> <br>
<a href="#">useless link</a> <br>


Ответы (1 шт):

Автор решения: UModeL

Думаю, что следующий код интуитивно понятен и отвечает всем условиям:

$('li').keydown(function(ev) {
    if (ev.keyCode === 9) {
      if (ev.shiftKey) {
        $(this).parent().prev().focus();
      } else {
        ev.preventDefault();
        $(this).parent().next().focus();
      }
    } else if (ev.keyCode === 38) {
      ev.preventDefault();
      if ($(this).is(':first-child')) {
        $(this).siblings(':last-child').focus();
      } else {
        $(this).prev().focus();
      }
    } else if (ev.keyCode === 40) {
      ev.preventDefault();
      if ($(this).is(':last-child')) {
        $(this).siblings(':first-child').focus();
      } else {
        $(this).next().focus();
      }
    }
  })
  .click(function() { $(this).focus(); })
  .attr('tabindex', '-1').filter(':first-child').attr('tabindex', '0');
li:focus, li:focus-visible, li:active { outline: 2px solid red; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<a href="#">useless link</a> <br>
<a href="#">useless link</a> <br>
<ul>
  <li>elem 1</li>
  <li>elem 2</li>
  <li>elem 3</li>
  <li>elem 4</li>
</ul>
<a href="#">useless link</a> <br>
<a href="#">useless link</a> <br>
<ul>
  <li>elem 1</li>
  <li>elem 2</li>
</ul>
<a href="#">useless link</a> <br>
<a href="#">useless link</a> <br>

Если возникнут какие-либо вопросы по данному коду, то прошу задавать в комментариях ниже.

→ Ссылка