Перейти к первой ссылке в списке с вкладкой, если нажата кнопка

#javascript #html

#javascript #HTML

Вопрос:

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

Это мой js:

 const button = document.querySelector(".button");
const list = document.querySelector(".list");

button.addEventListener("click", this.setFocus.bind(this));

function setFocus(e) {
  if(list.classList.contains("show")) {
     if (e.keyCode == 9) {
        list.querySelector("a").focus();
     }
  }
}
 

И скрипка

Комментарии:

1. Каким образом вопрос неясен?

2. Для меня желаемый результат не ясен. Не могли бы вы описать это лучше?

3. Что вы имеете в виду под «фокусом»? Вы хотите нажать «Меню» и перейти к первой ссылке через ее привязку?

4. Если я нажму «Меню», меню переключится (откроется), тогда я хочу, чтобы фокус был сосредоточен на первой ссылке в меню, когда я нажимаю клавишу tab.

5. Почему вы проверяете keyCode событие щелчка?

Ответ №1:

Если вы удалите if (e.keyCode == 9) проверку, ваш код будет работать так, как ожидалось.

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

 const button = document.querySelector(".button");
const list = document.querySelector(".list");

button.addEventListener("click", this.setFocus.bind(this));

function setFocus(e) {
  if (list.classList.contains("show")) {
    list.querySelector("a").focus();
  }
} 
 :focus {
  background: red;
} 
 <button class="button">Menu</button>
<a href="#">Another link</a>

<ul class="list show">
  <li class="li">
    <a class="link" href="#">Link</a>
    <button class="button">chevron</button>
  </li>
  <li class="li">
    <a class="link" href="#">Link</a>
    <button class="button">chevron</button>
  </li>
  <li class="li">
    <a class="link" href="#">Link</a>
    <button class="button">chevron</button>
  </li>
</ul> 

Если вам нужен визуальный эффект в этом случае, вы можете применить стиль к .link:focus (Chrome использует что-то вроде outline: #000 1px; )

Комментарии:

1. Хорошо, я понимаю это, спасибо! Но то, что я пытался выполнить с помощью проверки ключа, заключалось в том, что я хочу, чтобы фокус находился в меню после нажатия вкладки. Когда вы перемещаетесь только с помощью клавиатуры, затем вы переходите к кнопке меню, открываете меню, а затем переходите к первому элементу меню.

2. @pistevw Если вы нажмете enter на кнопке, она все равно должна поменять фокус для вас. Вы имеете в виду, что хотите открыть подменю, когда первая кнопка получит фокус? Если это так, вы также можете прослушать событие фокусировки: button.addEventListener("focus", this.setFocus.bind(this));

3. Я хочу иметь возможность переходить от кнопки меню к меню с помощью клавиатуры. Итак, когда я открываю меню, например, с помощью клавиши пробела, и после этого нажимаю клавишу tab ‘, я хочу, чтобы фокус переместился на первую ссылку меню. Извините, если я объясняю сложным способом.

4. Хм, ну, то, что уже есть в ответе, должно это сделать. Одна вещь, которая может быть проблемой, это если у вас есть код, который применяет .show класс, который вы не включили в вопрос. Если setFocus() применяется runs before show , он не будет работать.

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

Ответ №2:

Я думаю, вы пытаетесь переходить по ссылкам, не фокусируясь на кнопках? В этом случае вы можете установить tabindex для кнопок значение -1. Это предотвращает попадание их в фокус при переходе по элементам.

 <button class="button" tabindex="-1">chevron</button>
 

Кроме того, вы смешиваете свои события. Событие «щелчок», и вы проверяете нажатие вкладки. Просто избавьтесь от этой проверки, чтобы автоматически сфокусироваться на первом элементе.

 function setFocus(e) {
  if(list.classList.contains("show")) {
    list.querySelector("a").focus();
  }
}
 

Комментарии:

1. Шевроны — это кнопки, которые открывают подменю, поэтому их нужно фокусировать. Если я уберу проверку нажатия клавиш, когда я нажимаю кнопку меню, фокусируется первый шеврон, а не первая ссылка. Почему это так?

2. Это потому, что код устанавливает фокус на первую ссылку в списке. Нажатие tab затем перемещает фокус на следующий элемент, который является кнопкой chevron. Добавление проверки нажатия клавиш нарушает логику, поэтому функция не работает и никогда не устанавливает фокус. Фокус остается на кнопке меню, и нажатие tab переходит к следующему элементу, который является привязкой «другая ссылка». Это точно так же, как полное удаление обработчика кликов.

3. Я вроде это понимаю. Но как я могу сфокусироваться на ссылке, а не на шевроне, я пытаюсь выполнить обратную фокусировку, когда нажимаю shift tab, а затем возвращаю фокус на кнопку меню. Если я напишу anotherLink.focus(); , кнопка меню получит фокус, но не если я напишу menuButton.focus(); , возможно ли, что вы могли бы объяснить, как я могу добиться этого правильно?

4. На самом деле он уже сфокусирован на ссылке. Попробуйте использовать внешние ссылки, а не # для того, чтобы было понятнее, что происходит. Нажмите кнопку меню, затем нажмите enter. Вы перейдете к URL-адресу первой ссылки. Я обновил скрипку: jsfiddle.net/npx4rLqj

5. Я думаю, что ваша проблема связана с вашими стилями, поэтому вы не можете видеть, что сфокусировано, а что нет. Вместо этого взгляните на эту скрипку, добавив какой-то уродливый CSS, чтобы выделить сфокусированную ссылку. jsfiddle.net/npx4rLqj/1