Формы деревом
Форма в дереве бывает двух видов. Род формы — пустая , в которую кладут поля и кнопки узлами. Объявленная форма знает свои поля сама: печатает их, разбирает пришедшее и возвращает человеку отказ вместе с набранным.
Когда что брать#
- Род формы — форма из одной-двух кнопок, отбор списка, переключатель, форма, состав которой собирает экран.
- Объявленная форма — форма, которую сервер разбирает: создание и правка объекта, настройки. Поля объявлены один раз, и отрисовка с разбором не могут разойтись в именах.
Готовую строку поиска с полем и кнопкой печатает компонент «Форма отбора», отдельное поле — компонент «Поле формы».
Четыре рода формы#
Роды формы отличаются не оформлением, а тем, чем защищён отправленный запрос. Раскладка у всех общая — словом .Вид(…): «столбик», «строкой», «меню» (форма внутри пункта меню), «переключатель». Поля и кнопки — дети формы аргументами.
Форма вошедшего отправляет POST со скрытым полем CSRF первым. Токен задаётся словом .Токен(…) — у самой формы или у предка: форма ищет его у себя и дальше вверх по дереву. Без токена форма не печатается: она выглядела бы рабочей, а получала 403. Строка внутри формы не принимается вовсе — прежде вторым аргументом шёл токен, и строкой он напечатался бы на экране.
Форма вошедшего — токен словом, поле CSRF встаёт первым
HTML = Кит.Форма("/проекты",
Кит.Поле("имя", "Имя проекта"),
Кит.Кнопка("Создать").Основная()).Токен("т0кен-сессии").Вид("строкой").Рендер();Форма посетителя без сессии — вход, регистрация, запрос ссылки на смену пароля. Токена у неё нет, потому что его неоткуда взять: токен живёт в сессии.
Форма посетителя без сессии
HTML = Кит.ФормаБезСессии("/вход",
Кит.Поле("почта", "Почта").ТипЗначения("email"),
Кит.Кнопка("Войти").Основная()).Вид("столбик").Рендер();Форма отбора идёт GET и на сервере ничего не меняет. Отправленный отбор виден в адресе, и им можно поделиться ссылкой — в этом его смысл.
Форма отбора — GET, ничего не меняет
HTML = Кит.ФормаОтбора("/документы",
Кит.Поле("q", "Поиск"),
Кит.Кнопка("Найти").Вторичная()).Вид("строкой").Рендер();Форма без токена — у отправителя сессия есть, но сервер токена не спрашивает: цена подделки запроса — неудобство, а не ущерб. Так переключают тему и выходят.
Форма, у которой сервер токена не спрашивает
HTML = Кит.ФормаБезТокена("/оформление",
Кит.Кнопка("Переключить тему").Ссылкой().Иконка("луна").ТолькоИконка())
.Вид("переключатель").Рендер();Форма, которая несёт файлы, объявляет это словом СФайлами(). Без него браузер отправит вместо файла одно его имя.
Форма с файлами
<form method="post" action="/документы" enctype="multipart/form-data" class="form-stack"><input type="hidden" name="_csrf" value="т0кен-сессии"><label class="field"><span class="field__label">Архив документов</span><input class="field__control" type="file" name="архив"></label></form>HTML = Кит.Форма("/документы", Кит.Поле("архив", "Архив документов").Файл())
.Токен("т0кен-сессии").Вид("столбик").СФайлами().Рендер();Адрес и токен у контекста#
Адрес раздела и токен на экране задаются один раз — у дома настроек или у холста экрана, — а форма берёт их у ближайшего предка:
Кит.Форма("", …)уходит на адрес контекста — текущего раздела дома;Кит.Форма("revoke", …)— нараздел/revoke;Кит.Форма("/x", …)— на свой адрес; так же адрес с?и#в начале.
Форма с относительным адресом без дома вокруг не печатается: запрос ушёл бы на текущую страницу молча и не туда. Форма вошедшего без токена ни у себя, ни у предков — тоже.
Формы берут адрес у раздела дома, токен — у дома
Настройки
Ключи
Ключи доступа
Дом = Кит.ДомНастроек("Настройки", "/проекты/альфа/настройки", "т0кен-сессии",
Кит.Секция("Ключи доступа",
Кит.Ряд("действия",
Кит.Форма("", Кит.Кнопка("Выпустить ключ").Основная()),
Кит.Форма("7/revoke", Кит.Кнопка("Отозвать ключ 7").Опасная()))));
Дом.Раздел("Ключи", "ключи").Текущий();
HTML = Дом.Рендер();Относительный адрес без контекста — исключение
Разметка элементов: узел «форма» с относительным адресом «revoke» — форме нужен абсолютный адрес или дом/секция вокруг. Адрес без ведущей косой дописывается к адресу раздела дома настроек; вне дома задайте его от корня (/…).
Попытка
Кит.Форма("revoke", Кит.Кнопка("Отозвать")).Токен("т").Рендер();
Исключение
HTML = Кит.Примечание(КраткоеПредставлениеОшибки(ИнформацияОбОшибке())).Рендер();
КонецПопытки;Тип поля#
Тип поля задаётся словом .ТипЗначения(…) значением системы типов OneScript — тем же, что у реквизита в 1С. Имя слова не «Тип»: оно в OneScript занято самой системой типов.
| Значение | Поле |
|---|---|
Тип("Строка") |
текст |
Тип("Число") |
type="number" |
Тип("Булево") |
флажок |
Тип("Дата") |
type="date" |
ОписаниеТипов("Число", КвалификаторыЧисла(7, 2)) |
step="0.01", max="99999.99"; без дробной части — step="1" |
ОписаниеТипов("Строка", , КвалификаторыСтроки(50)) |
maxlength="50" |
КвалификаторыДаты(ЧастиДаты.Дата | ДатаВремя | Время) |
date | datetime-local | time |
| строка: «email», «url», «пароль», «файл», «многострочное», «выбор», «флажок», «число», «текст» | прежний тип модели |
Без явного типа он выводится из значения: число — числовое поле, Булево — отмеченный или снятый флажок, дата — поле даты в формате ввода ГГГГ-ММ-ДД. Явный тип старше выведенного. Не-типы остаются словами: .Многострочное(), .Секрет(), .Файл(), .Вариант(Значение, Подпись) — первый вариант делает поле выбором.
Тип описанием типов, выводом из значения и словом
<form method="post" action="/отчёт" class="form-stack"><label class="field"><span class="field__label">Сумма, ₽</span><input class="field__control" type="number" name="сумма" max="9999999.99" step="0.01"></label><label class="field"><span class="field__label">С даты</span><input class="field__control" type="date" name="с" value="2024-03-01"></label><label class="field field--check"><input type="checkbox" class="field__check" name="итоги" value="1" checked><span class="field__label">Показать итоги</span></label><label class="field"><span class="field__label">Формат</span><select class="field__control" name="формат"><option value="pdf">PDF</option><option value="csv" selected>CSV</option></select></label></form>HTML = Кит.ФормаБезТокена("/отчёт",
Кит.Поле("сумма", "Сумма, ₽").ТипЗначения(
Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(9, 2))),
Кит.Поле("с", "С даты").Значение(Дата(2024, 3, 1)),
Кит.Поле("итоги", "Показать итоги").Значение(Истина),
Кит.Поле("формат", "Формат").Вариант("pdf", "PDF").Вариант("csv", "CSV").Значение("csv"))
.Вид("столбик").Рендер();Без перезагрузки#
Форма, помеченная БезПерезагрузки(), уходит запросом в фоне, и страница не перезагружается. Ответ сервера скрипт кита кладёт на текущую страницу на место. Узел, который не изменился, остаётся тем же узлом, поэтому не прыгает прокрутка, не теряется фокус, раскрытые раскрывашки остаются раскрытыми, а бегунок тумблера доезжает своей анимацией.
Форма без перезагрузки — тот же адрес и метод, один признак
<form method="post" action="/настройки/почта" class="form-stack" data-quiet=""><input type="hidden" name="_csrf" value="т0кен-сессии"><div class="toggle-save"><div class="toggle"><label class="toggle__box"><input type="checkbox" class="toggle__input" name="сбои" value="1" checked data-autosubmit><span class="toggle__track" aria-hidden="true"><span class="toggle__thumb"></span></span><span class="toggle__text"><span class="toggle__label">Письма о сбоях</span></span></label><input type="hidden" name="сбои" value="0"></div><button type="submit" class="toggle__save button button--primary button--sm button--icon" title="Сохранить" aria-label="Сохранить"><svg class="icon" viewBox="0 -960 960 960" aria-hidden="true" focusable="false" fill="currentColor" xmlns="http://www.w3.org/2000/svg"><path d="M840-680v480q0 33-23.5 56.5T760-120H200q-33 0-56.5-23.5T120-200v-560q0-33 23.5-56.5T200-840h480l160 160Zm-80 34L646-760H200v560h560v-446ZM480-240q50 0 85-35t35-85q0-50-35-85t-85-35q-50 0-85 35t-35 85q0 50 35 85t85 35ZM240-560h360v-160H240v160Zm-40-86v446-560 114Z"></path></svg></button></div><div class="savebar" data-savebar><div class="savebar__actions"><button type="submit" class="button button--primary"><svg class="icon" viewBox="0 -960 960 960" aria-hidden="true" focusable="false" fill="currentColor" xmlns="http://www.w3.org/2000/svg"><path d="M840-680v480q0 33-23.5 56.5T760-120H200q-33 0-56.5-23.5T120-200v-560q0-33 23.5-56.5T200-840h480l160 160Zm-80 34L646-760H200v560h560v-446ZM480-240q50 0 85-35t35-85q0-50-35-85t-85-35q-50 0-85 35t-35 85q0 50 35 85t85 35ZM240-560h360v-160H240v160Zm-40-86v446-560 114Z"></path></svg><span>Сохранить</span></button></div></div></form>HTML = Кит.Форма("/настройки/почта",
Кит.Тумблер("сбои", "Письма о сбоях").Включено().СохранятьСразу(),
Кит.ПанельСохранения())
.Токен("т0кен-сессии").Вид("столбик").БезПерезагрузки().Рендер();Сервер для такой формы ничего нового не делает и отвечает тем же, чем ответил бы браузеру:
- Сохранил — перенаправляет обратно на страницу (POST, затем 303, затем GET). Форма сбрасывается к тому, что пришло с сервера: поле комментария пустеет, тумблер стоит так, как его запомнил сервер. Перенаправление на другой адрес тоже работает: страница сменится без перезагрузки, адрес вкладки — вместе с ней.
- Не принял — отдаёт страницу с ошибками (4xx). Введённое человеком остаётся в полях, подсказки об ошибках встают рядом.
Пока ответ в пути, форма помечена aria-busy. Две отправки подряд уходят по очереди, каждая со своими данными, а на страницу ложится только последний ответ. Если что-то пошло не так (нет сети, ответ — не страница, у новой страницы другие листы или скрипты), форма уходит обычной навигацией: страница перезагрузится, как и без скрипта.
Так в этой документации работают переключатель темы в шапке и выбор акцента.
Не помечайте так форму, которая отдаёт файл или уводит на чужой сайт, например вход через провайдера. Такому ответу место во вкладке, а не на текущей странице.
В окне#
Форма в окне уходит без перезагрузки так же, как любая тихая форма, — сервер отвечает тем же, что и браузеру. Скрипт кита только смотрит, где стояла форма:
- Сохранил — перенаправляет. Окно закрывается, страница ложится по ответу на место, и фокус встаёт на элемент, который сервер пометил словом
Фокус()(признакdata-focus), — обычно на только что созданную запись. Человек видит результат там, где начинал, и клавиатура продолжает с него. Без пометки фокус возвращается на кнопку, которой окно открыли. - Не принял — 4xx. Ответ несёт ту же страницу с этим же окном, напечатанным открытым (
Открыто()), и отказами у полей. Скрипт берёт из ответа только окно и кладёт его содержимое в открытое: введённое на месте, подсказки рядом, фокус на первом отбитом поле, остальная страница не тронута. - Ответил окном — 2xx без перенаправления. Ответ, который сам печатает другое окно открытым («ключ выпущен — скопируйте его сейчас»), ложится на страницу целиком: окно формы закрывается, окно ответа открывается модальным. Открытое окно, которого в ответе нет, и опустевшая оболочка окна по адресу закрываются.
Окно-форма и запись, которую сервер пометил фокусом
<button type="button" class="button button--primary" command="show-modal" commandfor="novyi-proekt"><span>Новый проект</span></button><div class="table-scroll"><table class="table"><thead><tr><th scope="col">Проект</th></tr></thead><tbody><tr><td>альфа</td></tr><tr data-focus=""><td>дельта</td></tr></tbody></table></div><dialog class="modal" id="novyi-proekt" aria-labelledby="novyi-proekt-title"><form method="post" action="/проекты" class="modal__box" data-quiet=""><input type="hidden" name="_csrf" value="т0кен-сессии"><div class="modal__head"><h2 class="modal__title" id="novyi-proekt-title">Новый проект</h2><button type="button" class="button button--link button--icon" title="Закрыть окно" aria-label="Закрыть окно" command="close" commandfor="novyi-proekt"><svg class="icon" viewBox="0 -960 960 960" aria-hidden="true" focusable="false" fill="currentColor" xmlns="http://www.w3.org/2000/svg"><path d="m256-200-56-56 224-224-224-224 56-56 224 224 224-224 56 56-224 224 224 224-56 56-224-224-224 224Z"></path></svg></button></div><div class="modal__body"><label class="field"><span class="field__label">Название</span><input class="field__control" type="text" name="name" required></label></div><div class="modal__actions"><button type="submit" class="button button--primary"><span>Создать</span></button></div></form></dialog>Окно = Кит.Окно("Новый проект", Кит.Поле("name", "Название").Обязательное())
.Форма("/проекты").БезПерезагрузки().Якорь("novyi-proekt")
.Действия(Кит.Кнопка("Создать").Основная());
HTML = Кит.Холст(
Кит.Кнопка("Новый проект").Открывает(Окно),
Кит.Таблица(Кит.Колонка("Проект"),
Кит.Запись(Кит.Ячейка("альфа")),
Кит.Запись(Кит.Ячейка("дельта")).Фокус()),
Окно).Токен("т0кен-сессии").Рендер();Признак тихой отправки у окна-формы печатается на <form>, а не на <dialog>: словом БезПерезагрузки() помечают само окно. Форма, которая стоит в окне вне его формы (кнопка подтверждения с атрибутом form), закрывает окно своей кнопки по тем же правилам.
Без скрипта форма окна уходит обычным POST, и приходит страница целиком: удача — список с новой записью, отказ — страница с окном, напечатанным открытым. Образец с настоящим сервером — список проектов.
Объявленная форма#
Объявление берут у желудя Формы: Формы.Новая(). Поле(Ключ, Метка) объявляет поле и отдаёт его описание — оно настраивается словами, как узел холста: ТипЗначения, Пределы(Мин, Макс), Обязательное, ТолькоЧтение, Подсказка, Источник, Пример, Автозаполнение, Умолчание, Вариант(Значение, Подпись), Кат, Рамка, Многострочное, Секрет, а проверку до отправки — Длина(Мин, Макс), Шаблон(Образец), ПроверкаНаСервере(Адрес), ПроверкаДоОтправки (раздел «Проверка» страницы Поле). Следующее Поле у описания объявляет следующее поле того же объявления — цепочка не рвётся. Из ключа выводится атрибут name, и разбор зовёт ту же функцию, что отрисовка.
Прежний вызов Поле(Ключ, Метка, Вид, Свойства) — вид «строка», «число», «флажок», «секрет», «многострочное», «выбор», «дата» и структура свойств — работает как раньше и печатает то же самое.
Объявленная форма — состав знает она сама
Объявление = Формы.Новая();
Объявление.Поле("имя", "Имя проекта").Обязательное().Подсказка("латиница и дефис")
.Поле("описание", "Описание").Многострочное()
.Поле("квота", "Квота, ГБ").ТипЗначения(Тип("Число")).Пределы(1, 100);
HTML = Кит.ОбъявленнаяФорма(Объявление, Новый Структура("имя, квота", "main", 20),
"/проекты", "т0кен-сессии", "столбик").Рендер();Второй аргумент — действующие значения по ключам полей. Их печатают в полях, пока человек ещё ничего не набрал; дата печатается в формате ввода.
Проверка полей#
Разобрать берёт тело запроса, приводит значения к объявленным типам и проверяет ограничения. Флажок становится Булево, число — Числом, дата — Датой. Поле только на чтение из запроса не берётся вовсе: подделанное значение не сохранится и не попадёт на экран.
Отказ возвращает ту же форму: под полем текст отказа, в поле — то, что человек набрал. Секрет не возвращается никогда.
Отказ возвращает форму с набранным
Объявление = Формы.Новая();
Объявление.Поле("имя", "Имя проекта").Обязательное()
.Поле("квота", "Квота, ГБ").ТипЗначения(Тип("Число")).Пределы(1, 100);
Присланное = Новый Соответствие();
Присланное.Вставить("имя", "");
Присланное.Вставить("квота", "500");
Итог = Объявление.Разобрать(Присланное);
HTML = Кит.ОбъявленнаяФорма(Объявление, Неопределено,
"/проекты", "т0кен-сессии", "столбик").Рендер();Текстов отказов у кита нет: он берёт их из словаря интерфейса инсталляции по ключам form.error.required, form.error.number, form.error.min, form.error.max, form.error.choice и form.error.date, а ограничения проверки до отправки — по ключам form.error.minlength, form.error.maxlength (%1 — длина), form.error.pattern, form.error.email и form.error.url. Ключ, которого словарь не знает, печатается маркером [?ключ] — так пропуск виден сразу, а не прячется за пустой строкой.
Разбор судит строку теми же ограничениями, что поле печатает браузеру: вид «email» и «url» (ТипЗначения("email")), Длина, Шаблон — совпадение целиком и с учётом регистра, как у атрибута pattern. Без скрипта браузер не отправит негодное, а сервер не примет подделанное — и скажет теми же словами, что скрипт до отправки.
Отказ, который видит только домен (имя занято, проект закрыт), приходит в форму тем же путём — методом Отбить.
Отказ домена
Объявление = Формы.Новая();
Объявление.Поле("имя", "Имя проекта");
Присланное = Новый Соответствие();
Присланное.Вставить("имя", "main");
Итог = Объявление.Разобрать(Присланное);
Если Итог.Принято Тогда
Объявление.Отбить("имя", "Проект с таким именем уже есть");
КонецЕсли;
HTML = Кит.ОбъявленнаяФорма(Объявление, Неопределено,
"/проекты", "т0кен-сессии", "столбик").Рендер();Кат и рамка#
Подряд идущие поля с одной подписью Кат уходят под общую раскрывашку, с одним видом Рамка — в общую область. Это объявляют у полей, а не собирают вокруг них руками.
Редкие настройки под раскрывашкой
Объявление = Формы.Новая();
Объявление.Поле("имя", "Имя проекта")
.Поле("ветка", "Ветка по умолчанию").Умолчание("main").Кат("Дополнительно")
.Поле("архив", "В архиве").ТипЗначения(Тип("Булево")).Кат("Дополнительно");
HTML = Кит.ОбъявленнаяФорма(Объявление, Неопределено,
"/проекты", "т0кен-сессии", "столбик").Рендер();Форма окном#
Та же объявленная форма печатается модальным окном: кнопка открытия и dialog, который места не занимает, пока не открыт. Открытие, закрытие по Esc и удержание фокуса делает браузер, скрипта нет.
Та же форма окном поверх экрана
Объявление = Формы.Новая();
Объявление.Поле("имя", "Имя проекта");
Окно = Новый Структура("Заголовок, Открывашка, Отправка",
"Новый проект", "Создать проект", "Создать");
HTML = Кит.Окно(Объявление, Новый Структура(), "/проекты", "т0кен-сессии", Окно).Рендер();Кнопка открытия не сработает в старом браузере, поэтому у экрана должна оставаться серверная дорога: адрес, по которому страница приходит с открытым окном (Открыта в свойствах окна). Им же отбитая форма возвращается человеку.
Это окно печатается той же рамкой, что окно со слотами, и в дереве оно — узел рода «окно»: кнопка открывает его словом Открывает(узел). Разметка — прежняя, байт в байт.
Гайдлайны#
Код
HTML = Кит.Форма("/проекты/7/удалить", Кит.Кнопка("Удалить").Опасная())
.Токен("т0кен-сессии").Рендер();Код
HTML = Кит.ФормаБезТокена("/проекты/7/удалить", Кит.Кнопка("Удалить").Опасная()).Рендер();Настройки
Участники
Код
Дом = Кит.ДомНастроек("Настройки", "/настройки", "т0кен-сессии",
Кит.Секция("Участники",
Кит.Форма("анна/исключить", Кит.Кнопка("Исключить анну").Опасная().Малая()),
Кит.Форма("борис/исключить", Кит.Кнопка("Исключить бориса").Опасная().Малая())));
HTML = Дом.Рендер();Настройки
Участники
Код
Дом = Кит.ДомНастроек("Настройки", "/настройки", "",
Кит.Секция("Участники",
Кит.Форма("/настройки/анна/исключить", Кит.Кнопка("Исключить анну").Опасная().Малая())
.Токен("т0кен-сессии"),
Кит.Форма("/настройки/борис/исключить", Кит.Кнопка("Исключить бориса").Опасная().Малая())
.Токен("т0кен-сессии")));
HTML = Дом.Рендер();Код
HTML = Кит.ФормаОтбора("/документы", Кит.Поле("q", "Поиск"), Кит.Кнопка("Найти").Вторичная())
.Вид("строкой").Рендер();Код
HTML = Кит.Форма("/документы", Кит.Поле("q", "Поиск"), Кит.Кнопка("Найти").Вторичная())
.Токен("т0кен-сессии").Вид("строкой").Рендер();Доступность#
- Поля объявленной формы печатаются компонентом «Поле формы»: метка связана с полем, отказ — с полем через описание.
- Окно называет себя скринридеру заголовком: без заголовка оно не соберётся.
- Форма без адреса действия не печатается: запрос ушёл бы на текущую страницу молча и не туда.
- Род формы не подставляет подписей сам: каждому полю нужна метка, кнопке-значку — подпись.
Справка#
Кит.Форма()src/Классы/холст/Кит.os
Форма, которую отправляет вошедший: POST со скрытым полем CSRF первым. Токен задаётся
словом Токен(…) у формы или у предка (дом настроек, холст экрана); без токена форма
не печатается — она выглядит рабочей, а получает 403. Относительный адрес дописывается
к адресу контекста: "" — адрес раздела дома вокруг, «revoke» — раздел/revoke, «/x» —
абсолютный. Вид словом: «столбик» | «строкой» | «меню» (форма внутри пункта меню)
| «переключатель» | "" (без раскладки).
Параметры:
Действие - Строка - URL, куда уходит POST.
Р1…Р8 - ЭлементЭкрана - (необязательные) поля и кнопки формы. Строка в форме не
принимается: токен — словом Токен, текст — узлом Кит.Текст.
Возвращаемое значение:
ЭлементЭкранаКит.ФормаБезСессии()src/Классы/холст/Кит.os
Форма посетителя, у которого сессии ещё нет: вход, регистрация, запрос ссылки на смену пароля, установка пароля по одноразовой ссылке. Токена не несёт, потому что его неоткуда взять: CSRF-токен живёт В СЕССИИ, и там, где сессии нет, сервер его и не спрашивает. Взятая по ошибке на форме вошедшего, она получит от сервера 403 на первой же отправке. Параметры: Действие - Строка - URL, куда уходит POST. Р1…Р8 - ЭлементЭкрана - (необязательные) поля и кнопки формы. Возвращаемое значение: ЭлементЭкрана
Кит.ФормаОтбора()src/Классы/холст/Кит.os
Форма отбора: GET, который на сервере ничего не меняет, а значит защищать в нём нечего. Отправленный отбор виден в адресе и повторяем ссылкой — это и есть его смысл. Со словом БезПерезагрузки (выпуск 0.13) отбор уходит тихо и сам, по изменению поля с задержкой. Параметры: Действие - Строка - URL, куда уходит GET. Р1…Р8 - ЭлементЭкрана - (необязательные) поля и кнопки формы. Возвращаемое значение: ЭлементЭкрана
Кит.ФормаБезТокена()src/Классы/холст/Кит.os
Форма, у отправителя которой сессия ЕСТЬ, а сервер токена не спрашивает: цена подделки такого запроса — неудобство, а не ущерб (переключить оформление, выйти). Отличается от ФормаБезСессии тем, ПОЧЕМУ токена нет: там его неоткуда взять, здесь он не нужен. Взятая на форме, которая меняет что-то по-настоящему, она получит от сервера 403 на первой же отправке: границей безопасности остаётся серверная проверка. Параметры: Действие - Строка - URL, куда уходит POST. Р1…Р8 - ЭлементЭкрана - (необязательные) поля и кнопки формы. Возвращаемое значение: ЭлементЭкрана
ЭлементЭкрана.СФайлами()src/Классы/холст/ЭлементЭкрана.os
Объявляет, что форма несёт файлы: без этого браузер отправляет вместо файла его имя. У секции настроек — то же для её формы. Возвращаемое значение: ЭлементЭкрана - этот же элемент.
ЭлементЭкрана.Токен()src/Классы/холст/ЭлементЭкрана.os
CSRF-токен сессии для форм внутри узла: форма ищет его у себя и дальше вверх по предкам, поэтому на экране он задаётся один раз — у дома настроек или у корня экрана. Параметры: Значение - Строка - токен. Возвращаемое значение: ЭлементЭкрана - этот же элемент.
ЭлементЭкрана.ТипЗначения()src/Классы/холст/ЭлементЭкрана.os
Тип значения поля — системой типов OneScript: Тип("Число") печатается полем type=number,
Тип("Булево") — флажком, Тип("Дата") — type=date, Тип("Строка") — текстом. ОписаниеТипов
с квалификаторами даёт пределы: КвалификаторыЧисла — step и max, КвалификаторыСтроки —
maxlength, КвалификаторыДаты — date, datetime-local или time. Строка («email», «url»,
«пароль», «файл», «многострочное», «выбор», «флажок», «число», «текст») — прежний Тип
модели. Явный тип старше выведенного из Значения. Слово называется ТипЗначения, потому
что имя «Тип» в OneScript занято самой системой типов.
Параметры:
Значение_ - Тип, ОписаниеТипов, Строка - тип значения.
Возвращаемое значение:
ЭлементЭкрана - этот же элемент.ЭлементЭкрана.Значение()src/Классы/холст/ЭлементЭкрана.os
Значение компонента. У поля — его значение, из которого выводится тип ввода, если тип не задан словом ТипЗначения: число печатается числовым полем, Булево — флажком (и отмечает его), дата — полем даты в формате ввода. Параметры: Значение_ - Произвольный - значение. Возвращаемое значение: ЭлементЭкрана - этот же элемент.
Формы.Новая()src/Классы/каркас/Формы.os
Новое пустое объявление формы. Возвращаемое значение: ОбъявлениеФормы - объявление, которому перечисляют поля и блоки.
ОбъявлениеФормы.Поле()src/Классы/каркас/ОбъявлениеФормы.os
Объявляет поле формы. Поле настраивается словами описания: ТипЗначения(Тип(…) |
ОписаниеТипов | строка), Пределы(Мин, Макс), Обязательное, ТолькоЧтение, Подсказка, Источник,
Пример, Автозаполнение, Умолчание, Вариант(Значение, Подпись), Кат, Рамка,
Многострочное, Секрет, Список, Цвет, Образец(Цвет, Имя); проверку до отправки —
Длина(Мин, Макс), Шаблон(Образец), ПроверкаНаСервере(Адрес), ПроверкаДоОтправки.
Прежний вызов с видом и свойствами работает как раньше.
Параметры:
Ключ - Строка - ключ поля; из него выводится атрибут name.
Метка - Строка - подпись поля для человека.
Вид - Строка - (необязательный) "строка" (по умолчанию) | "число" | "флажок" |
"секрет" | "многострочное" | "выбор" | "дата" | "список" | "цвет".
Свойства - Структура, Неопределено - (необязательный, по умолчанию Неопределено)
Обязательное, ТолькоЧтение, Подсказка, Источник, Плейсхолдер, Автозаполнение,
Мин и Макс (для числа), Варианты (для выбора: массив структур Значение,
Подпись, Выбрано), Умолчание (значение пустого поля), Кат (подпись
раскрывашки: подряд идущие элементы с одной подписью уходят под неё),
Рамка (вид области кита: подряд идущие элементы с одним видом
уходят в общий <div>).
Возвращаемое значение:
ОписаниеПоля - описание поля для слов; Поле, Блок и печать оно передаёт этому
объявлению, поэтому поля по-прежнему перечисляются цепочкой.ОписаниеПоля.ТипЗначения()src/Классы/каркас/ОписаниеПоля.os
Тип значения поля — системой типов OneScript: Тип("Число") — число, Тип("Булево") —
флажок, Тип("Дата") — дата; ОписаниеТипов с квалификаторами даёт пределы ввода (step,
max, maxlength) и вид даты (дата, дата и время, время). Строка — прежний вид поля
(«строка», «число», «флажок», «секрет», «многострочное», «выбор», «дата»). Разбор
приводит пришедшее к этому типу: число — Число, флажок — Булево, дата — Дата.
Параметры:
Значение - Тип, ОписаниеТипов, Строка - тип значения.
Возвращаемое значение:
ОписаниеПоля - это же описание.ОписаниеПоля.Пределы()src/Классы/каркас/ОписаниеПоля.os
Пределы числа: разбор отбивает значение вне них, а поле печатает их атрибутами min и max. Параметры: Мин - Число, Неопределено - нижний предел. Макс - Число, Неопределено - верхний предел. Возвращаемое значение: ОписаниеПоля - это же описание.
ОбъявлениеФормы.БезТокена()src/Классы/каркас/ОбъявлениеФормы.os
Объявляет форму анонимной: у неё нет сессии, к которой привязывался бы CSRF-токен. Причина обязательна и видна в объявлении — забыть токен молча нельзя, отказаться от него можно только назвав причину. Параметры: Причина - Строка - почему у формы не может быть токена. Возвращаемое значение: ОбъявлениеФормы - это же объявление.
ОбъявлениеФормы.Разобрать()src/Классы/каркас/ОбъявлениеФормы.os
Разбирает пришедшую форму по объявлению: приводит значения к видам полей, проверяет
ограничения и запоминает набранное, чтобы отрисовка вернула его человеку.
Параметры:
Присланное - Соответствие - разобранное тело запроса (имя поля -> значение).
Возвращаемое значение:
Структура - Принято (Булево: ни одного отказа), Значения (Соответствие: ключ ->
значение своего типа), Отказы (Соответствие: ключ -> текст),
Отказ (Строка: текст первого отказа, "" — отказов нет), Показ
(Соответствие: ключ -> набранное человеком; им форму заполняют заново,
когда отказ возвращает страницу; секрет сюда не попадает).ОбъявлениеФормы.Отбить()src/Классы/каркас/ОбъявлениеФормы.os
Отбивает поле отказом домена: то, что видно только сервису (имя занято, пул закрыт), приходит в форму тем же путём, что и отказ проверки. Параметры: Ключ - Строка - ключ поля. Текст - Строка - текст отказа для человека.
ПроверкаПоля.Прочитать()src/Классы/каркас/ПроверкаПоля.os
Читает сырое значение поля по его объявлению.
Параметры:
Описание - Структура - объявление поля (ОбъявлениеФормы.Состав): Вид, Обязательное,
Мин, Макс, Варианты, Умолчание. Вид «дата», «датавремя», «время» читается
Датой; нечитаемая дата отбивается текстом form.error.date. Вид «список»
читается массивом строк, вид «цвет» — кодом #rrggbb (иной код отбивается
текстом form.error.color). Строку судят ещё и ограничения проверки до
отправки — те же, что поле печатает браузеру: вид «email» и «url»
(form.error.email, form.error.url), ДлинаМин и ДлинаМакс (form.error.minlength,
form.error.maxlength), Шаблон (form.error.pattern); у списка — его строку
через запятую.
Сырое - Строка, Неопределено - значение из формы; Неопределено — поля в форме нет.
Возвращаемое значение:
Структура - Принято (Булево), Значение (Произвольный: Булево для флажка, Число для
числа, Дата для даты, Массив из Строка для списка, Строка для остальных;
Неопределено — не задано), Отказ (Строка:
текст для экрана, "" при успехе), Показ (Строка: что вернуть в поле).Кит.ОбъявленнаяФорма()src/Классы/холст/Кит.os
Объявленная форма: она знает свои поля и умеет разобрать пришедшее, поэтому входит в дерево узлом-компонентом, а не переписывается родами кита. Параметры: Объявление - ОбъявлениеФормы - объявленный состав формы. Действующие - Структура, Соответствие - значения полей. Действие - Строка - URL, куда уходит POST. Токен - Строка - CSRF-токен сессии. Вид - Строка - «столбик» | «строкой» | «меню» | «переключатель» | "" (без раскладки). Возвращаемое значение: ЭлементЭкрана
Кит.Окно()src/Классы/холст/Кит.os
Модальное окно со слотами: заголовок и крестик сверху, лид под ними, тело — дети узла, действия — второй холст Действия(д…) внизу. Открывает его кнопка словом Открывает(узел) (команда движка show-modal, скрипта не нужно); Esc и крестик закрывают его движком. Ширина — базового диалога Material: 560 px, у широкого 640. На телефоне (до 640 px) окно остаётся базовым — по центру, в экран без полей по 16 px; листом во весь экран (тело прокручивается, действия прилипают к низу) встаёт окно со словом ВоВесьЭкран и окно с шагами. Слова: Лид, Действия(д…), Вид («обычное» | «опасное» | «широкое»), Широкое, ВоВесьЭкран, Открыто (сервер печатает окно открытым по ?окно=…), Якорь (идентификатор; без него кит выдаёт свой, постоянный для того же дерева), Форма(Адрес) (окно целиком — форма; токен у предков), БезПерезагрузки (форма окна уходит тихо: успех закрывает окно, отказ остаётся в нём), Токен, СФайлами. Прежний вызов Кит.Окно(Объявление, Действующие, Действие, Токен, Свойства) печатает объявленную форму окном, как раньше: первым аргументом пришло объявление, а не заголовок. Параметры: Заголовок - Строка - заголовок окна: им окно называет себя скринридеру. Р1…Р8 - ЭлементЭкрана, Строка - (необязательные) тело окна; строка — текст. Возвращаемое значение: ЭлементЭкрана
ЭлементЭкрана.Фокус()src/Классы/холст/ЭлементЭкрана.os
Признак data-focus: элемент, на который скрипт ставит фокус, когда тихая отправка из окна удалась и окно закрылось, — сервер помечает им только что созданную запись. Скрипт делает элемент фокусируемым сам, если тот не был. Возвращаемое значение: ЭлементЭкрана - этот же элемент.
ПечатьФормы.Окно()src/Классы/каркас/ПечатьФормы.os
Кнопка открытия и модальное окно с готовой формой внутри. Скрипта нет: открытие,
закрытие по Esc и щелчку мимо, удержание фокуса и гашение фона — работа движка.
Связь кнопки с окном — по идентификатору, который выдаёт кит, а не данные.
Параметры:
Ид - Строка - идентификатор окна.
Внутри - Строка - ДОВЕРЕННЫЙ HTML формы окна.
Модель - Структура - Заголовок (обязателен: он же имя окна для скринридера),
Лид (что настраивает форма), Открывашка (подпись кнопки открытия; пусто —
кнопка не печатается), ИконкаОткрывашки, ВариантОткрывашки, Открыта
(окно печатается открытым — так отбитая форма возвращается человеку
вместе с набранным).
Возвращаемое значение:
Строка - кнопка и <dialog>; окно места на экране не занимает, пока не открыто.