Как перевести работу с полем HTML-документа на модель WebKit в 1С:Предприятии 8.3.14 и выше

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

С выходом технологической платформы 1С:Предприятие 8.3.14 разработчики столкнулись с масштабным изменением: встроенный движок отображения HTML-документов был заменен с устаревшего Internet Explorer (MSHTML) на современный кроссплатформенный WebKit. Это нововведение принесло полноценную поддержку стандартов HTML5, CSS3, SVG, значительно ускорило рендеринг страниц и обеспечило идентичное отображение форм во всех операционных системах и веб-клиентах. Однако обратной стороной медали стало то, что старый код интеграции JavaScript и 1С перестал работать.

В этой статье мы подробно разберем, почему возникает ошибка при обращении к контексту браузера, как правильно заменить устаревшие свойства, и рассмотрим ключевые архитектурные изменения при взаимодействии 1С и JavaScript в новой модели WebKit.

Выясняем причину: почему перестал работать привычный код

Рассмотрим классический пример интеграции внешнего HTML-редактора (например, популярного текстового редактора CKEditor) в форму 1С. В старых версиях платформы (до 8.3.14) для получения или записи данных в редактор использовался следующий код:


// Этот код отлично работал в среде Internet Explorer, но вызывает ошибку в WebKit
html = Элементы.Body.Документ.parentWindow.eval("CKEDITOR.instances.editor1.getData();");

При выполнении этой строки на новых версиях платформы система выдает ошибку. Происходит это по двум ключевым причинам:

  1. Свойство parentWindow является специфичным (нестандартным) свойством объекта document в Internet Explorer. Современные браузеры, включая движок WebKit, не поддерживают это свойство. Вместо него по спецификации W3C необходимо использовать стандартное свойство defaultView.
  2. Прямой вызов функции eval() из кода 1С к контексту WebKit теперь заблокирован или ограничен из-за ужесточения политик безопасности и изоляции контекстов исполнения (песочницы).

Давайте разберем по шагам, как переписать этот и сопутствующие механизмы под требования современной платформы.

Решение 1. Переход с parentWindow на defaultView

Для доступа к глобальному объекту окна (аналогу window в JavaScript) из кода 1С вместо свойства parentWindow мы должны использовать defaultView. Это стандартный способ получения ссылки на объект окна, которому принадлежит документ.

Посмотрим, как изменится код получения данных из редактора CKEditor:


// Было (до 8.3.14):
ДанныеHTML = Элементы.Body.Документ.parentWindow.CKEDITOR.instances.editor1.getData();

// Стало (после 8.3.14):
ДанныеHTML = Элементы.Body.Документ.defaultView.CKEDITOR.instances.editor1.getData();

Аналогично переписывается и код для инициализации или передачи данных обратно в редактор. Посмотрим на рабочий пример передачи текста в редактор с обработкой обратного вызова (callback):


Элементы.Body.Документ.defaultView.CKEDITOR.instances.editor1.setData(ПередаваемыйHTML, "function()
    |{
    |    this.checkDirty();
    |});");

Использование defaultView полностью восстанавливает доступ к глобальным переменным и библиотекам, объявленным на веб-странице.

Решение 2. Обход ограничений встроенного eval()

В некоторых сценариях разработчикам требуется динамически выполнять произвольный JavaScript-код, сформированный в 1С. Попытка вызвать defaultView.eval("код") напрямую может завершиться ошибкой безопасности.

Чтобы обойти это ограничение, мы рекомендуем использовать архитектурный паттерн "функция-обертка". Суть метода проста: внутри самого HTML-документа (в тегах <script>) объявляется стандартная функция, которая принимает строку кода и выполняет её локально в контексте страницы. Из 1С мы вызываем уже не системный eval, а нашу собственную безопасную функцию.

Разберем этот пример на практике. Добавим в HTML-код страницы следующую функцию:


function executeJsFrom1C(codeString) {
    try {
        return eval(codeString);
    } catch (e) {
        console.error("Ошибка выполнения кода: " + e.message);
        return null;
    }
}

Теперь из модуля формы 1С мы можем безопасно вызывать выполнение любого скрипта через нашу обертку:


КодДляВыполнения = "CKEDITOR.instances.editor1.getData();";
Результат = Элементы.Body.Документ.defaultView.executeJsFrom1C(КодДляВыполнения);

Важные изменения при переходе на WebKit, о которых нужно знать

Простая замена свойств — это лишь верхушка айсберга. Переход на WebKit принес глубокие изменения в объектную модель, которые могут полностью сломать более сложные интеграции. Проанализируем ключевые особенности взаимодействия 1С и нового движка.

1. Изменение типов данных: С COMОбъект на ВнешнийОбъект

В старой модели на базе IE свойство Документ у поля HTML-документа возвращало полноценный COMОбъект. Разработчик мог обращаться к специфическим интерфейсам Windows, манипулировать DOM-деревом напрямую через COM-методы и использовать специфичные библиотеки Microsoft.

В WebKit тип свойства Документ изменился на ВнешнийОбъект. Это означает следующее:

2. Полный отказ от externalForm (Интеграция JS -> 1С)

В старых конфигурациях для передачи события из браузера обратно в 1С часто использовался механизм externalForm. Разработчики передавали контекст формы 1С в JavaScript следующим образом:


// В коде 1С:
Элементы.ПолеHTML.Документ.parentWindow.externalForm = ЭтаФорма;

После этого внутри JavaScript-кода можно было напрямую вызвать экспортный метод формы 1С: externalForm.ИмяПроцедуры(Параметры). В WebKit этот механизм полностью заблокирован и не работает! Попытка передать сложный объект формы 1С в среду WebKit приведет к тому, что объект превратится в undefined.

Рассмотрим два надежных альтернативных способа организации обратной связи:

Способ А: Перехват события "ПриНажатии" (Click-хак)

Этот способ основан на том, что событие нажатия на элемент страницы перехватывается платформой 1С. Мы можем создать на странице скрытый элемент (например, тег <div>), записывать в его атрибуты или текст нужные данные из JS, а затем программно вызывать клик по нему.

Разберем реализацию по шагам.

Шаг 1. Размещаем скрытый элемент в HTML-коде нашей страницы:

<div id="comm_bridge" style="display:none;" data-payload=""></div>

Шаг 2. В JavaScript пишем функцию отправки сообщения в 1С:


function sendMessageTo1C(actionName, data) {
    var bridge = document.getElementById('comm_bridge');
    // Упаковываем данные в JSON-строку
    var packet = { action: actionName, payload: data };
    bridge.setAttribute('data-payload', JSON.stringify(packet));
    // Эмулируем клик, который перехватит 1С
    bridge.click();
}

Шаг 3. В 1С создаем обработчик события ПриНажатии для Поля HTML документа:


&НаКлиенте
Процедура ПолеHTMLПриНажатии(Элемент, ДанныеСобытия, СтандартнаяОбработка)
    
    // Проверяем, что клик совершен по нашему "мосту"
    Если ДанныеСобытия.Элемент.id = "comm_bridge" Тогда
        
        // Отменяем стандартное поведение браузера
        СтандартнаяОбработка = Ложь;
        
        // Считываем упакованные данные из атрибута элемента
        ДанныеПакета = Элементы.ПолеHTML.Документ.getElementById("comm_bridge").getAttribute("data-payload");
        
        // Десериализуем JSON в структуру 1С
        ЧтениеJSON = Новый ЧтениеJSON;
        ЧтениеJSON.УстановитьСтроку(ДанныеПакета);
        РезультатСобытия = ПрочитатьJSON(ЧтениеJSON);
        ЧтениеJSON.Закрыть();
        
        // Вызываем нужный обработчик в зависимости от действия
        Если РезультатСобытия.action = "saveText" Тогда
            ОбработатьСохранениеТекста(РезультатСобытия.payload);
        КонецЕсли;
        
    КонецЕсли;
    
КонецПроцедуры

Способ Б: Использование кастомных URI-схем (location.href)

Второй популярный метод заключается в изменении адреса страницы на специальную псевдо-ссылку, параметры которой парсятся на стороне 1С в событии ПриИзменении или ПриНажатии.

В JavaScript вызываем смену адреса:


window.location.href = "1c://action?name=save&payload=" + encodeURIComponent(myData);

В 1С перехватываем изменение навигации, парсим строку адреса, извлекаем параметры и отменяем переход, чтобы страница не перезагрузилась.

3. Работа со сложными структурами через JSON

При передаче сложных объектов (массивов, структур, соответствий) из JavaScript напрямую в 1С через возвращаемые значения функций, вы столкнетесь с тем, что они приходят в виде типов ВнешнийОбъект. Обращение к элементам таких коллекций в 1С может вызывать синтаксические трудности (например, обращение к индексам массива может требовать строковых ключей вида Результат["0"] вместо числовых Результат[0]).

Золотое правило интеграции: Всегда сериализуйте сложные данные в формат JSON при передаче границы сред "1С <-> JS". Это избавит вас от проблем несовместимости типов.

4. Строгие политики безопасности и CORS в WebKit

Движок Internet Explorer сквозь пальцы смотрел на безопасность при работе с локальными файлами. С переходом на WebKit вы столкнетесь со строгой политикой песочницы (Sandbox). Браузер заблокирует прямые попытки подключить внешние скрипты или стили по абсолютным путям файловой системы (например, <script src="C:/MyScripts/ckeditor.js">).

Для решения этой проблемы придерживайтесь следующих рекомендаций:

5. Настройки прокси-серверов

Обратите внимание на то, что старый встроенный браузер на базе IE автоматически наследовал системные настройки прокси-сервера из операционной системы Windows. Новый движок WebKit эти настройки игнорирует. Если ваши скрипты внутри поля HTML-документа обращаются к внешним веб-ресурсам и требуют работы через прокси, параметры прокси-сервера теперь необходимо принудительно прописать в конфигурационном файле платформы inetcfg.xml.

Подведем итоги

Перевод поля HTML-документа на модель WebKit требует от разработчика понимания современных веб-стандартов. Давайте зафиксируем ключевые шаги для успешной миграции кода:

  1. Замените все обращения .parentWindow на стандартные .defaultView.
  2. Откажитесь от прямого вызова eval() из кода 1С в пользу вызова локальных функций-оберток, объявленных внутри HTML-страницы.
  3. Полностью исключите использование externalForm. Для отправки данных из JS в 1С используйте механизм перехвата клика по скрытому элементу (Click-хак) или кастомные схемы URI.
  4. Используйте JSON в качестве универсального транспорта передачи данных между 1С и JavaScript.

Применение этих простых правил позволит сделать ваши интерактивные HTML-интерфейсы в 1С стабильными, быстрыми и полностью кроссплатформенными!

← На главную