Files
wordpress-theme-aksrt/assets/js/core/slider.js
T

379 lines
15 KiB
JavaScript

/**
* AKSRT Hero & Swiper Initialization
*/
(function () {
"use strict";
window.AksrtSwipers = { new: [], scroll: [], tab: [] };
function initHeroSlider() {
if (typeof Swiper === "undefined") return;
// ===== Type A: .swiper-scroll =====
document.querySelectorAll(".swiper-scroll:not(.swiper-initialized)").forEach(function (el, index) {
var c_w = el.offsetWidth;
var firstSlide = el.querySelector(".swiper-wrapper > *");
var i_w = firstSlide ? firstSlide.offsetWidth : 200;
var slidesPerGroup = Math.max(1, Math.floor(c_w / i_w));
var option = {
slidesPerView: "auto",
freeMode: true,
freeModeSticky: true,
mousewheel: { forceToAxis: true },
slidesPerGroup: slidesPerGroup,
autoplay: el.dataset.autoplay ? {
delay: parseInt(el.dataset.interval || "4000", 10),
disableOnInteraction: false,
} : false,
loop: !!el.dataset.loop,
navigation: {
nextEl: el.querySelector(".swiper-button-next"),
prevEl: el.querySelector(".swiper-button-prev"),
},
};
el.classList.add("swiper-scroll-eq-" + index);
el.setAttribute("swiper-scroll-index", String(index));
window.AksrtSwipers.scroll[index] = new Swiper(el, option);
});
// ===== Type B: .swiper-tab =====
document.querySelectorAll(".swiper-tab:not(.swiper-initialized)").forEach(function (el, index) {
var speed = parseInt(el.dataset.speed || "0", 10) || Math.floor((el.offsetWidth + 1200) / 170) * 50;
speed = Math.max(300, speed);
var initialSlide = parseInt(el.getAttribute("active-index") || "0", 10);
var option = {
loop: false,
initialSlide: initialSlide,
autoHeight: true,
spaceBetween: 20,
autoplay: false,
speed: speed,
pagination: {
el: el.querySelector(".swiper-pagination"),
clickable: true,
},
};
var tabId = el.getAttribute("swiper-tab");
if (tabId) {
var tabNav = document.querySelector('[swiper-tab-nav="' + tabId + '"]');
if (tabNav && tabNav.swiper) {
option.thumbs = {
swiper: tabNav.swiper,
autoScrollOffset: 2,
};
}
}
el.classList.add("swiper-tab-eq-" + index);
el.setAttribute("swiper-tab-index", String(index));
window.AksrtSwipers.tab[index] = new Swiper(el, option);
});
// ===== Type C: .new-swiper =====
// Prefer data-swiper-config JSON (used by hero/banner templates), then data-* attrs.
document.querySelectorAll(".new-swiper:not(.swiper-initialized)").forEach(function (el, index) {
var jsonConfig = null;
if (el.dataset.swiperConfig) {
try {
jsonConfig = JSON.parse(el.dataset.swiperConfig);
} catch (e) {
jsonConfig = null;
}
}
if (!jsonConfig || typeof jsonConfig !== "object") {
jsonConfig = {};
}
var delay = parseInt(el.dataset.interval || "6000", 10);
if (jsonConfig.autoplay && typeof jsonConfig.autoplay === "object" && jsonConfig.autoplay.delay) {
delay = parseInt(jsonConfig.autoplay.delay, 10) || delay;
}
var autoplay;
if (Object.prototype.hasOwnProperty.call(jsonConfig, "autoplay")) {
autoplay = jsonConfig.autoplay;
} else if (el.dataset.autoplay !== undefined) {
autoplay = {
delay: delay,
disableOnInteraction: false,
};
} else {
autoplay = false;
}
var speed = parseInt(el.dataset.speed || "0", 10) || Math.floor((el.offsetWidth + 1000) / 22) * 10;
if (jsonConfig.speed) {
speed = parseInt(jsonConfig.speed, 10) || speed;
}
speed = Math.max(400, speed);
if (!autoplay) speed = Math.floor(speed / 1.6);
var loop = Object.prototype.hasOwnProperty.call(jsonConfig, "loop")
? !!jsonConfig.loop
: !!el.dataset.loop;
var parallax = !!el.querySelector("[data-swiper-parallax],[data-swiper-parallax-scale]");
var effect = jsonConfig.effect || el.dataset.effect || "slide";
var direction = jsonConfig.direction || el.dataset.direction || "horizontal";
var spaceBetween = Object.prototype.hasOwnProperty.call(jsonConfig, "spaceBetween")
? parseInt(jsonConfig.spaceBetween, 10) || 0
: parseInt(el.dataset.spaceBetween || "0", 10);
var paginationType = el.dataset.paginationType || "bullets";
var autoHeight = Object.prototype.hasOwnProperty.call(jsonConfig, "autoHeight")
? !!jsonConfig.autoHeight
: el.hasAttribute("auto-height");
// Fixed-ratio modules (banner card) must not use autoHeight — it collapses absolute slides.
if (el.classList.contains("banner-module__swiper") || el.classList.contains("scale-height")) {
autoHeight = false;
}
var paginationEl = el.querySelector(".swiper-pagination, .header-components__pagination");
var prevBtn = el.querySelector(".swiper-button-prev, .banner-module__prev");
var nextBtn = el.querySelector(".swiper-button-next, .banner-module__next");
var pagination = false;
if (Object.prototype.hasOwnProperty.call(jsonConfig, "pagination")) {
if (jsonConfig.pagination === false) {
pagination = false;
} else if (jsonConfig.pagination && typeof jsonConfig.pagination === "object") {
pagination = Object.assign(
{
el: paginationEl,
clickable: true,
},
jsonConfig.pagination
);
if (!pagination.el) pagination.el = paginationEl;
if (!pagination.el) pagination = false;
} else if (jsonConfig.pagination) {
pagination = paginationEl
? { el: paginationEl, type: paginationType, clickable: true }
: false;
}
} else {
pagination = paginationEl
? { el: paginationEl, type: paginationType, clickable: true }
: false;
}
var navigation = false;
if (Object.prototype.hasOwnProperty.call(jsonConfig, "navigation")) {
if (jsonConfig.navigation === false) {
navigation = false;
} else if (jsonConfig.navigation === true || jsonConfig.navigation) {
navigation = prevBtn && nextBtn
? { nextEl: nextBtn, prevEl: prevBtn }
: false;
}
} else {
navigation = {
nextEl: nextBtn,
prevEl: prevBtn,
};
}
var keyboard = Object.prototype.hasOwnProperty.call(jsonConfig, "keyboard")
? jsonConfig.keyboard
: { enabled: true };
el.classList.add("swiper-new-eq-" + index);
el.setAttribute("swiper-new-index", String(index));
var swiperArgs = {
loop: loop,
autoHeight: autoHeight,
direction: direction,
spaceBetween: spaceBetween,
parallax: parallax,
effect: effect,
autoplay: autoplay,
speed: speed,
pagination: pagination,
navigation: navigation,
keyboard: keyboard,
a11y: { prevSlideMessage: "上一张", nextSlideMessage: "下一张" },
on: {
slideChange: function () {
el.querySelectorAll(".aksrt-dplayer, video").forEach(function (media) {
if (media.pause) media.pause();
var dp = media.closest("[data-dplayer]");
if (dp && dp._dplayer) dp._dplayer.pause();
});
},
init: function () {
if (loop) {
el.querySelectorAll(".swiper-slide-duplicate img").forEach(function (img) {
img.classList.add("no-imgbox");
});
}
},
},
};
if (effect === "fade") {
swiperArgs.fadeEffect = Object.assign(
{ crossFade: true },
(jsonConfig.fadeEffect && typeof jsonConfig.fadeEffect === "object")
? jsonConfig.fadeEffect
: {}
);
}
if (pagination && paginationType === "thumbnail") {
swiperArgs.pagination.type = "bullets";
swiperArgs.pagination.bulletClass = "pagination-thumbnail-item";
swiperArgs.pagination.bulletActiveClass = "pagination-thumbnail-item-active";
swiperArgs.pagination.renderBullet = function (idx, className) {
var slide = this.slides[idx];
if (!slide) return "";
var img = slide.querySelector("img");
var src = img ? (img.dataset.src || img.src) : "";
if (src) {
return '<div class="' + className + '"><img' + window.aksrtGetLazyImageAttr('lazy_sider', src, 'aksrt-tilt-thumb') + ' alt=""></div>';
}
return "";
};
}
var swiperInstance = new Swiper(el, swiperArgs);
window.AksrtSwipers.new[index] = swiperInstance;
if (el.classList.contains("banner-module__swiper")) {
if (prevBtn) {
prevBtn.addEventListener("click", function (e) {
e.preventDefault(); e.stopPropagation(); e.stopImmediatePropagation();
if (swiperInstance && !swiperInstance.destroyed) swiperInstance.slidePrev();
}, true);
}
if (nextBtn) {
nextBtn.addEventListener("click", function (e) {
e.preventDefault(); e.stopPropagation(); e.stopImmediatePropagation();
if (swiperInstance && !swiperInstance.destroyed) swiperInstance.slideNext();
}, true);
}
}
});
// ===== Compat: data-swiper-config JSON =====
document.querySelectorAll("[data-swiper-config]:not(.swiper-initialized):not(.new-swiper):not(.swiper-scroll):not(.swiper-tab)").forEach(function (el) {
var config = {};
try { config = JSON.parse(el.dataset.swiperConfig || "{}"); } catch (e) {}
var paginationEl = el.querySelector(".swiper-pagination, .header-components__pagination");
var prevBtn = el.querySelector(".swiper-button-prev");
var nextBtn = el.querySelector(".swiper-button-next");
var defaults = {
effect: "fade",
fadeEffect: { crossFade: true },
loop: true,
speed: 600,
autoplay: { delay: 5000, disableOnInteraction: false },
pagination: paginationEl ? { el: paginationEl, type: "progressbar" } : false,
navigation: (prevBtn && nextBtn) ? { prevEl: prevBtn, nextEl: nextBtn } : false,
keyboard: { enabled: true },
a11y: { prevSlideMessage: "上一张", nextSlideMessage: "下一张" },
};
var finalConfig = Object.assign({}, defaults, config);
if (config.pagination && typeof config.pagination === "object") {
if (!config.pagination.el && paginationEl) config.pagination.el = paginationEl;
finalConfig.pagination = Object.assign({}, defaults.pagination || {}, config.pagination);
} else if (config.pagination === false) {
finalConfig.pagination = false;
}
if (config.navigation === true && prevBtn && nextBtn) {
finalConfig.navigation = { prevEl: prevBtn, nextEl: nextBtn };
}
new Swiper(el, finalConfig);
});
// Clickable slides
document.querySelectorAll(".swiper-slide[data-link]").forEach(function (slide) {
var link = slide.dataset.link;
if (link && link !== "#") {
slide.style.cursor = "pointer";
slide.addEventListener("click", function (e) {
if (e.target.closest(".header-components-search, .header-slider-search, .header-components-card, .header-slider-card, .hero__btn, .swiper-button-prev, .swiper-button-next, .swiper-pagination, .hero-search, a, button, input")) return;
window.location.href = link;
});
}
});
// Legacy hero__slides fallback
document.querySelectorAll(".hero__slides:not(.swiper-wrapper)").forEach(function (slider) {
var slides = slider.querySelectorAll(".hero__slide");
var dots = slider.querySelectorAll(".hero__dot");
var prevBtn = slider.closest("section")?.querySelector(".hero__btn--prev");
var nextBtn = slider.closest("section")?.querySelector(".hero__btn--next");
if (!slides.length || slides.length <= 1) return;
var autoplayInterval = parseInt(slider.dataset.autoplay || "5000", 10) || 5000;
var pauseOnHover = slider.dataset.pauseOnHover === "true";
var current = 0;
var timer = null;
var paused = false;
function show(index) {
index = ((index % slides.length) + slides.length) % slides.length;
slides[current].classList.remove("active");
if (dots[current]) dots[current].setAttribute("aria-selected", "false");
current = index;
slides[current].classList.add("active");
if (dots[current]) dots[current].setAttribute("aria-selected", "true");
}
function next() { show(current + 1); }
function prev() { show(current - 1); }
function startAutoplay() { stopAutoplay(); timer = setInterval(next, autoplayInterval); }
function stopAutoplay() { if (timer) clearInterval(timer); timer = null; }
function restart() { if (!paused) { stopAutoplay(); startAutoplay(); } }
show(0);
if (nextBtn) nextBtn.addEventListener("click", function () { next(); restart(); });
if (prevBtn) prevBtn.addEventListener("click", function () { prev(); restart(); });
dots.forEach(function (dot, i) { dot.addEventListener("click", function () { show(i); restart(); }); });
slider.setAttribute("tabindex", "-1");
slider.addEventListener("keydown", function (e) {
if (e.key === "ArrowRight") { next(); restart(); }
else if (e.key === "ArrowLeft") { prev(); restart(); }
});
if (pauseOnHover) {
slider.addEventListener("mouseenter", function () { paused = true; stopAutoplay(); });
slider.addEventListener("mouseleave", function () { paused = false; startAutoplay(); });
}
slides.forEach(function (slide) {
var link = slide.dataset.link;
if (link && link !== "#") {
slide.style.cursor = "pointer";
slide.addEventListener("click", function () { window.location.href = link; });
}
});
var touchStartX = 0;
slider.addEventListener("touchstart", function (e) { touchStartX = e.changedTouches[0].screenX; stopAutoplay(); }, { passive: true });
slider.addEventListener("touchend", function (e) {
var diff = touchStartX - e.changedTouches[0].screenX;
if (Math.abs(diff) > 50) { if (diff > 0) next(); else prev(); }
startAutoplay();
}, { passive: true });
startAutoplay();
document.addEventListener("visibilitychange", function () {
if (document.hidden) stopAutoplay();
else if (!paused) startAutoplay();
});
});
}
window.AksrtFrontend.register("aksrt-hero-slider", function () { initHeroSlider(); });
})();