Самый простой способ вкладывать только через фокусируемых потомков определенного элемента?
Допустим, у меня есть документ, полный фокусируемых элементов, либо потому, что они изначально фокусируются (например, <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 ответа
В целях полноты картины я беру ссылку на диалоговое окно jQuery UI, предоставленное @Domenic, и заполняю детали.
Для реализации этого в стиле jQuery требуются две вещи:
Слушая для
Tab
или жеShift+Tab
(наkeydown
) для модального элемента, который должен захватывать фокус. Это единственное средство перемещения фокуса с помощью клавиатуры. (Если вы хотите предотвратить взаимодействие мыши с остальной частью документа, это отдельная проблема, решаемая путем покрытия его элементом, предотвращающим прохождение любых событий мыши.)Поиск всех элементов с вкладками внутри модального элемента. Это подмножество всех фокусируемых элементов, за исключением тех, которые имеют
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
,
Следует отметить, что JQuery's :visible
Селектор не выглядит правильным для этой реализации, потому что он говорит "элементы с visibility: hidden
... считаются видимыми ", но они не фокусируются.
Диалоговое окно jQuery UI делает это, захватывая keydown
события, проверяя, предназначены ли они для TAB или нет, затем вручную фокусируя правильный элемент.
Плагин jqModal jQuery делает это из коробки, устанавливая modal
вариант к истине. Примеры на этой странице с формами должны показать это. Я помню, как просматривал код, чтобы увидеть, что происходит, и вы могли бы сделать это довольно легко с простым JS.