Привет, Хабр! Меня зовут Стас Ганиев, программист 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 для создания анимаций и интерактива.