Показать виджет в зависимости от даты (времени, года, дня недели)

Делаю виджет, который будет извещать пользователей, что заведение не работает с 23 до 9 утра. При этом можно ориентироваться как на локальное время пользователя, если ваша целевая аудитория из вашего региона, так и на серверное, чтобы точно контролировать ситуацию и не зависеть от часового пояса клиента.

Привет, друзья. Небольшое отступление. Понимаю, что не простое время для всех нас. Переживаю по поводу того, что происходит по всей Украине. Людей очень жалко. Я сам из Донецка, живу тут с 2009 года и знаю, что такое прятаться в убежище.

Политики заигрались и нужно это срочно все останавливать. Держитесь. Кто-то скажет, что не время для подобных постов, но для моего блога не было такого понятия как "подходящее время" и он существует как раз со второй половины 2014 года. Я в такой обстановке много лет, поэтому надеюсь, что обойдется без осуждений. Люблю свою родину Украину и земляков украинцев, хорошо отношусь к россиянам. Много друзей, знакомых и близких в этих странах. Благоразумие должно победить.

Вернемся к статье. Итак, как и говорил выше - сегодня сделаем виджет, который показывает уведомление, что заведение не работает в определенные часы. При этом будет возможность выбрать промежуток не только времени, но и дней, месяцев и даже годов. То есть варианты использование виджета, ограничиваются только вашей фантазией.

Это может быть акция в течение определенного времени, например, скидка на обед с 13:00 до 15:00 часов или какие-то подарки только по выходным.

Виджет, появляющийся в определенное время

Итак, начнём с разметки. Я сделал небольшой блок с 2 строками текста и кнопкой для закрытия окна:

  <div class="time-informer">

    <p class="time-informer__title">К сожалению, сегодня мы больше не работаем</p>
    <p class="time-informer__description">Завтра с 9:00 мы будем готовы принять ваши заказы</p>
    <button class="time-informer__button">Понятно</button>

  </div>

Тут все просто. Единственное, на что нужно обратить внимание — это класс обертки "time-informer". Он используется и в js, поэтому, если будете переименовывать, то нужно будет сделать это везде. Также обратите внимание на класс кнопки, он тоже используется в скрипте.

Теперь разберемся с js. Сначала давайте объясню суть, а она в том, что изначально блок скрыт. Затем, при помощи javascript, проверяем время. Если текущее время в выбранном промежутке, то добавляем класс "time-informer_active", что означает - блок показывается.

Теперь давайте подключим файлы стилей и сам скрипт. Исходник в конце статьи. Стили, как обычно, подключаем между тегами <head></head>, а скрипт перед закрывающим тегом body. Вот пример:

Виджет, показывающийся в зависимости от времени

Теперь сам код скрипта:

document.addEventListener("DOMContentLoaded", () => {
  let timeType = "local"; // local, server
  let timeInformer = document.querySelector(".time-informer");
  let closeButton = document.querySelector(".time-informer__button");

  if (!getCookie("time-informer")) {
    if (timeType === "server") {
      fetch("/time/time.php")
        .then((response) => {
          return response.json();
        })
        .then((data) => {
          if (data.hours > 22 || data.hours < 9) {
            timeInformer.classList.add("time-informer_active");
          }
        });
    } else {
      let data = new Date();
      if (data.getHours() > 22 || data.getHours() < 9) {
        timeInformer.classList.add("time-informer_active");
      }
    }
  }

  function getCookie(name) {
    let matches = document.cookie.match(
      new RegExp(
        "(?:^|; )" +
          name.replace(/([\.$?*|{}\(\)\[\]\\\/\+^])/g, "\\$1") +
          "=([^;]*)"
      )
    );
    return matches ? decodeURIComponent(matches[1]) : undefined;
  }

  function setCookie(name, value, options = {}) {
    options = {
      path: "/",
      // при необходимости добавьте другие значения по умолчанию
      ...options
    };

    if (options.expires instanceof Date) {
      options.expires = options.expires.toUTCString();
    }

    let updatedCookie =
      encodeURIComponent(name) + "=" + encodeURIComponent(value);

    for (let optionKey in options) {
      updatedCookie += "; " + optionKey;
      let optionValue = options[optionKey];
      if (optionValue !== true) {
        updatedCookie += "=" + optionValue;
      }
    }

    document.cookie = updatedCookie;
  }

  closeButton.onclick = (e) => {
    e.preventDefault();
    timeInformer.classList.remove("time-informer_active");
    setCookie("time-informer", true);
  };
});

Тут нас, в первую очередь, интересуют всего несколько строк.

 let timeType = "local"; // local, server
 let timeInformer = document.querySelector(".time-informer");
 let closeButton = document.querySelector(".time-informer__button");

Переменная timeType — это выбор того, какое время будет учитываться (пользовательское или серверное). Если переменной присвоено "local" - то используется локальное время посетителя. В случае, если присвоено "server", то учитывается серверное время. При этом, для считывания серверного времени используется запрос к файлу time.php.

Переменная timeInformer — это класс обертки виджета, а closeButton - класс кнопки, закрывающей виджет.

Теперь, у нас есть 2 участка кода для работы, где мы будем писать условия. Если используете серверное время, то работать нужно в 13 строке:

if (data.hours > 22 || data.hours < 9) {

Здесь я пишу условие, что если время больше 22 часов, то есть 23 и больше или меньше 9, то добавляем класс "time-informer_active" и показываем виджет.

Доступные настройки для условий:

  • data.hours - часы (от 1 до 24);
  • data.mday - порядковый номер дня месяца;
  • data.minutes - минуты;
  • data.mon - порядковый номер месяца;
  • data.wday - день месяца. 1 - понедельник;
  • data.yday - порядковый номер дня года:
  • data.year - год (четырехзначное число).

В примере так:

if (data.hours > 22 || data.hours < 9) {
  timeInformer.classList.add("time-informer_active");
}

Рекомендую настроить время на хостинге и использовать именно его, так как пользователь может быть из другого часового пояса.

Посмотреть что именно выдает то или иное свойство можно выведя его в консоль, например, так: console.log(data.year)

Если вы все-таки решили использовать локальное время, то придется воспользоваться чуть другими свойствами.

Обратите внимание на 19 строку, все условия, в случае использования локального времени пешем тут:

if (data.getHours() > 22 || data.getHours() < 9) {
  timeInformer.classList.add("time-informer_active");
}

Как и говорил, для локального времени чуть иначе задаются условия:

  • date.getHours() - часы от 0 до 23;
  • date.getMinutes() - минуты от 0 до 59;
  • date.getSeconds() - секунды от 0 до 59;
  • date.getMonth() - порядковый номер месяца от 0 до 11, где 0 - январь;
  • date.getDate() - день месяца от 1 до 31;
  • date.getDay() - номер дня недели от 0 до 6, где 0 - воскресенье;
  • date.getFullYear() - год. 4 цифры.

Что касается стилей, то они могут быть любые, главное сделать так, чтобы изначально блок был не видим, а при получении класса "time-informer_active" - показать его. У меня получилось так:

.time-informer {
  display: block;
  -webkit-box-sizing: border-box;
          box-sizing: border-box;
  z-index: 10000;
  width: 300px;
  padding: 60px 30px;
  line-height: 1.5;
  position: fixed;
  font: "Roboto", "Tahoma", sans-serif;
  background: #ffda82;
  -webkit-box-shadow: 3px 3px 1px rgba(75, 51, 0, 0.2);
          box-shadow: 3px 3px 1px rgba(75, 51, 0, 0.2);
  -webkit-transition: 0.3s;
  transition: 0.3s;
  bottom: 30px;
  left: -400px;
  opacity: 0;
  border-radius: 15px 0 15px 0;
  visibility: hidden;
}

.time-informer_active {
  -webkit-transition: 0.3s;
  transition: 0.3s;
  opacity: 1;
  visibility: visible;
  border-radius: 0 15px 0 15px;
  left: 30px;
}

Виджет

Размер: 0,6 мб

Если возникнут какие-то сложности или вопросы - пишите. Помогу, чем смогу.

Похожие публикации

3 комментария

  1. Артём

    Спасибо огромное!! Очень полезный виджет!!

    1. Дмитрий Давыдов

      По твоему спецзаказу))

  2. Артём

    Дима, как всегда всё на высшем уровне) Спасибо!

Добавить комментарий