Визуальная индикация типов в Awesomplete строится вокруг переопределения стандартного способа рендеринга элемента списка. Библиотека по умолчанию выводит строки, но архитектура предусматривает замену функции формирования DOM-узла, что позволяет внедрять любые метки типа: категории, уровни, статусы, происхождение данных.
Ключевая точка расширения — функция item, отвечающая за
создание элемента списка.
Для реализации визуальной типизации данные перестают быть простым массивом строк и переходят в формат объектов.
Типичная структура:
const list = [
{ label: "Apple", type: "fruit" },
{ label: "Carrot", type: "vegetable" },
{ label: "Salmon", type: "fish" }
];
Минимально необходимое поле — label, поскольку именно
оно используется Awesomplete для фильтрации и подстановки. Остальные
поля служат исключительно для визуального оформления.
При этом можно расширять модель:
{
label: "Tesla Model S",
type: "car",
category: "electric",
popularity: "high"
}
Основной механизм индикации типов заключается в кастомизации функции
item.
new Awesomplete(input, {
list: list,
item: function(text, input) {
const li = document.createElement("li");
const span = document.createElement("span");
span.textContent = text.label;
const badge = document.createElement("span");
badge.textContent = text.type;
badge.className = "aw-type aw-type-" + text.type;
li.appendChild(span);
li.appendChild(badge);
return li;
}
});
В данном случае каждый элемент списка превращается в составной DOM-узел:
Awesomplete не ограничивает структуру элемента, поэтому возможно добавление любых вложенных узлов.
После внедрения DOM-разметки ключевая роль переходит к стилям.
.aw-type {
font-size: 12px;
padding: 2px 6px;
border-radius: 10px;
margin-left: 8px;
display: inline-block;
}
Типизация чаще всего реализуется через модификаторы классов:
.aw-type-fruit {
background: #ffeb3b;
color: #000;
}
.aw-type-vegetable {
background: #4caf50;
color: #fff;
}
.aw-type-fish {
background: #03a9f4;
color: #fff;
}
Такой подход обеспечивает масштабируемость: добавление нового типа не требует изменения JS-логики, достаточно добавить CSS-правило.
Визуальная типизация часто усиливается пиктограммами. Вместо текста типа можно использовать иконку или комбинировать оба подхода.
const icons = {
fruit: "?",
vegetable: "?",
fish: "?"
};
item: function(text) {
const li = document.createElement("li");
li.innerHTML = `
<span class="label">${text.label}</span>
<span class="icon">${icons[text.type] || ""}</span>
`;
return li;
}
Иконки позволяют снизить когнитивную нагрузку при большом количестве категорий.
Альтернативный визуальный паттерн — левый маркер.
item: function(text) {
const li = document.createElement("li");
li.className = "item item-" + text.type;
li.textContent = text.label;
return li;
}
.item {
padding-left: 10px;
}
.item-fruit {
border-left: 4px solid #ffeb3b;
}
.item-vegetable {
border-left: 4px solid #4caf50;
}
.item-fish {
border-left: 4px solid #03a9f4;
}
Такой подход особенно эффективен в плотных списках, где важно сохранить компактность интерфейса.
На практике используется сочетание нескольких сигналов одновременно: цвет, иконка и текстовый бейдж.
item: function(text) {
const li = document.createElement("li");
const icon = document.createElement("span");
icon.className = "icon";
icon.textContent = icons[text.type];
const label = document.createElement("span");
label.className = "label";
label.textContent = text.label;
const type = document.createElement("span");
type.className = "type";
type.textContent = text.type;
li.appendChild(icon);
li.appendChild(label);
li.appendChild(type);
return li;
}
Такой вариант позволяет пользователю считывать тип сразу на нескольких уровнях восприятия.
Awesomplete поддерживает доступ к текущему вводу через аргумент
input, что позволяет изменять визуализацию в зависимости от
контекста поиска.
item: function(text, input) {
const li = document.createElement("li");
if (input.value.startsWith("#")) {
li.className = "hashtag-mode";
}
li.textContent = text.label;
return li;
}
Таким образом тип может быть не только свойством данных, но и функцией контекста.
Хотя Awesomplete не имеет встроенных групп, визуальная группировка может быть реализована через специальные элементы-разделители.
const list = [
{ label: "Fruits", group: true },
{ label: "Apple", type: "fruit" },
{ label: "Banana", type: "fruit" }
];
item: function(text) {
const li = document.createElement("li");
if (text.group) {
li.className = "group-header";
li.textContent = text.label;
return li;
}
li.textContent = text.label;
li.className = "item item-" + text.type;
return li;
}
.group-header {
font-weight: bold;
background: #f5f5f5;
cursor: default;
}
Фильтрация Awesomplete не учитывает визуальные признаки, поэтому типы должны сохраняться независимо от поиска.
При необходимости можно модифицировать filter:
filter: function(text, input) {
return text.label.toLowerCase().includes(input.value.toLowerCase());
}
Дополнительная логика может учитывать тип:
filter: function(text, input) {
if (input.value.startsWith("@")) {
return text.type === "user";
}
return true;
}
При большом количестве типов и сложной DOM-структуре возникает необходимость оптимизации:
innerHTML при частых
обновленияхДополнительный эффект дает кэширование вычисленных элементов:
const cache = new Map();
function renderItem(text) {
if (cache.has(text.label)) return cache.get(text.label);
const li = document.createElement("li");
li.textContent = text.label;
cache.set(text.label, li);
return li;
}
Визуальная индикация типов в Awesomplete складывается из трех уровней:
item,
filter, частично sortТакое разделение обеспечивает масштабируемую систему, в которой добавление нового типа не требует переработки всей логики, а ограничивается точечными изменениями в данных и стилях.