// Modern Glassmorphic Slider Functionality
class GlassmorphicSlider {
constructor(options = {}) {
this.currentSlide = 0;
this.slides = document.querySelectorAll('.slide');
this.dots = document.querySelectorAll('.slider-dot');
this.prevBtn = document.querySelector('.slider-prev');
this.nextBtn = document.querySelector('.slider-next');
this.autoplayInterval = options.autoplay ? options.autoplayInterval || 5000 : null;
this.autoplayTimer = null;
this.isTransitioning = false;
this.totalSlides = this.slides.length;
// Preload images for smoother transitions
this.preloadImages();
this.init();
}
preloadImages() {
// Get all slide image URLs
const slideImages = Array.from(document.querySelectorAll('.slide-image')).map(
img => getComputedStyle(img).backgroundImage.replace(/url\(['"]?(.*?)['"]?\)/i, '$1')
);
// Preload each image
slideImages.forEach(src => {
const img = new Image();
img.src = src;
});
}
init() {
// Set initial active slide
this.showSlide(this.currentSlide);
// Add event listeners
if (this.prevBtn) {
this.prevBtn.addEventListener('click', (e) => {
e.preventDefault();
this.prevSlide();
});
}
if (this.nextBtn) {
this.nextBtn.addEventListener('click', (e) => {
e.preventDefault();
this.nextSlide();
});
}
// Add dot click events
this.dots.forEach((dot, index) => {
dot.addEventListener('click', (e) => {
e.preventDefault();
this.goToSlide(index);
});
});
// Add keyboard navigation
document.addEventListener('keydown', (e) => {
if (e.key === 'ArrowLeft') this.prevSlide();
if (e.key === 'ArrowRight') this.nextSlide();
});
// Add touch support
let touchStartX = 0;
let touchEndX = 0;
const sliderElement = document.querySelector('.hero-slider');
if (sliderElement) {
sliderElement.addEventListener('touchstart', (e) => {
touchStartX = e.changedTouches[0].screenX;
}, false);
sliderElement.addEventListener('touchend', (e) => {
touchEndX = e.changedTouches[0].screenX;
this.handleSwipe(touchStartX, touchEndX);
}, false);
}
// Start autoplay if enabled
if (this.autoplayInterval) {
this.startAutoplay();
// Pause on hover
if (sliderElement) {
sliderElement.addEventListener('mouseenter', () => {
this.stopAutoplay();
});
sliderElement.addEventListener('mouseleave', () => {
this.startAutoplay();
});
}
}
// Log initialization
console.log(`Slider initialized with ${this.totalSlides} slides`);
}
showSlide(index) {
// Validate index to ensure it's within bounds
if (index < 0 || index >= this.totalSlides) {
console.error(`Invalid slide index: ${index}. Total slides: ${this.totalSlides}`);
index = 0; // Reset to first slide if invalid
}
// Prevent rapid transitions
if (this.isTransitioning) return;
this.isTransitioning = true;
// Remove active class from all slides and dots
this.slides.forEach(slide => {
slide.classList.remove('active');
slide.classList.remove('fade-in');
});
this.dots.forEach(dot => dot.classList.remove('active'));
// Add active class to current slide and dot
this.slides[index].classList.add('active');
this.slides[index].classList.add('fade-in');
// Make sure the dot exists before adding the active class
if (this.dots[index]) {
this.dots[index].classList.add('active');
}
// Add slide-up animation to text elements
const title = this.slides[index].querySelector('.slide-title');
const description = this.slides[index].querySelector('.slide-description');
const button = this.slides[index].querySelector('.slide-button');
if (title) title.classList.add('slide-up');
if (description) description.classList.add('slide-up');
if (button) button.classList.add('slide-up');
// Update current slide index
this.currentSlide = index;
// Reset transition lock after animation completes
setTimeout(() => {
this.isTransitioning = false;
}, 700);
}
nextSlide() {
if (this.isTransitioning) return;
let next = (this.currentSlide + 1) % this.totalSlides;
console.log(`Moving to next slide: ${next}`);
this.showSlide(next);
}
prevSlide() {
if (this.isTransitioning) return;
let prev = (this.currentSlide - 1 + this.totalSlides) % this.totalSlides;
console.log(`Moving to previous slide: ${prev}`);
this.showSlide(prev);
}
goToSlide(index) {
if (this.isTransitioning) return;
if (index >= 0 && index < this.totalSlides) {
console.log(`Going to slide: ${index}`);
this.showSlide(index);
}
}
handleSwipe(touchStartX, touchEndX) {
const swipeThreshold = 50;
const diff = touchStartX - touchEndX;
if (Math.abs(diff) > swipeThreshold) {
if (diff > 0) {
this.nextSlide(); // Swipe left
} else {
this.prevSlide(); // Swipe right
}
}
}
startAutoplay() {
if (this.autoplayInterval) {
this.stopAutoplay(); // Clear any existing timer
this.autoplayTimer = setInterval(() => {
this.nextSlide();
}, this.autoplayInterval);
}
}
stopAutoplay() {
if (this.autoplayTimer) {
clearInterval(this.autoplayTimer);
this.autoplayTimer = null;
}
}
}
// Initialize slider when DOM is loaded
document.addEventListener('DOMContentLoaded', () => {
// Check if we should initialize this slider
// Don't initialize if the Swiper-based hero slider is present
const swiperSlider = document.querySelector('.hero-slider.swiper');
if (swiperSlider) {
console.log('Swiper-based hero slider detected. Not initializing GlassmorphicSlider.');
return;
}
// Check if slider elements exist
const sliderContainer = document.querySelector('.hero-slider');
const slides = document.querySelectorAll('.slide');
if (sliderContainer && slides.length > 0) {
console.log(`Found ${slides.length} slides for GlassmorphicSlider`);
const slider = new GlassmorphicSlider({
autoplay: true,
autoplayInterval: 5000
});
} else {
console.warn('Slider elements not found');
}
});