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