Перейти к содержанию

Счётчик обратного отсчёта в «Списке новостей» Битрикса

Инструкция
Как вывести ближайшее мероприятие компонентом «Список новостей» и повесить на него таймер обратного отсчёта, взяв дату из свойства элемента. Дату отдаём в JS через data-атрибут, а сам счётчик пишем на чистом JavaScript без jQuery.

8 мин 44 Обновлено 22 июля Сложность: Средняя

TL;DR

  • Свойство «Дата/время» TIME_EVENT отмечаем в «Источнике данных», чтобы оно попало в DISPLAY_PROPERTIES.
  • Дату отдаём в JS как Unix-timestamp в миллисекундах через data-атрибут – не зависит от формата и локали.
  • Таймер пишем на чистом JavaScript (const/let), без jQuery.countdown.
  • Каждый тик считает разницу от Date.now(), поэтому счётчик не «плывёт».
  • Русское склонение «день/дня/дней» выбирает функция plural по последней цифре.

Задача: вывести ближайшее событие компонентом «Список новостей» и показать под ним таймер «до старта осталось 3 дня 4 часа». Дату события берём из свойства элемента, а сам отсчёт – на чистом JavaScript, без внешней библиотеки. Раньше для этого подключали jQuery.countdown, но в 2026 году отдельная библиотека и сам jQuery ради одного таймера уже избыточны.

Шаг 1. Свойство и настройка компонента

В инфоблоке «Мероприятия» создаём свойство «Дата мероприятия» типа «Дата/время» с кодом TIME_EVENT – из него таймер возьмёт дедлайн. Дальше настраиваем компонент bitrix:news.list:

  • количество элементов на странице – 1 (нужно ближайшее событие);
  • сортировка – по дате начала активности или по свойству TIME_EVENT, чтобы «ближайшее» было первым;
  • в блоке «Источник данных» отмечаем свойство TIME_EVENT, иначе оно не попадёт в DISPLAY_PROPERTIES.

Шаг 2. Отдаём дату в HTML через data-атрибут

Копируем шаблон компонента в свой шаблон сайта. В нём переводим значение свойства в Unix-timestamp через MakeTimeStamp() и кладём его в data-атрибут блока таймера. Timestamp – самый надёжный способ передать момент времени в JavaScript: он не зависит от формата даты и локали.

<?php foreach ($arItem['DISPLAY_PROPERTIES'] as $pid => $arProperty): ?>
    <?php if ($pid === 'TIME_EVENT'): ?>
        <?php $eventTs = MakeTimeStamp($arProperty['VALUE']); ?>
        <div class="event__date">
            <?= FormatDate('d F Y в H:i', $eventTs) ?> <?php // читаемая дата для человека ?>
        </div>
        <!-- дедлайн для JS: timestamp в миллисекундах -->
        <div class="event__counter" data-deadline="<?= $eventTs * 1000 ?>"></div>
    <?php endif ?>
<?php endforeach ?>

Здесь MakeTimeStamp переводит строку из свойства в timestamp (секунды), а * 1000 даёт миллисекунды – именно в них работает Date в JavaScript. Заодно выводим человеку понятную дату через FormatDate('d F Y в H:i', ...).

Шаг 3. Таймер на чистом JavaScript

В отдельном JS-файле забираем дедлайн из data-атрибута и раз в секунду пересчитываем остаток. Никакого jQuery – только современный синтаксис (const/let, стрелочные функции):

const box = document.querySelector('.event__counter');

if (box) {
  const deadline = Number(box.dataset.deadline);

  // склонение: plural(5, ['день','дня','дней']) → 'дней'
  const plural = (n, forms) => {
    const idx = (n % 100 > 4 && n % 100 < 20)
      ? 2
      : [2, 0, 1, 1, 1, 2][Math.min(n % 10, 5)];
    return forms[idx];
  };

  const render = () => {
    const diff = deadline - Date.now();

    if (diff <= 0) {
      box.textContent = 'Событие началось';
      clearInterval(timer);
      return;
    }

    const totalSec = Math.floor(diff / 1000);
    const days = Math.floor(totalSec / 86400);
    const hours = Math.floor((totalSec % 86400) / 3600);
    const mins = Math.floor((totalSec % 3600) / 60);
    const secs = totalSec % 60;

    box.textContent =
      `${days} ${plural(days, ['день', 'дня', 'дней'])} ` +
      `${hours} ${plural(hours, ['час', 'часа', 'часов'])} ` +
      `${mins} ${plural(mins, ['минута', 'минуты', 'минут'])} ` +
      `${secs} ${plural(secs, ['секунда', 'секунды', 'секунд'])}`;
  };

  render();
  const timer = setInterval(render, 1000);
}

Почему именно так

  • Считаем от Date.now(), а не накапливаем. Каждый тик берёт свежую разницу «дедлайн − сейчас», поэтому таймер не «плывёт», даже если вкладка была свёрнута или браузер притормозил интервалы.
  • Останавливаемся на нуле. При diff <= 0 вызываем clearInterval, иначе счётчик уйдёт в отрицательные значения.
  • Склонение по русским правилам. Функция plural выбирает форму «день / дня / дней» по последней цифре и исключению для 11–14.

Подводные камни

  • Часовой пояс. Unix-timestamp не зависит от пояса, но MakeTimeStamp трактует строку свойства в поясе сайта. Если сервер и посетитель в разных поясах, договоритесь, что дедлайн задаётся во времени сайта, и не смешивайте это с локальным временем браузера.
  • Кэш компонента. Дата попадает в кэшируемый шаблон как timestamp – это правильно: кэшируется момент, а не «осталось столько-то». Сам отсчёт всегда живой, потому что считается на клиенте.
  • Свойство не выводится. Если DISPLAY_PROPERTIES пуст, значит свойство не отмечено в «Источнике данных» настроек компонента – проверьте настройки, это самая частая причина «пустого» таймера.
  • Одна дата – один блок. Скрипт написан под один .event__counter. Для нескольких таймеров на странице оберните логику в querySelectorAll(...).forEach(...), чтобы у каждого был свой дедлайн.

Тот же приём для баннера акции без инфоблока – в гайде «Скрипт отсчёта времени до конца акции». Про форматирование дат из свойств – «Сменить формат даты в CMS Битрикс» и «Формат Ydiff». Как вывести конкретное свойство элемента – «Как вывести определённое поле элемента инфоблока».

Частые вопросы

Как передать дату из свойства Битрикса в JavaScript-таймер?

Переведите значение свойства в Unix-timestamp через MakeTimeStamp, умножьте на 1000 и положите в data-атрибут блока. В JS заберите его через element.dataset и создайте счётчик – timestamp не зависит от формата даты и локали.

Нужен ли jQuery для счётчика обратного отсчёта?

Нет. В 2026 году таймер пишется на чистом JavaScript в несколько строк с setInterval и Date.now(). Отдельная библиотека вроде jQuery.countdown и сам jQuery ради одного счётчика избыточны.

Почему таймер показывает пустое значение?

Чаще всего свойство даты не отмечено в разделе «Источник данных» настроек компонента, поэтому оно не попадает в DISPLAY_PROPERTIES. Проверьте настройки news.list.

Как сделать правильное склонение «3 дня» / «5 дней»?

Используйте функцию plural, которая по последней цифре числа и исключению для 11–14 выбирает нужную форму из массива ['день','дня','дней'].

Почему счётчик уходит в минус после начала события?

Не остановлен интервал. Когда разница deadline − Date.now() становится

Материалы по теме

Что почитать дальше по этой теме

Инструкция Скрипт обратного отсчёта времени до конца акции Как поставить на сайт таймер обратного отсчёта до конца акции на чистом JavaScript, без библиотек. Разбираем надёжный разбор даты, счёт от текущего момента, склонение единиц и остановку по нулю. 7 мин 64 18 мая 2017 Инструкция Сменить формат даты в CMS «Битрикс» Как вывести поле «Начало активности» элемента инфоблока в формате «02 июня, 2016». Разбираем FormatDate с шаблоном «d F, Y», разбор строки через ParseDateTime и подводные камни с локалью и часовым поясом. 6 мин 50 18 мая 2017 Инструкция Как отформатировать дату в формате Ydiff (например, «2 года») Как вывести разницу между датой и сегодняшним днём словами – «2 года», «6 месяцев», «3 дня». Разбираем относительный формат FormatDate «Ydiff» в Битрикс, автоматическое склонение и как разбить результат на число и слово. 6 мин 54 18 июля 2019 Инструкция Как вывести определённое поле элемента инфоблока в Битриксе Как в шаблоне компонента 1С-Битрикс вывести одно конкретное поле элемента инфоблока – например счётчик показов SHOW_COUNTER. Разбираем массив FIELDS, служебные поля элемента и безопасный вывод значения. 6 мин 51 18 февраля 2017 Инструкция Вывод текущего года на PHP (копирайт в подвале) Как автоматически выводить в подвале сайта текущий год или интервал «2022–2026», чтобы копирайт не устаревал 1 января. Разбираем date('Y'), тернарный оператор, часовой пояс и вариант для 1С-Битрикс. 5 мин 69 22 сентября 2022