Адаптируем статью под время суток

Простая игрушка на JS.

Адаптируем статью под время суток

Есть такое медиа — «Кинжал», которое рассказывает про полезные навыки и подходы к жизни. Так сложилось, что наш главред Максим также работает и там. Он придумал такую мульку: чтобы статьи «Кинжала» напоминали всем, кто читает их после 10 вечера, что пора лечь спать. А если на улице уже утро, то и напоминать не нужно. 

Это мы и сделаем. 

Логика проекта

В конце каждой статьи «Кинжала» есть плашка с заключительной мыслью, в конце которой стоит картинка кинжала:

Адаптируем статью под время суток

Нам нужно, чтобы с 10 вечера и до 5 утра в каждую такую плашку перед кинжалом добавлялась фраза «А теперь ложитесь спать». Для этого сделаем так:

  1. Ждём, пока загрузится вся страница
  2. Находим в структуре HTML-документа эту плашку и получаем её содержимое.
  3. Смотрим на текущее время у пользователя.
  4. Если оно попадает в нужный нам диапазон — выполняем всё, что ниже, а если не попадает — ничего не делаем.
  5. Если на плашке есть картинка кинжала — добавляем текст перед ней.
  6. Если картинки кинжала нет — добавляем текст в самый конец плашки.

Готовим каркас

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

За это в JavaScript отвечает обработчик addEventListener с параметром
"DOMContentLoaded":

// ждём, пока страница полностью загрузится, потом алгоритм начинает работать
document.addEventListener("DOMContentLoaded", () => {
  // получаем текущую дату и время пользователя
  const now = new Date();
});

Всё остальное мы будем писать тоже внутри этого обработчика.

Находим финальную плашку

Чтобы не тащить в проект jQuery ради одного запроса, реализуем поиск нужного объекта родными средствами JavaScript:

// находим в документе среди всех разделов, которые относятся к статье, финальную плашку
const finalTexts = document
  .querySelector(".article-content")
  .querySelectorAll(".final");
// находим нужную и единственную плашку, с которой будем работать
const lastFinalText = finalTexts[finalTexts.length - 1];

Теперь поясним код.

Мы знаем от ребят из «Кинжала», что у них на странице есть один раздел с классом ".article-content", внутри которого лежит плашка с классом ".final". Мы могли бы просто найти элемент с классом ".final" и работать с ним, но мы хотим перестраховаться: вдруг их на странице будет несколько. Для этого мы сначала находим раздел со статьёй и уже внутри неё находим нужную плашку.

Последней строчкой мы получаем сам объект с плашкой, потому что команда поиска .querySelectorAll (".final") выдаст нам массив из объектов, а не конкретную плашку. Чтобы получить именно плашку как один объект, мы берём первый элемент массива. А так как нумерация начинается с нуля, мы берём размер массива (там один элемент, поэтому он равен единице) и вычитаем из него единицу. Получаем ноль — то, что нам нужно.

Добавляем проверку времени

Для проверки времени мы извлекаем из полной даты значение текущего часа. Так как нам нужно, чтобы код срабатывал с 10 вечера до 5 утра, то значение часа должно быть больше 21 и меньше 5:

// проверяем время — если наступил нужный нам диапазон
if ((now.getHours() > 21 || now.getHours() < 5) && finalTexts) { }

 👉 Обратите внимание — мы добавили в условие finalTexts. Если на предыдущем этапе мы всё-таки ничего не нашли, то при такой проверке результат будет false, условие не выполнится и делать внутри несуществующей плашки ничего не нужно.

Теперь всё остальное напишем внутри этой проверки.

Добавляем текст на плашку

У нас может быть две ситуации: картинка с кинжалом есть на плашке или её там нет. Если есть — надо добавить текст до неё, а если картинки нет — просто поставить текст в конец.

Чтобы поставить текст до картинки, нам нужно сделать так:

  1. Ищем в тексте начало тега картинки "<img" и смотрим, на какой позиции он начинается.
  2. Если такой текст внутри плашки есть и поиск нам вернул конкретную позицию, то берём фрагмент текста до этой позиции, добавляем наш текст, а потом приклеиваем тег с картинкой.
  3. Если тега с картинкой на плашке нет, то приклеиваем наш текст в конец исходной надписи.
  4. Результат отправляем в плашку вместо старого.

Запишем это в виде кода:

//  получаем содержимое финальной плашки
const s = lastFinalText.innerHTML;
// ищем начало картинки с кинжалом и его запоминаем позицию в строке
const c = s.indexOf("<img");
// если нашли…
if (c !== -1) {
  // то берём текст до картинки
  const s_begin = s.slice(0, c - 1);
  // затем берём текст после картинки
  const s_end = s.slice(c, s.length);
  // и склеиваем обратно, добавляя в середину наш текст
  const s_result = s_begin + ". А теперь ложитесь спать " + s_end;
  // отправляем результат обратно в финальную плашку
  lastFinalText.innerHTML = s_result;
// если картинки в плашке не оказалось…
} else {
  // то просто добавляем концовку
  const s_result = s + ". А теперь ложитесь спать";
 // и отправляем результат обратно в финальную плашку
  lastFinalText.innerHTML = s_result;

Собираем код в одно целое и проверяем результат:

Адаптируем статью под время суток

// ждём, пока страница полностью загрузится, потом алгоритм начинает работать
document.addEventListener("DOMContentLoaded", () => {
  // получаем текущую дату и время пользователя
  const now = new Date();
  // находим в документе среди всех разделов, которые относятся к статье, финальную плашку
  const finalTexts = document
    .querySelector(".article-content")
    .querySelectorAll(".final");
  // находим нужную и единственную плашку, с которой будем работать
  const lastFinalText = finalTexts[finalTexts.length - 1];
  //   проверяем время — если наступил нужный нам диапазон
  if ((now.getHours() > 21 || now.getHours() < 5) && finalTexts) {
    //  получаем содержимое финальной плашки
    const s = lastFinalText.innerHTML;
    // ищем начало картинки с кинжалом и его запоминаем позицию в строке
    const c = s.indexOf("<img");
    // если нашли…
    if (c !== -1) {
      // то берём текст до картинки
      const s_begin = s.slice(0, c - 1);
      // затем берём текст после картинки
      const s_end = s.slice(c, s.length);
      // и склеиваем обратно, добавляя в середину наш текст
      const s_result = s_begin + ". А теперь ложитесь спать " + s_end;
      // отправляем результат обратно в финальную плашку
      lastFinalText.innerHTML = s_result;
    // если картинки в плашке не оказалось…
    } else {
      // то просто добавляем концовку
      const s_result = s + ". А теперь ложитесь спать";
     // и отправляем результат обратно в финальную плашку
      lastFinalText.innerHTML = s_result;
    }
  }
});

Текст и иллюстрации:

Михаил Полянин

Художник:

Даня Берковский

Корректор:

Ирина Михеева

Вёрстка:

Кирилл Климентьев

Получите ИТ-профессию
В «Яндекс Практикуме» можно стать разработчиком, тестировщиком, аналитиком и менеджером цифровых продуктов. Первая часть обучения всегда бесплатная, чтобы попробовать и найти то, что вам по душе. Дальше — программы трудоустройства.
Получите ИТ-профессию Получите ИТ-профессию Получите ИТ-профессию Получите ИТ-профессию
Вам может быть интересно
Генератор статей для Кода
Генератор статей для Кода

Почти настоящие статьи на цепях Маркова

medium
Я сделяль: главная страница Яндекса
Я сделяль: главная страница Яндекса

Верстаем чистую страницу поисковика.

medium
Проект: собственный поиск по странице на jQuery
Проект: собственный поиск по странице на jQuery

Потому что почему бы и нет.

medium
Что означает ошибка ReferenceError: Cannot access uninitialized variable
Что означает ошибка ReferenceError: Cannot access uninitialized variable

Любопытная ошибка, которая находится совсем в другом месте

easy
Генератор лабиринтов
Генератор лабиринтов

Рисуем лабиринты любого размера.

hard
Создаём простые связи в базе данных
Создаём простые связи в базе данных

Немного практики по SQL-запросам перед серьёзным проектом

medium
Что означает ошибка TypeError: 'list' object cannot be interpreted as an integer
Что означает ошибка TypeError: 'list' object cannot be interpreted as an integer

Неочевидная ошибка при организации цикла в Python.

easy
Cортировка подсчётом: как работает сортировка без сравнений
Cортировка подсчётом: как работает сортировка без сравнений

Надо просто посчитать, сколько раз встречается каждый элемент

medium
Как устроен проект «Гадаем на статьях Кода»
Как устроен проект «Гадаем на статьях Кода»

Никакой магии, только JavaScript.

easy
easy