Семантическая разметка

Семантическая разметка в Choices.js определяет способ представления данных внутри выпадающих списков, мультиселектов и пользовательских инпутов, превращая плоский набор строк в структурированную модель с явным разделением значения, отображаемого текста, группировки и дополнительных метаданных. Именно семантика данных формирует основу для корректной работы поиска, фильтрации, кастомных шаблонов и интеграции с внешними источниками.

В основе работы библиотеки лежит разделение двух ключевых сущностей:

  • value — техническое значение, используемое в логике приложения
  • label — человекочитаемое представление

Такое разделение устраняет неоднозначность между отображением и хранением данных.

const choices = new Choices('#select', {
  choices: [
    { value: 'ru', label: 'Русский' },
    { value: 'en', label: 'English' },
    { value: 'de', label: 'Deutsch' }
  ]
});

Семантически важно, что value используется при отправке формы и сравнении, тогда как label участвует в рендеринге интерфейса и поиске.

Семантика выбора и внутреннее представление элемента

Каждый элемент внутри Choices.js преобразуется во внутреннюю структуру, включающую дополнительные поля:

  • id — внутренний идентификатор
  • active — состояние выбора
  • disabled — доступность
  • highlighted — состояние навигации клавиатурой
  • customProperties — расширенные метаданные
{
  id: 1,
  value: 'ru',
  label: 'Русский',
  selected: false,
  disabled: false,
  customProperties: {
    region: 'EU',
    rtl: false
  }
}

Наличие customProperties позволяет расширять семантическую модель без изменения базовой структуры.

Использование data-атрибутов как семантического слоя

HTML-источник часто содержит дополнительную семантику через data-* атрибуты. При инициализации они могут быть интерпретированы как расширенные свойства.

<select id="select">
  <option value="ru" data-region="EU" data-lang="cyrillic">Русский</option>
  <option value="en" data-region="US" data-lang="latin">English</option>
</select>

При обработке данные из data-* преобразуются в объектную модель:

{
  value: 'ru',
  label: 'Русский',
  customProperties: {
    region: 'EU',
    lang: 'cyrillic'
  }
}

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

Семантические группы и optgroup

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

<select id="select">
  <optgroup label="Европа">
    <option value="ru">Россия</option>
    <option value="de">Германия</option>
  </optgroup>
  <optgroup label="Азия">
    <option value="jp">Япония</option>
    <option value="cn">Китай</option>
  </optgroup>
</select>

Внутренняя модель преобразует это в вложенную структуру:

{
  label: 'Европа',
  choices: [...]
}

Семантика групп влияет не только на отображение, но и на поведение поиска: фильтрация может учитывать или игнорировать заголовки групп в зависимости от конфигурации.

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

Поисковый механизм в Choices.js строится на нормализации текста label и, при наличии, дополнительных полей.

Алгоритм обычно включает:

  • приведение к нижнему регистру
  • удаление диакритики
  • токенизацию строки
  • проверку совпадений по подстроке

При расширенной конфигурации в поиск включаются:

  • customProperties
  • альтернативные метки
  • скрытые поля данных
new Choices('#select', {
  searchFields: ['label', 'value', 'customProperties.region']
});

Таким образом, семантика поиска становится многослойной и выходит за пределы отображаемого текста.

Семантика пользовательского ввода (createItem)

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

new Choices('#tags', {
  duplicateItemsAllowed: false,
  editItems: true,
  addItems: true
});

В этом режиме:

  • ввод становится источником новых value
  • label может совпадать или отличаться от value
  • создаются новые узлы внутреннего состояния

Семантически важным является момент нормализации: введённая строка проходит через тот же pipeline, что и статические данные.

Семантика шаблонов отображения

Отображение элементов в DOM отделено от их данных через систему шаблонов. Это обеспечивает независимость визуального слоя от структуры данных.

new Choices('#select', {
  callbackOnCreateTemplates: function (template) {
    return {
      item: (classNames, data) => {
        return template(`
          <div class="${classNames.item}" data-value="${data.value}">
            <span>${data.label}</span>
          </div>
        `);
      }
    };
  }
});

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

Скрытые и недоступные элементы как часть семантики

Состояние disabled формирует отдельный семантический уровень, влияющий на:

  • возможность выбора
  • участие в поиске (опционально)
  • отображение в списке
{
  value: 'ru',
  label: 'Русский',
  disabled: true
}

Такие элементы сохраняются в модели, но исключаются из интерактивного поведения, что важно для согласованности состояния UI.

Семантика множественного выбора

В режиме multiple каждый выбранный элемент становится самостоятельной сущностью внутри коллекции.

new Choices('#select', {
  removeItemButton: true,
  maxItemCount: 5
});

Здесь семантическое значение смещается от одиночного значения к множеству, где:

  • порядок элементов может иметь значение
  • дубликаты регулируются конфигурацией
  • каждая сущность хранится независимо
[
  { value: 'ru', label: 'Русский' },
  { value: 'en', label: 'English' }
]

Семантика синхронизации с DOM

Исходный <select> элемент сохраняет роль источника истины. При изменении состояния библиотека синхронизирует:

  • selected
  • value
  • options

DOM при этом выступает как отражение внутренней модели, а не как первичная структура.

Семантика кастомных свойств

Расширение модели через customProperties позволяет внедрять произвольные атрибуты без нарушения базовой схемы.

{
  value: 'ru',
  label: 'Русский',
  customProperties: {
    flag: '??',
    popularity: 10,
    region: 'CIS'
  }
}

Эти данные могут использоваться в:

  • фильтрации
  • кастомных шаблонах
  • логике сортировки
  • интеграции с API

Семантика состояния и жизненного цикла элементов

Каждый элемент проходит несколько состояний:

  • initial — исходная загрузка
  • active — доступен для взаимодействия
  • selected — выбран
  • highlighted — фокус навигации
  • disabled — заблокирован

Эти состояния не изменяют саму семантическую сущность, но расширяют её поведенческую модель.

Семантическая совместимость с внешними API

При работе с серверными источниками данные обычно приходят в JSON-формате:

[
  { "id": 1, "name": "Русский" },
  { "id": 2, "name": "English" }
]

Преобразование в модель Choices.js включает маппинг:

choices: data.map(item => ({
  value: item.id,
  label: item.name
}))

Семантическая консистентность обеспечивается тем, что независимо от источника структура внутри библиотеки остаётся одинаковой.

Семантика приоритета данных

При конфликте источников данных применяется приоритет:

  • пользовательский ввод имеет наивысший приоритет
  • серверные данные — базовый слой
  • HTML-разметка — начальное состояние

Такая иерархия предотвращает потерю актуального состояния и сохраняет целостность модели.