Как сфокусировать первый элемент в соседнем ul с помощью клавиш со стрелками с помощью jquery

#javascript #html #jquery #arrow-functions

Вопрос:

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

До сих пор я могу заставить клавиши со стрелками перемещаться между первым и последним пунктом в одном списке, но не переходить в другой список.

     //left and and right arrow navigation functionality

 $('.someclass a').keydown(function(e){
        // Listen for the up, down, left and right arrow keys, otherwise, end here
        if ([37,38,39,40].indexOf(e.keyCode) == -1) {
            return;
        }

        // Store the reference to our top level link
        var link = $(this);
        console.log(link);

        switch(e.keyCode) {
            case 37: // left arrow
                // Make sure to stop event bubbling
                e.preventDefault();
                e.stopPropagation();

                //This is the first item in the top level mega menu list
                if(link.closest('ul').next('ul').prevAll('ul').first().length == 0) {
                    console.log(link.closest('ul'));
                    // Focus on the next first link in the submenu 
                    link.parent('li').nextAll('li').last().find('a').first().focus();
                } else {
                    // Focus on the previous first link in the submenu
                    link.parent('ul').prevAll('ul').first().find('a').first().focus();
                }
                break;
            case 38: /// up arrow
                // Find the nested element that acts as the menu
                var dropdown = link.parent('li').find('.truist-secondary-menu');

                // If there is a UL available, place focus on the first focusable element within
                if(dropdown.length > 0){
                    e.preventDefault();
                    e.stopPropagation();

                    dropdown.find('a').filter(':visible').first().focus();
                }

                break;
            case 39: // right arrow
                // Make sure to stop event bubbling
                e.preventDefault();
                e.stopPropagation();


                // This is the last item
                if(link.closest('ul').nextAll('li').filter(':visible').first().length == 0) {
                    // Focus on the next first link in the submenu
                    link.parent('li').prevAll('li').last().find('a').first().focus();
                } else {
                    // Focus on the previous first link in the submenu
                    link.parent('li').nextAll('li').first().find('a').first().focus();
                }
                break;
            case 40: // down arrow
                // Find the nested element that acts as the menu
                var dropdown = link.parent('li').find('.menu');

                // If there is a UL available, place focus on the first focusable element within
                if(dropdown.length > 0){
                    // Make sure to stop event bubbling
                    e.preventDefault();
                    e.stopPropagation();

                    dropdown.find('a').filter(':visible').first().focus();
                }
                break;
        }
    });
 

HTML довольно длинный, но вот сокращенная версия и лучшее объяснение того, что я хочу сделать.

 <h3>List Heading One</h3>
<ul class="someulclass">
   <li class="someclass">
   <a></a>//arrow key left from here
   </li> 
   <li class="someclass">
   <a></a>
   </li>
   <li class="someclass">
   <a></a>
   </li>
</ul>
<h3>List Heading Two</h3>
<ul class="someulclass">
   <li class="someclass">
   <a></a> // to here, arrow key right back the other way
   </li> 
   <li class="someclass">
   <a></a>
   </li>
   <li class="someclass">
   <a></a>
   </li>
</ul>
 

Ответ №1:

Наконец-то понял! Необходимо изменить .parent(‘li’) на .closest(‘ul’).

  $('.someclass a').keydown(function(e){
        // Listen for the up, down, left and right arrow keys, otherwise, end here
        if ([37,38,39,40].indexOf(e.keyCode) == -1) {
            return;
        }

        // Store the reference to our top level link
        var link = $(this);
        console.log(link);

        switch(e.keyCode) {
            case 37: // left arrow
                // Make sure to stop event bubbling
                e.preventDefault();
                e.stopPropagation();

                //This is the first item in the top level mega menu list
                if(link.closest('div').next('div').prevAll('div').first().length == 0) {
                    console.log(link.closest('ul'));
                    // Focus on the next first link in the submenu 
                    link.closest('ul').nextAll('ul').last().find('a').first().focus();
                } else {
                    // Focus on the previous first link in the submenu
                    link.closest('ul').prevAll('ul').first().find('a').first().focus();
                }
                break;
            case 39: // right arrow
                // Make sure to stop event bubbling
                e.preventDefault();
                e.stopPropagation();

                // This is the last item
                if(link.closest('div').nextAll('div').filter(':visible').first().length == 0) {
                    // Focus on the next first link in the submenu
                    link.closest('ul').prevAll('ul').last().find('a').first().focus();
                } else {
                    // Focus on the previous first link in the submenu
                    link.closest('ul').nextAll('ul').first().find('a').first().focus();
                }
                break;
        }
    });