Предыстория
Во время реализации одного проекта, возникла необходимость выполнять javascript(далее JS) код под управление объекта ПолеHTMLДокумента, с получением результат в 1С. Приведённые примеры, в найденных статьях, показались не очень удобными в использовании (сугубо личное мнение). Было принято решение попробовать найти другое, более простое, решение, на поиски отводилось не более 1 дня.
Меня заинтересовала статья на хабре в которой говорилось, что из HTML документа можно программно вызвать события (используется для вызова метода ПриНажатии из объекта ПолеHTMLДокумента). А на этом сайте управление атрибутами (использую для выполнения JS из 1С) .
Это и стало отправной точкой в разработке метода взаимодействия 1С и объекта ПолеHTMLДокумента.
Для эксперимента будем использовать простую HTML страницу.
<HTML>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=9"/>
</HEAD>
<body>
<div id="TEST" />
</body>
</html>
Ближе к делу!
Пример описанных методов вы можете посмотреть в прилагаемой обработке.
- Запуск скрипта
- Получения ответа скрипта
- Запуск с возвратом результата скрипта в 1с
После тестирования статья дополнилась вторым подходом, он получился более простым и понятным, советую пробовать методы описанные в дополнениях.
Выполнение JS из 1С
Для выполнения JS кода в объекте ПолеHTMLДокумента мы можем использовать стандартные события тегов. Такие как щелчок, двойной щелчок.... Для примера я буду использовать событие «OnClick», список тегов поддерживающих это событие можно посмотреть тут, выберем самый простой тег div.
Получим элемент по ИД из объекта DOM построеным Полем HTML Документа.
ДИВ = Элементы.Док.Документ.getElementById("TEST");
Попробуем найти атрибут "onclick", связанный с событием щелчок мыши, у элемента.
НашлиАтрибут = ДИВ.getAttributeNode("onclick");
Удалим атрибут если такой имеется
Если НашлиАтрибут <> null Тогда
ДИВ.removeAttribute("onclick");
КонецЕсли;
Создадим атрибут и установим необходимое нам действие
Атрибут = Элементы.Катра.Документ.createAttribute("onclick"); //создаем атрибут
Атрибут.value = "alert('сообщение от 1c');"; // прописываем скрипт который будем выполнять
ДИВ.attributes.setNamedItem(Атрибут); // привязываем атрибут
Вызовем действие щелчок мыши.
ДИВ.click();
Таким образом мы можем выполнять любые скрипты, и привязывать/подменять действия у элементов объекта ПолеHTMLДокумента, тем самым обеспечивая необходимое нам поведение. Например к ссылке/кнопке, отображаемой на открытом сайте, мы можем присоединть свое действие или поменять стандарное на свое. (Наверное так и работают вломщики )
В результате получим функцию выполнения скрипта
&НаКлиенте
Процедура ВыполнитьСкрипт(Команда)
ДИВ = Элементы.док.Документ.getElementById("TEST");
НашлиАтрибут = ДИВ.getAttributeNode("onclick");
Если НашлиАтрибут <> null Тогда
ДИВ.removeAttribute("onclick");
КонецЕсли;
Атрибут = Элементы.док.Документ.createAttribute("onclick");
Атрибут.value = "alert('Сообщение от 1с');";
ДИВ.attributes.setNamedItem(Атрибут); // привязываем атрибут
ДИВ.click();
КонецПроцедуры
Эту процедуру использую вместо старого метода ПолеHTMLДокумента.Документ.parentWindow.eval
который теперь(при использовании IE8 и выше) выдает ошибку ( Метод объекта не обнаружен (eval) )
Дополнение от 25.03.2016
Попытка выполнить данную конструкцию на платформе 8.3.5.1570 и ниже в толстом клиенте, под управляемой формой, не увенчалась успехом. Но был найден еще один способ выполнить данную операцию. Возможно даже более простой и удобный.
Получим наш Элемент по ИД
ДИВ = Элементы.Катра.Документ.getElementById("TEST");
Установим атрибут «onclick» и его значение, одной функцией (Подсмотрел ТУТ)
ДИВ.setAttribute("onclick", "alert('Координаты');");
Выполним скрипт
ДИВ.click();
ТАДА. все работает
Процедура ВыполнитьСкрипт(ТекстСкрипт)
ДИВ = Элементы.док.Документ.getElementById("TEST");
ДИВ.setAttribute("onclick", ТекстСкрипт);
ДИВ.click();
КонецПроцедуры
Дополнение от 02.08.2016
и затем в 1С:
Элементы.ПолеHTMLДокумента1.Документ.parentWindow.exec("alert('OK')");
Возврат результата JS в 1С
Для передачи результата скрипта в 1С из объекта ПолеHTMLДокумента будем использовать событие. Привяжем к ПолеHTMLДокумента событие ПриНажатии которое получает на вход 3 параметра:
- Элемент у которого произошло событие(само ПолеHTMLДокумента )
- Объект событие
- Признак выполнения стандартного поведения
Чтобы вызвать событие при нажатии понадобиться выполнить следующий js код
var evt = document.createEventObject(); // создадим пустой объект событие
evt.propertyName = 'функц1'; // в реквизит propertyName предлагаю помещать название результата ( что-то вроде типа, или название функции от которой получили данные )
evt.data = '156'; //в реквизит data будем передавать данные результата
document.body.fireEvent('onclick', evt); // выполним событие при нажатии ПолеHTMLДокумента
Выполнив данный js код в процедуру при нажатии вторым параметром придет созданный нами объект событие. Который довольно удобно обрабатывать.
Пример разбора ответа.
&НаКлиенте
// получаем имя и результат события
Процедура ДокПриНажатии(Элемент, ДанныеСобытия, СтандартнаяОбработка)
ИмяОперации = ДанныеСобытия.Event.propertyName;
ДанныеОперации = ДанныеСобытия.Event.data;
Если ИмяОперации = "" Тогда //не наше событие
Возврат;
КонецЕсли;
Если ИмяОперации = "Функц1" Тогда
// обработка результат
ИначеЕсли ИмяОперации = "функц2" Тогда
// обработка результат
//......
КонецЕсли;
КонецПроцедуры
Этот метод избавляет от использования обработчиков ожидания, и предоставляет удобный идентификатор события. По идентификатору мы точно знаем какие данные нам пришли, и как их разобрать.
Дополнения от 26.03.2016
И в этом месте тоже произошли непонятки (ошитбка восптроизводится только на плаформе 8.3.5.1570, но дабы предупредить эти ситуации в далнейшем, приведу решение) Сама причина - при повторном запуске формы с Поле HTML документа в момент вызова процедуры при нажатии по полю HTML платформенный вызов залипал и валил весь COM объект ( Произошла исключительная ситуация (htmlfile): Неопределенная ошибка ). Решением стало отключение стндарного выполнения события click, и отключение режима всплывания события. Как же это сделать смотрим ниже.
// отключим всплывание события подробнее тут
evt.cancelBubble = true;
// отключим стандартное поведение подробнее тут
evt.returnValue = false;
В результате для передачи данных в 1с из JS мы получим функцию.
function return1c(name,data){
var evt = document.createEventObject();
evt.propertyName = name;
evt.data = data;
evt.cancelBubble = true;
evt.returnValue = false;
document.fireEvent('onclick',evt);
};
Вывод.
Комбинируя эти методы, вы сможете довольно легко запускать необходимый вам js код, и получать данные в 1С, для дальнейшей обработки.
Пример реализации в публикации тут