gifts2017

Выполнение JavaScript кода из 1С в объекте Поле HTML Документа (HTML 5) и вызов события ПриНажатии из него

Опубликовал игорь Никик (igo1) в раздел Программирование - Практика программирования

Пример выполнения JS кода из 1С в Поле HTML Документа под управляемыми формами, с удобным получением результата в 1С(С помощью вызова привязанного события ПриНажатии к элементу ПолеHTMLДокумента)

Предыстория

Во время реализации одного проекта, возникла необходимость выполнять 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. Запуск скрипта
  2. Получения ответа скрипта
  3. Запуск с возвратом результата скрипта в 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

В комметариях был предложен еще один способ вызова JS (спасибо Rie), если у вас есть возможность менять код HTML документа, то можно прописать функцию в нем и затем ее вызывать.  передавая в нее код на JS.
<script type="text/javascript"> function exec(script) { eval(script); } </script>

и затем в 1С: 

Элементы.ПолеHTMLДокумента1.Документ.parentWindow.exec("alert('OK')");

Возврат результата JS в 1С

      Для передачи результата скрипта в 1С из объекта ПолеHTMLДокумента будем использовать событие. Привяжем к  ПолеHTMLДокумента событие ПриНажатии которое получает на вход 3 параметра:

  1. Элемент у которого произошло событие(само ПолеHTMLДокумента )
  2. Объект событие
  3. Признак выполнения стандартного поведения

Чтобы вызвать событие при нажатии понадобиться выполнить следующий 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С, для дальнейшей обработки.

Пример реализации в публикации тут

Скачать файлы

Наименование Файл Версия Размер Кол. Скачив.
ПРИМЕР РАБОТЫ С JS
.epf 6,83Kb
02.08.16
29
.epf 6,83Kb 29 Скачать

См. также

Подписаться Добавить вознаграждение

Комментарии

1. Андрей Акулов (DrAku1a) 24.03.16 03:39
По выполнению JS из 1С - вроде было что-то попроще, вроде eval или EvalExpr. По поводу возврата результата - думаю, будет полезно!
2. игорь Никик (igo1) 24.03.16 11:55
(1) DrAku1a, Да, раньше выполнять скрипты можно было с помощью конструкции ПолеHTMLДокумента.Документ.parentWindow.eval("Скрипт"); , но с переходом на IE8 и выше такой возможности больше нет. Да и статья показывает не только, что можно вызвать JS код, но и изменить поведение HTML документа, загруженного в ПолеHTMLДокумент.
3. Яков Коган (Yashazz) 24.03.16 13:01
(2) igo1, и это в общем логично. Поле HTML и выполнение в нём произвольного js, да ещё с eval, было страшенной дырой в безопасности. Поэтому и возможности поля порезали, и вообще.
Интересный способ, спасибо. Как-нибудь на досуге попробую.

Если статья понравилась не забываем щелкнуть на звездочку
Статья так понравилась, особенно эта фраза, что щёлкнул звёздочку даже дважды)
4. игорь Никик (igo1) 24.03.16 13:21
(3) Yashazz, Вот всегда так, паришься, а потом все по два раза звездочку жмут (((
5. Яков Коган (Yashazz) 24.03.16 16:57
(4) igo1, а просто не люблю попрошаек. Статья дельная, и я было щёлкнул, а потом дочитал до конца и даже расстроился.
6. игорь Никик (igo1) 24.03.16 19:03
(5) Yashazz,
Я просто на другие статьи посмотрел, дак там даже Яндекс кошель прицеплен. Да, и к тому же, не понятно нормальная статья или нет, звездочку не жмут и Комменты не пишут. Вот и думай стоит писать еще или нет.

Но не в это суть. Статья гуд и отлично )
7. Сергей Кудашкин (sikuda) 25.03.16 09:50
8. игорь Никик (igo1) 25.03.16 11:45
(7) sikuda, Спасибо за коммент, посмотрел вашу статью.
В ней действительно есть похожие места, но думаю посмотрев структуру возврата события в 1С более удобных мест передачи данных не придумать, поэтому у нас места совпали. И сам подход у меня немного другой.
9. Юрий Пермитин (YPermitin) 28.03.16 15:05
(2) igo1, скажите, а не пытались ли вы использовать объект XMLHttpRequest для отправки запрос из поля HTML-документа?
Вроде как функция эта заблочена, но вдруг есть обходной путь)
10. игорь Никик (igo1) 13.05.16 14:42
(9) YPermitin, XMLHttpRequest не понимаю какую цель вы хотите этим достичь. вроде запросы из ПолеHTMLДокумент нормально уходят, проверил в помощью тега "Кнопка".
11. Николай Верещагин (ut11) 27.07.16 19:09
Опробовал методику, столкнулся с тем, что при повторных вызовах обработки происходит ошибка:

"Ошибка при вызове метода контекста (setAttribute)
ДИВ.setAttribute("onclick", ТекстСкрипт);
по причине:
Произошла исключительная ситуация: Не поддерживается"

либо "Произошла исключительная ситуация (0x800a01b6)"

кто нибудь решал такую проблему?
12. игорь Никик (igo1) 27.07.16 19:25
Да такая проблема была на платформе 8.3.5 обновите и все ОК, или посмотрите эту публикацию http://infostart.ru/public/506854/ (11) ut11,
13. Николай Верещагин (ut11) 27.07.16 19:44
у клиента 8.2.19 и обновить нет возможности :(
14. Николай Верещагин (ut11) 27.07.16 19:46
а что именно там смотреть? я ту обработку и брал за образец
15. игорь Никик (igo1) 27.07.16 19:47
Это поправили в 8.3.7 как я знаю. Не понятно почему нельзя обновить, режим совместимости вполне работает.
16. Николай Верещагин (ut11) 27.07.16 19:53
я субподрядчик на большом проекте, от меня это не зависит, увы
17. Андрей Ромашов (Zixxx) 28.07.16 06:17
Ни как не получается в Поле HTML Документа отобразить следующую страницу
http://wsde.ru/timeline/index.html
Постоянно валится с ошибками, описанный здесь пример тоже пробовал использовать, но может не так чего сделал.

Подскажите плиз как сделать
18. игорь Никик (igo1) 28.07.16 11:50
(16) ut11, Это косяк платформы, методов обхода мне найти не удалось
19. игорь Никик (igo1) 28.07.16 12:53
(17) Zixxx, попробуйте поиграть с этим тегом <meta http-equiv="X-UA-Compatible" content="IE=9"/>. сначала откройте свой HTML с эти тегом(1с запустит эмуляцию IE). а потом переходите по ссылке
20. Алексей Кожушко (Rie) 29.07.16 00:05
(2) igo1, можно определить функцию в самом документе -- и вызывать её:
<script type="text/javascript">
function exec(script) { eval(script); }
</script>

и затем в 1С:

Элементы.ПолеHTMLДокумента1.Документ.parentWindow.exec("alert('OK')");
21. Александр Костенко (alex_ua85) 29.07.16 01:23
К чему эти извращения? Вопрос из ряда "Знаю JS и лень учить 1С. Как писать в 1С средствами JS?". Вопрос, зачем?
22. игорь Никик (igo1) 29.07.16 12:57
(21) alex_ua85, Либо я не очень понятно написал, либо читать вам надо внимательней. Так есть определяется функция в самом документе и вызывается (Это для передачи данных из 1с в док), а ели у вас произошло событие в документе, определен второй вариант с вызовом из документа в 1с через события "ПриНажатии" с передачей строковых данных.
23. игорь Никик (igo1) 29.07.16 13:36
24. Alex Nikulin (Al-77) 02.08.16 16:23
(16) ut11, Добрый день, вам удалось решить проблему на платформе 8.2 ?
25. игорь Никик (igo1) 02.08.16 18:15
(24) Al-77, Ее не решить на 8.2, там COM объект после вызова события разваливается. только 8.3.7 и выше. под 8.2 должен работать старый метод eval просто поставьте <meta http-equiv="X-UA-Compatible" content="IE=9"/> в место IE=9 -> IE=7. должно заработать. Пример такой работы в моей старой обработке http://infostart.ru/public/238697/
26. Александр Папка (SherifSP) 21.09.16 13:00
При использовании тега <meta http-equiv="X-UA-Compatible" content="IE=edge"/>, недоступно обращение через функцию eval html документа, как можно обратится к функции html документа с этим тегом?
27. Дмитрий Кузьменко (Дмитрий_кдс) 22.09.16 11:06
Добрый день. Подскажите, как обойти проблему Eval() на обычных формах 8.3? Ругается на метод Евал при открытии карты((
28. игорь Никик (igo1) 26.09.16 13:22
(27) Дмитрий_кдс, Статья сверху (Весь текст) посвещен именно этому вопросу
29. игорь Никик (igo1) 26.09.16 13:23
(26) SherifSP, к сожалению работу с edge (это не IE) не тестировал .....
Для написания сообщения необходимо авторизоваться
Прикрепить файл
Дополнительные параметры ответа