Клавиша Escape

Клавиша Escape в интерфейсах автодополнения выполняет роль механизма мгновенного прерывания взаимодействия с выпадающим списком подсказок. В реализации Awesomplete она обрабатывается как сигнал отмены текущего состояния компонента: активный список предложений скрывается, фокус остаётся в поле ввода, а текущий текст пользователя не модифицируется.

В стандартной конфигурации Awesomplete нажатие Escape приводит к вызову внутренней логики закрытия списка, эквивалентной программному awesomplete.close(). При этом компонент сбрасывает визуальное состояние активного элемента списка, если он был выделен стрелками, но не применяет его к значению input.


Механика обработки клавиатурного события

Awesomplete работает через подписку на событие keydown у связанного элемента input. При нажатии Escape происходит проверка кода клавиши и дальнейшая маршрутизация в обработчик управления списком.

Упрощённо логика выглядит следующим образом:

input.addEventListener("keydown", function (evt) {
    if (evt.key === "Escape") {
        awesomplete.close();
    }
});

Внутренняя реализация библиотеки дополнительно учитывает состояние списка:

  • открыт ли список предложений;
  • есть ли активный (highlighted) элемент;
  • находится ли пользователь в режиме навигации по результатам.

Состояния компонента при Escape

При срабатывании Escape библиотека переводит интерфейс в нейтральное состояние. Это включает несколько последовательных шагов:

1. Закрытие dropdown-списка Список подсказок становится скрытым, элементы DOM больше не участвуют в навигации.

2. Сброс активного элемента Если пользователь перемещался по списку с помощью стрелок, текущая подсветка удаляется.

3. Сохранение текста input Значение поля ввода остаётся неизменным. Awesomplete не подставляет выбранный элемент автоматически при Escape.

4. Обновление ARIA-атрибутов Для доступности обновляются состояния aria-expanded и aria-activedescendant, отражая закрытие списка.


Отличие Escape от Enter и Tab

Поведение Escape принципиально отличается от других управляющих клавиш:

  • Enter — подтверждает текущий выбор и может заменить значение input на выбранный элемент.
  • Tab — часто используется для автозаполнения и перехода к следующему элементу формы.
  • Escape — отменяет взаимодействие без изменений данных.

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


Взаимодействие с методом close()

В Awesomplete существует прямой метод управления состоянием списка:

awesomplete.close();

Нажатие Escape фактически инициирует аналогичное поведение. Однако между пользовательским действием и прямым вызовом метода есть различие: при событии клавиатуры дополнительно учитываются условия фокуса и текущего состояния навигации.

Программный вызов:

awesomplete.close();
input.value = input.value;

не выполняет никаких дополнительных проверок, в то время как клавиша Escape обрабатывается внутри event pipeline компонента.


Перехват и переопределение поведения

В некоторых интерфейсах требуется изменить стандартное поведение Escape. Например, можно оставить список открытым или выполнить дополнительную логику очистки.

Это достигается через перехват события:

input.addEventListener("keydown", function (evt) {
    if (evt.key === "Escape") {
        evt.preventDefault();
        evt.stopPropagation();

        // пользовательская логика
        console.log("Escape перехвачен");

        awesomplete.close();
    }
});

Вызов preventDefault() предотвращает стандартную реакцию браузера, а stopPropagation() блокирует дальнейшее распространение события, что важно при вложенных компонентах интерфейса.


Сценарии использования Escape в интерфейсах автодополнения

Клавиша Escape часто становится частью предсказуемого пользовательского поведения:

Отмена выбора Пользователь открыл список, начал навигацию, но решил вернуться к ручному вводу.

Сброс поиска При длинных списках Escape позволяет быстро скрыть результаты без удаления текста.

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


Особенности при быстром вводе

При высокой скорости набора текста Escape может срабатывать в момент, когда список ещё обновляется через evaluate(). В таких случаях Awesomplete сначала завершает текущую отрисовку списка, затем закрывает его.

Это предотвращает визуальные артефакты:

  • «мигание» списка;
  • повторное открытие после закрытия;
  • неконсистентное состояние highlighted элемента.

Сочетание Escape с динамическими источниками данных

При использовании асинхронных списков (например, загрузка подсказок с сервера) Escape не отменяет сам запрос. Он только управляет UI-слоем компонента.

Пример архитектуры:

input.addEventListener("input", async function () {
    const data = await fetch("/search?q=" + this.value).then(r => r.json());
    awesomplete.list = data;
});

Если пользователь нажимает Escape во время ожидания ответа, список закрывается, но после получения данных он может быть открыт снова через обновление list. Это поведение важно учитывать при проектировании UX.


Влияние Escape на состояние выделения

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

  • index = -1
  • selected = null

Это гарантирует, что последующее открытие списка начинается без остаточного состояния предыдущей сессии.


Интеграция с кастомными рендерами

При использовании item-рендереров Awesomplete Escape не влияет на DOM-структуру элементов напрямую. Он изменяет только состояние видимости контейнера и внутренние индексы.

new Awesomplete(input, {
    item: function (text, input) {
        return Awesomplete.$.create("li", {
            innerHTML: "<strong>" + text + "</strong>"
        });
    }
});

При нажатии Escape созданные элементы остаются в памяти до следующего пересоздания списка, но становятся недоступны для навигации.


Поведение при потере фокуса

Escape и blur часто работают совместно, но не идентичны. Потеря фокуса автоматически закрывает список, однако Escape делает это без смены фокуса.

Разница:

  • blur — системное событие смены фокуса
  • Escape — явное пользовательское действие отмены

Это позволяет использовать Escape в интерфейсах, где фокус должен оставаться в input, например при повторном поиске.


Итоговая модель обработки

Логика Escape в Awesomplete сводится к следующей цепочке:

  1. Перехват keydown
  2. Проверка key === "Escape"
  3. Сброс навигационного состояния
  4. Закрытие списка
  5. Сохранение input значения
  6. Обновление ARIA-атрибутов
  7. Возврат управления пользователю