В этом уроке мы углубимся в малоиспользуемый элемент HTML5 <datalist>
. Он может реализовать легковесный, доступный, кросс-браузерный автокомплит для формы, не требующий JavaScript.
Что не так с <select>
?
HTML5 <select>
контролирует идеально, когда вы хотите, чтобы пользователь выбирал из небольшого диапазона вариантов. Они менее практичны, когда:
- когда есть много вариантов, таких как страны или должности
- когда пользователю нужно ввести свой вариант, который не находится в списке
Очевидным решением является контроль автозаполнения. Это позволяет пользователю ввести несколько символов, что ограничивает доступные варианты для более быстрого выбора.
<select>
перейдет к правильному месту, когда вы начнете печатать, но это не всегда очевидно. Это не будет работать на всех устройствах (например, на сенсорных экранах), и оно сбрасывается через секунду или две.
Разработчики часто обращаются к одному из многих решений на JavaScript, но настраиваемый контроль автозаполнения не всегда необходим. Элемент HTML5 <datalist>
легковесен, доступен и не имеет зависимостей от JavaScript. Возможно, вы слышали, что он имеет ошибки или не поддерживается. Это неправда в 2021 году, но есть некоторые расхождения в браузерах и предостережения.
<datalist>
Начало быстрого старта
Выбор вашей страны из списка, содержащего более 200 вариантов, является идеальным кандидатом для контроля автозаполнения. Определите <datalist>
с дочерними элементами <option>
для каждой страны непосредственно на HTML-странице:
<datalist id="countrydata">
<option>Afghanistan</option>
<option>Åland Islands</option>
<option>Albania</option>
<option>Algeria</option>
<option>American Samoa</option>
<option>Andorra</option>
<option>Angola</option>
<option>Anguilla</option>
<option>Antarctica</option>
...etc...
</datalist>
Идентификатор datalist затем можно ссылаться с помощью атрибута list
в любом поле <input>
:
<label for="country">country</label>
<input type="text"
list="countrydata"
id="country" name="country"
size="50"
autocomplete="off" />
Запутывающе, но лучше установить autocomplete="off"
. Это обеспечит отображение значений в <datalist>
, но не значений, которые пользователь ранее вводил в браузере.
Результат:
Это стандартное отображение в Microsoft Edge. Другие приложения реализуют похожую функциональность, но внешний вид варьируется в зависимости от платформы и браузера.
<option>
Опции
Использование лейбла в виде текстового дочернего элемента <option>
является распространенным:
<datalist id="mylist">
<option>label one</option>
<option>label two</option>
<option>label three</option>
</datalist>
Использование атрибута value
дает идентичные результаты:
<datalist id="mylist">
<option value="label one" />
<option value="label two" />
<option value="label three" />
</datalist>
Примечание: закрывающий />
слэш является необязательным в HTML5, хотя он может помочь предотвратить ошибки в кодировании.
Вы также можете установить значение в соответствии с выбранным лейблом, используя один из следующих форматов.
Вариант 1:
<datalist id="mylist">
<option value="1">label one</option>
<option value="2">label two</option>
<option value="3">label three</option>
</datalist>
Вариант 2:
<datalist id="mylist">
<option value="1" label="label one" />
<option value="2" label="label two" />
<option value="3" label="label three" />
</datalist>
В обоих случаях поле ввода устанавливается в 1
, 2
или 3
при выборе допустимой опции, но пользовательский интерфейс варьируется в зависимости от браузеров:
- Chrome отображает список с и значением, и лейблом. Остается только значение после выбора опции.
- Firefox отображает список только с лейблом. Оно переключается на значение после выбора опции.
- Edge отображает только значение.
Следующий пример CodePen демонстрирует все вариации:
Смотреть перо
HTML5 <datalist> автозаполнение примеров от SitePoint (@SitePoint)
на CodePen.
Реализации будут развиваться, но сейчас я бы посоветовал не использовать значение и лейбл, так как это может сбить с толку пользователей. (Обходной путь обсуждается ниже.)
<datalist>
Поддержка браузеров и резервные варианты
Элемент <datalist>
хорошо поддерживается в современных браузерах а также в Internet Explorer 10 и 11:
Есть несколько замечаний по реализации, но они не повлияют на большинство случаев использования. Худшее, что может случиться, это что поле вернется к стандартному текстовому вводу.
Если вам абсолютно необходимо поддерживать IE9 и ниже, есть резервный вариант, который использует стандартный <select>
в сочетании с текстовым вводом, когда <datalist>
не работает. Применительно к примеру с страной:
<label for="country">country</label>
<datalist id="countrydata">
<select name="countryselect">
<option></option>
<option>Afghanistan</option>
<option>Åland Islands</option>
<option>Albania</option>
<option>Algeria</option>
<option>American Samoa</option>
<option>Andorra</option>
<option>Angola</option>
<option>Anguilla</option>
<option>Antarctica</option>
...etc...
</select>
<label for="country">or other</label>
</datalist>
<input type="text"
id="country" name="country"
size="50"
list="countrydata"
autocomplete="off" />
Увидеть песочницу
HTML5 <datalist> автодополнение резервное от SitePoint (@SitePoint)
на CodePen.
В современных браузерах элементы <option>
становятся частью <datalist>
, и метка “или другое” не отображается. Он выглядит идентично примеру выше, но значение формы countryselect
будет установлено в пустую строку.
В IE9 и ниже, как очень длинный <select>
, так и текстовые поля ввода активны:
Оба значения можно вводить в старых IE. Ваше приложение должно либо:
- решить, какое из них наиболее действительно, или
- использовать небольшую функцию JavaScript для сброса одного, когда изменяется другой
Использование <datalist>
на нетекстовых элементах управления
Браузеры на основе Chrome также могут применять значения <datalist>
к:
-
Вводу с типом
"date"
. Пользователь может выбирать из диапазона опций, определенных какYYYY-MM-DD
значения, но представленных в их локальном формате. -
Ввод с типом
"color"
. Пользователь может выбирать из набора цветовых опций, определенных как шестизначные шестнадцатеричные значения (трехзначные значения не работают). -
Ввод с типом
"range"
. Слайдер показывает метки, хотя это не ограничивает ввод значения.
Смотрите код
HTML5 <datalist> на других типах ввода от SitePoint (@SitePoint)
на CodePen.
<datalist>
Стили CSS
Если вы когда-либо изо всех сил пытались стилизовать <select>
поле, … у вас все было легко!
Элемент <input>
можно стилизовать как обычно, но связанный <datalist>
и его дочерние элементы <option>
не могут быть стилизованы в CSS. Отображение списка полностью определяется платформой и браузером.
I hope this situation improves, but for now, a solution is proposed at MDN which:
- переопределяет стандартное поведение браузера
- эффективно обрабатывает
<datalist>
как<div>
чтобы его можно было стилизовать в CSS - воспроизводит все функциональные возможности автозаполнения на JavaScript
I’ve enhanced it further and the code is available on GitHub. To use it, load the script anywhere in your HTML page as an ES6 module. The jsDelivr CDN URL can be used:
<script src="https://cdn.jsdelivr.net/npm/datalist-css/dist/datalist-css.min.js"></script>
Или вы можете установить его с помощью npm
, если используете сборщик:
npm install datalist-css
Ваши элементы <datalist>
должны использовать формат <option>value</option>
. Например:
<datalist id="mylist">
<option>label one</option>
<option>label two</option>
<option>label three</option>
</datalist>
Примечание: использование <option value="value" />
не подходит, так как приводит к пустому элементу, который не может быть стилизован!
Затем можно добавить CSS для стилизации некоторых или всех элементов <datalist>
и <option>
. Например:
datalist {
position: absolute;
max-height: 20em;
border: 0 none;
overflow-x: hidden;
overflow-y: auto;
}
datalist option {
font-size: 0.8em;
padding: 0.3em 1em;
background-color: #ccc;
cursor: pointer;
}
/* стилизация активной опции */
datalist option:hover, datalist option:focus {
color: #fff;
background-color: #036;
outline: 0 none;
}
Пример:
Смотрите демонстрацию
Стилизация автозаполнения HTML5 <datalist> с помощью CSS от SitePoint (@SitePoint)
на CodePen.
Стилизация работает, но стоит ли это усилий? Я подозреваю, что нет…
- Реализация стандартных браузерных элементов управления клавиатурой, мышью и сенсорным экраном с достаточной доступностью — сложна. Пример MDN не поддерживает события клавиатуры, и хотя я пытался его улучшить, на некоторых устройствах неизбежно возникнут проблемы.
- Вы полагаетесь на 200 строк JavaScript для решения проблемы, которая должна решаться с помощью CSS. Это минифицируется до 1,5 кБ, но может вызвать проблемы с производительностью, если на одной странице требуется множество длинных элементов
<datalist>
. - Если требуется JavaScript, предпочтительнее ли использовать более красивый, единообразный и проверенный временем компонент JavaScript?
Управление переходит к стандартному HTML5 <datalist>
без стилизации при сбое JavaScript, но это незначительное преимущество.
Создание усовершенствованного Ajax <datalist>
Предполагая, что ваш дизайнер готов принять различия в стилях браузеров, можно улучшить стандартную функциональность <datalist>
с помощью JavaScript. Например:
- Реализовать необязательную валидацию, которая принимает только известные значения в
<datalist>
. - Задать элементы
<option>
из данных, возвращаемых вызовами Ajax к API поиска. - Установить другие значения полей при выборе опции. Например, выбор “Соединенные Штаты Америки” устанавливает “US” в скрытом входе.
Основная необходимость кода заключается в переопределении элементов <option>
, хотя есть и другие аспекты программирования:
- Запрос к Ajax API должен происходить только после ввода минимального количества символов.
- События ввода должны быть дебаунседы. То есть Ajax-вызов запускается только после того, как пользователь перестал печатать не менее полусекунды.
- Результаты запроса должны кэшироваться, чтобы не нужно было повторять или анализировать идентичные вызовы.
- Необходимо избегать лишних запросов. Например, ввод “un” возвращает 12 стран. Нет необходимости делать дополнительные Ajax-вызовы для “unit” или “united”, так как все возможные варианты уже содержатся в первоначальных 12 результатах.
I’ve created a standard Web Component for this, and the code is available on GitHub. The CodePen example below allows you to select a valid country after entering at least two characters. A music artist autocomplete then returns artists who originated in that country with names matching the search string:
Смотрите Pen
HTML5 <datalist> с автодополнением Ajax от SitePoint (@SitePoint)
на CodePen.
- API поиска стран предоставляется restcountries.eu.
- API поиска музыкальных исполнителей предоставляется musicbrainz.org.
Чтобы использовать его в вашем приложении, загрузите скрипт в любое место вашей HTML-страницы в качестве модуля ES6. URL-адрес CDN jsDelivr можно использовать:
<script src="https://cdn.jsdelivr.net/npm/datalist-ajax/dist/datalist-ajax.min.js"></script>
Или вы можете установить его с помощью npm
, если используете сборщик:
npm install datalist-ajax
Создайте элемент <auto-complete>
с дочерним элементом <input>
для использования в качестве поля ввода данных. Например, поиск стран использует это:
<label for="country">country lookup:</label>
<auto-complete
api="https://restcountries.eu/rest/v2/name/${country}?fields=name;alpha2Code;region"
resultname="name"
querymin="2"
optionmax="50"
valid="please select a valid country"
>
<input type="text" id="country" name="country" size="50" required />
</auto-complete>
Атрибуты элемента <auto-complete>
:
attribute | description |
---|---|
api |
the REST API URL (required) |
resultdata |
the name of the property containing a result array of objects in the returned API JSON (not required if only results are returned) |
resultname |
the name of the property in each result object which matches the search input and is used for datalist <option> elements (required) |
querymin |
the minimum number of characters to enter before a search is triggered (default: 1) |
inputdelay |
the minimum time to wait in milliseconds between keypresses before a search occurs (default debounce: 300) |
optionmax |
the maximum number of autocomplete options to show (default: 20) |
valid |
if set, this error message is shown when an invalid value is selected |
URL REST должен содержать по крайней мере один идентификатор ${id}
, который заменяется значением, установленным в <input>
с таким id
. В приведенном выше примере ${country}
в URL api
ссылается на значение в дочернем <input>
, который имеет id
"country"
. URL обычно использует дочерний ввод, но можно ссылаться на любые другие поля на странице.
API restcountries.eu возвращает один объект или массив объектов, содержащих данные о стране. Например:
[
{
"name": "Cyprus",
"alpha2Code": "CY",
"region": "Europe"
},
{
"name": "Sao Tome and Principe",
"alpha2Code": "ST",
"region": "Africa"
},
{
"name": "Andorra",
"alpha2Code": "AD",
"region": "Europe"
}
]
Атрибут resultdata
не нужно устанавливать, так как это единственные возвращаемые данные (нет оберточного объекта). Атрибут resultname
должен быть установлен в "name"
, поскольку это свойство используется для заполнения элементов datalist <option>
.
Другие поля могут быть автоматически заполнены при выборе опции. Следующие входы получают данные свойств "alpha2Code"
и "region"
, так как установлен атрибут data-autofill
:
<input data-autofill="alpha2Code" type="text" id="countrycode" name="countrycode" readonly />
<input data-autofill="region" type="text" id="region" name="region" readonly />
Как работает datalist-ajax
Вы можете пропустить этот раздел, если не хотите читать 230 строк кода и сохранить магию!
Код изначально создает новый <datalist>
внутри <auto-complete>
, который присоединяется к дочернему <input>
с помощью атрибута list
. Обработчик события input
отслеживает <input>
и вызывает функцию runQuery()
когда введено минимальное количество символов и пользователь не продолжает печатать.
runQuery()
строит URL API из данных формы и делает Ajax-запрос с использованием Fetch API. Возвращенный JSON анализируется, затем создается повторно используемая DOM-фрагментация, содержащая <option>
элементы, и помещается в кэш.
A datalistUpdate()
function is called, which updates the <datalist>
with the appropriate cached DOM fragment. Further calls to runQuery()
avoid Ajax calls if a query has already been cached or a previous query can be used.
A change
event handler also monitors the <input>
, which is triggered when focus is moved from the field and the value has been modified. The function checks that the value matches a known option and, if necessary, uses the Constraint Validation API to show the error message provided in the valid
attribute.
Предполагая, что был выбран действительный вариант, функция обработчика изменений заполняет все поля с соответствующими атрибутами data-autofill
. Ссылка на поля автозаполнения сохраняется, чтобы их можно было сбросить, если впоследствии будет введен недействительный вариант.
Обратите внимание, что теневой DOM не используется. Это обеспечивает возможность стилизации автозаполнения <input>
(и <datalist>
) элементов с помощью CSS и доступ к ним других скриптов, если это необходимо.
Dunkin’ <datalist>
HTML5 <datalist>
имеет ограничения, но идеально подходит, если вам нужно простое независимое от фреймворка поле автозаполнения. Отсутствие поддержки CSS – это жаль, но производители браузеров могут в конечном итоге исправить этот пробел.
Любой из кода и примеров, показанных в этом уроке, можно применить в своих проектах.
Вопросы и ответы о легковесных контролах автодополнения с элементом datalist HTML5
Что такое элемент datalist в HTML5 и как он работает?
Элемент datalist в HTML5 представляет собой предварительно определенный список вариантов для элемента input. Он предоставляет функцию “автодополнения” для элементов формы. Элемент datalist использует атрибут id для связывания с конкретным элементом input. Элемент input использует атрибут list для идентификации datalist. Внутри datalist вы можете определять элементы option, которые представляют доступные варианты для поля ввода.
Как использовать элемент datalist HTML5 для автодополнения?
Для использования элемента datalist HTML5 для автодополнения необходимо связать datalist с элементом input. Это делается путем добавления атрибута list к элементу input и установки его значения равным id datalist. Браузер затем предложит варианты автодополнения на основе ввода пользователя и определенных вариантов в datalist.
Можно ли использовать элемент datalist HTML5 во всех браузерах?
Элемент datalist HTML5 поддерживается в большинстве современных браузеров, включая Chrome, Firefox, Safari и Edge. Однако он не поддерживается в Internet Explorer 9 и более ранних версиях. Вы можете проверить совместимость браузеров на сайтах, таких как Can I Use.
Как можно стилизовать варианты элемента datalist HTML5?
К сожалению, варианты стилизации для элемента datalist HTML5 довольно ограничены. Внешний вид выпадающего списка контролируется браузером и не может быть легко изменен с помощью CSS. Однако вы можете стилизовать элемент input, связанный с datalist.
Можно ли использовать несколько datalists для одного элемента input?
Нет, нельзя связать несколько datalist с одним полем ввода. Атрибут list поля ввода может принимать только один id, который соответствует одному datalist. Если вам нужно предоставить несколько наборов опций, вам, возможно, придется использовать JavaScript для динамического изменения опций на основе ввода пользователя.
Могу ли я использовать HTML5 datalist с другими типами ввода?
Да, HTML5 datalist можно использовать с различными типами ввода, включая текст, поиск, url, tel, email, дата, месяц, неделя, время, datetime-local, число, диапазон и цвет. Однако функция автозаполнения может не работать так, как ожидается, с некоторыми типами ввода, такими как диапазон или цвет.
Могу ли я использовать HTML5 datalist с элементом select?
Нет, HTML5 datalist нельзя использовать с элементом select. Datalist предназначен для предоставления подсказок автозаполнения для поля ввода, в то время как элемент select предоставляет выпадающий список опций. Если вам нужен выпадающий список, вы должны использовать элемент select.
Могу ли я использовать JavaScript с HTML5 datalist?
Да, вы можете использовать JavaScript с HTML5 datalist для динамического добавления, удаления или изменения опций. Однако имейте в виду, что datalist не поддерживает события, такие как onchange или onclick, на своих опциях. Вам нужно добавить слушатели событий к связанному полю ввода.
Могу ли я использовать HTML5 datalist для поля поиска?
Да, HTML5 datalist может быть отличным выбором для поля поиска. Он может предоставлять подсказки автозаполнения на основе ввода пользователя, что может улучшить пользовательский опыт. Однако вам нужно вручную заполнить datalist возможными поисковыми терминами.
Можно ли использовать HTML5 datalist с текстовым полем?
Нет, HTML5 datalist нельзя использовать с текстовым полем. Datalist предназначен для предоставления подсказок автозаполнения для поля ввода, а не для текстового поля. Если вам нужна функция автозаполнения для текстового поля, вам, возможно, потребуется использовать библиотеку JavaScript или создать свое решение.
Source:
https://www.sitepoint.com/html5-datalist-autocomplete/