Как вызвать функцию 1С из JavaScript в обычной форме при использовании WebKit

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

При разработке интерфейсов на базе Поля HTML-документа в 1С:Предприятии (особенно в обычных формах) разработчики часто сталкиваются с проблемой «изоляции» среды исполнения JavaScript. В отличие от управляемых форм, где механизм window.external реализован более прозрачно, в обычных формах (ОФ) прямого способа передать ссылку на объект 1С или форму внутрь DOM-модели не существует. Попытки передать ЭтаФорма напрямую приводят к получению значения null или простой строки.

В этой статье мы подробно разберем, как преодолеть барьер «песочницы» JavaScript и организовать надежный вызов процедур 1С из веб-интерфейса, используя доступные события и механизмы платформы 1С 8.3.

Понимание архитектуры взаимодействия

Прежде всего, проанализируем ситуацию: JavaScript в браузере ничего не знает о внутреннем устройстве 1С. Для него 1С — это внешнее приложение, которое просто отображает страницу. Чтобы «достучаться» до 1С, нам нужно использовать одно из стандартных событий элемента управления «Поле HTML-документа», которое 1С умеет перехватывать. Суть любого решения сводится к следующему алгоритму:

  1. В JavaScript мы подготавливаем данные (например, упаковываем их в строку или записываем в скрытый элемент HTML).
  2. Инициируем стандартное событие (клик, вызов справки или переход по ссылке).
  3. В 1С срабатывает соответствующий обработчик, который считывает подготовленные данные из DOM-модели и выполняет требуемое действие.

Решение 1: Использование события onclick и объекта Document

Это один из самых распространенных способов. Мы не можем напрямую привязать функцию 1С к атрибуту onclick в HTML-коде, но мы можем «подписаться» на клики по документу со стороны 1С. Рассмотрим этот процесс по шагам.

Сначала подготовим HTML-код с кнопкой, имеющей определенный идентификатор:

<button id="mySuperButton" data-param="777">Нажать для вызова 1С</button>

Теперь в модуле обычной формы нам нужно перехватить момент окончания загрузки страницы, чтобы установить обработчик события. Используем событие ДокументСформирован (DocumentComplete):


Процедура ПолеHTMLДокументаДокументСформирован(Элемент)
    // Получаем объект COM-объекта документа
    Документ = ЭлементыФормы.ПолеHTML.Документ;
    
    // Подписываемся на событие клика по всему документу
    Документ.onclick = Новый COMОбъект("htmlfile").parentWindow.eval("
    |(function(event) {
    |    window.lastClickedElement = event.srcElement;
    |})"); 
    
    // В ОФ чаще используется прямое назначение обработчика события через встроенные механизмы
    Документ.onclick = ЭтаФорма; // В некоторых реализациях
КонецПроцедуры

Однако более надежным методом в ОФ является анализ элемента в процедуре-обработчике, которая привязана к событию onmouseup или onclick через COM-соединение. Проанализируем пример получения данных:


Процедура ПриНажатииВПолеHTML(Элемент)
    ТекущийДокумент = ЭлементыФормы.ПолеHTML.Документ;
    // Получаем элемент, по которому кликнули
    АктивныйЭлемент = ТекущийДокумент.activeElement;
    
    Если АктивныйЭлемент.id = "mySuperButton" Тогда
        Параметр = АктивныйЭлемент.getAttribute("data-param");
        ВыполнитьДействиеВ1С(Параметр);
    КонецЕсли;
КонецПроцедуры

Решение 2: Использование стандартного события Справка (onhelp)

Вызов справки — это стандартное событие браузерного движка, которое 1С перехватывает штатно. Это едва ли не самый быстрый способ передачи сигнала без необходимости парсинга координат клика.

Разберем реализацию в JavaScript:


function call1C(data) {
    // Записываем данные в скрытый инпут, чтобы 1С могла их прочитать
    var transferField = document.getElementById('transfer_data');
    if (!transferField) {
        transferField = document.createElement('input');
        transferField.id = 'transfer_data';
        transferField.type = 'hidden';
        document.body.appendChild(transferField);
    }
    transferField.value = data;
    
    // Вызываем штатное событие справки
    window.showHelp();
}

Теперь в 1С в свойствах Поля HTML-документа находим событие Справка (OnHelp):


Процедура ПолеHTMLСправка(Элемент, ДанныеСобытия, СтандартнаяОбработка)
    СтандартнаяОбработка = Ложь; // Чтобы не открывалось окно справки системы
    
    Документ = ЭлементыФормы.ПолеHTML.Документ;
    ПолеПередачи = Документ.getElementById("transfer_data");
    
    Если ПолеПередачи <> Неопределено Тогда
        ЗначениеОтJS = ПолеПередачи.value;
        Сообщить("JavaScript прислал данные: " + ЗначениеОтJS);
        // Здесь вызываем любую функцию 1С
        МояПроцедураОбработки(ЗначениеОтJS);
    КонецЕсли;
КонецПроцедуры

Решение 3: Перехват навигации (схема 1ccommand)

Этот метод основан на попытке браузера перейти по новому адресу. Мы подменяем window.location.href, а 1С перехватывает это событие до того, как страница начнет перезагружаться.

В JavaScript пишем функцию-обертку:


function sendTo1C(command, params) {
    var url = "1capp://command=" + encodeURIComponent(command) + "¶ms=" + encodeURIComponent(JSON.stringify(params));
    window.location.href = url;
}

В 1С используем событие ПередЗагрузкойУстановкойУказателя (BeforeNavigate):


Процедура ПолеHTMLПередЗагрузкойУстановкойУказателя(Элемент, URL, Узел, Фрейм, Ресурс, Отказ)
    Если Найти(URL, "1capp://") > 0 Тогда
        // Отменяем переход в браузере
        Отказ = Истина;
        
        // Извлекаем данные из URL
        ПараметрыСтрокой = Сред(URL, Найти(URL, "1capp://") + 8);
        // Выполняем парсинг параметров и запуск логики 1С
        ОбработатьКомандуИзJS(ПараметрыСтрокой);
    КонецЕсли;
КонецПроцедуры

Работа со сложными данными через JSON

Выясним важную деталь: поскольку передать ссылку на объект (например, на СправочникСсылка) напрямую невозможно, всегда используйте сериализацию. 1С в обычных формах (начиная с платформы 8.3.6) отлично работает с JSON.

Рассмотрим пример передачи сложной структуры из JavaScript в 1С:


// JS код
var orderInfo = {
    id: "000001",
    date: "2023-10-27",
    items: [{name: "Товар 1", qty: 2}, {name: "Товар 2", qty: 5}]
};
call1C(JSON.stringify(orderInfo));

В 1С для восстановления данных воспользуемся объектом ЧтениеJSON:


Функция ПрочитатьДанныеИзJS(СтрокаJSON)
    Чтение = Новый ЧтениеJSON;
    Чтение.УстановитьСтроку(СтрокаJSON);
    Результат = ПрочитатьJSON(Чтение);
    Чтение.Закрыть();
    Возврат Результат; // Получаем структуру 1С
КонецФункции

Особенности WebKit и ограничения

Если вы используете WebKit в обычных формах, следует учитывать, что его поведение может отличаться от старого движка Internet Explorer (MSHTML). В частности:

Резюме: Несмотря на то, что обычные формы не предоставляют такого удобного моста, как СредстваКриптографии.ExternalEvent в управляемых формах, использование события onhelp или перехват навигации позволяет построить полноценное двустороннее взаимодействие между 1С и JavaScript.

← На главную