Сортировка и фильтрация

Библиотека ally.js предназначена для управления доступностью элементов интерфейса на веб-страницах. Она предоставляет набор функций для поиска, фильтрации и сортировки интерактивных элементов, облегчая создание интерфейсов, удобных для клавиатурной навигации и вспомогательных технологий. В контексте сортировки и фильтрации ally.js особенно полезна для работы с группами элементов, фокусируемыми по различным критериям.

Поиск интерактивных элементов

Метод query.tabbable() возвращает все элементы, доступные для фокусировки клавиатурой (tabbable elements). Он принимает объект настроек, позволяющий фильтровать результаты:

const tabbableElements = ally.query.tabindex({ context: document.body });
  • context – корневой элемент, в котором производится поиск.
  • includeContext – включает сам контекст в результаты поиска, если он соответствует критериям.
  • displayCheck – функция для проверки видимости элемента (например, full, none, partial).

Фильтрация элементов по критериям

Фильтрация позволяет исключить ненужные элементы из найденного набора. Ally.js поддерживает фильтры по типу интерактивности, состоянию элемента и атрибутам.

Пример фильтрации элементов по состоянию disabled и атрибуту aria-hidden:

const visibleTabbable = ally.query.tabindex({
  context: document.body,
  filter: element => !element.disabled && element.getAttribute('aria-hidden') !== 'true'
});
  • Использование кастомного фильтра позволяет создавать точные списки интерактивных элементов.
  • Фильтры могут комбинироваться с сортировкой по порядку в DOM или по логике пользовательского интерфейса.

Сортировка элементов

Ally.js предоставляет встроенную поддержку сортировки через опции поиска:

  • tabindex order – элементы с положительным tabindex получают приоритет.
  • DOM order – стандартный порядок следования элементов в DOM.

Пример сортировки tabbable-элементов по порядку их появления в DOM:

const sortedElements = ally.query.tabbable({ context: document.body })
  .sort((a, b) => {
    return a.compareDocumentPosition(b) & Node.DOCUMENT_POSITION_FOLLOWING ? -1 : 1;
  });

Особенности сортировки:

  • Элементы с tabindex="0" считаются стандартными tabbable.
  • Элементы с tabindex>0 получают приоритет и оказываются в начале списка.
  • Отрицательные tabindex исключаются из фокусируемых элементов.

Использование focusable и tabbable

Методы query.focusable() и query.tabbable() отличаются по своему поведению:

  • focusable() возвращает все элементы, которые можно сфокусировать программно.
  • tabbable() возвращает только элементы, доступные через клавишу Tab.

Сочетание этих методов с фильтрацией и сортировкой позволяет точно управлять последовательностью фокуса:

const focusableButtons = ally.query.focusable({ context: formElement })
  .filter(el => el.tagName === 'BUTTON')
  .sort((a, b) => a.tabIndex - b.tabIndex);

Применение кастомных функций сортировки

Ally.js позволяет задавать собственные функции сортировки для специфичных сценариев, например, для логической группировки кнопок в модальных окнах:

const modalElements = ally.query.tabbable({ context: modal })
  .sort((a, b) => {
    const groupA = a.dataset.group || 0;
    const groupB = b.dataset.group || 0;
    return groupA - groupB;
  });

Такой подход позволяет управлять фокусом внутри интерфейса в зависимости от структуры компонентов, а не только от DOM-порядка.

Использование tabindex для контроля порядка

tabindex играет ключевую роль в сортировке tabbable-элементов. Ally.js учитывает этот атрибут при построении списка:

  • tabindex="0" – стандартный порядок фокуса по DOM.
  • tabindex>0 – элементы с положительным tabindex выводятся первыми.
  • tabindex<0 – элементы игнорируются в таб-навигации.

Пример применения:

const customOrder = ally.query.tabbable({ context: container })
  .sort((a, b) => (a.tabIndex || 0) - (b.tabIndex || 0));

Комбинирование фильтрации и сортировки

Для сложных интерфейсов важно одновременно фильтровать и сортировать элементы. Ally.js предоставляет возможность цепочечного вызова методов:

const interactiveElements = ally.query.tabbable({ context: document.body })
  .filter(el => el.offsetParent !== null) // видимые элементы
  .sort((a, b) => (a.tabIndex || 0) - (b.tabIndex || 0));

Такой подход гарантирует, что элементы будут соответствовать критериям видимости, доступности и логическому порядку.

Итоговое применение в динамических интерфейсах

В современных приложениях часто требуется динамически управлять доступностью элементов:

  • Модальные окна: фокус внутри модального диалога.
  • Дропдауны: фильтрация видимых элементов при открытии списка.
  • Таблицы и списки: сортировка элементов по логике пользователя.

Ally.js позволяет создавать гибкие сценарии навигации, где фокус и доступность элементов управляются программно с учетом состояния интерфейса и пользовательских требований.

Фильтрация и сортировка в ally.js обеспечивают точный контроль над взаимодействием с элементами и повышают общую доступность веб-приложений.