oscript-ui
oscript-ui

Форма отбора

Форма отбора сужает список: поле подстроки и кнопка, а при нужде — несколько полей. Она отправляется методом GET, поэтому отбор живёт в адресе: его можно обновить, сохранить закладкой и отправить ссылкой.

Когда использовать#

  • Поиск по списку или таблице: имя, часть имени, логин.
  • Фильтр журнала по нескольким условиям: событие, кто, с какой даты.

Не берите форму отбора для того, что меняет данные на сервере: GET не несёт токена CSRF, и правка через него — дыра. Для таких форм есть Кит.Форма (см. Формы деревом). Переключение соседних видов одного объекта — это вкладки, а не отбор.

В дереве холста готовая строка поиска собирается словами: адрес позицией, метка, значение, кнопка и скрытые поля — цепочкой (см. Язык узлов). Без слова Кнопка значок поиска стоит внутри поля (см. «Строка поиска со значком»).

Узлом холста — словами

HTML = Кит.СтрокаПоиска("/документы").Метка("Поиск").Значение("отчёт") .Пример("Имя документа или его часть").Кнопка("Найти", "поиск") .СкрытоеПоле("проект", "main").Рендер();

Строка поиска со значком#

Строка поиска без слова Кнопка — строка поиска Material: значок «поиск» стоит внутри рамки поля справа, как в поисковиках, и отдельной кнопки нет. Поле занимает всю строку на любой ширине, и на телефоне ничего не уезжает второй строкой. Значок — настоящая кнопка отправки (<button type="submit">): Enter в поле и щелчок по значку отправляют форму и без скрипта. Имя кнопки для скринридера — текст словаря search.submit («Найти»); значок другой — словом Иконка модели.

Значок поиска в строке — сузьте окно до телефона

HTML = Кит.СтрокаПоиска("/документы").Метка("Поиск по документам").СкрытаяМетка() .Пример("Имя документа или его часть").Значение("отчёт").СкрытоеПоле("проект", "main").Рендер();

Значок встаёт только в одиночное поле: у формы из нескольких полей не ясно, внутри какого его ставить, поэтому без Кнопка она не собирается. Отдельная кнопка с подписью — прежний вид, словом Кнопка(Подпись, Иконка): разметка та же, что была.

Поле и кнопка#

Обязательно Действие — адрес, куда уходит GET. Кнопка — подпись отдельной кнопки; без неё у одиночного поля — значок в строке (см. выше). Поле по умолчанию называется q; другое имя параметра задаёт Имя.

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

Поле и кнопка

HTML = Набор.ФормаОтбора().Отрисовать(Новый Структура("Действие, Метка, Кнопка", "/настройки/проекты", "Отбор по имени проекта", "Отобрать"));

Строке поиска над списком видимая метка часто не нужна: смысл поля ясен из места, а в поле стоит пример. Пример — не имя: он пропадает при вводе, и скринридер его не обязан читать. Слово СкрытаяМетка() прячет метку с экрана, но оставляет её скринридеру: поле садится как поле без метки, пример виден, а имя поля — метка.

Метка только для скринридера

HTML = Кит.СтрокаПоиска("/настройки/проекты").Метка("Поиск по проектам").Пример("Имя проекта или его часть") .СкрытаяМетка().Кнопка("Найти").Рендер();

Сохранение остального отбора#

Отправка GET-формы заменяет запрос в адресе целиком. Если список уже отобран по проекту, поиск по подстроке этот отбор потеряет. СкрытыеПоля — массив Имя, Значение — везут остальные параметры вместе с подстрокой.

Значение — текущая подстрока: после отправки человек видит в поле то, что искал. Плейсхолдер — пример, что вводить. Иконка ставится в кнопку.

С сохранением GET-отбора

Скрытые = Новый Массив(); Скрытые.Добавить(Новый Структура("Имя, Значение", "проект", "main")); HTML = Набор.ФормаОтбора().Отрисовать( Новый Структура("Действие, Метка, Значение, Плейсхолдер, Кнопка, Иконка, СкрытыеПоля", "/документы", "Поиск", "отчёт", "Имя документа или его часть", "Найти", "поиск", Скрытые));

Несколько полей#

Поля — массив моделей поля формы. Если он задан, одиночное поле подстроки не печатается: форма состоит из этих полей и кнопки. Годятся любые типы поля — выбор, текст, дата.

Несколько полей отбора

Варианты = Новый Массив(); Варианты.Добавить(Новый Структура("Значение, Подпись", "", "Все события")); Варианты.Добавить(Новый Структура("Значение, Подпись", "доступ.выдан", "Доступ: выдан")); Поля = Новый Массив(); Поля.Добавить(Новый Структура("Имя, Метка, Тип, Варианты", "type", "Событие", "выбор", Варианты)); Поля.Добавить(Новый Структура("Имя, Метка, Плейсхолдер", "who", "Кто", "Логин")); Поля.Добавить(Новый Структура("Имя, Метка, Тип", "since", "С даты (UTC)", "date")); HTML = Набор.ФормаОтбора().Отрисовать(Новый Структура("Действие, Кнопка, Иконка, Поля", "/настройки/журнал", "Показать", "поиск", Поля));

Пустой вариант выбора («Все события») отправляет пустую строку: сервер читает её как «без отбора по событию».

Без перезагрузки#

Слово БезПерезагрузки() у строки поиска (и у рода Кит.ФормаОтбора) делает отбор тихим: форма печатается с признаком data-quiet, тем же, что у тихой формы. Скрипт кита отправляет её запросом в фоне и кладёт ответ на место: список отобран, а фокус и набранное остаются в поле. Ждать Enter не нужно — отбор уходит сам по изменению поля: через 0,4 с после последней буквы, а выбор в списке, флажок и дата — почти сразу. Тот же отбор дважды не уходит. Адрес вкладки уходит в её историю: «Назад» возвращает прежний список и прежнее значение поля.

Строка поиска без перезагрузки

HTML = Кит.СтрокаПоиска("/проекты").Метка("Имя проекта").Значение("бета") .Кнопка("Найти", "поиск").СкрытоеПоле("sort", "name").БезПерезагрузки().Рендер();

Род «форма-отбора» без перезагрузки

HTML = Кит.ФормаОтбора("/журнал", Кит.Поле("who", "Кто"), Кит.Поле("since", "С даты").ТипЗначения(Тип("Дата")), Кит.Кнопка("Показать")).Вид("строкой").БезПерезагрузки().Рендер();

Без скрипта это обычная GET-форма: Enter и кнопка отправляют её, и приходит страница целиком. Сервер ничего нового не учит. Номер страницы в отбор не входит — новый отбор начинается с первой страницы. Сортировку и прочий отбор, которые должны пережить поиск, везите скрытыми полями. Живой образец с сервером — список проектов.

Гайдлайны#

ДелайтеМетка говорит, по чему ищем, плейсхолдер — пример
Код
HTML = Набор.ФормаОтбора().Отрисовать(Новый Структура("Действие, Метка, Плейсхолдер, Кнопка, Иконка",
	"/документы", "Имя документа", "например, отчёт", "Найти", "поиск"));
Не делайтеБезымянное поле: непонятно, по имени ищем или по автору
Код
HTML = Набор.ФормаОтбора().Отрисовать(Новый Структура("Действие, Кнопка",
	"/документы", "Найти"));
ДелайтеКнопка — глагол того, что произойдёт
Код
HTML = Набор.ФормаОтбора().Отрисовать(Новый Структура("Действие, Метка, Кнопка, Иконка",
	"/настройки/журнал", "Логин", "Показать", "поиск"));
Не делайтеКнопка «ОК»
Код
HTML = Набор.ФормаОтбора().Отрисовать(Новый Структура("Действие, Метка, Кнопка",
	"/настройки/журнал", "Логин", "ОК"));
ДелайтеПоиск помнит остальной отбор скрытыми полями
Код
Скрытые = Новый Массив();
Скрытые.Добавить(Новый Структура("Имя, Значение", "проект", "main"));

HTML = Набор.ФормаОтбора().Отрисовать(Новый Структура("Действие, Метка, Кнопка, СкрытыеПоля",
	"/документы", "Имя документа", "Найти", Скрытые));
Не делайтеПоиск без скрытых полей: выбранный проект сбросится
Код
HTML = Набор.ФормаОтбора().Отрисовать(Новый Структура("Действие, Метка, Кнопка",
	"/документы", "Имя документа", "Найти"));

Доступность#

  • Форма — настоящий <form method="get">: отбор работает без скрипта, Enter в поле отправляет форму.
  • Поле — поле формы с подписью в <label>; без Метки скринридер не назовёт поле. Задавайте её всегда — а где видимая метка лишняя, прячьте её словом СкрытаяМетка(), а не заменяйте примером.
  • Кнопка — кнопка отправки с видимой подписью.
  • Форма без Действия не собирается: кит кидает исключение, а не отправляет отбор «куда-то».
  • Тихий отбор (БезПерезагрузки) не уводит фокус из поля: набранное и курсор остаются на месте, пока список меняется под ним. Кнопку отправки оставляйте: с клавиатуры и без скрипта отбор уходит ею.

Узлом холста#

На холсте готовая строка поиска — Кит.СтрокаПоиска(Действие): поля модели компонента пишут слова Имя, Метка, Значение, Пример, Кнопка(Подпись, Иконка), СкрытоеПоле(Имя, Значение), БезПерезагрузки() (поле модели БезПерезагрузки, выпуск 0.13), а несколько полей — Поле(Кит.Поле(…)). От рода Кит.ФормаОтбора(Действие, д…) она отличается тем, что собрана целиком: род даёт пустую GET-форму, в которую поля кладут узлами.

Строка поиска узлом дерева

HTML = Кит.СтрокаПоиска("/документы").Метка("Поиск").Кнопка("Найти").Рендер();

Своя раскладка отбора собирается из рода: GET-форма, поля и кнопка — её дети.

Род «форма-отбора» — форма из узлов

HTML = Кит.ФормаОтбора("/документы", Кит.Поле("q", "Имя документа"), Кит.Поле("автор", "Автор"), Кит.Кнопка("Найти").Иконка("поиск")).Вид("строкой").Рендер();

Модель#

Поля модели — из комментария в исходнике компонента. Структура с этими полями — прежний вид модели: в дереве холста те же поля пишут слова Кит.СтрокаПоиска.

ФормаОтбора.Отрисовать()src/Классы/компоненты/ФормаОтбора.os

Отрисовывает форму отбора списка.

Параметры:
 Модель - Структура - Действие (URL отправки, ОБЯЗАТЕЛЕН), Имя (GET-параметр поля,
          "q"), Метка, Значение (текущий отбор), Плейсхолдер, Поля (массив моделей
          компонента «Поле» — форма из нескольких полей; заданы они — одиночное поле
          не печатается), Кнопка (подпись, обязательна), Иконка кнопки, СкрытыеПоля
          (массив структур Имя, Значение — GET-параметры, которые отправка обязана
          сохранить). Выпуск 0.13: БезПерезагрузки (Булево) — форма уходит тихо
          (data-quiet): ответ ложится на страницу на место, адрес меняется в истории
          вкладки, а отбор уходит сам по изменению поля, с задержкой.
          Выпуск 0.13 (дев-сборка 5): СкрытаяМетка (Булево) — метка одиночного поля
          только для скринридера, доступное имя не от примера.
          Выпуск 0.13 (дев-сборка 6): без Кнопки у одиночного поля — строка поиска Material:
          кнопка-значок «поиск» внутри рамки поля, справа (обёртка .search-bar), имя
          кнопки — текст словаря search.submit; Enter и значок отправляют форму, на любой
          ширине ничего не переносится. С Кнопкой — прежний вид с отдельной кнопкой.

Возвращаемое значение:
 Строка - фрагмент <form class="filters" method="get">. Кидается исключением,
          если Действие пусто.

Кит.СтрокаПоиска()src/Классы/холст/Кит.os

Строка поиска по списку: поле, кнопка и скрытые поля, сохраняющие остальной отбор.
От рода «форма-отбора» отличается тем, что собрана целиком: род даёт пустую GET-форму,
а этот компонент — готовую строку поиска. Слова: Имя (GET-параметр, «q»), Метка,
Значение, Пример, Кнопка(Подпись, Иконка), СкрытоеПоле(Имя, Значение), Поле(узел поля),
БезПерезагрузки (выпуск 0.13: тихо и по изменению поля с задержкой). Без слова Кнопка
(0.13, дев-сборка 6) — строка поиска Material: значок «поиск» кнопкой отправки внутри
поля справа, имя — словарь search.submit; со словом — прежняя отдельная кнопка.

Параметры:
 Модель - Строка, Структура - адрес отправки (Действие); Структура — прежний вид модели.

Возвращаемое значение:
 ЭлементЭкрана

Кит.ФормаОтбора()src/Классы/холст/Кит.os

Форма отбора: GET, который на сервере ничего не меняет, а значит защищать в нём нечего.
Отправленный отбор виден в адресе и повторяем ссылкой — это и есть его смысл. Со словом
БезПерезагрузки (выпуск 0.13) отбор уходит тихо и сам, по изменению поля с задержкой.

Параметры:
 Действие - Строка - URL, куда уходит GET.
 Р1…Р8    - ЭлементЭкрана - (необязательные) поля и кнопки формы.

Возвращаемое значение:
 ЭлементЭкрана