Использование клавиш со стрелками для выбора дочернего элемента списка - PullRequest
0 голосов
/ 05 октября 2018

Я пытаюсь создать меню с подменю, в котором можно перемещаться с помощью клавиатуры.По сути, у меня есть неупорядоченный список, и у каждого элемента списка есть другой неупорядоченный список.Я могу перемещаться по списку своего верхнего уровня следующим образом:

var li = $('li.tile');
var liSelected;
$(window).keydown(function(e) {
    if(e.which === 40) {
        if(liSelected) { // just a boolean variable at this point?
            liSelected.removeClass('selected');
            next = liSelected.next();
            if(next.length > 0) {
                liSelected = next.addClass('selected');
            } else {
                liSelected = li.first().addClass('selected');
            }
        } else {
            liSelected = li.first().addClass('selected');
        }
    } else if(e.which === 38) {
        if(liSelected) {
            liSelected.removeClass('selected');
            next = liSelected.prev();
            if(next.length > 0) {
                liSelected = next.addClass('selected');
            } else {
                liSelected = li.last().addClass('selected'); // not properly selecting last() because of submenu items ? 
            }
        } else {
            liSelected = li.last().addClass('selected');
        } 
    } /* begin experiment*/ else if (e.which === 13){
      $(".selected").click();
    } 
});

Затем я попытался добавить это, прямо перед оператором 'else if', чтобы переключиться на клавишу вниз (случай 38) -

 if(liSelected && ($(".subTile").is(":visible"))){
        $(".selected:first-child").addClass("selectedSub");
      }

Я не могу понять, почему это не работает.

У меня есть два класса CSS, по одному для каждого уровня меню.«selected» для слоев верхнего уровня и «selectedSub» для слоев нижнего уровня, все, что они делают, это изменяют цвет фона элемента, чтобы пользователь знал, где они находятся.

Мои подменю вначале скрыты, они открываются / закрываются следующим образом:

var acc = document.getElementsByClassName("tile");
var i;


for (i=0;i<acc.length;i++){
  acc[i].addEventListener("click", function(){
    this.classList.toggle("active");

    var $subItem = $("ul, li", this);
    this.classList.contains("active") ? $subItem.show() : $subItem.hide() ;
  })
}

Я довольно новичок в коде и в настоящее время очень потерян.Вот мой код, если это полезно: https://codepen.io/kbeats/pen/YJWzeP

1 Ответ

0 голосов
/ 05 октября 2018

Манипулирование DOM напрямую не рекомендуется.

Возможно, вам будет трудно это отпустить (мы все были там), но попробуйте переписать ваш код следующим образом.Я поделюсь псевдо-кодом, как я бы это сделал.

$('.select').removeClass('select')

arrayOfListElems = [
   '#li-elem1', 
   '#li-elem1-1', // sub-menu of li-elem1
   '#li-elem1-2', // sub-menu of li-elem1
   '#li-elem2', 
   '#li-elem3', 
]
currIndex = 0;
maxIndex = currIndex.length - 1;

if(key is pressed){
  if(key is down-button){
    currIndex--;
    // makes sure currIndex isn't below 0
    currIndex = currIndex < 0 ? 0 : currIndex; 
  } else if(key is up-button){
    currIndex++;
    // makes sure currIndex isn't below 0
    currIndex = currIndex > maxIndex 
      ? maxIndex 
      : currIndex; 
  }
  currElem = arrayOfListElems[currIndex];

  // do stuff with the element:
  $(currElem).addClass('select')
}

Таким образом, вам нужно только как-то правильно получить arrayOfListElems, будь то жесткое кодирование вручную или какое-то динамическое получение,код будет работать.

...