У меня есть многоуровневый выпадающий список, который я хочу сделать навигационным с помощью клавиш со стрелками, используя vanilla js. Первая ссылка первого выпадающего списка пропускается, когда я добавляю список в список. Поскольку у его родителя li нет родного брата, обход останавливается здесь. Должна быть какая-то логическая ошибка, но по прошествии длительного времени я ее не вижу.
Я пытался ссылаться на кнопку, которая должна получить фокус после этой ссылки разными способами, но безуспешно
Я ожидал, что обход перейдет из подменю 3 в подменю 2 в подменю 1 к кнопке рядом с меню 2. Вместо этого он перейдет из подменю 2 к кнопке, пропуская подменю 1
<style>
ul.nav { display: flex; list-style: none; }
body:not(.js) ul.sub {
position: absolute;
left: -9999em;
}
body:not(.js) li.has-sub:hover > ul.sub,
body:not(.js) li.has-sub:focus-within > ul.sub,
body:not(.js) li.has-sub ul:hover {
position: relative;
left: 0;
}
body.js .hidden {
position: absolute;
left: -9999em;
}
.hidden {
position: absolute;
left: -9999em;
}
body.js .visible {
position: relative;
left: 0;
}
.visible {
position: relative;
left: 0;
}
</style>
</head>
<body>
<ul class="nav" id="main_nav">
<li>
<a href="#">Menu 1</a>
</li>
<li class="has-sub">
<a href="#">Menu 2</a>
<!-- <button class="trigger">More</button> -->
<ul class="sub">
<li><a href="#">Sub-Menu 1</a></li>
<li class="has-sub">
<a href="#">Sub-Menu 2</a>
<!-- <button class="trigger">More</button> -->
<ul class="sub">
<li>
<a href="#">Nested-Menu 1</a>
</li>
<li>
<a href="#">Nested-Menu 2</a>
</li>
<li>
<a href="#">Nested-Menu 3</a>
</li>
</ul>
</li>
<li>
<a href="#">Sub-Menu 3</a>
</li>
</ul>
</li>
<li><a href="#">Menu 3</a></li>
</ul>
<script type="text/javascript">
document.querySelector('body').classList.add('js');
//ADD BUTTONS
let triggers = document.querySelectorAll('li.has-sub > a');
for(var i=0; i < triggers.length; i++) {
let toggler = document.createElement('button');
toggler.setAttribute("class", "trigger");
triggers[i].parentNode.insertBefore(toggler, triggers[i].parentNode.querySelector('ul.sub'));
}
//HIDE SUBS BY DEFAULT
let subs = document.querySelectorAll('ul.sub');
for(let a = 0; a < subs.length; a++) {
subs[a].classList.add('hidden');
}
//ADD TABINDEX -1
var dropdownLinks = document.querySelectorAll('ul.sub a');
dropdownLinks.forEach(dropdownLink => dropdownLink.setAttribute("tabindex", "-1"));
var dropdownButtons = document.querySelectorAll('ul.sub button');
dropdownButtons.forEach(dropdownButton => dropdownButton.setAttribute("tabindex", "-1"));
//SHOW SUBS ON CLICK - DEFINE TOGGLE AND APPLY
var toggle = function(elem) {
// elem.classList.toggle('visible');
if(elem.classList.contains('hidden')) {
elem.classList.remove('hidden');
elem.classList.add('visible');
} else if(elem.classList.contains('visible')) {
elem.classList.remove('visible');
elem.classList.add('hidden');
}
};
var hide = function(elem) {
if(elem.classList.contains('visible')) {
elem.classList.remove('visible');
}
if(!elem.classList.contains('hidden')){
elem.classList.add('hidden');
}
}
var buttonTogglers = document.querySelector('.nav').querySelectorAll('button.trigger');
for(var f = 0; f < buttonTogglers.length; f++) {
buttonTogglers[f].addEventListener("click", function(){
toggle(this.nextElementSibling);
});
buttonTogglers[f].addEventListener("focusout", function(){
//hides parent too which we don't want.
});
}
// var = document.querySelector("ul.nav");
// nav.addEventListener("keydown", function(e) {
var subMamas = document.querySelectorAll('li.has-sub');
for(var g = 0; g < subMamas.length; g++) {
subMamas[g].addEventListener("keydown", function(e) {
var active = document.activeElement;
active = '';
if(e.keyCode === 40) {
console.log('down');
if(document.activeElement.nextElementSibling) {
if(document.activeElement.nextElementSibling.classList.contains('visible')) {
document.activeElement.nextElementSibling.firstElementChild.firstElementChild.focus();
} else {
document.activeElement.parentElement.nextElementSibling.firstElementChild.focus();
}
} else if (document.activeElement.parentElement.nextElementSibling){
document.activeElement.parentElement.nextElementSibling.firstElementChild.focus();
}
else {
document.activeElement.parentElement.parentElement.firstElementChild.focus();
}
}
//UP
if(e.keyCode === 38) {
console.log('up');
var active;
console.log('start' + document.activeElement.textContent );
if(document.activeElement.parentElement.previousElementSibling) {
// console.log(active.parentElement.previousElementSibling);
active = document.activeElement.parentElement.previousElementSibling.firstElementChild;
active.focus();
console.log('finish' + active.textContent);
active = '';
}
else if(!document.activeElement.parentElement.previousElementSibling) {
console.log('no sib');
active = document.activeElement.closest('.sub').previousElementSibling;
active.focus();
active = '';
}
}
//RIGHT
if(e.keyCode === 39) {
console.log('right');
}
//LEFT
if(e.keyCode === 37) {
console.log('left');
}
});
}
</script>