Path : /home/vishqocm/pcib.in/assets/js/
File Upload :
Current File : /home/vishqocm/pcib.in/assets/js/main.js

/**
 * Main JavaScript file for Popular Computer Institute website
 */

// Document Ready Function
document.addEventListener('DOMContentLoaded', function() {
    // Hide preloader when page is loaded
    const preloader = document.querySelector('.preloader');
    if (preloader) {
        preloader.style.display = 'none';
    }

    // Initialize Back to Top button
    initBackToTop();

    // Initialize dropdown menus
    initDropdowns();

    // Add active class to nav items based on current page
    highlightActiveNavItem();

    // Initialize image fallbacks
    initImageFallbacks();

    // Smooth scrolling for anchor links
    document.querySelectorAll('a[href^="#"]').forEach(anchor => {
        anchor.addEventListener('click', function(e) {
            e.preventDefault();
            const targetId = this.getAttribute('href');
            if (targetId === '#') return;
            
            const targetElement = document.querySelector(targetId);
            if (targetElement) {
                targetElement.scrollIntoView({
                    behavior: 'smooth'
                });
            }
        });
    });

    // Counter animation for statistics
    const counters = document.querySelectorAll('.counter');
    if (counters.length > 0) {
        const observerOptions = {
            threshold: 0.5
        };
        
        const observer = new IntersectionObserver((entries) => {
            entries.forEach(entry => {
                if (entry.isIntersecting) {
                    const counter = entry.target;
                    const target = parseInt(counter.getAttribute('data-target'));
                    const duration = 2000; // 2 seconds
                    const step = Math.ceil(target / (duration / 16)); // 60fps
                    
                    let current = 0;
                    const updateCounter = () => {
                        current += step;
                        if (current > target) current = target;
                        counter.textContent = current.toLocaleString();
                        
                        if (current < target) {
                            requestAnimationFrame(updateCounter);
                        }
                    };
                    
                    updateCounter();
                    observer.unobserve(counter);
                }
            });
        }, observerOptions);
        
        counters.forEach(counter => {
            observer.observe(counter);
        });
    }

    // Mobile menu toggle
    const navbarToggler = document.querySelector('.navbar-toggler');
    if (navbarToggler) {
        navbarToggler.addEventListener('click', function() {
            document.body.classList.toggle('nav-open');
        });
    }

    // Lazy loading images
    if ('loading' in HTMLImageElement.prototype) {
        // Browser supports native lazy loading
        const lazyImages = document.querySelectorAll('img[loading="lazy"]');
        lazyImages.forEach(img => {
            img.src = img.dataset.src;
        });
    } else {
        // Fallback for browsers that don't support native lazy loading
        const lazyImages = document.querySelectorAll('.lazy-image');
        if (lazyImages.length > 0) {
            const lazyImageObserver = new IntersectionObserver((entries) => {
                entries.forEach(entry => {
                    if (entry.isIntersecting) {
                        const lazyImage = entry.target;
                        lazyImage.src = lazyImage.dataset.src;
                        lazyImage.classList.remove('lazy-image');
                        lazyImageObserver.unobserve(lazyImage);
                    }
                });
            });
            
            lazyImages.forEach(lazyImage => {
                lazyImageObserver.observe(lazyImage);
            });
        }
    }

    // Initialize tooltips
    var tooltipTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="tooltip"]'));
    var tooltipList = tooltipTriggerList.map(function (tooltipTriggerEl) {
        return new bootstrap.Tooltip(tooltipTriggerEl);
    });

    // Hero Slider Functionality
    initHeroSlider();
    
    // Initialize particles for hero slider
    createParticles();
    
    // Handle image loading errors
    handleImageErrors();
    
    // Initialize counters for stats
    initCounters();
    
    // Mobile menu toggle
    initMobileMenu();
});

/**
 * Initialize Back to Top button
 */
function initBackToTop() {
    const backToTopButton = document.querySelector('.back-to-top');
    
    if (backToTopButton) {
        // Show/hide button based on scroll position
        window.addEventListener('scroll', function() {
            if (window.pageYOffset > 300) {
                backToTopButton.classList.add('show');
            } else {
                backToTopButton.classList.remove('show');
            }
        });

        // Scroll to top when button is clicked
        backToTopButton.addEventListener('click', function(e) {
            e.preventDefault();
            window.scrollTo({
                top: 0,
                behavior: 'smooth'
            });
        });
    }
}

/**
 * Initialize dropdown menus
 */
function initDropdowns() {
    const dropdownToggles = document.querySelectorAll('.dropdown-toggle');
    
    dropdownToggles.forEach(toggle => {
        toggle.addEventListener('click', function(e) {
            e.preventDefault();
            const parent = this.parentElement;
            const dropdown = parent.querySelector('.dropdown-menu');
            
            // Toggle dropdown
            dropdown.classList.toggle('show');
            
            // Close dropdown when clicking outside
            document.addEventListener('click', function closeDropdown(e) {
                if (!parent.contains(e.target)) {
                    dropdown.classList.remove('show');
                    document.removeEventListener('click', closeDropdown);
                }
            });
        });
    });
}

/**
 * Highlight active navigation item
 */
function highlightActiveNavItem() {
    const currentLocation = location.pathname;
    const navLinks = document.querySelectorAll('.navbar-nav .nav-link');
    
    navLinks.forEach(link => {
        if (link.getAttribute('href') === currentLocation) {
            link.classList.add('active');
        } else {
            link.classList.remove('active');
        }
    });
}

/**
 * Initialize image fallbacks
 */
function initImageFallbacks() {
    const slideImages = document.querySelectorAll('.slide-image');
    
    slideImages.forEach(img => {
        const fallbackUrl = img.getAttribute('data-fallback');
        if (fallbackUrl) {
            const mainImage = new Image();
            mainImage.onload = function() {
                // Main image loaded successfully
            };
            mainImage.onerror = function() {
                // Main image failed to load, use fallback
                img.style.backgroundImage = `url('${fallbackUrl}')`;
            };
            
            // Extract the URL from the background-image style
            const bgUrl = getComputedStyle(img).backgroundImage.replace(/url\(['"]?(.*?)['"]?\)/i, '$1');
            mainImage.src = bgUrl;
        }
    });
}

// Initialize tooltips
const tooltipTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="tooltip"]'));
tooltipTriggerList.map(function(tooltipTriggerEl) {
    return new bootstrap.Tooltip(tooltipTriggerEl);
});

// Initialize popovers
const popoverTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="popover"]'));
popoverTriggerList.map(function(popoverTriggerEl) {
    return new bootstrap.Popover(popoverTriggerEl);
});

// Animate stats counter
function animateStats() {
    const statElements = document.querySelectorAll('.stat-number');
    
    statElements.forEach(function(stat) {
        const target = parseInt(stat.getAttribute('data-count'));
        const duration = 2000; // 2 seconds
        const step = target / (duration / 16); // 60fps
        let current = 0;
        
        const updateCounter = function() {
            current += step;
            if (current < target) {
                stat.textContent = Math.ceil(current).toLocaleString();
                requestAnimationFrame(updateCounter);
            } else {
                stat.textContent = target.toLocaleString();
            }
        };
        
        updateCounter();
    });
}

// Check if element is in viewport
function isInViewport(element) {
    const rect = element.getBoundingClientRect();
    return (
        rect.top >= 0 &&
        rect.left >= 0 &&
        rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) &&
        rect.right <= (window.innerWidth || document.documentElement.clientWidth)
    );
}

// Handle scroll animations
function handleScrollAnimations() {
    const statsSection = document.querySelector('.stats-section');
    if (statsSection && isInViewport(statsSection)) {
        animateStats();
        // Remove event listener after animation starts
        window.removeEventListener('scroll', handleScrollAnimations);
    }
}

// Add scroll event listener
window.addEventListener('scroll', handleScrollAnimations);
// Also check on page load
handleScrollAnimations();

// Testimonial slider initialization
if (typeof Slick !== 'undefined') {
    $('.testimonial-slider').slick({
        dots: true,
        infinite: true,
        speed: 300,
        slidesToShow: 3,
        slidesToScroll: 1,
        autoplay: true,
        autoplaySpeed: 5000,
        responsive: [
            {
                breakpoint: 1024,
                settings: {
                    slidesToShow: 2,
                    slidesToScroll: 1
                }
            },
            {
                breakpoint: 600,
                settings: {
                    slidesToShow: 1,
                    slidesToScroll: 1
                }
            }
        ]
    });
}

// Hero Slider
function initHeroSlider() {
    const slides = document.querySelectorAll('.slide');
    const dots = document.querySelectorAll('.slider-dot');
    const prevBtn = document.querySelector('.slider-prev');
    const nextBtn = document.querySelector('.slider-next');
    let currentSlide = 0;
    let slideInterval;
    
    // Function to show a specific slide
    function showSlide(index) {
        // Hide all slides
        slides.forEach(slide => {
            slide.classList.remove('active');
        });
        
        // Remove active class from all dots
        dots.forEach(dot => {
            dot.classList.remove('active');
        });
        
        // Show the current slide and dot
        slides[index].classList.add('active');
        dots[index].classList.add('active');
        
        // Update current slide index
        currentSlide = index;
    }
    
    // Function to show the next slide
    function nextSlide() {
        let next = currentSlide + 1;
        if (next >= slides.length) {
            next = 0;
        }
        showSlide(next);
    }
    
    // Function to show the previous slide
    function prevSlide() {
        let prev = currentSlide - 1;
        if (prev < 0) {
            prev = slides.length - 1;
        }
        showSlide(prev);
    }
    
    // Start automatic slideshow
    function startSlideshow() {
        slideInterval = setInterval(nextSlide, 5000);
    }
    
    // Stop automatic slideshow
    function stopSlideshow() {
        clearInterval(slideInterval);
    }
    
    // Event listeners for navigation
    if (prevBtn) {
        prevBtn.addEventListener('click', function() {
            prevSlide();
            stopSlideshow();
            startSlideshow();
        });
    }
    
    if (nextBtn) {
        nextBtn.addEventListener('click', function() {
            nextSlide();
            stopSlideshow();
            startSlideshow();
        });
    }
    
    // Add click event to dots
    dots.forEach((dot, index) => {
        dot.addEventListener('click', function() {
            showSlide(index);
            stopSlideshow();
            startSlideshow();
        });
    });
    
    // Start the slideshow if there are slides
    if (slides.length > 0) {
        startSlideshow();
    }
}

// Create particles for hero slider background
function createParticles() {
    const sliderBg = document.querySelector('.slider-bg');
    
    if (!sliderBg) return;
    
    // Create 50 particles
    for (let i = 0; i < 50; i++) {
        const particle = document.createElement('div');
        particle.classList.add('particle');
        
        // Random size between 5px and 20px
        const size = Math.random() * 15 + 5;
        
        // Random position
        const x = Math.random() * 100 - 50 + '%';
        const y = Math.random() * 100 - 50 + '%';
        
        // Random animation duration and delay
        const duration = Math.random() * 10 + 5 + 's';
        const delay = Math.random() * 5 + 's';
        
        // Set CSS variables
        particle.style.setProperty('--size', size + 'px');
        particle.style.setProperty('--x', x);
        particle.style.setProperty('--y', y);
        particle.style.setProperty('--duration', duration);
        particle.style.setProperty('--delay', delay);
        
        sliderBg.appendChild(particle);
    }
}

// Handle image loading errors
function handleImageErrors() {
    const slideImages = document.querySelectorAll('.slide-image');
    
    slideImages.forEach(img => {
        // Check if the background image fails to load
        const url = getComputedStyle(img).backgroundImage.replace(/url\(['"]?(.*?)['"]?\)/i, '$1');
        const fallback = img.getAttribute('data-fallback');
        
        if (url && fallback) {
            const testImg = new Image();
            testImg.onerror = function() {
                img.style.backgroundImage = `url('${fallback}')`;
            };
            testImg.src = url;
        }
    });
}

// Initialize counters for stats
function initCounters() {
    const statValues = document.querySelectorAll('.stat-value');
    
    if (statValues.length === 0) return;
    
    // Check if element is in viewport
    function isInViewport(element) {
        const rect = element.getBoundingClientRect();
        return (
            rect.top >= 0 &&
            rect.left >= 0 &&
            rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) &&
            rect.right <= (window.innerWidth || document.documentElement.clientWidth)
        );
    }
    
    // Animate counter
    function animateCounter(element, target) {
        let current = 0;
        const increment = target / 100;
        const duration = 2000; // 2 seconds
        const interval = duration / 100;
        
        const timer = setInterval(() => {
            current += increment;
            element.textContent = Math.round(current);
            
            if (current >= target) {
                element.textContent = target;
                clearInterval(timer);
            }
        }, interval);
    }
    
    // Start animation when element is in viewport
    function checkCounters() {
        statValues.forEach(value => {
            if (isInViewport(value) && !value.classList.contains('counted')) {
                const target = parseInt(value.getAttribute('data-count') || value.textContent);
                animateCounter(value, target);
                value.classList.add('counted');
            }
        });
    }
    
    // Check on scroll
    window.addEventListener('scroll', checkCounters);
    
    // Check on page load
    checkCounters();
}

// Mobile menu toggle
function initMobileMenu() {
    const menuToggle = document.querySelector('.mobile-menu-toggle');
    const mobileMenu = document.querySelector('.mobile-menu');
    
    if (!menuToggle || !mobileMenu) return;
    
    menuToggle.addEventListener('click', function() {
        mobileMenu.classList.toggle('active');
        this.classList.toggle('active');
    });
}