В стандартной конфигурации Slim Select механизм поиска реализует нечувствительное к регистру сравнение строк, что упрощает пользовательский ввод и повышает вероятность совпадений при различном написании. Однако во многих прикладных сценариях требуется строгое соответствие регистру, особенно когда значения имеют семантическую разницу в зависимости от написания или когда данные поступают из систем, где регистр является частью идентификатора.
Внутренний поиск Slim Select работает через функцию фильтрации
массива опций. Каждая опция представлена объектом с полями
text, value и дополнительными метаданными. При
вводе строки поиска библиотека сравнивает введённый запрос с текстом
опций.
По умолчанию используется приведение строк к единому регистру:
option.text.toLowerCase().includes(query.toLowerCase())
Такой подход обеспечивает:
Регистрозависимая логика становится необходимой в следующих случаях:
Admin,
admin, ADMIN)Ab12, AB12)Node,
node)В таких ситуациях стандартное поведение приводит к ложным совпадениям и неоднозначности выбора.
Slim Select предоставляет возможность кастомизации логики фильтрации
через параметр searchFilter. Именно он используется для
внедрения регистрозависимого поведения.
Простейшая реализация без нормализации регистра:
new SlimSelect({
select: '#example',
searchFilter: (option, search) => {
return option.text.includes(search)
}
})
Здесь сравнение выполняется напрямую, без преобразований. Это означает, что совпадение произойдёт только при точном совпадении символов, включая регистр.
Метод includes сохраняет поведение подстрочного поиска.
Однако регистр теперь становится частью условия:
| Ввод | Значение опции | Результат |
|---|---|---|
Node |
NodeJS |
совпадение |
node |
NodeJS |
нет совпадения |
NODE |
NodeJS |
нет совпадения |
Такой подход делает поиск более строгим, но снижает вероятность случайных совпадений.
В некоторых случаях требуется более сложное поведение, например частичная регистрозависимость или комбинированный режим. Это можно реализовать через явное управление сравнением символов.
Пример функции, учитывающей только начало строки и сохраняющей регистр:
new SlimSelect({
select: '#example',
searchFilter: (option, search) => {
if (search.length === 0) return true
return option.text.startsWith(search)
}
})
Здесь совпадение происходит только если строка начинается с введённого запроса и регистр полностью совпадает.
Часто требуется динамическое переключение между регистрозависимым и стандартным режимом. Это реализуется через внешний флаг:
const caseSensitive = true
new SlimSelect({
select: '#example',
searchFilter: (option, search) => {
if (!caseSensitive) {
return option.text.toLowerCase().includes(search.toLowerCase())
}
return option.text.includes(search)
}
})
Такой подход позволяет адаптировать поведение под разные контексты интерфейса без изменения структуры данных.
Slim Select может комбинировать фильтрацию с сортировкой результатов. При регистрозависимом поиске важно учитывать, что сортировка по алфавиту также чувствительна к ASCII-порядку символов.
В Unicode и ASCII верхний регистр имеет меньшие коды символов, чем нижний, поэтому результаты могут выглядеть неожиданно:
AppleZebrabananazooТакой порядок не является ошибкой, а отражает поведение строкового сравнения в JavaScript.
Регистрозависимый поиск часто конфликтует с нормализацией диакритических знаков. Если одновременно требуется учитывать регистр и игнорировать акценты, логика усложняется:
const normalize = (str) => str.normalize('NFD').replace(/[\u0300-\u036f]/g, '')
new SlimSelect({
select: '#example',
searchFilter: (option, search) => {
return normalize(option.text).includes(normalize(search)) && option.text.includes(search)
}
})
Такое условие может использоваться в системах, где диакритика не влияет на идентичность, но регистр критичен.
Регистрозависимый поиск сам по себе не увеличивает вычислительную сложность, однако кастомные функции фильтрации могут влиять на производительность при большом количестве элементов.
Основные факторы:
normalizeОптимизация достигается предварительной подготовкой данных:
const preparedOptions = options.map(o => ({
...o,
rawText: o.text
}))
new SlimSelect({
select: '#example',
searchFilter: (option, search) => {
return option.rawText.includes(search)
}
})
При регистрозависимой логике важно определить поведение пустого ввода. В большинстве интерфейсов возвращаются все элементы:
searchFilter: (option, search) => {
if (!search) return true
return option.text.includes(search)
}
Это сохраняет консистентность UX и предотвращает пустые списки при отсутствии ввода.
Регистрозависимый поиск увеличивает точность, но снижает устойчивость к пользовательским ошибкам. Основные ограничения:
В системах с массовым вводом данных это может приводить к снижению скорости выбора.
На практике часто используется гибридный подход, где:
Пример разделения логики по атрибуту:
new SlimSelect({
select: '#example',
searchFilter: (option, search) => {
const strict = option.data?.strictCase
if (strict) {
return option.text.includes(search)
}
return option.text.toLowerCase().includes(search.toLowerCase())
}
})
Такой подход позволяет сохранять универсальность компонента при работе с разнородными данными.