oscript-ui
oscript-ui

Окно

Окно — модальный диалог поверх экрана: короткая задача, которую человек решает, не уходя со страницы. Новая запись, правка одного поля, выбор из небольшого списка. Это нативный : открывает его кнопка командой браузера, Esc и крестик закрывают, фокус держится внутри и возвращается на кнопку, с которой окно открыли.

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

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

Не открывайте окном длинную форму с разделами и не открывайте окно из окна: длинной задаче место на своей странице, а второе окно поверх первого прячет, откуда человек пришёл. Сообщение об итоге — не окно, а тост.

Окно и кнопка#

Окно — узел Кит.Окно(Заголовок, тело…): дети узла — тело окна, кнопки внизу — второй холст Действия(…). Кнопка открывает его словом Открывает(Окно): кит печатает команду браузера command="show-modal" и commandfor с идентификатором окна. Скрипт для этого не нужен — движок знает команду сам, а движку постарше её доучивает скрипт кита.

Кнопка и окно — нажмите «Новый проект»

Окно = Кит.Окно("Новый проект", Кит.Поле("name", "Название").Обязательное()) .Лид("Проект появится в списке сразу.") .Действия(Кит.Кнопка("Отмена").Вторичная().Команда("закрыть", "novyi-proekt-obrazec"), Кит.Кнопка("Создать").Основная()) .Форма("/образец-окон").Якорь("novyi-proekt-obrazec"); HTML = Кит.Холст(Кит.Кнопка("Новый проект").Иконка("плюс").Открывает(Окно), Окно) .Токен("т0кен-сессии").Рендер();

Форма этого окна уходит на образец с сервером: созданный проект появится в его списке.

Открытое окно стоит по центру экрана, где бы его ни напечатали: в теле карточки, секции или записи реестра ритм контейнера его не сдвигает.

Окно печатается слотами в одном порядке: шапка — заголовок и крестик, под ней лид (что это окно делает), тело, ряд действий. Порядок задаёт кит, а не порядок слов в коде.

Словом Форма(Адрес) окно целиком становится формой: шапка, тело и действия лежат внутри <form>, поэтому кнопка «Создать» отправляет её сама, а крестик и «Отмена» — кнопки-команды, они форму не шлют. Адрес и токен окно берёт у контекста, как любая форма холста: относительный адрес — от дома настроек вокруг, токен — у ближайшего предка. Как форма в окне уходит без перезагрузки и закрывает окно — раздел «В окне» страницы Формы деревом.

Вид#

Вид Для чего
обычное (или без вида) короткая форма, выбор, сведения
опасное заголовок цветом ошибки: необратимое действие. Готовое окно такого рода — подтверждение
широкое шаги мастера, таблица или две колонки, которым тесно в обычной ширине; слово Широкое() — то же

Широкое окно со сведениями

Окно = Кит.Окно("Ключи проекта", Кит.Таблица(Кит.Колонка("Ключ"), Кит.Колонка("Создан"), Кит.Запись(Кит.Ячейка("ноутбук"), Кит.Ячейка("12 марта")), Кит.Запись(Кит.Ячейка("сервер сборки"), Кит.Ячейка("2 апреля")))) .Вид("широкое").Якорь("klyuchi"); HTML = Кит.Холст(Кит.Кнопка("Все ключи").Вторичная().Открывает(Окно), Окно).Рендер();

Ширина окна — базового диалога Material: 560 пикселей, у широкого — 640. Шире окна не бывают: то, чему тесно в 640, просится на свою страницу.

Идентификатор#

На окно ссылаются кнопка (commandfor), заголовок (aria-labelledby) и форма с подтверждением. Слово Якорь(Ид) задаёт его явно. Без якоря кит выдаёт идентификатор сам — из заголовка и места окна в дереве: ответ на тот же запрос повторяется байт в байт, а два окна с одним заголовком в разных местах страницы получают разные идентификаторы. Кнопке узел окна передают словом Открывает(Окно); строкой — идентификатор окна этой же страницы.

Окно открытым с сервера#

Без скрипта и в движке, который не знает команд, кнопка окна не сработает. Поэтому у экрана должна оставаться серверная дорога: адрес, по которому страница приходит с уже открытым окном, обычно тот же адрес с ?окно=…. Слово Открыто() печатает окно открытым. Скрипт кита поднимает такое окно модальным — с фоном и удержанием фокуса; без скрипта оно работает как обычная форма. Тем же словом возвращают человеку отбитую форму вместе с набранным.

Без скрипта окно не модальное — в верхний слой браузера его поднимает только скрипт, — но выглядит и ведёт себя как модальное: стоит по центру экрана поверх шапки и секций ниже, страницу под ним гасит подложка, а щелчок мимо окна страницу не нажимает. Сама страница под окном прокручивается, длинное окно прокручивается само. Закрывает такое окно крестик там, где движок знает команду close, а в любом браузере — ссылка на адрес страницы без ?окно: дайте её окну в действиях, Кит.Кнопка("Закрыть").Вторичная().Адрес("/проекты"). Так устроено окно правки образца: секция с записями реестра ниже окна его не перекрывает.

Окно, напечатанное открытым

<dialog class="modal" id="pereimenovat" aria-labelledby="pereimenovat-title" open><form method="post" action="/проекты/альфа" class="modal__box"><input type="hidden" name="_csrf" value="т0кен-сессии"><div class="modal__head"><h2 class="modal__title" id="pereimenovat-title">Переименовать проект</h2><button type="button" class="button button--link button--icon" title="Закрыть окно" aria-label="Закрыть окно" command="close" commandfor="pereimenovat"><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 field--error"><span class="field__label">Название</span><input class="field__control" type="text" name="name" aria-invalid="true" value="альфа"><span class="field__error" role="alert">Такой проект уже есть</span></label></div><div class="modal__actions"><button type="submit" class="button button--primary"><span>Сохранить</span></button></div></form></dialog>
Окно = Кит.Окно("Переименовать проект", Кит.Поле("name", "Название").Значение("альфа").Ошибка("Такой проект уже есть")) .Форма("/проекты/альфа").Открыто().Якорь("pereimenovat") .Действия(Кит.Кнопка("Сохранить").Основная()); HTML = Кит.Холст(Окно).Токен("т0кен-сессии").Рендер();

Кнопка, которая работает без скрипта#

Команда show-modal есть не в каждом движке, и без скрипта кита кнопка окна в старом браузере молчит. Дайте окну адрес его серверной дороги словом Адрес("?окно=…") — страницу, где сервер печатает это окно открытым, — и кнопка Открывает(Окно) печатается ссылкой на неё с признаком data-opens. Без скрипта ссылка ведёт на страницу с открытым окном в любом браузере. Со скриптом кит открывает окно этой страницы на месте: без запроса и без перехода, фокус возвращается на кнопку. Свой Адрес у кнопки главнее адреса окна. Адрес — своего приложения: чужой останавливает сборку. Без адреса кнопка — прежняя команда браузера.

Ссылка на окно — со скриптом окно открывается на месте

Новый проект
Окно = Кит.Окно("Новый проект", Кит.Поле("name", "Название").Обязательное()) .Лид("Проект появится в списке сразу.") .Действия(Кит.Кнопка("Создать").Основная()) .Форма("/образец-окон").Адрес("/образец-окон?окно=новый").Якорь("novyi-proekt-ssylkoi"); HTML = Кит.Холст(Кит.Кнопка("Новый проект").Иконка("плюс").Открывает(Окно), Окно) .Токен("т0кен-сессии").Рендер();

Так же открывается и подтверждение: у него та же серверная дорога.

Окно по адресу#

У таблицы на сотню строк сотню окон правки заранее не печатают. Кит.ОкноПоАдресу(Адрес, Подпись) — кнопка окна, которое приходит с сервера, когда его открывают. Без скрипта это ссылка на страницу с ?окно=…, где сервер печатает окно открытым. Со скриптом кит берёт ту же страницу запросом в фоне, вынимает из неё окно, кладёт в оболочку и открывает. Форма такого окна уходит и закрывается так же, как у окна на странице.

Кнопка окна по адресу

HTML = Кит.Ряд("действия", Кит.ОкноПоАдресу("/образец-окон?окно=правка&project=Альфа", "Переименовать").Малая().Иконка("карандаш"), Кит.ОкноПоАдресу("/образец-окон?окно=правка&project=Бета", "Переименовать бету") .ТолькоИконка().Иконка("карандаш")).Рендер();

Оболочка — одна пустая <dialog> на страницу и рядом скрытый тост «не удалось открыть окно». Её печатает каркас страницы, и только там, где на странице есть хоть одна кнопка окна по адресу: страница без них остаётся той же байт в байт. Кто собирает документ без каркаса, ставит её узлом Кит.ОболочкаОкна() в конец тела.

Адрес окна — адрес своего приложения: окно берётся запросом с куками сессии, поэтому чужой хост и чужая схема останавливают сборку.

Образец с настоящим сервером — список проектов с окнами: новый проект, правка по адресу и удаление с подтверждением.

На телефоне#

До 640 px окно остаётся базовым диалогом: по центру экрана, шириной в экран без полей по 16 пикселей, действия — под телом. Подтверждение из пары строк и двух кнопок так и выглядит окном, а не пустым листом с кнопками внизу.

Короткое окно на телефоне — базовое

Окно = Кит.Окно("Переименовать проект", Кит.Поле("name", "Название").Значение("альфа")) .Действия(Кит.Кнопка("Отмена").Вторичная().Команда("закрыть", "pereimenovat-telefon"), Кит.Кнопка("Сохранить").Основная()) .Якорь("pereimenovat-telefon"); HTML = Кит.Холст(Кит.Кнопка("Переименовать").Вторичная().Открывает(Окно), Окно).Рендер();

Сложная задача — мастер с шагами, длинный выбор — на телефоне встаёт листом во весь экран, как полноэкранный диалог Material: прокручивается само окно, а ряд действий прилипает к низу и всегда под пальцем. Такое окно называют словом ВоВесьЭкран(); окно с шагами встаёт листом и без него. На широком экране слово ничего не меняет.

Мастер на телефоне — во весь экран

Окно = Кит.Окно("Подключить источник", Кит.Поле("url", "Адрес источника"), Кит.Поле("branch", "Ветка").Значение("main"), Кит.Поле("token", "Токен доступа").Секрет()) .Действия(Кит.Кнопка("Подключить").Основная()) .ВоВесьЭкран().Широкое().Якорь("istochnik-telefon"); HTML = Кит.Холст(Кит.Кнопка("Подключить источник").Вторичная().Открывает(Окно), Окно).Рендер();

Окно, напечатанное открытым без скрипта, листом не становится — оно базовое по центру экрана и прокручивается само.

Гайдлайны#

ДелайтеЗаголовок называет задачу, кнопка — действие
Код
Окно = Кит.Окно("Новый проект", Кит.Поле("name", "Название"))
	.Форма("/проекты").Якорь("novyi")
	.Действия(Кит.Кнопка("Создать").Основная());
HTML = Кит.Холст(Окно).Токен("т0кен-сессии").Рендер();
Не делайтеБезликий заголовок и «ОК»: из окна непонятно, что произойдёт
Код
Окно = Кит.Окно("Внимание", Кит.Поле("name", "Название"))
	.Форма("/проекты").Якорь("vnimanie")
	.Действия(Кит.Кнопка("ОК").Основная());
HTML = Кит.Холст(Окно).Токен("т0кен-сессии").Рендер();
ДелайтеДлинная настройка — своей страницей с разделами
Код
HTML = Кит.Кнопка("Настройки проекта").Вторичная().Иконка("шестерёнка").Адрес("/проекты/альфа/настройки").Рендер();
Не делайтеОкно на десяток полей: прокрутка внутри окна прячет кнопку и контекст
Код
Окно = Кит.Окно("Настройки проекта",
		Кит.Поле("name", "Название"), Кит.Поле("desc", "Описание").Многострочное(),
		Кит.Поле("site", "Сайт"), Кит.Поле("mail", "Почта для писем"),
		Кит.Поле("lang", "Язык"), Кит.Поле("zone", "Часовой пояс"),
		Кит.Поле("owner", "Владелец"), Кит.Поле("team", "Команда"))
	.Форма("/проекты/альфа").Якорь("nastroiki")
	.Действия(Кит.Кнопка("Сохранить").Основная());
HTML = Кит.Холст(Окно).Токен("т0кен-сессии").Рендер();

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

  • Окно — нативный <dialog>, открытый showModal: фон недоступен, Tab ходит только внутри окна, Esc закрывает. Это делает браузер, а не скрипт.
  • Окно названо заголовком (aria-labelledby), лид — его описание (aria-describedby): скринридер слышит «Новый проект, диалог» и следом, о чём оно. Окно без заголовка не собирается.
  • Крестик — кнопка-значок с именем из словаря интерфейса (ключ window.close).
  • Открытое окно ставит фокус на первое поле своего тела — поле с отказом сервера раньше, — а окно без полей на заголовок, а не на крестик в шапке: человек сразу печатает, и кольцо не загорается на крестике. Это делает скрипт кита (дев-сборка 8); без него фокус ставит браузер — на первое, что в окне можно сфокусировать.
  • Закрытое окно возвращает фокус на кнопку, которой его открыли. Когда форма окна ушла удачно и окно закрылось, фокус встаёт на то, что сервер пометил словом Фокус(), — обычно новую запись.
  • Движение окна — проявление с небольшим ростом; при «меньше движения» оно мгновенное.

Адрес закрытия#

Окно, открытое по адресу (?окно=…, отбитая форма), без скрипта закрывает крестик — команда движка close. Движок, который команд ещё не знает, без скрипта окно не закроет. Слово АдресЗакрытия(Адрес) (дев-сборка 8) — адрес страницы без окна: крестик печатается ссылкой туда, а первой в действиях — «Отмена» у окна-формы или «Закрыть» у окна без формы (ключи словаря window.cancel, window.dismiss). Без скрипта они ведут на страницу без окна, со скриптом закрывают окно на месте — без перехода и перезагрузки (признак data-closes). У подтверждения ссылкой становится его «Отмена», у окна с шагами «Отмена» встаёт первой в ряд кнопок шагов — второго подвала под шагами нет. Адрес — как у слова Форма: относительный дописывается к адресу контекста.

Окно правки с адресом закрытия

Окно = Кит.Окно("Переименовать проект", Кит.Поле("name", "Новое название").Значение("альфа")) .Форма("/проекты/альфа").АдресЗакрытия("/проекты").Якорь("pereimenovat") .Действия(Кит.Кнопка("Сохранить").Основная()); HTML = Кит.Холст(Кит.Кнопка("Переименовать").Открывает(Окно), Окно).Токен("т0кен-сессии").Рендер();

Тот же поток с сервером — в образце со списком проектов: окно правки по адресу и подтверждение удаления закрываются «Отменой» и без скрипта.

Окно-ответ с одноразовым секретом — выпущенный токен, ссылка установки пароля, секрет подписи — закрывать на месте нельзя: секрет останется в DOM закрытого окна, а вкладка — на ответе POST, где F5 предложит повторить выпуск. Слово Переходом() после АдресЗакрытия (дев-сборка 10) печатает крестик и «Закрыть» обычными ссылками — без признака закрытия на месте, — а окно несёт data-close-to: Esc со скриптом тоже уводит на адрес закрытия. У подтверждения так же ведёт себя его «Отмена». Без адреса закрытия слово останавливает сборку.

Секрет показан один раз — окно закрывается только переходом

Окно = Кит.Окно("Токен выпущен", Кит.Свойства(Кит.Свойство("Токен", Кит.Код("ru_8f2c…")).Копируемое())) .Лид("Скопируйте токен сейчас: больше он показан не будет.") .АдресЗакрытия("/окно").Переходом().Якорь("vypushchen"); HTML = Кит.Холст(Кит.Кнопка("Выпустить токен").Открывает(Окно), Окно).Рендер();

Модель#

Кит.Окно()src/Классы/холст/Кит.os

Модальное окно со слотами: заголовок и крестик сверху, лид под ними, тело — дети узла,
действия — второй холст Действия(д…) внизу. Открывает его кнопка словом Открывает(узел)
(команда движка show-modal, скрипта не нужно); Esc и крестик закрывают его движком.
Ширина — базового диалога Material: 560 px, у широкого 640. На телефоне (до 640 px) окно
остаётся базовым — по центру, в экран без полей по 16 px; листом во весь экран (тело
прокручивается, действия прилипают к низу) встаёт окно со словом ВоВесьЭкран и окно с шагами.
Слова: Лид, Действия(д…), Вид («обычное» | «опасное» | «широкое»), Широкое, ВоВесьЭкран, Открыто (сервер
печатает окно открытым по ?окно=…), Якорь (идентификатор; без него кит выдаёт свой,
постоянный для того же дерева), Форма(Адрес) (окно целиком — форма; токен у предков),
БезПерезагрузки (форма окна уходит тихо: успех закрывает окно, отказ остаётся в нём),
Токен, СФайлами.

Прежний вызов Кит.Окно(Объявление, Действующие, Действие, Токен, Свойства) печатает
объявленную форму окном, как раньше: первым аргументом пришло объявление, а не заголовок.

Параметры:
 Заголовок - Строка - заголовок окна: им окно называет себя скринридеру.
 Р1…Р8     - ЭлементЭкрана, Строка - (необязательные) тело окна; строка — текст.

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

ЭлементЭкрана.АдресЗакрытия()src/Классы/холст/ЭлементЭкрана.os

Адрес закрытия окна — страница без окна (раздел без ?окно=…). Кит печатает крестик ссылкой
на этот адрес, а первой в действиях — «Отмена» (у окна-формы и подтверждения) или
«Закрыть» ссылкой; у окна шагами «Отмена» встаёт в ряд кнопок шагов. Без скрипта они
ведут на страницу без окна — окно закрывается и там, где движок не знает команды close;
со скриптом закрывают окно на месте, без перехода и перезагрузки (признак data-closes).
Адрес — как у слова Форма: относительный дописывается к адресу контекста. У слота
картинки (дев-сборка 10) — адрес закрытия его окна сброса «Вернуть стандартную?».

Параметры:
 Адрес_ - Строка - адрес страницы без окна.

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

ЭлементЭкрана.Переходом()src/Классы/холст/ЭлементЭкрана.os

Закрытие окна только переходом (дев-сборка 10, ревью ui-окна З3): крестик, «Закрыть» или
«Отмена» — обычные ссылки на адрес закрытия без признака закрытия на месте, и Esc со
скриптом тоже уводит туда. Для окна-ответа с одноразовым секретом (выпущенный токен,
ссылка установки пароля): закрытое на месте, оно оставило бы секрет в DOM, а вкладку —
на ответе POST, где F5 повторяет выпуск. Без слова АдресЗакрытия печать останавливается.

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

Кит.ОкноПоАдресу()src/Классы/холст/Кит.os

Кнопка окна, которое не печатается заранее (правка строки таблицы на сотню строк): ссылка
на страницу с ?окно=…, где сервер печатает окно открытым. Скрипт берёт ту страницу
запросом в фоне, кладёт её окно в оболочку и открывает; отправка формы окна закрывает
его по успеху тихой отправки. Оболочку — одну на страницу — печатает каркас страницы.
Слова: Основная, Вторичная, Опасная, Ссылкой, Малая, Большая, Иконка, ТолькоИконка,
Подсказка, Подпись.

Параметры:
 Адрес   - Строка - адрес своего приложения: страница, где сервер печатает окно открытым.
 Подпись - Строка - подпись кнопки.

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

Кит.ОболочкаОкна()src/Классы/холст/Кит.os

Оболочка окна по адресу — одна на страницу пустая <dialog> и тост ошибки загрузки.
Каркас страницы ставит её в тело сам; руками она нужна тому, кто собирает документ без
каркаса. Печатается, только если в том же дереве есть кнопка окна по адресу.

Параметры:
 Всегда - Булево - (необязательный, по умолчанию Ложь) печатать без кнопки в дереве:
          содержимое пришло готовой строкой, и дерево его не видит.

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

ЭлементЭкрана.Открывает()src/Классы/холст/ЭлементЭкрана.os

Кнопка открывает окно (Кит.Окно, Кит.Подтверждение) — команда движка show-modal
и commandfor — либо всплывающую панель (popovertarget). Узел окна даёт свой
идентификатор; строка — идентификатор окна этой же страницы, а не нашлось такого
окна в дереве — всплывающей панели. Известен адрес окна (слово Адрес у кнопки или
у окна) — кнопка печатается ссылкой на него с признаком data-opens: без скрипта она
ведёт на страницу с окном, открытым сервером, а скрипт кита открывает окно этой
страницы без перехода.

Параметры:
 Ид_ - ЭлементЭкрана, Строка - узел окна либо идентификатор окна или панели.

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

ЭлементЭкрана.Адрес()src/Классы/холст/ЭлементЭкрана.os

Адрес компонента: кнопка и плашка становятся ссылкой, карточка — ссылкой-заголовком,
плитка — ссылкой целиком. У окна (Кит.Окно, Кит.Подтверждение) — страница своего
приложения, где сервер печатает это окно открытым (обычно ?окно=…): кнопка, которая
открывает окно словом Открывает, печатается ссылкой на неё — без скрипта переход,
со скриптом окно страницы открывается без запроса. Свой Адрес кнопки главнее адреса окна.

Параметры:
 Значение - Строка - URL.

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

ЭлементЭкрана.Открыто()src/Классы/холст/ЭлементЭкрана.os

Окно печатается открытым: так сервер отдаёт страницу с окном по адресу ?окно=… (кнопка
окна по адресу без скрипта ведёт туда) и возвращает отбитую форму вместе с набранным.
Скрипт кита поднимает такое окно модальным.

Параметры:
 Флаг - Булево - (необязательный, по умолчанию Истина)

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

ЭлементЭкрана.ВоВесьЭкран()src/Классы/холст/ЭлементЭкрана.os

Окно на телефоне — лист во весь экран, как полноэкранный диалог Material: прокручивается
само окно, ряд действий прилипает к низу. Это для сложной задачи — мастер, длинный выбор;
короткое окно (подтверждение, одно-два поля) на телефоне остаётся базовым: по центру,
шириной в экран без полей 16 px. Окно с шагами (Кит.Шаги) встаёт листом и без этого
слова. На широком экране слово ничего не меняет.

Параметры:
 Флаг - Булево - (необязательный, по умолчанию Истина)

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

ЭлементЭкрана.Широкое()src/Классы/холст/ЭлементЭкрана.os

Окно шире базового: 640 px вместо 560 — для шагов мастера и таблицы, которым тесно в
базовой ширине диалога Material. То же, что вид «широкое».

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

ЭлементЭкрана.Фокус()src/Классы/холст/ЭлементЭкрана.os

Признак data-focus: элемент, на который скрипт ставит фокус, когда тихая отправка из окна
удалась и окно закрылось, — сервер помечает им только что созданную запись. Скрипт
делает элемент фокусируемым сам, если тот не был.

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

Окно.Отрисовать()src/Классы/холст/Окно.os

Печатает окно со слотами: шапка (заголовок и крестик), лид, тело, действия. Окно
называет себя заголовком (aria-labelledby), лид — его описание (aria-describedby).
Словом Форма окно целиком становится формой: кнопки действий отправляют её сами.

Параметры:
 Модель - Структура - Ид (обязателен: на него ссылается открывашка), Заголовок
          (обязателен: им окно называет себя скринридеру), Класс (CSS-класс вида),
          Лид, Открыто (печатать открытым — так сервер возвращает окно по адресу
          с ?окно= и отбитую форму), Тело и Действия (ДОВЕРЕННЫЙ HTML), Признаки
          (ДОВЕРЕННАЯ строка data-атрибутов окна), Форма (Структура: Действие, Поле
          токена — ДОВЕРЕННЫЙ HTML, Файлы, Признаки — data-атрибуты формы; Неопределено —
          окно без своей формы). Дев-сборка 8: АдресЗакрытия — адрес страницы без окна:
          крестик — ссылка туда, а первым в действиях — «Отмена» (у окна-формы) или
          «Закрыть» ссылкой; со скриптом они закрывают окно на месте (data-closes).
          СвояОтмена (Булево) — отмену печатают действия сами (подтверждение, шаги).
          Дев-сборка 10: Переходом (Булево) — крестик и «Закрыть» обычными ссылками на
          АдресЗакрытия, без закрытия на месте; окно несёт data-close-to — Esc со скриптом
          тоже уводит туда.

Возвращаемое значение:
 Строка - HTML <dialog>; закрытое окно места на экране не занимает.

ОкноПоАдресу.Отрисовать()src/Классы/холст/ОкноПоАдресу.os

Печатает кнопку окна по адресу — ссылку-кнопку с признаком data-window-link.

Параметры:
 Модель - Структура - Адрес (обязателен: адрес своего приложения — страница, на которой
          сервер печатает окно открытым), Подпись (обязательна), Вариант (как у кнопки,
          по умолчанию «вторичная»), Размер, Иконка, ТолькоИконка, Подсказка.

Возвращаемое значение:
 Строка - HTML <a>.