Почему ПолеHTMLДокумента перестает ловить события и как вернуть его к жизни

Программист IT и автоматизация бизнеса
← На главную

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

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

Разберем причины «засыпания» событий

Для того чтобы эффективно бороться с проблемой, нам необходимо понять, что происходит «под капотом» платформы. Рассмотрим основные технические факторы:

  1. Потеря связи с COM-объектом (Event Sink). В обычных формах 1С взаимодействует с компонентом ActiveX (MSHTML/Internet Explorer). Когда пользователь переходит по ссылке, старый объект document уничтожается, и создается новый. В некоторых сценариях навигации (особенно при переходах между разными доменами или возвратах через историю браузера) 1С не успевает или не может корректно переподписаться на события нового COM-объекта.
  2. Специфика клавиши Backspace. В движке MSHTML клавиша Backspace по умолчанию зарезервирована для команды «Назад». При ее нажатии управление перехватывается самим браузером на низком уровне. После такого «аппаратного» перехода часто происходит рассинхронизация фокуса между окном Windows и контейнером 1С. В результате события клавиатуры (onkeydown, onkeypress) перестают доходить до обработчиков 1С, пока пользователь принудительно не кликнет мышкой в область документа.
  3. Смена зон безопасности. Если в процессе навигации происходит переход с одного сайта на другой (например, с поисковой выдачи Яндекса на внешний ресурс), Internet Explorer может инициировать запуск нового процесса или переинициализацию контрола из соображений безопасности. В этот момент связь между обработчиками в коде 1С и DOM-деревом документа полностью обрывается.

Решение 1: Использование JavaScript-моста для перехвата кликов

Поскольку стандартные события 1С могут работать нестабильно, проанализируем подход с внедрением собственного JavaScript-кода в загружаемую страницу. Это позволит нам не полагаться на стандартный механизм подписки 1С, а самостоятельно инициировать вызовы.

Рассмотрим пример кода, который можно внедрить в событии ДокументСформирован. Мы добавим обработчик события onclick на весь документ, который будет передавать данные в 1С:


Процедура ПолеHTMLДокументаДокументСформирован(Элемент)
    Документ = Элемент.Документ;
    Если Документ = Неопределено Тогда
        Возврат;
    КонецЕсли;

    // Создаем скрипт для перехвата кликов
    Скрипт = Документ.createElement("script");
    Скрипт.text = "document.onclick = function(e) {
    |    var target = e.target || e.srcElement;
    |    if (target.tagName === 'A') {
    |        window.location.href = 'v8event:click:' + target.href;
    |        return false;
    |    }
    |};";
    Документ.body.appendChild(Скрипт);
КонецПроцедуры

В данном примере мы используем подмену window.location.href с префиксом v8event:. Это позволяет перехватить событие в 1С через обработчик ПередПереходом (если он доступен) или анализировать изменение состояния документа. Однако в обычных формах более надежным способом будет использование объекта external, если конфигурация позволяет настроить внешние компоненты.

Решение 2: Принудительное управление фокусом

Если проблема заключается в «зависании» после использования клавиши Backspace, часто помогает программное управление фокусом. Выясним, как «оживить» документ, заставив систему пересчитать состояние контрола.

Попробуем выполнить следующую последовательность действий при возникновении подозрений на потерю событий:

  1. Перевести фокус на любой другой невидимый или вспомогательный элемент формы (например, невидимую кнопку).
  2. Вернуть фокус обратно в ПолеHTMLДокумента.
  3. Вызвать метод focus() непосредственно у объекта document внутри поля.

Пример программного сброса фокуса:


Процедура ОживитьПолеHTML()
    // Предположим, у нас есть вспомогательная кнопка КнопкаФокус
    ЭтаФорма.ТекущийЭлемент = ЭлементыФормы.КнопкаФокус;
    
    // Возвращаем фокус в поле HTML
    ЭтаФорма.ТекущийЭлемент = ЭлементыФормы.ПолеHTMLДокумента;
    
    // Принудительно вызываем focus через COM
    Попытка
        ЭлементыФормы.ПолеHTMLДокумента.Документ.parentWindow.focus();
    Исключение
        // Обработка ситуации, если документ еще не загружен
    КонецПопытки;
КонецПроцедуры

Решение 3: Перехват события клика через объект события

Рассмотрим вариант, когда нам нужно предотвратить открытие внешнего браузера, сохранив при этом работоспособность событий. Проанализируем стандартный подход с использованием pEvtObj.returnValue = Ложь. Чтобы события не «отваливались», важно правильно обрабатывать момент перехода.

Вместо того чтобы просто отменять действие (так часто работают Яндекс-карты в 1С (обычные и управляемые формы)), попробуем использовать метод Перейти() самой платформы 1С, но с небольшой задержкой или через обработку очереди сообщений Windows:


Процедура ПолеHTMLДокументаПриНажатии(Элемент, pEvtObj)
    // Получаем URL ссылки, по которой кликнули
    ТекущийURL = pEvtObj.srcElement.href;
    
    Если Найти(ТекущийURL, "yandex.ru") = 0 Тогда
        // Отменяем стандартное поведение браузера
        pEvtObj.returnValue = Ложь;
        
        // Выполняем переход программно через метод 1С
        Элемент.Перейти(ТекущийURL);
    КонецЕсли;
КонецПроцедуры

Важный нюанс: при программном вызове метода Перейти() платформа 1С инициирует корректный цикл переподписки на события нового документа. Если же переход происходит «внутри» самого ActiveX без уведомления контейнера 1С, связь может быть потеряна.

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

Проанализировав поведение платформы на релизах 8.3.19, 8.3.20 и выше, можно дать несколько практических советов:

Таким образом, мы выяснили, что основной причиной проблемы является архитектурная особенность взаимодействия 1С с устаревшим движком Internet Explorer. Использование JavaScript-инъекций для прямой передачи событий и принудительное управление фокусом — это наиболее жизнеспособные методы «реанимации» интерфейса в обычных формах 1С.

← На главную