Как исправить ошибку события ondatasetcomplete в поле HTML-документа 1С и перейти на современный стандарт обмена с JavaScript?

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

Интеграция веб-технологий в решения на базе платформы 1С — задача весьма популярная. Разработчики часто используют поле HTML-документа для отображения интерактивных карт (например, Google Maps или Яндекс.Карты), графиков, диаграмм или сложных веб-интерфейсов. Однако при обновлении операционной системы, браузера Internet Explorer или самой платформы 1С старые, годами работавшие механизмы взаимодействия между JavaScript (JS) и кодом 1С (BSL) могут внезапно выйти из строя.

В этой статье мы подробно разберем, почему перестает работать популярное событие ondatasetcomplete, как быстро вернуть работоспособность старому коду и как правильно переписать взаимодействие между 1С и JS по современным кроссплатформенным стандартам, которые гарантированно будут работать на любых версиях платформы 1С.

Почему перестал работать старый механизм передачи событий?

Раньше в операционной системе Windows для рендеринга содержимого поля HTML-документа платформа 1С использовала встроенный движок MSHTML (Internet Explorer). Для передачи данных из JavaScript обратно в форму 1С разработчики часто использовали специфические для IE методы генерации событий. Код в JS выглядел следующим образом:


var evt = document.createEventObject();
document.body.fireEvent('ondatasetcomplete', evt);

В самой 1С на стороне формы существовал предопределенный обработчик события поля HTML-документа с именем ondatasetcomplete() (в русскоязычной локализации — Эксплорерondatasetcomplete()), который успешно перехватывал это событие и позволял прочитать переданные данные.

Начиная с версии Internet Explorer 11 (и даже в некоторых режимах IE10), Microsoft объявила проприетарные методы document.createEventObject() и fireEvent() устаревшими (deprecated) и полностью удалила их поддержку в угоду стандартам W3C. Попытка переписать код на стандартный веб-интерфейс создания событий тоже часто терпит неудачу:


var evt = document.createEvent("HTMLEvents");
evt.initEvent('ondatasetcomplete', true, true);
// Событие создается, но 1С его больше не видит!

Ситуация усложняется тем, что начиная с версии платформы 1С 8.3.14, фирма «1С» полностью отказалась от использования Internet Explorer в пользу кроссплатформенного движка WebKit (Chromium). В этом новом окружении любые специфические вызовы, ориентированные на IE, принципиально не работают, а объектная модель COM-соединения с формой полностью отсутствует.

Решение 1: Временный обходной путь для старых конфигураций (Обычные формы и старая платформа)

Если ваша конфигурация работает на обычных формах, используется старая версия платформы (ниже 8.3.14), а пользователи работают на компьютерах с установленным Internet Explorer, вы можете быстро вернуть работоспособность старому коду. Для этого необходимо принудительно заставить движок рендеринга использовать режим совместимости с IE10 или IE9.

Разберем по шагам, как это сделать. Вам нужно добавить специальный мета-тег в заголовок <head> вашего HTML-документа:


<!DOCTYPE html>
<html>
<head>
    <meta http-equiv="X-UA-Compatible" content="IE=10" />
    <title>Интеграция с картой</title>
</head>
<body>
    <!-- Ваш HTML-код -->
</body>
</html>

Этот тег указывает браузеру эмулировать стандарты и поведение JavaScript-движка версии IE10. После этого старый код инициализации события через document.createEventObject() снова начнет функционировать. Однако помните: это временное решение. При обновлении платформы до актуальных релизов этот код окончательно перестанет работать, поэтому крайне рекомендуется перейти на современный стандарт.

Решение 2: Современный кроссплатформенный стандарт обмена данными (Рекомендуется)

Для того чтобы ваше решение работало стабильно как в обычных, так и в управляемых формах, а также на новых версиях платформы 1С с движком WebKit, необходимо полностью отказаться от привязки к событию ondatasetcomplete. Вместо этого мы применим стандартный и универсальный механизм перехвата кликов через событие «ПриНажатии» (в JS — onclick).

Суть метода заключается в создании скрытого элемента-моста на HTML-странице. Когда JS-коду требуется передать данные в 1С, он записывает эти данные в атрибуты скрытого элемента и программно имитирует клик по нему. 1С перехватывает это нажатие, считывает данные и отменяет стандартный переход по ссылке.

Рассмотрим детально реализацию этого механизма.

Шаг 1. Создание скрытого элемента в HTML-коде

Добавим в тело HTML-документа невидимую ссылку. Для передачи сложных структур данных будем использовать пользовательские атрибуты спецификации HTML5 (семейство data-*):

<a id="1c-bridge" style="display:none;" data-event="" data-payload=""></a>

Шаг 2. Реализация функции отправки данных на стороне JavaScript

Напишем универсальную функцию в JS, которая будет упаковывать переданные объекты в формат JSON и инициировать событие клика:


function sendDataTo1C(eventName, dataObject) {
    var bridge = document.getElementById('1c-bridge');
    if (bridge) {
        // Записываем имя события и сериализуем данные в JSON-строку
        bridge.setAttribute('data-event', eventName);
        bridge.setAttribute('data-payload', JSON.stringify(dataObject));
        
        // Симулируем клик мышкой для перехвата в 1С
        bridge.click();
    }
}

// Пример вызова при получении координат от Google Maps:
var coordinates = { lat: 55.7558, lng: 37.6173 };
sendDataTo1C('MapCoordinates', coordinates);

Шаг 3. Обработка события в коде 1С (BSL)

В модуле формы 1С для элемента управления «Поле HTML-документа» назначим обработчик события ПриНажатии (или onclick). Код обработчика будет выглядеть следующим образом:


&НаКлиенте
Процедура ПолеHTMLПриНажатии(Элемент, ДанныеСобытия, СтандартнаяОбработка)
    
    // Проверяем, что событие произошло именно на нашем скрытом элементе-мосте
    Если ДанныеСобытия.Anchor <> Неопределено Тогда
        
        Атрибуты = ДанныеСобытия.Anchor.attributes;
        Попытка
            ИмяСобытия = Атрибуты.getNamedItem("data-event").value;
            СтрокаДанных = Атрибуты.getNamedItem("data-payload").value;
        Исключение
            // Кликнули по другой ссылке, не относящейся к нашему мосту
            Возврат;
        КонецПопытки;
        
        Если ИмяСобытия = "MapCoordinates" Тогда
            // Блокируем стандартную реакцию браузера на клик
            СтандартнаяОбработка = Ложь; 
            
            // Обрабатываем полученные данные
            РазберемПолученныеКоординаты(СтрокаДанных);
        КонецЕсли;
        
    КонецЕсли;
    
КонецПроцедуры

&НаКлиенте
Процедура РазберемПолученныеКоординаты(Знач СтрокаJSON)
    // Используем встроенные средства платформы для десериализации JSON
    Чтение = Новый ЧтениеJSON;
    Чтение.УстановитьСтроку(СтрокаJSON);
    ДанныеКоординат = ПрочитатьJSON(Чтение);
    Чтение.Закрыть();
    
    // Теперь у нас есть структура 1С с полями lat и lng
    Широта = ДанныеКоординат.lat;
    Долгота = ДанныеКоординат.lng;
    
    ПоказатьПредупреждение(, "Получены координаты из JS: Широта " + Широта + ", Долгота " + Долгота);
КонецПроцедуры

Как теперь вызывать функции JS из кода 1С в новых версиях?

Помимо передачи данных из JS в 1С, часто требуется и обратное действие — вызвать JS-функцию из кода модуля 1С. В старых решениях, ориентированных на Internet Explorer, разработчики использовали обращение через parentWindow:


// Этот код БОЛЬШЕ НЕ РАБОТАЕТ в WebKit
Элементы.ПолеHTML.Документ.parentWindow.myFunction(Параметр);

В современных версиях платформы на базе WebKit/Chromium объект parentWindow не поддерживается. Для вызова глобальных функций JavaScript необходимо использовать стандартное свойство defaultView:


// Современный кроссплатформенный вызов JS-функции из 1С
ДокументHTML = Элементы.ПолеHTML.Документ;
Если ДокументHTML <> Неопределено Тогда
    ДокументHTML.defaultView.myFunction(Параметр1, Параметр2);
КонецЕсли;

Обратите внимание на важный нюанс: при передаче параметров из 1С в JavaScript старайтесь использовать только простые типы данных (числа, строки, булево). Если вам необходимо передать сложный объект (например, ТаблицуЗначений или Структуру), обязательно предварительно сериализуйте его в JSON-строку на стороне 1С с помощью объекта ЗаписьJSON, а на стороне JS преобразуйте обратно через JSON.parse(). Это убережет вас от ошибок несовместимости типов в разных браузерных движках.

Особенности сборки современных JS-интерфейсов для 1С

Если вы планируете развивать интеграцию и строить сложные интерфейсы на базе современных JS-фреймворков (React, Vue, Svelte), учитывайте особенности встроенного в 1С движка WebKit:

  1. Версия движка зависит от релиза платформы. В старых релизах 1С (например, в районе 8.3.15–8.3.18) встроенный WebKit может не поддерживать самые свежие спецификации ECMAScript (ESNext). Поэтому при сборке вашего JS-кода (например, с помощью Vite, Webpack или Babel) всегда настраивайте таргет сборки (target compilation) на стандарты ES2015 (ES6) или ES2018. Это обеспечит обратную совместимость.
  2. Используйте Single-File сборку. Загрузка локальных веб-страниц со множеством относительных путей к стилям и картинкам в 1С часто вызывает проблемы с правами доступа и путями к файлам. Рекомендуется компилировать всё веб-приложение в один монолитный HTML-файл (где все стили и JS-скрипты встроены внутрь тегов <style> и <script>, а картинки переведены в формат Base64). Такой файл легко хранить в конфигурации 1С в качестве макета двоичных данных и загружать в поле HTML-документа одной строкой.

Применение предложенного кроссплатформенного шаблона на базе скрытого элемента-моста и свойства defaultView позволит вам полностью избавиться от устаревших технологий Microsoft и гарантирует стабильную работу ваших интеграционных решений на любых современных релизах платформы 1С.

← На главную