Как вернуть значение из JavaScript (Yandex Maps API) в 1С?

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

При интеграции карт Яндекс в решения на базе 1С:Предприятие разработчики часто сталкиваются с фундаментальной проблемой: попытка вернуть результат работы функции JavaScript обычным оператором return не приносит успеха. Это происходит потому, что работа с картами (построение маршрутов, геокодирование) осуществляется асинхронно. Когда 1С вызывает функцию JS, ответ от серверов Яндекса еще не получен, и функция завершается раньше, чем данные становятся доступны.

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

Разбор проблемы: почему return не работает

Рассмотрим ситуацию: мы вызываем расчет расстояния. В коде JavaScript это выглядит как создание объекта router. Метод получения данных является асинхронным, то есть он принимает "функцию обратного вызова" (callback), которая сработает только тогда, когда сервер Яндекса пришлет ответ. Программа 1С, вызывая функцию через Document.parentWindow, не ждет этого ответа и моментально получает undefined или пустую строку.

Чтобы решить эту задачу, нам нужно инвертировать логику: не 1С должна "забирать" значение, а JavaScript должен "сообщать" 1С, что данные готовы. Выясним, какими способами это можно реализовать.

Способ 1: Использование программного события (fireEvent)

Этот метод отлично подходит для обычных форм и ранних версий 8.3. Суть заключается в том, чтобы имитировать нажатие на элемент HTML-документа изнутри кода JavaScript. 1С перехватывает это событие в процедуре-обработчике ПриНажатии (или onclick).

Шаг 1. Подготовка HTML-макета

Добавим в наш HTML скрытый элемент (например, кнопку или поле ввода), который будет служить каналом передачи данных.


<input type="hidden" id="Rasstoyanie" value="">
<button id="TriggerButton" style="display:none;" onclick="return true;"></button>

Шаг 2. Код в JavaScript

В функции обработки успешного построения маршрута мы записываем значение в поле и программно вызываем событие клика на кнопке.


function DobavitMarshrut(Tochka1, Tochka2) {
    var router = new YMaps.Router([Tochka1, Tochka2]);
    
    YMaps.Events.observe(router, router.Events.Success, function() {
        var distance = router.getDistance();
        // Записываем результат в скрытое поле
        document.getElementById('Rasstoyanie').value = distance;
        
        // Генерируем событие нажатия для 1С
        var btn = document.getElementById('TriggerButton');
        btn.fireEvent("onclick"); 
    });
}

Шаг 3. Обработка в 1С

В свойствах элемента ПолеHTMLДокумента на форме 1С выберем событие onclick (или ПриНажатии). В обработчике мы считаем данные.


Процедура КартаПриНажатии(Элемент, ДанныеСобытия)
    // Проверяем, что событие пришло именно от нашей кнопки
    Если ДанныеСобытия.Element.id = "TriggerButton" Тогда
        Расстояние = Элемент.Документ.getElementById("Rasstoyanie").value;
        Сообщить("Расстояние получено: " + Расстояние);
    КонецЕсли;
КонецПроцедуры

Способ 2: Использование обработчика ожидания (для Управляемых форм)

В управляемых формах прямое использование fireEvent может быть затруднено. Более надежным способом является установка флага готовности в JavaScript и его периодическая проверка со стороны 1С. Рассмотрим этот алгоритм подробнее.

JavaScript часть:

Создадим глобальную переменную-флаг DataChanged.


var DataChanged = false;
var DistanceValue = 0;

function MakeRoute(coords) {
    ymaps.route(coords).then(function (route) {
        DistanceValue = route.getLength();
        DataChanged = true; // Сигнализируем о готовности
    });
}

1С часть (Управляемая форма):

После вызова функции построения маршрута мы запускаем цикл проверки.


&НаКлиенте
Процедура ПостроитьМаршрут()
    // Вызываем JS функцию
    Элементы.ЯндексКарта.Документ.defaultView.MakeRoute(МассивКоординат);
    
    // Подключаем обработчик ожидания, который сработает через 1 секунду
    ПодключитьОбработчикОжидания("ПрочитатьДанныеСКарты", 1, Ложь);
КонецПроцедуры

&НаКлиенте
Процедура ПрочитатьДанныеСКарты()
    // Обращаемся к контексту JS окна
    JSWindow = Элементы.ЯндексКарта.Документ.defaultView;
    
    Если JSWindow.DataChanged Тогда
        // Данные готовы — считываем их
        ОтключитьОбработчикОжидания("ПрочитатьДанныеСКарты");
        Результат = JSWindow.DistanceValue;
        JSWindow.DataChanged = false; // Сбрасываем флаг
        Сообщить("Результат расчета: " + Результат);
    КонецЕсли;
КонецПроцедуры

Способ 3: Современный метод window.external.notify

Если вы используете платформу версии 8.3.14 и выше, программный интерфейс ПоляHTMLДокумента позволяет использовать объект window.external. Это наиболее "чистый" способ передачи данных из браузера в 1С без костылей с кнопками.

В JavaScript:

Проанализируем, как передать данные одной строкой. Мы можем использовать JSON для передачи сложных структур.


function sendTo1C(data) {
    if (window.external && window.external.notify) {
        window.external.notify(JSON.stringify(data));
    }
}

// Пример вызова в callback API карт
ymaps.route(points).then(function(route) {
    var info = {
        distance: route.getLength(),
        duration: route.getTime()
    };
    sendTo1C(info);
});

В 1С:

Используйте событие ВнешнееСобытие (для некоторых конфигураций) или специализированный обработчик ПриНажатии (в зависимости от настроек компонента). В новых версиях платформы реализовано событие ТекстУведомления в объекте ПолеHTMLДокумента.

Важные рекомендации по работе с типами данных

При передаче значений из JavaScript в 1С помните о следующих нюансах:

  1. Числа и точки: JavaScript использует точку в качестве разделителя дробной части. При получении строки в 1С убедитесь, что вы правильно преобразуете её в число, используя Число(), предварительно заменив точку на запятую, если этого требуют региональные настройки 1С.
  2. JSON: Если нужно передать много параметров (длину маршрута, время, список точек), всегда используйте JSON.stringify() в JS и ЧтениеJSON в 1С. Это избавит вас от проблем с парсингом строк.
  3. Фокус: Иногда события из HTML не доходят до 1С, если поле HTML не находится в фокусе. В таких случаях перед вызовом события в JS добавьте window.focus().

Таким образом, мы выяснили, что ключ к успешному возврату значений из Yandex API в 1С лежит в использовании событийной модели. Выбор конкретного метода (скрытая кнопка, флаг в обработчике ожидания или window.external) зависит от версии вашей платформы и типа используемых форм.

← На главную