У меня есть набор кнопок, запускающих различные функции на странице. Пользователь может навести указатель мыши на нужную кнопку и щелкнуть по ней, как обычно, или может перемещаться по кнопкам с помощью клавиш со стрелками вверх и вниз и нажимать клавишу ввода для запуска соответствующей функции.
Используя клавиши со стрелками, кнопка, которая в данный момент находится в фокусе, имеет цвет, отличный от других (зеленый). Кнопки, которые наведены, также зеленые.
В настоящее время зеленым может быть несколько кнопок: кнопка с зависанием и кнопка с фокусом. Я не хочу, чтобы это случилось.
Идеальным решением было бы переключить фокус на любую нажатую кнопку. Это возможно? Если да, то как я могу этого добиться? Желательно, не прибегая к jQuery.
Вот с чем я работаю:
var inputs = document.getElementsByClassName("move");
for (var i = 0; i < inputs.length; i++)
inputs[i].addEventListener("keyup", function(event) {
if (event.keyCode == 38) {
if (this.previousElementSibling) {
this.previousElementSibling.focus();
}
} else if (event.keyCode == 40) {
if (this.nextElementSibling) {
this.nextElementSibling.focus();
}
}
}, false); .move {
display: block;
width: 200px;
padding: 10px;
text-align: center;
background-color: aquamarine;
margin-top: 10px;
}
.move:hover, .move:focus {
background-color: greenyellow;
} <input class = "move" type = "button" value = "1" autofocus />
<input class = "move" type = "button" value = "2" />
<input class = "move" type = "button" value = "3" />


![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Я не большой поклонник использования мыши для смещения фокуса. Если вы не хотите, чтобы состояние наведения отображалось, если у поля есть фокус, вы можете добавить обертывающий div и использовать focus-within.
Поскольку focus-within не поддерживается в ie и edge, вы можете добавить имитацию с помощью класса .enable-hover, который вы переключаете на focus / blur.
const wrapper = document.querySelector('.group');
[].slice
.call(document.querySelectorAll('.move'))
.map(input => {
input.addEventListener('focus', e => {
wrapper.classList.remove('enable-hover')
});
input.addEventListener('blur', e => {
wrapper.classList.add('enable-hover')
});
input.addEventListener('keyup', e => {
if (e.keyCode == 38 && input.previousElementSibling)
input.previousElementSibling.focus();
if (e.keyCode == 40 && input.nextElementSibling)
input.nextElementSibling.focus();
});
}).group:not(:focus-within) > .move:hover,
.group.enable-hover > .move:hover,
.move:focus {
background: greenyellow;
}
.move {
display: block;
width: 200px;
padding: 10px;
text-align: center;
background-color: aquamarine;
margin-top: 10px;
}<div class = "group">
<input class = "move" type = "button" value = "1" autofocus />
<input class = "move" type = "button" value = "2" />
<input class = "move" type = "button" value = "3" />
</div>В этом примере фокус не устанавливается на наведение. ИМО, это плохая практика (смешивание состояний сбивает с толку, раздражает и плохо для доступности). Наведение отключено, если у кнопки есть фокус, и включено, если его нет.
Если вы нажимаете за пределами кнопок, наведение включено, но вы больше не можете использовать стрелки (ожидаемое поведение, поскольку для этого требуется фокусировка на элементе)
Я понимаю ваше беспокойство. Однако я не верю, что доступность будет проблемой в этом конкретном случае, над которым я работаю. Что касается вашего последнего комментария, я обошел это, добавив прослушиватель событий, который перемещает фокус на первую кнопку всякий раз, когда нажимается клавиша со стрелкой, когда ни один элемент не сфокусирован. В любом случае спасибо за вашу помощь.
Пожалуйста :-). PS. будьте осторожны с добавлением фокуса на клавиши со стрелками, если вы добавляете более фокусируемые элементы (группы радиокнопок используют стрелки для «табуляции»).
Для этого вы можете использовать событие mouseover с функцией focus. Должно работать нормально ...
var inputs = document.getElementsByClassName("move");
for (var i = 0; i < inputs.length; i++) {
inputs[i].addEventListener("keyup", function(event) {
if (event.keyCode == 38) {
if (this.previousElementSibling) {
this.previousElementSibling.focus();
}
} else if (event.keyCode == 40) {
if (this.nextElementSibling) {
this.nextElementSibling.focus();
}
}
}, false);
inputs[i].addEventListener("mouseover", function(event) {
this.focus();
}, false);
} .move {
display: block;
width: 200px;
padding: 10px;
text-align: center;
background-color: aquamarine;
margin-top: 10px;
}
.move:hover, .move:focus {
background-color: greenyellow;
} <input class = "move" type = "button" value = "1" autofocus />
<input class = "move" type = "button" value = "2" />
<input class = "move" type = "button" value = "3" />Большое тебе спасибо! Это прекрасно работает. По-прежнему можно было иметь две разные кнопки, стилизованные так, как если бы они обе были сфокусированы. Я исправил это, удалив ".move: hover" из CSS.
Если я запустил этот фрагмент кода, он будет работать нормально ... пока я не запустил его в полноэкранном режиме. Затем он перестает работать по назначению. Когда кнопка фокусируется с помощью клавиш со стрелками, я больше не могу фокусироваться с помощью наведения курсора. Есть идеи, почему это происходит?