Модификации для Tilda
Потоки

Иконки даты события и времени чтения в CMS-потоке Tilda

Подходит для настраиваемых CMS-потоков Tilda, в которых подробная страница поста сделана в Zero Block.

Что делает код

  • Берёт дату из отдельного поля CMS, а не дату публикации.
  • Добавляет перед ней иконку календаря.
  • Считает слова только в тексте статьи: без заголовка, даты и фотографий.
  • Делит количество слов на 140 слов в минуту, округляет результат и выводит `1 минута`, `2 минуты` или `5 минут` с иконкой часов.
  • Срабатывает только на страницах, где есть нужные CMS-поля, поэтому не влияет на обычные страницы сайта.
  • На телефоне строка остаётся компактной и помещается в шаблоне шириной от 320 px.

Что должно быть в потоке

В настройках полей у даты события задай имя переменной `event_date`. Для текстового поля статьи используй `article`.

В шаблоне подробной страницы оба поля должны быть выведены в Zero Block и связаны с полями потока: дата — с `event_date`, текст статьи — с `article`.

Куда вставлять

Добавь на страницу-шаблон подробного поста HTML-блок T123 и помести его внизу страницы. Сохрани и опубликуй страницу-шаблон. Код не нужно вставлять в каждую карточку поста отдельно.
<style>
.nlm-event-meta-date .tn-atom {
  display: inline-flex !important;
  align-items: center;
  white-space: nowrap;
}

.nlm-event-meta-date .tn-atom::before,
.nlm-event-meta-time::before {
  content: "";
  flex: 0 0 16px;
  width: 16px;
  height: 16px;
  margin-right: 7px;
  background-color: currentColor;
  -webkit-mask-repeat: no-repeat;
  -webkit-mask-position: center;
  -webkit-mask-size: contain;
  mask-repeat: no-repeat;
  mask-position: center;
  mask-size: contain;
}

.nlm-event-meta-date .tn-atom::before {
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3' y='4.5' width='18' height='16.5' rx='2'/%3E%3Cpath d='M8 2.5v4M16 2.5v4M3 10h18'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3' y='4.5' width='18' height='16.5' rx='2'/%3E%3Cpath d='M8 2.5v4M16 2.5v4M3 10h18'/%3E%3C/svg%3E");
}

.nlm-event-meta-time {
  display: inline-flex;
  align-items: center;
  margin-left: 18px;
}

.nlm-event-meta-time::before {
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='9'/%3E%3Cpath d='M12 7v5l3.5 2'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='9'/%3E%3Cpath d='M12 7v5l3.5 2'/%3E%3C/svg%3E");
}

@media screen and (max-width: 359px) {
  .nlm-event-meta-date .tn-atom {
    font-size: 13px;
  }

  .nlm-event-meta-time {
    margin-left: 14px;
  }
}
</style>

<script>
(function () {
  var WORDS_PER_MINUTE = 140;

  function minuteWord(number) {
    var lastTwo = number % 100;
    var last = number % 10;

    if (lastTwo >= 11 && lastTwo <= 14) return "минут";
    if (last === 1) return "минута";
    if (last >= 2 && last <= 4) return "минуты";
    return "минут";
  }

  function addEventMeta() {
    var dateField = document.querySelector('[data-fe-post-field="event_date"]');
    var articleField = document.querySelector('[data-fe-post-field="article"]');

    if (!dateField || !articleField) return false;

    var dateAtom = dateField.querySelector(".tn-atom");
    if (!dateAtom || dateAtom.querySelector(".nlm-event-meta-time")) return true;

    var textBlocks = articleField.querySelectorAll(".t-redactor__text");
    var articleText = textBlocks.length
      ? Array.prototype.map.call(textBlocks, function (block) {
          return block.innerText;
        }).join(" ")
      : articleField.innerText;

    var words = articleText.match(/[\p{L}\p{N}]+(?:[-'’][\p{L}\p{N}]+)*/gu) || [];
    if (!words.length) return false;

    var minutes = Math.max(1, Math.round(words.length / WORDS_PER_MINUTE));
    var time = document.createElement("span");

    dateField.classList.add("nlm-event-meta-date");
    time.className = "nlm-event-meta-time";
    time.textContent = minutes + " " + minuteWord(minutes);
    time.setAttribute("aria-label", "Время чтения: " + time.textContent);

    dateAtom.appendChild(time);
    return true;
  }

  function init() {
    if (addEventMeta()) return;

    var observer = new MutationObserver(function () {
      if (addEventMeta()) observer.disconnect();
    });

    observer.observe(document.body, {
      childList: true,
      subtree: true
    });

    setTimeout(function () {
      observer.disconnect();
    }, 15000);
  }

  if (document.readyState === "loading") {
    document.addEventListener("DOMContentLoaded", init);
  } else {
    init();
  }
})();
</script>

Если в другом потоке другие имена полей

Код не привязан к названию самого потока, но ему важны имена переменных. Если в другом CMS-потоке дата называется, например, `date_event`, а текст — `text`, замени в двух строках `event_date` и `article` на свои значения.

Скорость чтения меняется в строке `var WORDS_PER_MINUTE = 140;`. Для спокойного чтения оставь 140, для более быстрого можно поставить 160–180.