gifts2017

Управляемые формы: Поле HTML Документа и веб-клиент

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

Взаимодействие javascript и интерфейса 1С дает огромные возможности для реализации нестандартных функций. Раньше можно было напрямую вызывать функции JavaScript через DOM объект document Поля HTML документа. В современных браузерах эта возможность ушла. Более того, в веб-клиенте появляется тип ВнешнийОбъект, который вообще нигде не описан. На Инфостарте были предложения вызывать JavaScript через fireEvent, но это очень неудобно. Предлагаю свой вариант решения.

Вступление

Взаимодействие javascript и интерфейса 1С дает огромные возможности для реализации нестандартных функций. Раньше можно было напрямую вызывать функции JavaScript через DOM объект document Поля HTML документа. В современных браузерах эта возможность ушла. Более того, в веб-клиенте появляется тип ВнешнийОбъект, который вообще нигде не описан. На Инфостарте были предложения вызывать JavaScript через fireEvent, но это очень неудобно. Предлагаю свой вариант решения.

С чего все началось

Разбираться с HTML полем меня сподвигло большое количество задач, в которых была необходимость реализовать интерактивные карты с мониторингом, маршрутизацией и т.д. Поскольку встроенными средствами 1С сделать это невозможно, то раньше использовал ActiveX компоненту собственного изготовления. На обычных формах все работало приемлимо, не считая, что решение и рядом не стояло с открытыми фреймворками типа OpenLayers. После появления управляемых форм, была попытка встроить все тот же ActiveX в HTML документ и разместить его в поле. Решение работает, но в виду ужесточения политики безопасности Microsoft, требовало изменения настроек безопасности на каждом клиенте, что в конечном счете оказалось неприемлимым. Вот тогда мы и поставили перед собой задачу, прикрутить к управляемым формам карты на основе Web-движков (Яндекс.Карты, OpenLayers и прочие Tile ориентированные движки).

Вариант 1. Работает в толстом клиенте, работает в тонком клиенте, не работает в веб-клиенте

Суть метода заключается в получении свойства parentWindow элемента формы ПолеHTMLДокумента. Выглядит примерно так:

<html>
  <head>
    <meta http-equiv="X-UA-Compatible" content="IE=9" />
    <script>
      function HelloWorld(FormLink)
      {
        FormLink.WebMapJavascriptAction("Hello from outside!");
        return "Hello world!";
      }
    </script>
  </head>
  <body>
  </body>
</html>
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
	WebКартаРеквизитФормыСтрока = Обработки.УНП_WEBКарта.ПолучитьМакет("HTMLМакет").ПолучитьТекст();
КонецПроцедуры

&НаКлиенте
Процедура WebКартаДокументСформирован(Элемент)
    Сообщить(Элементы.WebКарта.Документ.parentWindow.HelloWorld(ЭтаФорма));
КонецПроцедуры

&НаКлиенте
Процедура WebMapJavascriptAction(Переменная) Экспорт
    Сообщить(Переменная);
КонецПроцедуры

Все это прекрасно работает в толстом и тонком клиенте, но в веб-клиенте это работать не будет, так как в веб-клиенте у ПоляHTMLДокумента в свойстве Документ нет parentWindow.

Вариант 2. Работает в Толстом клиенте, тонком клиенте, веб-клиенте (проверено Chrome, IE, Edge)

Для реализации этого варианта необходимо немного исправить HTML макет. А именно:

<html>
  <head>
    <meta http-equiv="X-UA-Compatible" content="IE=9" />    
  </head>
  <body>
  </body>
  <script>
    document.body.HelloWorld = function(FormLink)
    {
      FormLink.WebMapJavascriptAction("Hello from outside!");
      return "Hello world!";
    }
  </script>
</html>

И небольшие правки в коде формы

&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
    ПовторноеСрабатывание = Ложь;
	WebКартаРеквизитФормыСтрока = Обработки.УНП_WEBКарта.ПолучитьМакет("HTMLМакет").ПолучитьТекст();
КонецПроцедуры

&НаКлиенте
Процедура WebКартаДокументСформирован(Элемент)
    Если Не ПовторноеСрабатывание Тогда // В некоторых случаях, при подключении дополнительных библиотек,
                                        //событие может сработать повторно в уже загруженном документе
       ОбъектBody = Неопределено;

       Попытка
          ОбъектBody = Элементы.WebКарта.Документ.parentWindow.document.body;
       Исключение
       КонецПопытки;

       Если Не ЗначениеЗаполнено(ОбъектBody) Тогда
          Попытка
             ОбъектBody = Элементы.WebКарта.Документ.body;
          Исключение
          КонецПопытки;
       КонецЕсли;

       Если Не ЗначениеЗаполнено(ОбъектBody) Тогда
          Сообщить("Что-то пошло не так");
       Иначе
          Сообщить(ОбъектBody.HelloWorld(ЭтаФорма));
       КонецЕсли;
       
       ПовторноеСрабатывание = Истина;
    КонецЕсли;
КонецПроцедуры

&НаКлиенте
Процедура WebMapJavascriptAction(Переменная) Экспорт
    Сообщить(Переменная);
КонецПроцедуры

Таким образом для толстого и тонкого клиента мы оставляем все как и было, но для универсальности используем расширенный нами объект DOM body. В веб-клиенте элемент формы ПолеHTMLДокумента.Документ содержит тип ВнешнийОбъект, что на самом деле является COM реализацией элемента body по структуре DOM.

Теоретически можно написать функцию в body, которая вернет ссылку на window, и тогда можно вызывать глобальные функции.

Надеюсь кому-то поможет ;-)

См. также

Подписаться Добавить вознаграждение
Комментарии
1. Виталий Чебан (VitaliyCeban) 18.07.16 14:13
Более полное раскрытие вопроса http://infostart.ru/public/398366/
McLer; Yashazz; compguru; +3 Ответить 1
2. Владимир Вагин (compguru) 18.07.16 15:12
(1) VitaliyCeban, Согласен, defaultView будет работать в Веб-клиенте
3. Яков Коган (Yashazz) 19.07.16 16:04
А уж первым-то вариантом и вовсе в замшелые времена пользовались, безо всяких извратов с актив-иксом.
Я ещё в 2012-м году продемонстировал все эти приёмы на примере работы с API Яндекс-карт.

Баян, короче. Вы уж извините, уважаемый комп-гуру)))
4. Владимир Вагин (compguru) 19.07.16 17:11
(3) Yashazz, Да бывает :-) Я, по правде говоря, за оригинальностью и не стремился )
5. Владимир Гусев (adhocprog) 20.07.16 19:18
6. Владимир Вагин (compguru) 20.07.16 20:09
(5) adhocprog, Если поможет хотя бы одному человеку, значит не напрасен был мой труд :-)