При разработке интерфейсов на управляемых формах 1С программисты часто сталкиваются с неприятным визуальным эффектом: при динамическом обновлении какого-либо элемента (например, часов в шапке формы) страница самопроизвольно прокручивается (скроллится) в самое начало. Если обновление происходит каждую секунду, работать с формой становится невозможно — любой скролл вниз тут же сбрасывается вверх.
В этой статье мы подробно разберем причины такого поведения платформы 1С:Предприятие 8.3 и рассмотрим несколько эффективных способов решения проблемы, начиная от простых настроек свойств элементов и заканчивая использованием HTML-контейнеров.
Проанализируем ситуацию: когда выполняется обработчик ожидания, подключенный через ПодключитьОбработчикОжидания, и в нем происходит изменение текста декорации (надписи) или заголовка элемента, движок управляемых форм инициирует так называемый Reflow (пересчет геометрии). Платформа пытается заново вычислить размеры всех групп и элементов, чтобы корректно отобразить обновленные данные.
Если форма имеет сложную структуру, содержит группы с автоматическим распределением высоты или элементы, у которых установлено свойство «Растягивать по вертикали», система может «потерять» текущую позицию прокрутки. В результате фокус или видимая область принудительно возвращаются к активному элементу или в начало формы. Ситуация усугубляется, если обновление данных провоцирует неявный серверный вызов, что заставляет форму полностью обновить свое состояние.
Как показывает практика и обсуждение в теме, использование элемента вида Декорация — Надпись для часто обновляемых данных — не самое удачное решение. Вместо этого рассмотрим использование обычного Поля ввода, связанного с реквизитом формы типа Строка или Дата.
Чтобы поле ввода визуально не отличалось от обычной надписи и не мешало пользователю, выполним следующие настройки в конфигураторе:
Поле ввода.Истина. Это позволит тексту оставаться черным (в отличие от свойства Доступность = Ложь, которое делает текст серым).Нет.Цвет фона формы или оставим Авто.Истина, чтобы пользователь не попадал в это поле при нажатии клавиши Tab.Разберем пример кода для обновления такого поля:
&НаКлиенте
Процедура ПриОткрытии(Отказ)
// Подключаем обработчик с интервалом в 1 секунду
ПодключитьОбработчикОжидания("ОбновитьОтображениеВремени", 1, Ложь);
КонецПроцедуры
&НаКлиенте
Процедура ОбновитьОтображениеВремени() Экспорт
// Прямое присваивание значения реквизиту формы, связанному с полем ввода
ТекущееВремяНаФорме = Формат(ТекущаяДата(), "ДЛФ=Т");
КонецПроцедуры
Важный момент: при таком подходе изменение значения реквизита формы обычно не вызывает полного пересчета интерфейса, и форма перестает «дергаться».
Если первый способ не помогает (например, из-за специфической верстки формы), воспользуемся самым надежным методом — интеграцией HTML. Суть метода заключается в том, что мы создаем на форме поле HTML-документа, которое работает внутри своего изолированного контейнера. Изменения внутри этого контейнера никак не влияют на геометрию основной управляемой формы 1С.
Рассмотрим по шагам, как это реализовать:
1. Создадим на форме реквизит с типом Строка (например, СодержимоеHTML) и вытащим его на форму как Поле HTML-документа.
2. При создании формы на сервере или при открытии заполним этот реквизит специальным кодом, который содержит JavaScript-таймер. Это критически важно: таймер будет работать внутри браузера, не обращаясь к серверу 1С и даже не дергая основной поток клиентского приложения 1С.
Проанализируем пример формирования такого HTML-текста:
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
СодержимоеHTML =
"<html>
|<body style='margin:0; padding:0; overflow:hidden; background-color: transparent;'>
| <div id='clock' style='font-family: Arial; font-size: 14px; color: #333;'></div>
| <script>
| function updateClock() {
| var now = new Date();
| var time = now.getHours() + ':' +
| ('0' + now.getMinutes()).slice(-2) + ':' +
| ('0' + now.getSeconds()).slice(-2);
| document.getElementById('clock').innerHTML = time;
| }
| setInterval(updateClock, 1000);
| updateClock();
| </script>
|</body>
|</html>";
КонецПроцедуры
Этот метод полностью исключает влияние обновления времени на скролл формы, так как платформа 1С вообще не участвует в процессе ежесекундного обновления текста. Вы просто загружаете страницу один раз, и она живет своей жизнью.
Если вы все же хотите использовать стандартные средства 1С, проанализируем настройки размещения элементов. Часто «прыжки» связаны с тем, что система не может зафиксировать высоту элементов.
Попробуем следующие шаги:
0 (Авто).Ложь.В некоторых сообщениях на форумах встречается совет запускать обновление времени через Фоновое задание. Разберем, почему это плохая идея. Каждое фоновое задание — это отдельный сеанс на сервере 1С. Запуск нового сеанса каждую секунду создаст колоссальную нагрузку на кластер серверов и сетевой трафик. Это приведет не к решению проблемы скролла, а к тотальному зависанию интерфейса у всех пользователей информационной базы. Фоновые задания предназначены для длительных расчетов, а не для обновления интерфейсных мелочей.
Для решения проблемы «прыгающей» формы мы рекомендуем придерживаться следующего алгоритма:
Поле ввода с включенным флагом Только просмотр и отключенной рамкой. Это решает проблему в 90% случаев.Поле HTML-документа с локальным JavaScript кодом. Это самый технологичный способ, который экономит ресурсы сервера и гарантирует стабильность интерфейса.Заголовок у элементов формы в обработчиках ожидания, так как это наиболее частая причина принудительной перерисовки всей формы. Если нужно менять текст, меняйте значение Данных (реквизита), связанных с элементом.Рассмотренные подходы позволят вам создавать динамичные и удобные интерфейсы, не раздражая пользователей внезапными скачками экрана.