Библиотека ally.js предназначена для управления фокусом и улучшения доступности веб-интерфейсов. Одной из ключевых её возможностей является упрощение навигации между элементами формы, особенно в сложных интерфейсах с множеством интерактивных компонентов.
Для управления фокусом используется функция tabster и
вспомогательные методы библиотеки:
const focusableElements = ally.query.tabbable({
context: document.querySelector('#form-container')
});
context — корневой элемент, внутри
которого выполняется поиск.tabbable — возвращает только элементы,
доступные для табуляции (инпуты, кнопки, ссылки с
href).Метод tabbable учитывает атрибуты disabled,
aria-hidden, tabindex=-1, что позволяет
исключать недоступные для фокуса элементы.
Для перемещения фокуса между полями формы используется
ally.focus:
ally.focus.next({ context: document.querySelector('#form-container') });
ally.focus.previous({ context: document.querySelector('#form-container') });
next — перемещает фокус на следующий
tabbable-элемент.previous — перемещает фокус на
предыдущий tabbable-элемент.context ограничивает область
поиска элементов.Можно также задавать фильтры по селекторам:
ally.focus.next({
context: document.querySelector('#form-container'),
filter: '[data-required]'
});
Фокус переместится только на элементы, имеющие атрибут
data-required.
Библиотека позволяет создавать циклическую навигацию, возвращая фокус к первому элементу после последнего:
const inputs = ally.query.tabbable({ context: form });
let currentIndex = 0;
form.addEventListener('keydown', (event) => {
if (event.key === 'Tab') {
event.preventDefault();
currentIndex = (currentIndex + (event.shiftKey ? -1 : 1) + inputs.length) % inputs.length;
inputs[currentIndex].focus();
}
});
event.shiftKey для
определения направления перемещения.Для форм, где элементы добавляются или удаляются динамически, ally.js предоставляет методы для пересчёта tabbable-элементов:
const refreshFocusable = () => {
return ally.query.tabbable({ context: document.querySelector('#form-container') });
};
let focusableElements = refreshFocusable();
// После добавления нового поля
document.querySelector('#add-field').addEventListener('click', () => {
focusableElements = refreshFocusable();
});
ally.query.tabbable динамически сканирует DOM.Ally.js корректно учитывает атрибуты
aria-disabled,
aria-hidden, что важно для обеспечения
доступности:
<input type="text" aria-disabled="true" />
<input type="text" aria-hidden="true" />
Для сложных форм возможно задание приоритета полей с помощью
tabindex:
<input type="text" tabindex="2" />
<input type="text" tabindex="1" />
<input type="text" tabindex="3" />
Ally.js учитывает tabindex при вычислении порядка
навигации. Элементы с положительным tabindex получают
приоритет над элементами с tabindex="0".
Дополнительно можно объединять поля в группы и навигировать внутри группы:
const group = document.querySelectorAll('.form-section input');
ally.focus.next({ context: group[0].closest('.form-section') });
Модальные окна: при открытии модального окна фокус можно закрепить внутри него.
ally.maintain.disabled({ context: modal });
Скрытые вкладки: поля на неактивной вкладке исключаются из tabbable.
Валидация и навигация: перед перемещением фокуса можно проверять значение текущего поля и блокировать переход, если поле невалидно.
Эти возможности ally.js позволяют создавать формы с
интуитивной и доступной навигацией, обеспечивая
корректную работу клавиатурных пользователей и ассистивных технологий.
Правильное применение функций tabbable,
focus.next, focus.previous и управление
контекстом позволяет строить сложные интерактивные формы с гибкой
логикой перемещения фокуса.