upas-web-site/js/banner.js

108 lines
5.8 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// Модуль для смены изображения в баннере по таймеру
// Подключить CSS, который относится к данному модулю при подключении модуля
import "../css/banner.css";
// указывается блок, в котором будет баннер
// блок должен содержать изображения
function myBanner(root) {
console.info("Baner logic successfully loaded");
// Константы
const DARK_CLASS = "carousel-dark";
const TIMEOUT_ATTR = "data-interval";
const THEME_ATTR = "data-dark";
const TIMEOUT = 5000;
// Переменная для хранения текущего ID таймера
let timerId;
// Получение всех необходимых элементов внутри блока с баннером
// Блок с баннерами
const bannerRoot = document.querySelector(root);
// Баннеры
const banners = Array.from(document.querySelectorAll(`${root} .carousel-item`));
// Интерактивные элементы для переключения баннеров, в том числе надписи
const indicators = Array.from(document.querySelectorAll(`${root} .carousel-indicators button`));
const controls = Array.from(document.querySelectorAll(".carousel-control-prev, .carousel-control-next"));
// Последний индекс для баннеров
const LAST_INDEX = banners.length - 1;
// Получить сведения о баннере для показа и его настройках
// function getBannerConfig() {
const getBannerConfig = () => {
// Получить текущий баннер
const currentElement = banners.find((banner) => banner.classList.contains("active"));
// Получить индекс текущего баннера
const hideIndex = currentElement === undefined ? LAST_INDEX : banners.indexOf(currentElement);
// Получить индекс следующего баннера
const showIndex = hideIndex === LAST_INDEX ? 0 : hideIndex + 1;
// Получить параметр времени показа баннера (значение атрибута data-interval)
const interval = parseInt(banners[showIndex].getAttribute(TIMEOUT_ATTR) ?? TIMEOUT, 10);
// Получить параметр темы надписи баннера (значение атрибута data-dark)
const isDark = banners[showIndex].getAttribute(THEME_ATTR);
// Если требуется темная тема, то добавить класс carousel-dark к блоку баннеров,
// иначе удалить его
if (isDark) {
bannerRoot.classList.add(DARK_CLASS);
} else {
bannerRoot.classList.remove(DARK_CLASS);
}
// Вывести отладочные сведения
console.debug(banners[showIndex], interval, hideIndex, showIndex);
// Возврат объекта
return { hideIndex, showIndex, interval };
};
// Функция для смены баннера
const changeBanner = () => {
// Получить сведения о текущем и следующем баннере
const config = getBannerConfig();
// Скрыть текущий баннер и его надпись
banners[config.hideIndex].classList.remove("active");
indicators[config.hideIndex].classList.remove("active");
// Показать следующий баннер и его надпись
banners[config.showIndex].classList.add("active");
indicators[config.showIndex].classList.add("active");
// Вывеси сообщение об автоматической смене баннера
console.info("Banner changed automatically");
// Установка таймера на n секунд, после чего функция будет запущена повторно
timerId = setTimeout(changeBanner, config.interval);
};
// Функция для сброса текущего таймера и создания нового с учетом настроек баннера,
// на который пользователь перешел с помощью элементов управления
const resetTimer = () => {
// Если таймер с указанным ID существует, то удалить его
if (timerId) {
clearTimeout(timerId);
}
// Получить сведения о текущем и следующем баннере
const config = getBannerConfig();
// Вывеси сообщение о ручной смене баннера (пользователь нажал на кнопку)
console.info("Banner changed manually");
// Установка таймера на n секунд, после чего функция будет запущена повторно
timerId = setTimeout(changeBanner, config.interval);
};
// Скрываем все баннеры
banners.forEach((banner) => banner.classList.remove("active"));
// Установка обработчика дополнительных событий для события click элементов ручного переключения баннеров
[...indicators, ...controls].forEach((element) => element.addEventListener("click", () => resetTimer(timerId)));
// Показываем первый баннер, после чего будет создан цикл переключений через вызов таймеров
changeBanner();
}
// Экспорт функции myBanner
export default myBanner;