document.addEventListener("DOMContentLoaded", function () {
const startTime = Date.now(); // Record page script start time for preloader minimum display
// =================================================================
// SECTION: Preloader Setup & Logic
// =================================================================
const preloader = document.querySelector('.preloader-container');
const preloaderCounter = document.querySelector('.preloader-counter');
const vimeoDesktopIframe = document.getElementById('vimeo-desktop'); // Use your desktop ID
const vimeoMobileIframe = document.getElementById('vimeo-mobile'); // Use your mobile ID
const minimumDisplayTime = 1500; // Minimum preloader time in milliseconds (e.g., 1.5 seconds)
let preloaderCount = 0;
let pageLoadComplete = false;
let videoReady = false;
let preloaderHidden = false;
let preloaderCounterInterval;
let preloaderFailsafeTimeout;
// --- Preloader Element Checks ---
if (!preloader || !preloaderCounter) {
console.warn('Preloader elements (.preloader-container or .preloader-counter) not found! Cannot initialize preloader.');
// Attempt to hide preloader container if it exists but counter doesn't, to prevent blocking page
if(preloader) {
preloader.style.opacity = '0';
preloader.style.visibility = 'hidden';
preloader.style.display = 'none';
}
return; // Stop execution of preloader logic if elements are missing
}
// --- Determine visible Vimeo iframe ---
let visibleVimeoIframe = null;
if (vimeoDesktopIframe && vimeoDesktopIframe.offsetParent !== null) {
// offsetParent is null if display:none (or parent is display:none)
visibleVimeoIframe = vimeoDesktopIframe;
console.log("Preloader: Detected visible video - Desktop");
} else if (vimeoMobileIframe && vimeoMobileIframe.offsetParent !== null) {
visibleVimeoIframe = vimeoMobileIframe;
console.log("Preloader: Detected visible video - Mobile");
} else {
console.log("Preloader: No visible Vimeo background iframe detected on load.");
}
const shouldWaitForVideo = !!visibleVimeoIframe;
// Initialize videoReady state: If no video visible, consider it 'ready'.
videoReady = !shouldWaitForVideo;
// --- Preloader Hide Function (with minimum display time) ---
function checkAndHidePreloader() {
// Prevent running if already hidden or elements missing
if (preloaderHidden || !preloader || !preloaderCounter) return;
// Check conditions: page loaded AND video ready (or not needed)
if (pageLoadComplete && videoReady) {
preloaderHidden = true; // Mark as hidden early to prevent race conditions
console.log('Preloader: Conditions met. Calculating hide delay...');
// Stop counter interval and failsafe timeout
if (preloaderCounterInterval) clearInterval(preloaderCounterInterval);
if (preloaderFailsafeTimeout) clearTimeout(preloaderFailsafeTimeout);
// Ensure 100% is displayed
preloaderCounter.textContent = '100%';
// Calculate time needed to meet minimum display duration
const elapsedTime = Date.now() - startTime;
const delayNeeded = Math.max(0, minimumDisplayTime - elapsedTime);
console.log(`Preloader: Elapsed: ${elapsedTime}ms, Delaying hide by: ${delayNeeded}ms to meet minimum of ${minimumDisplayTime}ms`);
// Use calculated delay before starting fade-out animation
setTimeout(() => {
preloader.classList.add('preloader-hidden');
preloader.setAttribute('aria-busy', 'false'); // Accessibility update
// Remove from layout after animation (match CSS transition duration)
setTimeout(() => {
preloader.style.display = 'none';
console.log('Preloader: Set display to none.');
}, 500); // Should match your CSS transition duration for opacity/visibility
}, delayNeeded);
} else {
// Optional log for debugging if called but conditions aren't met
// console.log('checkAndHidePreloader called but conditions not met:', { pageLoadComplete, videoReady });
}
}
// --- Preloader Failsafe Function ---
function forceHidePreloader() {
if (!preloaderHidden) {
console.warn('Preloader failsafe triggered after timeout. Forcing hide.');
pageLoadComplete = true; // Force completion states
videoReady = true;
checkAndHidePreloader(); // Attempt to hide gracefully
}
}
// --- Preloader Event Listener: Window Load ---
window.addEventListener('load', function() {
console.log('Preloader: window.load event fired.');
pageLoadComplete = true;
checkAndHidePreloader();
});
// --- Preloader: Initialize Vimeo Player API (if needed) ---
if (shouldWaitForVideo) {
console.log("Preloader: Initializing Vimeo Player API for the visible iframe...");
try {
// Ensure the Vimeo Player API script is loaded before this runs
if (typeof Vimeo === 'undefined' || !Vimeo.Player) {
console.error("Preloader: Vimeo Player API not loaded or available. Video readiness cannot be checked.");
videoReady = true; // Treat video as ready to not block indefinitely
checkAndHidePreloader(); // Check if page load is ready
} else {
const player = new Vimeo.Player(visibleVimeoIframe);
player.on('playing', function() {
console.log('Preloader: Visible Vimeo player "playing" event fired.');
if (!videoReady) { // Ensure this runs only once
videoReady = true;
checkAndHidePreloader();
}
});
player.on('error', function(error) {
console.error('Preloader: Visible Vimeo player error:', error);
if (!videoReady) { // Prevent calling check multiple times
videoReady = true; // Don't block preloader on video error
checkAndHidePreloader();
}
});
// Optional: Add loaded listener as a fallback in case playing never fires?
// player.on('loaded', function() { ... });
}
} catch (error) {
console.error("Preloader: Error initializing or using Vimeo Player API:", error);
if (!videoReady) { // Prevent calling check multiple times
videoReady = true; // Don't block preloader if API fails
checkAndHidePreloader();
}
}
} else {
console.log("Preloader: Skipping Vimeo Player API initialization (no visible video).");
}
// --- Preloader Counter Animation ---
// Start only if conditions are not already met (preventing instant 100% jump if possible)
if (!pageLoadComplete || !videoReady) {
console.log("Preloader: Starting counter animation.");
preloaderCounterInterval = setInterval(function() {
if (preloaderHidden) { // Stop if hidden prematurely
clearInterval(preloaderCounterInterval);
return;
}
if (preloaderCount < 99) {
preloaderCount++;
preloaderCounter.textContent = preloaderCount + '%';
} else {
// Stop incrementing counter at 99 if loading isn't finished.
// It will be forced to 100% in checkAndHidePreloader when ready.
// We can clear interval here if everything IS loaded, just waiting for min display time
if (pageLoadComplete && videoReady) {
clearInterval(preloaderCounterInterval);
console.log("Preloader: Counter reached 99%, conditions met, stopping interval.");
}
}
}, 30); // Adjust interval timing (e.g., 30-50ms)
} else {
// If conditions already met before interval logic runs (very fast load), attempt hide.
console.log("Preloader: Conditions met before counter interval setup, attempting hide.");
checkAndHidePreloader();
}
// --- Preloader Failsafe Timeout ---
// Set a timeout to hide the preloader regardless after X seconds
preloaderFailsafeTimeout = setTimeout(forceHidePreloader, 15000); // 15 seconds failsafe
}); // End DOMContentLoaded