При обновлении платформы 1С:Предприятие до версий 8.3.14, 8.3.18 и выше многие разработчики сталкиваются с тем, что привычный код для взаимодействия с Полем HTML-документа перестает работать. Чаще всего это проявляется в виде ошибки «Значение не является значением объектного типа (Closed)» или аналогичной ошибки для метода (Eval). В этой статье мы подробно разберем, почему это происходит и как адаптировать ваш код под новые реалии платформы.
Разберем первопричину. В старых версиях платформы 1С для отображения HTML-контента использовался движок Internet Explorer (Trident). Взаимодействие с ним строилось через COM-объекты, где свойство parentWindow было стандартным способом доступа к глобальному объекту окна из объекта документа. Однако в современных версиях платформы произошел переход на движки WebKit и Chromium (в зависимости от режима работы), а также изменились механизмы маршалинга данных между 1С и браузерным компонентом.
Проанализируем ситуацию: когда вы обращаетесь к Элементы.ОписаниеHTML.Документ.parentWindow, новая платформа возвращает Неопределено, так как свойство parentWindow является специфичным для Microsoft и более не поддерживается. Соответственно, любая попытка проверить свойство .Closed или вызвать метод .Eval() у значения Неопределено приводит к аварийному завершению процедуры.
Первое и самое важное изменение, которое нам необходимо внести в код — это замена обращения к окну. В соответствии с современными стандартами DOM (Document Object Model), для получения доступа к объекту окна через документ следует использовать свойство defaultView.
Рассмотрим пример исправления условия проверки состояния окна. Вместо старого варианта:
// Устаревший способ
Если Не Элементы.ОписаниеHTML.Документ.parentWindow.Closed Тогда
// Ваш код
КонецЕсли;
Мы должны использовать следующий синтаксис:
// Современный способ
Если Элементы.ОписаниеHTML.Документ.defaultView <> Неопределено
И Не Элементы.ОписаниеHTML.Документ.defaultView.Closed Тогда
// Ваш код
КонецЕсли;
Обратите внимание, что мы добавили проверку на Неопределено. Это критически важно для обеспечения стабильности работы формы, так как в момент инициализации документа объект defaultView может быть еще не доступен.
Второй важный аспект касается выполнения произвольного JavaScript-кода. В среде Internet Explorer метод часто назывался Eval (с заглавной буквы). Однако в стандартном JavaScript метод пишется как eval (строчными буквами). Новая платформа 1С стала крайне чувствительна к регистру имен методов при обращении к объектам HTML-документа.
Выясним причину ошибки в Сообщении 5 из обсуждения. Код Body.Документ.parentWindow.Eval(...) падал, потому что parentWindow не существует, а Eval не является методом объекта. Исправленный вариант должен использовать defaultView.eval или, что еще лучше, прямой вызов необходимых функций редактора.
Если вы используете встроенные редакторы типа TinyMCE или CKEditor, то современная платформа позволяет обращаться к их программному интерфейсу (API) напрямую через объект окна, минуя медленный метод eval. Рассмотрим, как это реализовать на практике.
Для редактора TinyMCE:
Вместо того чтобы передавать строку кода в функцию интерпретации, мы можем обратиться к активному редактору напрямую:
// Получение контента из TinyMCE
Попытка
Окно = Элементы.ОписаниеHTML.Документ.defaultView;
ТекстСообщения = Окно.tinyMCE.activeEditor.getContent();
Исключение
ТекстСообщения = "";
Сообщить("Ошибка получения данных из редактора: " + ОписаниеОшибки());
КонецПопытки;
Для редактора CKEditor:
Аналогично поступим и с CKEditor. Проанализируем пример записи данных в редактор, который был предложен в Сообщении 4 форума. Здесь важно правильно передать параметры в функцию setData.
// Установка контента в CKEditor
Процедура УстановитьТекстВРедактор(ЭлементФормыHTML, ИсходныйТекст)
Документ = ЭлементФормыHTML.Документ;
Окно = Документ.defaultView;
// Очищаем текст от символов переноса строк, чтобы не сломать JS-строку
ОчищенныйТекст = СтрЗаменить(ИсходныйТекст, Символы.ПС, " ");
// Прямой вызов метода API редактора
Окно.CKEDITOR.instances.editor1.setData(ОчищенныйТекст);
КонецПроцедуры
Одной из часто встречающихся проблем является передача многострочного текста из 1С в JavaScript-функцию. Если в переменной html содержатся символы переноса строки (Символы.ПС), то при попытке выполнить код JavaScript возникнет синтаксическая ошибка, так как строковая константа в JS не может просто так разрываться на несколько строк.
Разберем, как правильно подготовить строку:
СтрЗаменить(Текст, Символы.ПС, " ") для удаления переносов.<br> или на экранированный символ \n.Подводя итог, проанализируем шаги, которые необходимо выполнить для восстановления работоспособности ваших обработок и форм:
parentWindow и замените его на defaultView.eval вместо Eval, getContent вместо GetContent).defaultView.eval в пользу прямого обращения к методам JS-объектов через точку. Это не только надежнее, но и упрощает отладку кода.Соблюдение этих правил позволит вашим решениям стабильно работать на любой современной версии платформы 1С:Предприятие 8.3, независимо от используемого движка отображения контента.