107 lines
5.8 KiB
JavaScript
107 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;
|
|||
|
|
|||
|
// Получить сведения о баннере для показа и его настройках
|
|||
|
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;
|