Параметр item

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

В стандартной конфигурации Awesomplete каждый элемент списка создаётся автоматически и отображается как простой <li> с текстовым содержимым. Переопределение item полностью заменяет этот механизм, позволяя разработчику контролировать разметку каждого элемента.


Сигнатура и базовое поведение

Функция item вызывается для каждого элемента списка данных и принимает два аргумента:

  • text — исходное значение элемента списка
  • input — текущее значение, введённое пользователем

Функция должна возвращать DOM-элемент (обычно <li>), который будет вставлен в список подсказок.

Общий вид:

item: function (text, input) {
    return document.createElement("li");
}

Минимальная реализация без кастомизации:

new Awesomplete(inputElement, {
    list: ["Apple", "Banana", "Cherry"],
    item: function (text) {
        var li = document.createElement("li");
        li.textContent = text;
        return li;
    }
});

Роль item в процессе рендеринга

Внутренний цикл Awesomplete при построении списка работает следующим образом:

  1. Получение отфильтрованных данных (через filter)
  2. Сортировка (через sort)
  3. Для каждого элемента вызов item
  4. Добавление результата в список <ul>
  5. Навешивание внутренних обработчиков событий (hover, click, keyboard navigation)

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


Взаимодействие с filter и sort

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

  • filter определяет, какие элементы попадут в список
  • sort определяет порядок этих элементов
  • item определяет их визуальное представление

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


Формирование сложной разметки

Основное применение item — создание структурированных элементов списка, включающих дополнительные данные: описание, категории, подсветку совпадений.

Пример с дополнительным описанием:

new Awesomplete(inputElement, {
    list: [
        { label: "JavaScript", desc: "Язык программирования" },
        { label: "Java", desc: "Платформа и язык" }
    ],
    item: function (item, input) {
        var li = document.createElement("li");

        var title = document.createElement("div");
        title.textContent = item.label;

        var desc = document.createElement("small");
        desc.textContent = item.desc;

        li.appendChild(title);
        li.appendChild(desc);

        return li;
    }
});

Здесь item уже не строка, а объект, и функция рендера полностью управляет структурой DOM.


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

Одно из типичных применений — визуальное выделение совпадающей части строки.

item: function (text, input) {
    var li = document.createElement("li");

    var index = text.toLowerCase().indexOf(input.toLowerCase());

    if (index >= 0 && input.length > 0) {
        var before = text.slice(0, index);
        var match = text.slice(index, index + input.length);
        var after = text.slice(index + input.length);

        li.innerHTML =
            before +
            "<strong>" + match + "</strong>" +
            after;
    } else {
        li.textContent = text;
    }

    return li;
}

Использование innerHTML требует аккуратности: при работе с пользовательскими данными необходимо учитывать риск внедрения HTML-кода.


Безопасность и HTML-инъекции

При использовании item разработчик получает полный контроль над DOM. Это означает:

  • textContent безопасен по умолчанию
  • innerHTML потенциально опасен
  • данные из внешних источников требуют очистки

Безопасный вариант:

li.textContent = text;

Потенциально опасный вариант:

li.innerHTML = text;

Если используется HTML-разметка, необходимо предварительно экранировать данные или использовать проверенные источники.


Доступ к исходному элементу данных

Awesomplete передаёт в item ровно то значение, которое находится в списке. Это может быть:

  • строка
  • массив
  • объект

При использовании объектов структура сохраняется полностью:

list: [
    { label: "React", version: "18" }
]
item: function (item) {
    var li = document.createElement("li");
    li.textContent = item.label + " v" + item.version;
    return li;
}

Кастомизация поведения элемента

Помимо визуального оформления, item позволяет добавлять поведение к каждому пункту:

item: function (text) {
    var li = document.createElement("li");

    li.textContent = text;

    li.addEventListener("mouseenter", function () {
        li.classList.add("hovered");
    });

    li.addEventListener("mouseleave", function () {
        li.classList.remove("hovered");
    });

    return li;
}

Awesomplete всё равно добавляет собственные обработчики для выбора элемента, поэтому кастомные события не должны блокировать стандартные.


Интеграция с CSS-классами Awesomplete

Каждый элемент списка автоматически получает базовые классы, например:

  • awesomplete
  • awesomplete li
  • awesomplete li:hover (через состояние)

Внутри item можно расширять структуру:

item: function (text) {
    var li = document.createElement("li");
    li.className = "custom-item";
    li.textContent = text;
    return li;
}

Это позволяет полностью переопределять внешний вид через CSS, сохраняя логику библиотеки.


Производительность при большом списке

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

Особенности:

  • вызывается для каждого элемента после фильтрации
  • DOM-операции внутри неё выполняются многократно
  • сложные вычисления внутри item замедляют рендеринг

Оптимизированный подход:

item: function (text) {
    var li = document.createElement("li");
    li.textContent = text;
    return li;
}

Тяжёлую логику лучше переносить в filter или предварительную обработку списка.


Комбинация с кастомными данными и кешированием

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

var cache = new Map();

item: function (text) {
    if (cache.has(text)) {
        return cache.get(text).cloneNode(true);
    }

    var li = document.createElement("li");
    li.textContent = text;

    cache.set(text, li.cloneNode(true));

    return li;
}

Это снижает количество DOM-операций при повторном открытии списка.


Влияние на UX и поведение списка

Переопределение item напрямую влияет на:

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

Неправильная структура (например, слишком сложный DOM внутри <li>) может ухудшить навигацию с клавиатуры и мыши, поскольку Awesomplete рассчитывает позицию и размеры элементов на основе итогового DOM.


Использование item для группировки элементов

Хотя Awesomplete не поддерживает группы нативно, их можно имитировать:

item: function (text) {
    var li = document.createElement("li");

    if (text.startsWith("#")) {
        li.className = "group-header";
        li.textContent = text.replace("#", "");
    } else {
        li.textContent = text;
    }

    return li;
}

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


Поведение при отсутствии item

Если параметр item не задан, Awesomplete использует внутреннюю реализацию:

  • создаётся <li>
  • в него вставляется текстовое значение
  • применяется базовое форматирование

Это поведение является минимальным и рассчитано на стандартные сценарии автодополнения без кастомизации интерфейса.