Начиная с версии платформы 1С:Предприятие 8.3.14.1565, разработчики столкнулись с серьезным архитектурным изменением. На операционной системе Windows платформа отказалась от использования устаревшего COM-объекта Internet Explorer для рендеринга HTML и перешла на современный кроссплатформенный движок WebKit (который ранее уже использовался в клиентах под Linux и macOS). С одной стороны, это сделало отображение веб-страниц более быстрым и соответствующим современным стандартам HTML5/CSS3. С другой стороны, старый код, написанный с расчетом на COM-взаимодействие с Internet Explorer, перестал работать.
В этой статье мы подробно разберем, почему возникают ошибки вида "Метод не обнаружен", как правильно работать с DOM-деревом в новых реалиях и какими способами можно запускать произвольные JavaScript-скрипты на веб-странице из кода 1С.
Прежде чем переходить к написанию кода, проанализируем ключевое изменение в типах данных. Ранее в свойстве Документ объекта ПолеHTMLДокумента возвращался полноценный COMОбъект (ActiveX-обертка над Internet Explorer). Это позволяло напрямую обращаться к свойствам и методам объектной модели документа (DOM), используя привычный синтаксис 1С через точку.
После перехода на WebKit тип свойства Документ изменился на ВнешнийОбъект. Платформа 1С больше не может транслировать произвольные вызовы методов JavaScript напрямую через интерфейсы COM. Именно поэтому прямые обращения к функциям вроде getElementById приводят к ошибкам времени выполнения.
Первая проблема, с которой сталкиваются разработчики при поддержке старого кода — это получение глобального объекта окна браузера. В Internet Explorer для этого использовалось свойство parentWindow, в то время как во всех современных браузерах (включаю WebKit) стандартом является defaultView.
Посмотрим на пример универсального кода, который позволит вашей обработке или форме корректно работать как на старых релизах платформы (с IE), так и на новых (с WebKit):
Если Элементы.ПолеHTMLДокумента.Документ.parentWindow = Неопределено Тогда
// Вариант для WebKit (Chrome/Safari-совместимый движок)
ОкноБраузера = Элементы.ПолеHTMLДокумента.Документ.defaultView;
Иначе
// Вариант для старого Internet Explorer (COM-объект)
ОкноБраузера = Элементы.ПолеHTMLДокумента.Документ.parentWindow;
КонецЕсли;
Использование этого условия гарантирует, что программа не завершится аварийно при попытке получить контекст окна.
Вызов конструкции Элемент.Документ.getElementById("ИмяЭлемента") напрямую из встроенного языка 1С в режиме WebKit больше не поддерживается. Чтобы обойти это ограничение, нам необходимо перенести логику поиска элементов на сторону самого HTML-документа, создав там простую JavaScript-функцию.
Рассмотрим, как это сделать по шагам:
<script>
function getElementValueById(elementId) {
var elem = document.getElementById(elementId);
return elem ? elem.value : "";
}
</script>
defaultView:
// Получаем доступ к окну WebKit
ОкноБраузера = Элементы.ПолеHTMLДокумента.Документ.defaultView;
// Вызываем нашу JS-функцию напрямую из 1С
ЗначениеПоля = ОкноБраузера.getElementValueById("MyInputFieldID");
Через объект defaultView платформа 1С успешно вызывает любые глобальные JavaScript-функции, объявленные в контексте загруженной веб-страницы. Это открывает нам путь к созданию удобного API-посредника между 1С и веб-интерфейсом.
В старых версиях на базе Internet Explorer разработчики часто использовали метод eval() напрямую из 1С для динамического выполнения кода на веб-странице. В WebKit прямой вызов eval из 1С заблокирован из соображений безопасности. Тем не менее, нам никто не мешает написать собственную функцию-обертку.
Давайте выясним, как реализовать универсальный выполнитель JavaScript-кода:
<script type="text/javascript">
function execJavaScript(scriptText) {
return eval(scriptText);
}
</script>
// Пример вызова простого сообщения alert
Элементы.ПолеHTMLДокумента.Документ.defaultView.execJavaScript("alert('Успешно запущено из 1С!');");
Довольно часто при интеграции с внешними сайтами (например, при парсинге или автоматическом заполнении форм логина/пароля) требуется эмулировать действия пользователя. Например, запустить стандартный ASP.NET скрипт отправки формы: __doPostBack.
Разберем ситуацию, когда вам нужно выполнить следующий код:
javascript:setTimeout('__doPostBack(\'ctl00$CCAuth1$persTypeDrop\',\'\')', 0)
С использованием WebKit мы можем реализовать это двумя эффективными способами:
Способ А. Прямой вызов функции страницы (если функция объявлена глобально)
Если метод __doPostBack присутствует в глобальной области видимости window, мы можем вызвать его напрямую, передав параметры из 1С. В большинстве случаев задержка через setTimeout не является обязательной:
Элементы.ПолеHTMLДокумента.Документ.defaultView.__doPostBack("ctl00$CCAuth1$persTypeDrop", "");
Способ Б. Использование нашей функции-обертки execJavaScript
Если для логики сайта критически важно запустить код именно через асинхронный таймаут, мы конструируем строку вызова и передаем её в нашу функцию-посредник:
JSКод = "setTimeout(function() { __doPostBack('ctl00$CCAuth1$persTypeDrop', ''); }, 0);";
Элементы.ПолеHTMLДокумента.Документ.defaultView.execJavaScript(JSКод);
Помимо работы с DOM и выполнения скриптов, при миграции кода на движок WebKit следует учитывать еще несколько важных ограничений:
element.dataset из кода 1С напрямую не поддерживается. Для чтения и записи таких атрибутов всегда используйте JS-методы getAttribute("data-...") и setAttribute("data-...", value) через функции-обертки.window.pageYOffset или document.documentElement.scrollTop.Резюмируем: Переход на движок WebKit лишил нас возможности использовать "грязные" прямые обращения к COM-объектам Internet Explorer, однако он предоставил более быструю и стабильную среду выполнения. Использование JavaScript-функций в качестве интерфейса взаимодействия между 1С и страницей (через объект defaultView) является наиболее надежным, чистым и кроссплатформенным решением.