При разработке интерфейсов на управляемых формах часто возникает необходимость добавить динамические элементы, которые сложно или неэффективно реализовывать стандартными средствами платформы. Одним из таких элементов является таймер обратного отсчета. Использование Поля HTML документа кажется логичным решением, однако разработчики часто сталкиваются с тем, что код, идеально работающий в обычном браузере, выдает ошибку NaN (Not a Number) внутри клиента 1С. В этой статье мы подробно разберем причины этой проблемы и рассмотрим несколько способов реализации надежного таймера.
Проанализируем ситуацию, описанную пользователем. В коде JavaScript расчет времени завязан на объект Date. Основная причина некорректной работы в 1С (особенно в версиях ниже 8.3.14) заключается в том, что платформа использует движок Internet Explorer (MSHTML) для рендеринга HTML-содержимого. Рассмотрим ключевые ошибки в исходном коде, которые «прощает» современный Chrome, но не принимает старый движок IE:
new Date('2021-03-01T11:00:00') с использованием разделителя «T» часто не распознается старыми версиями движка MSHTML. Это приводит к тому, что объект даты не создается, и любые математические операции с ним возвращают NaN..getTime(), а не .getTime. Старые движки не интерпретируют обращение к методу как вызов функции без явного указания оператора вызова.setInterval требует четкого соблюдения синтаксиса, иначе выполнение скрипта прервется еще на этапе инициализации.Для того чтобы таймер корректно заработал в любой версии платформы, нам необходимо адаптировать код под стандарты старых браузеров. Рассмотрим исправленный вариант скрипта, который будет стабильно работать в поле HTML документа. Разберем по шагам, как правильно подготовить строку HTML.
// Формируем текст HTML-документа
ТекстHTML =
"<html>
|<head>
|<style>
| body { font-family: sans-serif; text-align: center; margin: 0; padding: 10px; overflow: hidden; }
| #demo { font-weight: bold; color: #ff0000; }
|</style>
|</head>
|<body>
| <div id='demo'>Загрузка...</div>
| <script>
| // Используем формат даты, понятный для IE: YYYY/MM/DD HH:mm:ss
| var countDownDate = new Date('2025/12/31 23:59:59').getTime();
|
| var x = setInterval(function() {
| var now = new Date().getTime();
| var distance = countDownDate - now;
|
| var days = Math.floor(distance / (1000 * 60 * 60 * 24));
| var hours = Math.floor((distance % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
| var minutes = Math.floor((distance % (1000 * 60 * 60)) / (1000 * 60));
| var seconds = Math.floor((distance % (1000 * 60)) / 1000);
|
| var output = 'Осталось времени: ';
| if (days > 0) output += days + 'д ';
| output += hours + 'ч ' + minutes + 'м ' + seconds + 'с ';
|
| document.getElementById('demo').innerHTML = output;
|
| if (distance < 0) {
| clearInterval(x);
| document.getElementById('demo').innerHTML = 'Время истекло';
| }
| }, 1000);
| </script>
|</body>
|</html>";
В этом примере мы заменили дефисы в дате на слэши и добавили вызовы функций getTime(). Также мы обернули код в полноценную структуру HTML с тегами head и body, что критически важно для корректного парсинга документа внутри 1С.
Начиная с версии платформы 8.3.14, у разработчиков появилась возможность выбирать движок отображения HTML. Если ваша конфигурация работает на актуальных версиях платформы, мы рекомендуем переключить режим использования HTML-документа на WebKit. Это позволит использовать современные возможности JavaScript (ES6+), CSS Grid и Flexbox без оглядки на ограничения Internet Explorer.
Для активации WebKit выполните следующие действия:
Поле HTML документа.WebKit (в некоторых версиях — Хромиум).После этого ваш первоначальный код (с исправлением синтаксических ошибок) заработает без проблем, так как 1С будет использовать современный движок рендеринга.
Рассмотрим альтернативную ситуацию: что если нам нужно не только показывать время, но и выполнять действия в самой 1С (например, закрыть форму или обновить данные в БД), когда таймер дойдет до нуля? В этом случае полагаться только на JavaScript внутри HTML-поля рискованно. Выясним, как реализовать это через встроенный механизм ПодключитьОбработчикОжидания.
Этот подход заключается в том, что расчет времени ведется в коде 1С, а HTML-поле используется только как «красивая оболочка» для вывода текста. Разберем реализацию:
&НаКлиенте
Перем КонечнаяДата;
&НаКлиенте
Процедура ПриОткрытии(Отказ)
КонечнаяДата = ТекущаяДата() + 3600; // Таймер на 1 час
ПодключитьОбработчикОжидания("ОбновитьТаймерНаФорме", 1);
КонецПроцедуры
&НаКлиенте
Процедура ОбновитьТаймерНаФорме() Экспорт
ТекущийОстаток = КонечнаяДата - ТекущаяДата();
Если ТекущийОстаток <= 0 Тогда
ОтключитьОбработчикОжидания("ОбновитьТаймерНаФорме");
ТекстТаймера = "Время вышло!";
Иначе
// Форматируем время программно
Часов = Цел(ТекущийОстаток / 3600);
Минут = Цел((ТекущийОстаток % 3600) / 60);
Секунд = ТекущийОстаток % 60;
ТекстТаймера = СтрШаблон("Осталось: %1ч %2м %3с", Часов, Минут, Секунд);
КонецЕсли;
// Обновляем HTML-поле
ТекстHTML = "<html><body style='margin:0; font-family:Arial;'><h1>" + ТекстТаймера + "</h1></body></html>";
Элементы.ПолеHTMLТаймер.УстановитьТекст(ТекстHTML);
КонецПроцедуры
Преимущества этого метода:
Если вы все же решили использовать чистый JavaScript внутри HTML, проанализируем, как передать сигнал из таймера обратно в 1С. В современных версиях (при использовании WebKit) доступен механизм window.external. Вы можете вызвать процедуру 1С прямо из JS-кода:
// В JavaScript внутри HTML
if (distance < 0) {
window.external.Notification1C("TimerFinished", "Время истекло!");
}
В самой форме 1С для этого должен быть настроен обработчик события ПриНажатии или специализированный метод для перехвата событий HTML-документа. Это позволяет строить сложные интерактивные интерфейсы, где визуальная часть на HTML бесшовно интегрирована с логикой 1С:Предприятия.
Подводя итог, можно сказать, что ошибка NaN — это чаще всего признак несовместимости формата даты или синтаксиса JavaScript с движком Internet Explorer. Исправление формата на YYYY/MM/DD и использование метода УстановитьТекст() в сочетании с обработчиком ожидания 1С являются наиболее надежными способами реализации таймера в современных решениях.