Как получить и восстановить позицию прокрутки в Поле HTML документа 1С?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При работе с ПолеHTMLДокумента в среде 1С программисты часто сталкиваются с неприятной особенностью: стандартные методы получения позиции скролла, такие как window.scrollY или document.body.scrollTop, упорно возвращают «0», даже если страница прокручена далеко вниз. Это происходит из-за того, что движок браузера внутри 1С интерпретирует документ как единое полотно, а прокрутку осуществляет сам контейнер платформы, «не сообщая» об этом внутреннему JavaScript-контексту.

В этой статье мы подробно разберем, как обойти это ограничение, заставить 1С правильно считывать координаты прокрутки и восстанавливать их после обновления данных или переоткрытия формы.

Почему стандартные методы JavaScript не работают в 1С?

Разберем ситуацию: мы пытаемся вызвать window.scrollY в обработчике события, но получаем пустое значение. Проанализируем причину. В зависимости от версии платформы и режима приложения (тонкий, толстый или веб-клиент), 1С использует разные движки рендеринга (Internet Explorer/Trident или WebKit/Chromium). В большинстве случаев встроенное поле ведет себя так, будто высота контента неограничена, и полосы прокрутки рисует сама форма 1С, а не окно браузера.

Проверим это экспериментально: если мы подписываемся на событие onscroll окна, оно просто не вызывается. Чтобы решить эту проблему, нам нужно изменить структуру HTML-документа так, чтобы прокрутка происходила внутри контролируемого нами элемента.

Решение: Использование контейнера «Scroller»

Самый надежный способ — это обернуть все содержимое тега body в отдельный блок div, который будет имитировать окно просмотра. Мы зададим ему высоту 100% и разрешим внутреннюю прокрутку средствами CSS. Рассмотрим, как должен выглядеть наш HTML-код.


<html>
<head>
<style>
    html, body {
        height: 100%;
        margin: 0;
        padding: 0;
        overflow: hidden; /* Отключаем скролл самого body */
    }
    #scroller {
        height: 100%;
        overflow-y: auto; /* Включаем вертикальный скролл для дива */
        width: 100%;
    }
</style>
</head>
<body>
    <div id="scroller">
        <!-- Здесь размещается весь ваш контент -->
        <p>Много текста для появления прокрутки...</p>
    </div>
</body>
</html>

Теперь, когда прокрутка происходит внутри элемента с id="scroller", мы можем легко получить его позицию через свойство scrollTop. Рассмотрим пример кода на стороне 1С, который считывает это значение.

Получение позиции прокрутки из 1С

Для того чтобы получить данные из ПолеHTMLДокумента, мы обращаемся к объектной модели документа (DOM). Выясним, как это реализовать в коде модуля формы:


& Процедура СохранитьПозициюПрокрутки()
    ДокументHTML = Элементы.ПолеПросмотра.Документ;
    ЭлементСкролла = ДокументHTML.getElementById("scroller");
    
    Если ЭлементСкролла <> Неопределено Тогда
        ПозицияY = ЭлементСкролла.scrollTop;
        Сообщить("Текущая позиция: " + ПозицияY);
        // Сохраняем это значение в реквизит формы или переменную
        ПоследняяПозицияСкролла = ПозицияY;
    КонецЕсли;
КонецПроцедуры

Важный момент: если вы используете современный движок (WebKit), обращение напрямую через Элементы.Поле.Документ может работать медленно или требовать асинхронного вызова через ВыполнитьJavaScript(). В этом случае лучше передавать значение из JS в 1С через механизм оповещений.

Восстановление позиции после обновления

Когда данные в 1С обновились и HTML-текст был переформирован, нам нужно вернуть пользователя в ту же точку, где он находился. Проанализируем последовательность действий:

  1. Перед обновлением текста HTML считываем scrollTop нашего контейнера.
  2. Обновляем текст в ПолеHTMLДокумента.
  3. После завершения загрузки (событие ДокументСформирован) устанавливаем scrollTop обратно.

Посмотрим на пример установки позиции:


& Процедура ВосстановитьПозициюПрокрутки()
    ДокументHTML = Элементы.ПолеПросмотра.Документ;
    ЭлементСкролла = ДокументHTML.getElementById("scroller");
    
    Если ЭлементСкролла <> Неопределено Тогда
        // Устанавливаем сохраненное ранее значение
        ЭлементСкролла.scrollTop = ПоследняяПозицияСкролла;
    КонецЕсли;
КонецПроцедуры

Альтернативный метод: scrollIntoView

Рассмотрим ситуацию, когда нам не нужно знать точные координаты в пикселях, а достаточно вернуться к определенному элементу (например, к последней просмотренной строке отчета). В этом случае удобно использовать встроенный метод JavaScript scrollIntoView().

При генерации HTML-кода добавьте уникальный id или временный класс к нужному элементу. Затем вызовите скрипт:


ТекстСкрипта = "document.getElementById('target_element').scrollIntoView({behavior: 'smooth', block: 'start'});";
Элементы.ПолеПросмотра.ВыполнитьJavaScript(ТекстСкрипта);

Этот метод более гибок, так как он автоматически учитывает размеры окна и положение элемента, избавляя нас от вычисления точных пикселей.

Инструменты отладки

Если код не работает так, как ожидалось, проанализируем состояние документа через встроенный отладчик. В платформе 1С (начиная с определенных релизов 8.3) можно вызвать консоль разработчика прямо в режиме предприятия. Для этого используйте комбинацию клавиш Ctrl + Shift + Alt + F12.

В открывшейся консоли вы можете интерактивно проверить свойства объектов:

Итоги и рекомендации

Подведем итог нашему исследованию. Для стабильной работы с прокруткой в 1С необходимо соблюдать следующие правила:

  1. Всегда используйте контейнер: Не полагайтесь на скролл body или window. Создавайте корневой div с overflow: auto.
  2. Следите за DOCTYPE: Наличие строки <!DOCTYPE html> в начале документа переводит браузер в стандартный режим, что критично для правильного вычисления высот в IE-движке.
  3. Отключайте системные полосы: В свойствах элемента формы 1С Поле HTML документа установите параметр Полосы прокрутки в значение Нет, чтобы избежать эффекта «двойного скролла».

Следуя этим шагам, мы обеспечим комфортную работу пользователя с динамическим контентом в 1С, сохраняя контекст его работы даже при частом обновлении данных.

← На главную