Работа клавиатурной навигации в Awesomplete строится вокруг
управления списком подсказок без использования мыши. Основная задача
механизма — обеспечить предсказуемое перемещение по элементам списка,
быстрый выбор значения и корректное закрытие/сброс выпадающего меню.
Поведение навигации интегрировано в стандартные DOM-события
keydown, а также в внутреннюю логику управления состоянием
экземпляра автодополнения.
Клавиатурное взаимодействие в Awesomplete опирается на несколько ключевых клавиш, каждая из которых связана с конкретным действием.
ArrowDown / ArrowUp используются для перемещения по списку предложений:
ArrowDown — переход к следующему элементу спискаArrowUp — переход к предыдущему элементу спискаПри достижении границ списка поведение зависит от конфигурации:
Внутри библиотеки поддерживается индекс выделенного элемента, который обновляется при каждом нажатии клавиш.
Пример базовой логики:
input.addEventListener("keydown", function (e) {
if (e.key === "ArrowDown") {
awesomplete.next();
}
if (e.key === "ArrowUp") {
awesomplete.previous();
}
});
Клавиша Enter используется для подтверждения текущего
выделенного элемента.
Поведение:
Важно учитывать, что Enter может конфликтовать с
отправкой формы, если поле находится внутри <form>. В
таком случае требуется управление событием:
input.addEventListener("keydown", function (e) {
if (e.key === "Enter" && awesomplete.opened) {
e.preventDefault();
awesomplete.select();
}
});
Tab применяется для быстрого автозаполнения:
Это поведение часто используется для ускоренного ввода данных.
input.addEventListener("keydown", function (e) {
if (e.key === "Tab" && awesomplete.opened) {
awesomplete.select();
}
});
Клавиша Escape полностью закрывает список подсказок:
input.addEventListener("keydown", function (e) {
if (e.key === "Escape") {
awesomplete.close();
}
});
Внутренне навигация опирается на индекс текущего элемента:
index = -1 означает отсутствие выделенияindex >= 0 — активный элемент спискаПри движении вниз индекс увеличивается, при движении вверх — уменьшается.
Особенность реализации заключается в том, что визуальное выделение синхронизируется с ARIA-атрибутами:
aria-selected="true" — активный элементfalseЭто обеспечивает доступность для экранных считывателей.
Опция autoFirst влияет на поведение клавиатурной
навигации:
true первый элемент списка автоматически становится
активным при открытииfalse выделение отсутствует до первого нажатия
стрелокПример конфигурации:
new Awesomplete(input, {
autoFirst: true
});
С точки зрения UX это снижает количество нажатий клавиш при выборе наиболее релевантного результата.
Навигация становится активной только при открытом списке:
При изменении значения input список пересоздаётся, что сбрасывает индекс:
-1 или
0 (в зависимости от autoFirst)При достижении начала или конца списка стандартная реализация:
Однако при кастомизации можно реализовать циклическую навигацию:
awesomplete.next = function () {
this.index = (this.index + 1) % this.ul.children.length;
this.goto(this.index);
};
awesomplete.previous = function () {
this.index =
(this.index - 1 + this.ul.children.length) %
this.ul.children.length;
this.goto(this.index);
};
Клавиатурная навигация тесно связана с изменением значения input:
Enter или
Tab)Это разделение важно для предотвращения преждевременного изменения данных.
При быстром удержании клавиш стрелок:
keydown генерируются многократноОптимизация достигается за счёт минимального DOM-обновления: изменяется только активный элемент, без полного перерендера списка.
Клавиатурная навигация в Awesomplete интегрирована с ARIA-ролями:
role="listbox" для контейнера спискаrole="option" для элементовaria-activedescendant для текущего выбораЭто позволяет:
Поведение навигации можно полностью переопределить через обработчики
keydown. Часто используется перехват событий:
input.addEventListener("keydown", function (e) {
switch (e.key) {
case "ArrowDown":
awesomplete.next();
break;
case "ArrowUp":
awesomplete.previous();
break;
case "Enter":
if (awesomplete.opened) awesomplete.select();
break;
case "Escape":
awesomplete.close();
break;
}
});
Такой подход позволяет:
Стандартная реализация имеет ряд особенностей:
Эти ограничения обычно компенсируются расширением API и переопределением методов экземпляра.