JavaScript - переключить фокус на зависший элемент

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

Используя клавиши со стрелками, кнопка, которая в данный момент находится в фокусе, имеет цвет, отличный от других (зеленый). Кнопки, которые наведены, также зеленые.

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

Идеальным решением было бы переключить фокус на любую нажатую кнопку. Это возможно? Если да, то как я могу этого добиться? Желательно, не прибегая к 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" />
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
0
0
488
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Я не большой поклонник использования мыши для смещения фокуса. Если вы не хотите, чтобы состояние наведения отображалось, если у поля есть фокус, вы можете добавить обертывающий 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>

Если я запустил этот фрагмент кода, он будет работать нормально ... пока я не запустил его в полноэкранном режиме. Затем он перестает работать по назначению. Когда кнопка фокусируется с помощью клавиш со стрелками, я больше не могу фокусироваться с помощью наведения курсора. Есть идеи, почему это происходит?

MikeMichaels 27.12.2018 14:59

В этом примере фокус не устанавливается на наведение. ИМО, это плохая практика (смешивание состояний сбивает с толку, раздражает и плохо для доступности). Наведение отключено, если у кнопки есть фокус, и включено, если его нет.

Jakob E 27.12.2018 15:07

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

Jakob E 27.12.2018 15:09

Я понимаю ваше беспокойство. Однако я не верю, что доступность будет проблемой в этом конкретном случае, над которым я работаю. Что касается вашего последнего комментария, я обошел это, добавив прослушиватель событий, который перемещает фокус на первую кнопку всякий раз, когда нажимается клавиша со стрелкой, когда ни один элемент не сфокусирован. В любом случае спасибо за вашу помощь.

MikeMichaels 27.12.2018 15:16

Пожалуйста :-). PS. будьте осторожны с добавлением фокуса на клавиши со стрелками, если вы добавляете более фокусируемые элементы (группы радиокнопок используют стрелки для «табуляции»).

Jakob E 27.12.2018 15:20
Ответ принят как подходящий

Для этого вы можете использовать событие 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.

MikeMichaels 27.12.2018 15:10

Другие вопросы по теме