Самый простой способ вкладки только через фокусируемых потомков определенного элемента? - PullRequest
12 голосов
/ 24 октября 2011

Допустим, у меня есть документ, полный фокусируемых элементов, либо потому, что они изначально фокусируются (например, <input type="text">), либо потому, что они имеют tabindex="0" или тому подобное.

Теперь предположим, что есть раздел моего документа, который я хочу отобразить в виде модального диалогового окна, и я не хочу, чтобы пользователь отвлекался на что-либо за пределами диалогового окна. Я хотел бы, чтобы клавиша табуляции циклически проходила только через фокусируемые элементы внутри элемента контейнера для диалогового окна. Какой самый простой способ сделать это?

Если возможно, я ищу решение, которое не заботится о содержании диалогового окна или остальной части страницы и не пытается их изменить. То есть я не хочу, чтобы элементы вне диалогового окна, например, не фокусировались. Во-первых, это требует внесения обратимых изменений и отслеживания состояния. Во-вторых, для этого необходимо знать все возможные способы фокусировки элемента. Мне это кажется грязным, хрупким и не масштабируемым.

Моя первая попытка выглядит следующим образом, но работает только в прямом направлении (нажатие клавиши Tab). Он не работает в обратном направлении (нажатие Shift + Tab).

<div>Focusable stuff outside the dialog.</div>
<div class="dialog" tabindex="0">
  <!-- Focus should be trapped inside this dialog while it's open -->
  <div class="content">
    Form contents and focusable stuff here.
  </div>
  <div class="last-focus" tabindex="0" onfocus="this.parentNode.focus()"></div>
</div>
<div>More focusable stuff outside the dialog.</div>

Я бы предпочел увидеть чистые решения JavaScript. Если есть способ сделать это с библиотекой, такой как jQuery, я бы предпочел ссылку на код библиотеки, который делает это.

Ответы [ 3 ]

12 голосов
/ 24 октября 2011

В целях полноты, я беру ссылку на диалоговое окно jQuery UI , предоставленное @Domenic, и заполняя детали.

Для реализации этого в стиле jQuery требуется двавещи:

  1. Прослушивание для Tab или Shift+Tab (на keydown) для модального элемента, который должен захватывать фокус.Это единственное средство перемещения фокуса с помощью клавиатуры.(Если вы хотите предотвратить взаимодействие мыши с остальной частью документа, это отдельная проблема, решаемая путем покрытия его элементом, предотвращающим прохождение любых событий мыши.)

  2. Поисквсе табулируемые элементы внутри модального элемента.Это подмножество всех фокусируемых элементов, за исключением тех, которые имеют tabindex="-1".

Tab.Shift+Tab идет назад.При каждом нажатии Tab, когда последний элемент tabbable в модальном элементе находится в фокусе, первый должен получить фокус.Точно так же, каждый раз, когда нажимается Shift+Tab, когда первый элемент с вкладками находится в фокусе, последний должен получить фокус.Это сохранит фокус внутри модального элемента.

Сложная часть - знать, какие элементы могут быть вкладками.Поскольку все элементы с вкладками являются фокусируемыми элементами, которые не имеют tabindex="-1", нам нужно знать, какие элементы являются фокусируемыми.Поскольку нет свойства определить, является ли элемент фокусируемым, jQuery делает это путем жесткого кодирования следующих случаев :

  • input, select, textarea,Элементы button и object, которые не отключены. Элементы
  • a и area, которые имеют href или имеют числовое значение для набора tabindex.
  • любой элемент, который имеет числовое значение для набора tabindex.

Недостаточно проверить эти три случая.jQuery продолжает обеспечивать видимость элемента.Это означает, что оба следующих условия должны быть истинными:

  • Ни один из его предков не является display: none.
  • Вычисленное значение visibility равно visible.Это означает, что у ближайшего предка, который должен установить visibility, должно быть значение visible.Если ни у какого предка не установлено visibility, то вычисленное значение равно visible.

Следует отметить, что селектор :visible jQuery не выглядит правильным для этой реализациипотому что он говорит «элементы с visibility: hidden… считаются видимыми», но они не могут быть сфокусированы.

1 голос
/ 24 октября 2011

Диалоговое окно jQuery UI делает это, захватывая события keydown, проверяя, предназначены они для TAB или нет, затем вручную фокусируя нужный элемент.

0 голосов
/ 24 октября 2011

Плагин jqModal jQuery делает это из коробки, устанавливая для параметра modal значение true. Примеры на этой странице с формами должны показать это. Я помню, как просматривал код, чтобы увидеть, что происходит, и вы могли бы сделать это довольно легко с простым JS.

...