При разработке интерфейсов на платформе 1С:Предприятие 8.3 часто возникает задача интеграции внешнего веб-контента в управляемые формы. Мы привыкли, что в тонком или толстом клиенте обращение к объектной модели (DOM) загруженной страницы происходит прозрачно через свойство Документ. Однако при переходе в веб-клиент многие разработчики сталкиваются с тем, что это же свойство возвращает Неопределено (undefined). В этой статье мы подробно разберем, почему это происходит, проанализируем механизмы безопасности современных браузеров и найдем эффективные способы решения задачи.
Для начала выясним причину, по которой 1С ведет себя по-разному в разных клиентах. Когда мы запускаем тонкий клиент, платформа использует встроенный движок (WebKit или движок Internet Explorer), который работает в контексте операционной системы как полновесное приложение. В этом случае 1С имеет полный контроль над компонентом и может беспрепятственно обращаться к любым свойствам загруженного контента.
Рассмотрим ситуацию в веб-клиенте. Здесь сама 1С работает внутри браузера (Chrome, Firefox, Safari). Поле HTML-документа в веб-клиенте превращается в обычный HTML-тег <iframe>. Здесь в силу вступает Same-Origin Policy (SOP) — фундаментальная модель безопасности веб-контента. Браузер запрещает скриптам, находящимся на одной странице (ваша база 1С, например, https://1c.company.com), обращаться к содержимому фрейма, если он загружен с другого домена (например, https://google.com). Если протокол, домен или порт не совпадают, доступ к свойству document внутри iframe будет заблокирован на уровне ядра браузера. Именно поэтому 1С возвращает Неопределено: она просто не может пробиться сквозь защиту браузера.
Начиная с версии платформы 8.3.14, фирма «1С» рекомендует отказываться от прямого обращения к DOM через свойство Документ в пользу асинхронного или синхронного выполнения скриптов. Метод ВыполнитьJavaScript() является более универсальным, так как он позволяет передать команду внутрь контекста страницы.
Проанализируем ситуацию: нам нужно получить данные из поля ввода на сторонней странице. Вместо того чтобы писать Элементы.ПолеHTML.Документ.getElementById(...), мы будем использовать внедрение кода. Рассмотрим пример:
// В контексте управляемой формы
ТекстСкрипта = "
|var element = document.getElementById('myInput');
|if (element) {
| return element.value;
|}";
Элементы.ПолеHTML.ВыполнитьJavaScript(ТекстСкрипта);
Важно помнить, что если страница загружена из другого домена, даже ВыполнитьJavaScript может быть ограничен браузером в целях безопасности. Однако этот метод гораздо стабильнее работает в веб-клиенте при манипуляциях с контентом, который вы генерируете сами.
Если нам нужно не просто «читать» данные, а реагировать на события внутри HTML-поля (например, на двойной клик dblclick, как упоминалось в обсуждении), то лучшим способом будет использование механизма перехвата URL. Мы можем внедрить в HTML-код обработчик, который будет менять window.location, а 1С перехватит это событие.
Разберем по шагам, как это реализовать:
v8app.ПриНажатии (или аналогичного для перехвата навигации).Пример JavaScript кода внутри вашего HTML:
function sendTo1C(action, data) {
window.location.href = "v8app://" + action + "/" + encodeURIComponent(data);
}
document.addEventListener('dblclick', function() {
sendTo1C('double_click', 'User clicked the document');
});
В платформе 1С этот переход не вызовет открытия новой страницы, а будет интерпретирован как внешнее событие. Это позволяет обойти ограничения Same-Origin Policy, так как инициатором связи выступает «внутренняя» страница, а не «внешняя» база 1С.
Рассмотрим ситуацию из сообщения №1: разработчик скачивает HTML программно и устанавливает его в поле через УстановитьТекст(). В этом случае страница считается открытой из источника about:blank или localhost. При попытке выполнить AJAX-запрос внутри такой страницы, браузер блокирует его из-за отсутствия заголовков CORS (Cross-Origin Resource Sharing).
Чтобы решить эту проблему, необходимо убедиться, что сервер, к которому обращается AJAX, отдает заголовок Access-Control-Allow-Origin: * (или указывает конкретный домен вашей публикации 1С). Без этого заголовка браузер в веб-клиенте никогда не позволит скрипту получить ответ от сервера.
Самый надежный, но архитектурно сложный способ заставить свойство Документ работать в веб-клиенте — это обеспечить совпадение доменов. Если ваша база 1С опубликована по адресу https://apps.mysite.ru/base, а HTML-ресурс доступен по адресу https://apps.mysite.ru/helper.html, то браузер посчитает их принадлежащими к одному источнику.
В такой ситуации ограничение SOP снимается, и вы сможете программно обращаться к Элементы.ПолеHTML.Документ точно так же, как в тонком клиенте. Если ресурсы находятся на разных серверах, можно использовать Reverse Proxy (например, Nginx), чтобы «склеить» их в один домен.
Мы выяснили, что отсутствие доступа к свойству Документ в веб-клиенте — это не баг платформы 1С, а стандартное поведение системы безопасности браузеров. Для эффективной работы рекомендуем следующее:
ВыполнитьJavaScript() для манипуляций с контентом.v8app:// для передачи событий из HTML в 1С.Соблюдение этих правил позволит создавать отказоустойчивые решения, которые будут работать одинаково стабильно как в локальных приложениях 1С, так и через обычный браузер.