При разработке интерфейсов на управляемых формах 1С часто возникает необходимость использовать Поле HTML-документа для отображения логов, чатов или детальной информации. Одной из типичных задач является автоматическая прокрутка содержимого в самый низ при добавлении новых данных. Однако разработчики часто сталкиваются с тем, что стандартные JavaScript-решения, успешно работавшие в старых релизах платформы (до 8.3.14), перестают функционировать корректно. Рассмотрим подробнее, почему это происходит и как решить проблему современными средствами платформы.
Начиная с версии платформы 8.3.14, компания 1С перешла с использования движка Internet Explorer (MSHTML) на Chromium (CEF — Chromium Embedded Framework) для рендеринга HTML-контента в управляемых формах. Это привело к изменению поведения объектной модели документа (DOM). Основные причины, по которым старые скрипты перестали работать, заключаются в следующем:
onload может срабатывать до того, как платформа полностью рассчитает геометрические размеры элементов (высоту блоков). В этот момент scrollHeight возвращает 0, и прокрутка не происходит.document.body, а document.documentElement (тег html).Выясним, как обойти эти ограничения, используя комбинированный подход: управление из кода 1С и оптимизированный JavaScript.
Наиболее стабильным решением, как показала практика обсуждения, является использование метода ПодключитьОбработчикОжидания. Это позволяет дать платформе и движку Chromium необходимое время (десятые доли секунды) для завершения формирования DOM-дерева. Разберем по шагам реализацию этого метода.
Сначала создадим процедуру, которая будет отвечать за установку текста и запуск таймера:
&НаКлиенте
Процедура ОбновитьЛог(ТекстHTML)
// Устанавливаем содержимое поля
Объект.ТекстHTMLПоля = ТекстHTML;
// Даем небольшую паузу для рендеринга (0.1 - 0.2 секунды)
ПодключитьОбработчикОжидания("ВыполнитьПрокруткуВниз", 0.1, Истина);
КонецПроцедуры
Затем опишем саму процедуру прокрутки, которая обращается к объектной модели документа непосредственно из встроенного языка 1С:
&НаКлиенте
Процедура ВыполнитьПрокруткуВниз()
Попытка
ДокументHTML = Элементы.ПолеHTMLДокумента.Документ;
Если ДокументHTML <> Неопределено Тогда
// Устанавливаем scrollTop в значение высоты всей страницы
// Добавление большого числа (например, +9999) гарантирует скролл до самого низа
ДокументHTML.body.scrollTop = ДокументHTML.body.scrollHeight + 9999;
КонецЕсли;
Исключение
// В веб-клиенте доступ к Документ может появиться не сразу
ПодключитьОбработчикОжидания("ВыполнитьПрокруткуВниз", 0.1, Истина);
КонецПопытки;
КонецПроцедуры
Если вы предпочитаете управлять логикой внутри самого HTML-документа, проанализируем ситуацию с выбором правильных свойств прокрутки. Современные браузеры лучше реагируют на использование метода window.scrollTo или работу с document.documentElement.
Рассмотрим пример кода, который можно вставить в конец вашего HTML-документа перед закрывающим тегом </body>:
<script>
function scrollBottom() {
// Используем универсальный метод определения элемента прокрутки
var scrollingElement = document.scrollingElement || document.documentElement;
scrollingElement.scrollTop = scrollingElement.scrollHeight;
}
// Вызываем функцию через небольшую задержку после загрузки
window.onload = function() {
setTimeout(scrollBottom, 50);
};
</script>
Важный нюанс: Использование setTimeout внутри JS часто выполняет ту же роль, что и обработчик ожидания в 1С, позволяя скрипту дождаться завершения расчетов высоты элементов движком Chromium.
Проанализируем еще один эффективный способ — использование метода scrollIntoView. Он избавляет нас от необходимости вручную вычислять scrollHeight. Суть метода заключается в создании невидимого "якоря" в самом конце документа и программной фокусировке на нем.
Добавьте в самый конец вашего HTML-текста пустой элемент:
<div id="end-of-page"></div>
Теперь функция прокрутки в 1С или JS будет выглядеть гораздо проще:
// Пример для вызова из кода 1С
Элементы.ПолеHTMLДокумента.Документ.getElementById("end-of-page").scrollIntoView(false);
Параметр false указывает браузеру, что элемент должен быть выровнен по нижней границе видимой области, что идеально подходит для нашей задачи.
Разберем ситуацию, когда решение работает в тонком клиенте, но дает сбои в браузере (веб-клиент). В веб-клиенте 1С поле HTML-документа оборачивается в iframe. Это накладывает дополнительные ограничения:
Элементы.Поле.Документ может быть ограничен политиками кросс-доменных запросов, если контент загружается не напрямую.Документ в веб-клиенте инициализируется медленнее. Как отмечено в сообщениях форума, иногда требуется 2-3 итерации опроса через обработчик ожидания, прежде чем объект станет доступен (не равен Неопределено).Для веб-клиента рекомендуется всегда использовать проверку на существование объекта Документ и его свойства body перед попыткой чтения высоты или установки позиции скролла.
В новых релизах платформы (8.3.14+) событие onscroll, назначенное на тег body, также может не срабатывать. Это связано с тем, что фактическая прокрутка происходит на уровне html или контейнера с overflow: auto. Чтобы восстановить отслеживание прокрутки, попробуйте назначать обработчик на уровень window:
window.addEventListener('scroll', function() {
// Ваш код обработки скролла
console.log("Текущая позиция: " + window.pageYOffset);
}, true);
Использование третьего параметра true (перехват события) позволяет ловить события прокрутки, даже если они не "всплывают" стандартным образом.
Резюмируя: Для стабильной работы автопрокрутки в современных версиях 1С используйте связку из ПодключитьОбработчикОжидания на стороне 1С и метода scrollIntoView или установки scrollTop со значительным запасом (+9999) на стороне клиента. Это обеспечит корректное поведение интерфейса независимо от скорости рендеринга страницы движком Chromium.