Встала передо мной задача использовать в обработке HTML документ к которому подключена здоровенная библиотека на JavaScript. Задумался я об удобном размещении в обработке HTML разметки и скриптов а так же об удобном встраивании скриптов в документ перед его выполнением. В результате было найдено несколько достойных решений:
Размещение HTML документа и скриптов в макетах обработке
Было принято решение HTML разметку и скрипты хранить в макетах обработки. Для каждого документа HTML и для каждого скрипта или библиотеки скриптов свой макет. Ниже пример такой организации:
На скриншоте находится три макета.
HTML_DOC - макет в котором находится документ HTML. Тип макета HTML документ
script_01, script_02 - макеты в которых находятся скрипты на JavaScript. Тип макета Текстовый документ.
Устройство документа HTML для удобного подключения скриптов
Вначале покажу содержимое HTML документа моего примера
<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=9">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<link href="__STYLE__" rel="stylesheet" type="text/css">
<meta name="GENERATOR" content="MSHTML 11.00.9600.19003">
<base href="/redirect.php?url=djhjb25maWc6Ly9jMWQzZTdkMi03MTUwLTQ3ZmMtOGRjYy0xNThlMjBlNTE5OTUvbWRvYmplY3QvaWQ2MTI5YzI1Ni1iMWVjLTRlMTYtOTUxMi0xNDljNjhkMzdjYWUvOGViNGZhZDEtMWZhNi00MDNlLTk3MGYtMmMxMmRiYjQzZTIz">
<script src="script_01"></script>
<script src="script_02"></script>
</head>
<body>
<div>
<p>
<h1>TEST_JS</h1>
</p>
</div>
<div id="block1">
<p>Текст скрываемого блока 1</p>
</div>
<div id="block2">
<p>Текст скрываемого блока 2</p>
</div>
</body>
</html>
В секции <head> объявлено подключение двух скриптов с помощью конструкции <script src="script_ХХ"></script> Документ считает, что скрипты находятся в ресурсах "script_01" и "script_02". Количество подключаемых скриптов не ограничено, два взято для примера.
Я воспользовался следующими возможностями документа:
- подключать можно много скриптов, обрамляя каждый конструкцией <script></script>
- скрипт может находится на внешнем ресурсе и документ его самостоятельно импортирует при построении дерева
- платформа 1С предоставляет инструменты для манипулирования атрибутами документа, поэтому "фейковые" пути к скриптам, типа script_01 или script_02 я смогу подменить на истинные пути реальных файлов.
Перемещение скриптов в папку на локальном диске
Напомню, что скрипты у нас располагаются в текстовом макете обработки. Браузер 1С при исполнении HTML документа может импортировать скрипт с внешнего ресурса, в том числе из папки на локальном диске. Код копирования из макета на диск прост: Здесь свойство ОО это объект обработка.
сПутьКФайлу = ПолучитьИмяВременногоФайла("js");
макетJS = ОО.ПолучитьМакет(сИмяМакетаСкрипта);
макетJS.Записать(сПутьКФайлу);
Путь к файлу как URL
Мы скопировали файл скрипта на диск и он располагается, например по пути c:\temp\script_01.js Браузер 1С не сможет импортировать скрипт если путь к ресурсу указать как путь Windows. То есть, вот так работать не будет:
<script src="c:\temp\script_01.js"></script>
Проблема в пути, его нужно указывать как URL, добавляя префикс file:///. Вот так будет все в порядке:
<script src="file:///c:/temp/script_01.js"></script>
сделаем функцию преобразования локального пути в URL
&НаКлиентеНаСервереБезКонтекста
Функция ПутьКФайлуКакURL(сПуть)
Возврат "file:///"+СокрЛП(СтрЗаменить(сПуть,"\","/"));
КонецФункции
Подмена в HTML документе "фейковых путей на локальные"
Последний шаг нашего плана изменить документ HTML и подставить настоящие пути к ресурсам вместо "фейковых". В начале получим коллекцию элементов <script>. Помните, в документе их может быть несколько?
элементыScript = документHTML.ПолучитьЭлементыПоИмени("script");
Если элементыScript.Количество() = 0 Тогда
бВыполненоБезОшибок = Ложь;
Возврат бВыполненоБезОшибок;
КонецЕсли;
Теперь для каждого элемента <script> нашего документа изменим значение атрибута "src" указав правильный путь к ресурсу. Я применил одну военную хитрость, назвал "фейковый" ресурс в исходном документе и макет скрипта одинаково и таким образом по названию макета я понимаю в какой элемент коллекции подставить правильный ресурс.
Для каждого элементScript Из элементыScript Цикл
Если элементScript.Источник = сИмяМакетаСкрипта Тогда
элементScript.УстановитьАтрибут("src", ПутьКФайлуКакURL(сПутьКФайлу));
бВыполненоБезОшибок = Истина;
Возврат бВыполненоБезОшибок;
КонецЕсли;
КонецЦикла;
Выгрузка HTML документа в текст разметки
И самый последний шаг. Выгрузим наш документ в текст и передадим этот текст в элемент формы с типом "Поле HTML документа". Тут просто
&НаКлиентеНаСервереБезКонтекста
Функция ТекстHTMLДокумента(Знач документHTML, сТекстДокументаHTML)
Перем бВыполненоБезОшибок, ЗаписьDOM, ЗаписьHTML;
ЗаписьDOM = Новый ЗаписьDOM();
ЗаписьHTML = Новый ЗаписьHTML();
ЗаписьHTML.УстановитьСтроку();
Попытка
ЗаписьDOM.Записать(документHTML, ЗаписьHTML);
сТекстДокументаHTML = ЗаписьHTML.Закрыть();
бВыполненоБезОшибок = Истина;
Исключение
сТекстДокументаHTML = "";
бВыполненоБезОшибок = Ложь;
КонецПопытки;
Возврат бВыполненоБезОшибок;
КонецФункции
Итог
Подведем итог. Изначально HTML документ и скрипты существовали как макеты обработки. Скрипты мы сохранили как файлы на локальном диске. В HTML документе изменили элементы <script>, указав в них реальные пути до скриптов. Документ выгрузили в текст и передали его браузеру 1С в элементе формы "Поле HTML документа". Ура, все работает.
Дополнение от 09.10.2019
Известно, что начиная с версии платформы 8.3.14 в качестве веб движка используется WebKit. Теперь для DOM не доступно свойство parentWindow, через которое мы раньше вызывали скрипт. Для новых версий платформы 1С Предприятие нужно использовать свойство defaultView. В новой версии обработки, текст метода, который вызывает скрипт переписан так:
Если Лев(Элементы.HTML_Fild.ИнформацияПрограммыПросмотра, 11) = "Mozilla/5.0" Тогда
Элементы.HTML_Fild.Документ.defaultView.display_div(сИДБлока);
Иначе
Элементы.HTML_Fild.Документ.parentWindow.display_div(сИДБлока);
КонецЕсли;
То есть, я пытаюсь определить, какой движок используется платформой и после этого выбираю свойство DOM parentWindow или defaultView.
Обработка протестирована на платформе версии 8.3.15
К статье приложена новая версия обработки от 09.10.2019
Так же этот проект можно найти на GitHub