/* FIRST Australia — front-end behaviours Kept intentionally light so it ports straight into a WP theme's main.js. */ (function () { 'use strict'; // --- Smooth scroll for in-page anchor links --------------------------- document.querySelectorAll('a[href^="#"]:not([data-bs-toggle])').forEach(function (link) { link.addEventListener('click', function (e) { var id = this.getAttribute('href'); if (id.length < 2) return; var target = document.querySelector(id); if (!target) return; e.preventDefault(); target.scrollIntoView({ behavior: 'smooth', block: 'start' }); // Collapse the mobile menu after navigating. var nav = document.getElementById('mainNav'); if (nav && nav.classList.contains('show')) { bootstrap.Collapse.getOrCreateInstance(nav).hide(); } }); }); // --- Back-to-top button ---------------------------------------------- var backToTop = document.getElementById('backToTop'); if (backToTop) { window.addEventListener('scroll', function () { backToTop.classList.toggle('d-none', window.scrollY < 600); }); } // --- Animated stat counters ------------------------------------------ // Counts numbers up when they scroll into view. Leaves the final value // intact when JS/IntersectionObserver are unavailable, and skips values // with no leading number (e.g. "K–12"). var statNums = document.querySelectorAll('.stat-num'); var reduceMotion = window.matchMedia && window.matchMedia('(prefers-reduced-motion: reduce)').matches; if (statNums.length && 'IntersectionObserver' in window && !reduceMotion) { var animateCount = function (el) { var match = el.textContent.trim().match(/^(\d[\d,]*)(.*)$/); if (!match) return; // e.g. "K–12" — leave as-is var hasComma = match[1].indexOf(',') !== -1; var target = parseInt(match[1].replace(/,/g, ''), 10); var suffix = match[2]; // Larger numbers run longer so they don't fly past too fast // (e.g. "100+" counts noticeably slower than "3"). var duration = 1400 + Math.min(target, 200) * 12; var startTime = null; var step = function (now) { if (startTime === null) startTime = now; var progress = Math.min((now - startTime) / duration, 1); var eased = 1 - Math.pow(1 - progress, 3); // easeOutCubic var value = Math.round(eased * target); el.textContent = (hasComma ? value.toLocaleString() : value) + suffix; if (progress < 1) requestAnimationFrame(step); }; el.textContent = '0' + suffix; // start from zero requestAnimationFrame(step); }; var statObserver = new IntersectionObserver(function (entries) { entries.forEach(function (entry) { if (entry.isIntersecting) { animateCount(entry.target); statObserver.unobserve(entry.target); } }); }, { threshold: 0.6 }); statNums.forEach(function (el) { statObserver.observe(el); }); } // --- Carousels -------------------------------------------------------- // Explicitly initialise every Bootstrap carousel (don't rely solely on the // data-api auto-init, which can be missed depending on script timing). This // also lets us set a sensible cycle interval and pause-on-hover behaviour. var carousels = document.querySelectorAll('.carousel'); if (carousels.length) { if (window.bootstrap && bootstrap.Carousel) { carousels.forEach(function (el) { bootstrap.Carousel.getOrCreateInstance(el, { interval: 6000, ride: 'carousel', pause: 'hover', wrap: true, touch: true }); }); } else { // Bootstrap's JS bundle didn't load — the carousel can't run without it. // Surfaced here to make the cause obvious in the browser console. console.warn('[ftcindia2026] Bootstrap JS not found — carousel/dropdowns will not work. Check that bootstrap.bundle.min.js is loading (CDN reachable / not blocked).'); } } })();