108 lines
5.8 KiB
JavaScript
108 lines
5.8 KiB
JavaScript
// Модуль для смены изображения в баннере по таймеру
|
||
|
||
// Подключить 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;
|