Поиск по первой букве

Библиотека Tabbable предназначена для определения элементов на странице, доступных для фокусировки с помощью клавиши Tab. Она позволяет точно определить, какие элементы могут быть интерактивными, а какие — игнорируются браузером при навигации по клавиатуре. Библиотека полезна для улучшения доступности интерфейсов и создания управляемых схем фокусировки.

Основной функционал реализован через функцию tabbable(), которая принимает DOM-элемент или его контейнер и возвращает массив элементов, доступных для фокусировки.

import { tabbable } from 'tabbable';

const focusableElements = tabbable(document.body);
console.log(focusableElements);

Возвращаемый массив упорядочен в том порядке, в котором элементы будут доступны при навигации с клавиатуры.

Поиск элементов по первой букве

Для интерфейсов, где требуется реализовать быстрый поиск элементов по первой букве (например, в списках ссылок или меню), библиотека Tabbable служит базой для фильтрации элементов, доступных для фокусировки.

Получение tabbable-элементов

Сначала необходимо получить все фокусируемые элементы в контейнере:

const container = document.querySelector('#menu');
const focusableElements = tabbable(container);

На этом этапе focusableElements содержит только те элементы, которые реально могут принимать фокус, исключая скрытые или отключённые элементы.

Фильтрация по первой букве

Чтобы реализовать фильтр по первой букве, используется метод filter() массива:

function filterByFirstLetter(elements, letter) {
  const lowerLetter = letter.toLowerCase();
  return elements.filter(el => {
    const text = el.textContent.trim().toLowerCase();
    return text.startsWith(lowerLetter);
  });
}

const filteredElements = filterByFirstLetter(focusableElements, 'a');

Особенности работы:

  • Игнорируются пустые или пробельные элементы.
  • Применяется toLowerCase() для обеспечения нечувствительности к регистру.
  • Работает как для <a>, <button>, <input> с типом text, так и для других tabbable-элементов.

Обработка динамических элементов

Если DOM изменяется динамически (добавляются новые элементы или изменяется текст), необходимо обновлять массив tabbable-элементов перед фильтрацией:

function updateFilteredElements(container, letter) {
  const elements = tabbable(container);
  return filterByFirstLetter(elements, letter);
}

Такой подход гарантирует актуальность результатов поиска и корректную навигацию с клавиатуры.

Навигация между элементами с одинаковой первой буквой

После фильтрации часто требуется реализовать циклическую навигацию между найденными элементами:

let currentIndex = 0;

function focusNext(elements) {
  if (elements.length === 0) return;
  currentIndex = (currentIndex + 1) % elements.length;
  elements[currentIndex].focus();
}

function focusPrevious(elements) {
  if (elements.length === 0) return;
  currentIndex = (currentIndex - 1 + elements.length) % elements.length;
  elements[currentIndex].focus();
}

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

Учет атрибутов ARIA и табуляции

Tabbable учитывает следующие атрибуты при формировании списка элементов:

  • tabindex (значение -1 исключает элемент из навигации, 0 или положительное число добавляет);
  • disabled на <button>, <input>, <select>, <textarea>;
  • видимость элемента (display: none, visibility: hidden, родитель с display: none).

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

Примеры расширенной фильтрации

Можно комбинировать фильтр по первой букве с дополнительными условиями, например, по типу элемента:

function filterByLetterAndType(elements, letter, tagName) {
  const lowerLetter = letter.toLowerCase();
  return elements.filter(el => 
    el.tagName.toLowerCase() === tagName.toLowerCase() &&
    el.textContent.trim().toLowerCase().startsWith(lowerLetter)
  );
}

const filteredLinks = filterByLetterAndType(focusableElements, 'm', 'a');

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

Производительность и оптимизация

При больших списках элементов рекомендуется:

  • Кешировать результаты tabbable(container), обновляя их только при изменении DOM.
  • Использовать делегирование событий при навигации.
  • Ограничивать количество DOM-операций, выполняя фильтрацию и фокусировку в памяти.

Эти методы обеспечивают быструю и отзывчивую работу интерфейсов с клавиатурой, особенно в сложных SPA или динамически генерируемых меню.