Привет, Хабр! Меня зовут Стас Ганиев, программист 1С, в статье рассказал о возможностях поля HTML-документа для решения задач в 1С, а также привел примеры реализации. Далеко не все 1С-разработчики знают, как использовать этот элемент диалога.
Что такое поле HTML-документа?
Это возможность использовать движок браузера у себя на форме, прямо в 1С. По факту, это и есть интерфейс браузера на вашей форме. Он даже использует то же самое программное ядро Webkit, что и браузер Google Chrome. С объектом поля HTML-документа можно выполнять все те же операции (иногда с ограничениями), что и в полноценном браузере, включая использование веб-технологий и инструментов управления веб-приложениями.
Зачем это нужно
Поле HTML-документа удобно использовать в различных задачах, чтобы:
предоставить доступ к веб-интерфейсу сторонней конфигурации;
использовать дополнительные элементы диалога формы или альтернативные элементы интерфейса;
отображать макеты печатных форм. Например, в решении «1С:Документооборот» при подготовке документа в этой же форме можно увидеть миниатюру готового документа, то есть использовать функцию предварительного просмотра;
отображать страницу сайта. Редко используется на практике, но тем не менее может пригодиться. Достаточно присвоить элементу поля URL-адрес сайта;
запустить код на языке JavaScript. Благодаря этому можно реализовать в программе то, что невозможно сделать на языке 1С;
реализовать крутые редакторы текста. Например, редактор кода в IS Toolkit.
Давайте разберем три первых пункта более подробно.
Открываем окно в другую конфигурацию
Для начала нужно добавить элемент «Поле HTML-документа» на форму. Во всех случаях я использовал демо-версию конфигурации «Управляемое приложение» на платформе 8.3.23. Предположим, необходимо предоставить администратору доступ к настройкам сразу для двух конфигураций из одной формы, чтобы не нужно было запускать вторую конфигурацию.
Обратите внимание: пользовательская лицензия в этом случае все равно используется, поскольку необходим отдельный веб-клиент.
На форме обработки АдминистративныйСервис создайте новый реквизит формы ВебСеанс. Тип реквизита – Строка (длина не ограничена). Установите вид элемента «Поле HTML-документа».

В обработчике ПриСозданииНаСервере() напишите следующий код:
&НаСервере Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка) НастройкиПодключения = ПолучитьНастройкиПодключения(); // пользователь и пароль в подключаемой базе Пользователь = НастройкиПодключения.Пользователь; Пароль = НастройкиПодключения.Пароль; // строка подключения зависит от наличия авторизации ТребуетсяАвторизация = ЗначениеЗаполнено(Пользователь) Или ЗначениеЗаполнено(Пароль); // URL-ссылка публикации веб-клиента, например: http://127.0.0.1:8080/demo/ АдресБазы = НастройкиПодключения.АдресБазы; ПараметрЗапуска = НастройкиПодключения.ПараметрЗапуска; Если ТребуетсяАвторизация Тогда Шаблон = "%1/?n=%2&p=%3&c=%4"; АдресПодключения = СтрШаблон(Шаблон, АдресБазы, Пользователь, Пароль, ПараметрЗапуска); Иначе Шаблон = "%1/?&c=%2"; АдресПодключения = СтрШаблон(Шаблон, АдресБазы, ПараметрЗапуска); КонецЕсли; ВебСеанс = АдресПодключения; КонецПроцедуры
Поле HTML-документа работает следующим образом: оно отражает то, что приходит в «поток вывода». То есть это та информация, которая присваивается реквизиту ВебСеанс. Например, в реквизите можно указать URL-адрес сайта, тогда будет загружена страница сайта. Или передать полную строку HTTP-запроса и получить визуальное представление результата, правда, для этого лучше использовать другие инструменты.
Самое главное: вы можете передать элементу полную HTML-верстку страницы или отдельного объекта интерфейса, стилизовать его с помощью CSS и добавить интерактив с использованием языка JavaScript. Подробнее расскажу в следующем примере.
Мы остановились на параметре ПараметрЗапуска. Он необходим, чтобы на стороне запускаемой базы можно было по его значению переопределить интерфейс приложения в обработчике ПередНачаломРаботыСистемы() модуля приложения. Например, запустить конфигурацию в режиме рабочего стола, чтобы лишние меню не мешали навигации.
Создаем нужный элемент, если его нет
Другой пример: использовать произвольную верстку HTML-элемента. Здесь необходимо создать поле на форме заказа с историей статусов (см. скриншот).

Добавьте поле HTML-документа ИсторияСостояний на форму заказа. Код верстки может быть достаточно большим, поэтому для удобства сформируйте отдельные текстовые макеты. Добавьте к документу Заказ новый макет ИсторияСтатусов и заполните его:
<!DOCTYPE html> <html lang="ru"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> p { margin: 0; padding: 0; } .wrap { border: 2px solid #dddd11; border-radius: 5px; padding: 5px; } .status { font-size: 12px; margin-bottom: 7px; padding: 3px; border-radius: 5px; display: flex; justify-content: space-between; } .status-opened { background-color: #ddffdd; } .status-work { background-color: #dddddd; } .status-closed { background-color: #ffdddd; } </style> </head> <body> <div class="wrap"> <!-- начало блока элемента --> <div class="status status-opened"> <p><a href="#" class="link-opened">Открыт</a></p> <p>13.02.2023</p> </div> <!-- конец блока элемента --> <div class="status status-work"> <p><a href="#" class="link-work">В работе</a></p> <p>17.02.2023</p> </div> <div class="status status-closed"> <p><a href="#" class="link-closed">Закрыт</a></p> <p>27.04.2023</p> </div> </div> </body> </html>
В обработчике формы ПриСозданииНаСервере() добавьте следующий код:
ДокументОбъект = РеквизитФормыВЗначение("Объект"); МакетВерстки = ДокументОбъект.ПолучитьМакет("ИсторияСтатусов"); ИсторияСостояний = МакетВерстки.ПолучитьТекст();
Вы сразу получите результат, изображенный на рисунке выше. Чтобы добавить динамический элемент, который будет изменяться в зависимости от происходящих процессов, необходимо выполнить следующие действия. В HTML-коде (см. листинг выше) нужно собрать блок body. Он состоит из отдельных элементов-статусов, первый из которых выделен комментариями. Существует несколько способов, как это сделать. Один из вариантов я описал ниже.
Шаг 1. Создайте отдельную функцию, чтобы получить шаблон текста для элемента.
&НаСервере Функция HTMLТекстЭлементСтатус() Результат = " |<div class=""status %1""> | <p> | <a href=""#"" class=""link-%1"">%2</a> | </p> | <p>%4</p> |</div>"; Возврат Результат; КонецФункции
Шаг 2. В макете замените код тела элемента на идентификатор. Вынесите формирование виджета в отдельную процедуру.
&НаСервере Процедура ОбновитьВиджетСтатусов() ДокументОбъект = РеквизитФормыВЗначение("Объект"); ТекстВерстки = ДокументОбъект.ПолучитьМакет("ИсторияСтатусов").ПолучитьТекст(); ТекстВерстки = СтрЗаменить(ТекстВерстки, "%БлокСтатусов%", HTMLТекстБлокСтатусов()); ИсторияСостояний = ТекстВерстки; КонецПроцедуры
Шаг 3. Добавьте функцию формирования блока виджета.
&НаСервере Функция HTMLТекстБлокСтатусов() ИсторияСтатусов = ПолучитьИсториюСтатусов(); ШаблонЭлементаСтатус = HTMLТекстЭлементСтатус(); Фрагменты = Новый Массив; МенеджерСтатусов = Перечисления.СостоянияЗаказов; ИменаКлассов = Новый Соответствие; ИменаКлассов.Вставить(МенеджерСтатусов.Открыт, "status-opened"); ИменаКлассов.Вставить(МенеджерСтатусов.ВРаботе, "status-work"); ИменаКлассов.Вставить(МенеджерСтатусов.Выполнен, "status-work"); ИменаКлассов.Вставить(МенеджерСтатусов.Закрыт, "status-closed"); Для Каждого СтрокаСтатус Из ИсторияСтатусов Цикл ТекстЭлемента = СтрШаблон(ШаблонЭлементаСтатус, ИменаКлассов[СтрокаСтатус.Статус], Строка(СтрокаСтатус.Статус), Формат(СтрокаСтатус.ДатаСтатуса, "ДЛФ=D")); Фрагменты.Добавить(ТекстЭлемента); КонецЦикла; Возврат СтрСоединить(Фрагменты, Символы.ПС); КонецФункции
Не забудьте добавить функцию ПолучитьИсториюСтатусов(). Она зависит от функционала конкретной конфигурации. Результат отображения варианта истории выполнен в таком виджете (см. скриншот).

Альтернативный интерфейс
Используйте поля HTML-документа, чтобы настроить интерфейс главного окна приложения, придав ему индивидуальный дизайн. Чтобы получить такой вариант интерфейса конфигурации (см. скриншот), откройте главное окно приложения в режиме полноэкранного рабочего стола и используйте два поля HTML-документа.

Дополнительные возможности
Где провести отладку HTML-кода?
На примерах вы видите, что код наполнения может быть достаточно объемным. Чтобы не ошибиться при его написании, а также предварительно посмотреть результаты своего труда, используйте сторонние редакторы.
Мне нравится онлайн-консоль CodePen, но есть и другие, не менее удобные сервисы:
Любой из этих сервисов поможет быстро набрать и проверить код. Или используйте полноценный редактор, например VSCode. Еще больше информации по HTML-тегам и CSS-свойствам вы найдете здесь.
Отлавливаем события на элементе
Разберем вопрос подробнее, чтобы понять, что происходит при интерактивных действиях на элементе «Поле HTML-документа». Ссылки в названиях статусов добавлены не просто так (см. пример с виджетом). Следующий шаг — понять, на какую ссылку нажал пользователь и что следует делать дальше.
У поля HTML-документа есть событие ПриНажатии, создаем для него обработчик.

ДанныеСобытия — второй параметр, который передается в обработчик. Это упакованная структура с подробным описанием текущего состояния элемента в целом или конкретного элемента верстки (ссылка с тегом <a> в нашем случае).
Собрал несколько примеров свойств данных, которых будет достаточно для решения различных задач при 1С-разработке:
ДанныеСобытия.Element.className— строка с перечислением CSS-классов элемента. Позиционирование на элементах по именам классов — это лишь один из способов. Позиционирование возможно по идентификаторам, тегам, родительским или дочерним элементам, в зависимости от стратегии работы со структурой документа и решаемой задачи. Используйте пробелы, если для одного элемента указываются несколько классов;ДанныеСобытия.Element.innerHTML— полное содержание активного элемента. В нашем примере используется наименование статуса. В общем случае — HTML-код, вложенный в текущий тег;ДанныеСобытия.Element.tagName— имя тега текущего элемента;ДанныеСобытия.Element.outerHTML— HTML-код текущего элемента. Можно сказать, что это содержимое свойства innerHTML, включая описание самого текущего элемента;ДанныеСобытия.Event.type— тип события, которое выполняется над элементом;ДанныеСобытия.Event.x и ДанныеСобытия.Event.y— точное положение курсора мыши в пикселях в момент клика на элементе.
Чтобы определить, какой статус выбрал пользователь, используем имя CSS-класса текущего элемента HTML-верстки:
&НаКлиенте Процедура ИсторияСостоянийПриНажатии(Элемент, ДанныеСобытия, СтандартнаяОбработка) Классы = СтрРазделить(ДанныеСобытия.Element.className, " ", Ложь); Если Классы.Найти("link-opened") <> Неопределено Тогда // обработка статуса "открыт" ИначеЕсли Классы.Найти("link-work") <> Неопределено Тогда // обработка статуса "в работе" // и т.д. КонецЕсли; КонецПроцедуры
Размещение стилей CSS
Стили CSS — это отдельный специализированный язык описания стилей для отдельных блоков, тегов, классов. То есть любого элемента HTML-верстки документа. На этом языке можно описать взаиморасположение, размер, цвет, шрифт, тени, трансформацию и анимацию для элементов.
Код CSS сам по себе может быть очень объемным. В классической веб-разработке его принято выносить в отдельные файлы или библиотеки. Если он используется в формах 1С, его можно вынести в отдельные модули или макеты. Так код станет более читабельным и понятным.
Заключение
В статье я привел базовые возможности элемента «Поле HTML-документа». Их вполне достаточно для решения различных задач. Если вам интересна эта тема, в следующих статьях я расскажу подробнее как работать с кодом JavaScript и манипулировать версткой с его помощью, а также о возможностях CSS для создания анимаций и интерактива.
