Суть проблемы:
В ранних версиях Internet Explorer (далее IE) вплоть до IE8 вызовы функций Javascript (далее JS) можно было осуществлять примерно так:
ПолеHTMLДокумента.document.parentWindow.MyFunc (...);
Начиная с версии IE9 такие вызовы, а также вызовы через eval () не работают, однако именно с этой версии начинается поддержка HTML5 и объекта Canvas, который предоставляет огромные возможности по рисованию, работе с картинками, аудио и видео и т.д. Также начиная с IE9 размер строки картинки в формате Base64 не ограничен (в IE8 - до 32К).
Однако, взаимодействие между Javascript'ом (далее JS) и 1С выглядит не так, как в старых версиях.
Решение:
Решением является использование JS-функции fireEvent.
Далее в статье рассматриваются вызовы 1С->JS и JS->1С для IE9 на примере функций вычисления суммы 2 чисел в 1С и JS. Cоответсвенно, функция JS вызывается из 1С, а 1С-функция - из JS.
Стоит сказать, что описываемая схема передачи параметров функций и их результатов - не единственное возможное решение, но достаточно универсальное.
В обработке к статье - полная версия примера.
Итак, начнем:
Сначала укажем, что наш HTML-код должен выполняться на движке IE9. Для этого в разделе <head> напишем строчку:
<head>
...
<meta http-equiv="X-UA-Compatible" content="IE=9" />
...
</head>
Идем дальше. Поскольку JS-функция fireEvent может получать в качестве параметра только данные, относящиеся к сообщению, организуем передачу данных через невидимые на странице HTML-контейнеры <DIV>.
<div id="ExtCommand" style="display:none">extcommand</div>
<div id="EventName" style="display:none">js_event</div>
<div id="BufferData" style="display:none">js_result</div>
Можно обойтись и одним <DIV>, в нашем примере их несколько для наглядности. Содержимое DIV-контейнера (точнее, свойство innerHTML) имеет строковый тип.
ExtCommand - сюда будем передавать код вызываемой JS-функции.
EventName - здесь будет имя действия, которое нужно выполнить в 1С
BufferData - для передачи параметров или любых других строковых данных
Также нам понадобится невидимая кнопка для вызова JS-функций:
<input type=button style="display:none" id="SendEvent" = "ExecCommand ()" />
И JS-функция ExecCommand (), которая будет выполнять любой JS-код, передаваемый из 1С.
function ExecCommand ()
{
code = document.getElementById ("ExtCommand").innerHTML;
result = "" + eval (code);
document.getElementById ("BufferData").innerHTML = result;
}
Вызов Javascript из 1С:
&НаКлиенте Процедура КомандаJS(Команда) // формуруем текст команды JS лКомандаJS = СкриптПоШаблону("SumJS (%1, %2)", ФрмЧ (Число1), ФрмЧ (Число2)); // записываем команду JS в контейнер div Элементы.НТМЛ.Документ.getElementById ("ExtCommand").innerHTML = лКомандаJS; // Посылаем сообщение невидимой кнопке, чтобы выполнить команду JS лКоманда = Элементы.НТМЛ.Документ.getElementById ("SendEvent"); лРезЕ = лКоманда.fireEvent ("onclick"); // получаем результат из контейнера DIV лРез = Элементы.НТМЛ.Документ.getElementById ("BufferData").innerHTML; Сумма = Число (лРез); КонецПроцедуры
Вызов 1С из Javascript:
Разместим на HTML-странице такие элементы:
<body>
...
Число 1:<input type=text id="Val1" value="4" /><br />
Число 2:<input type=text id="Val2" value="5" /><br />
Сумма :<input type=text id="Summa" value="0" /><br />
<input type=button id="Button1" value="Сумма" ()" /><br />
...
</body>
Их назначение понятно из названий.
Далее функция ExtSum, которая вызывает обработчик ПриНажатии у ПолеHTMLДокумента в 1С:
function ExtSum ()
{
// параметры вызова - имя действия
document.getElementById ("EventName").innerHTML = 'CalcSum';
// параметры действия строкой через точку с запятой
document.getElementById ("BufferData").innerHTML = Val1.value+";"+Val2.value;
var evt = document.createEventObject();
// вызывает обработчик "НТМЛПриНажатии" в 1С
document.body.fireEvent('onclick', evt);
document.getElementById ("Summa").value = document.getElementById ("BufferData").innerHTML;
}
Ну, и обработчик ПриНажатии в 1С:
&НаКлиенте Процедура НТМЛПриНажатии(Элемент, ДанныеСобытия, СтандартнаяОбработка) // получаем имя нашего события из контейнера DIV лИмяСобытия = Элементы.НТМЛ.Документ.getElementById ("EventName").innerHTML; // очищаем содержимое контейнера DIV Элементы.НТМЛ.Документ.getElementById ("EventName").innerHTML = ""; Если лИмяСобытия = "CalcSum" Тогда // получаем параметры из контейнера DIV в виде строки через точку с запятой лПараметры = Элементы.НТМЛ.Документ.getElementById ("BufferData").innerHTML; лПараметры = СтрЗаменить(лПараметры, ";", Символы.ПС); лЧисло1 = Число (СтрПолучитьСтроку(лПараметры, 1)); лЧисло2 = Число (СтрПолучитьСтроку(лПараметры, 2)); лСумма = лЧисло1+лЧисло2; лРез = ФрмЧ(лСумма); // помещаем результат в DIV Элементы.НТМЛ.Документ.getElementById ("BufferData").innerHTML = лРез; // здесь происходит возврат в JS Иначе // обработка других событий КонецЕсли; КонецПроцедуры
Этот пример тестировался и работает на платформе 1С 8.3.5.1517, на платформе 8.3.5.1383 выдавалась ошибка, похоже, платформенный баг.