/** * Countdown Timer for LeafBox Technologies Website * Creates an animated countdown to New Year */ class CountdownTimer { constructor() { this.targetDate = this.getNewYearDate(); this.elements = { days: document.getElementById('days'), hours: document.getElementById('hours'), minutes: document.getElementById('minutes'), seconds: document.getElementById('seconds') }; this.interval = null; this.isActive = false; this.init(); } init() { if (this.hasValidElements()) { this.start(); } else { console.warn('Countdown elements not found'); } } hasValidElements() { return this.elements.days && this.elements.hours && this.elements.minutes && this.elements.seconds; } getNewYearDate() { const now = new Date(); const currentYear = now.getFullYear(); const nextYear = currentYear + 1; // New Year is January 1st of next year at 00:00:00 return new Date(nextYear, 0, 1, 0, 0, 0, 0); } start() { if (this.isActive) return; this.isActive = true; this.updateCountdown(); // Initial update this.interval = setInterval(() => this.updateCountdown(), 1000); } stop() { if (!this.isActive) return; this.isActive = false; clearInterval(this.interval); this.interval = null; } updateCountdown() { const now = new Date().getTime(); const timeLeft = this.targetDate.getTime() - now; if (timeLeft <= 0) { this.handleCountdownComplete(); return; } const timeComponents = this.calculateTimeComponents(timeLeft); this.displayTime(timeComponents); this.addAnimationEffects(timeComponents); } calculateTimeComponents(timeLeft) { const days = Math.floor(timeLeft / (1000 * 60 * 60 * 24)); const hours = Math.floor((timeLeft % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60)); const minutes = Math.floor((timeLeft % (1000 * 60 * 60)) / (1000 * 60)); const seconds = Math.floor((timeLeft % (1000 * 60)) / 1000); return {days, hours, minutes, seconds}; } displayTime({days, hours, minutes, seconds}) { this.updateElement(this.elements.days, this.padNumber(days)); this.updateElement(this.elements.hours, this.padNumber(hours)); this.updateElement(this.elements.minutes, this.padNumber(minutes)); this.updateElement(this.elements.seconds, this.padNumber(seconds)); } updateElement(element, value) { if (!element) return; const currentValue = element.textContent; if (currentValue !== value) { // Add flash effect when number changes element.parentElement.classList.add('number-change'); element.textContent = value; // Remove flash effect after animation setTimeout(() => { element.parentElement.classList.remove('number-change'); }, 500); } } padNumber(number) { return number.toString().padStart(2, '0'); } addAnimationEffects({days, hours, minutes, seconds}) { // Add special effects for certain values if (seconds === 0) { // New minute reached this.addMinuteEffect(); } if (minutes === 0 && seconds === 0) { // New hour reached this.addHourEffect(); } if (hours === 0 && minutes === 0 && seconds === 0) { // New day reached this.addDayEffect(); } // Add glow effect when we're close to New Year const daysUntilNewYear = Math.floor((this.targetDate.getTime() - new Date().getTime()) / (1000 * 60 * 60 * 24)); if (daysUntilNewYear <= 7) { this.addNearNewYearEffect(); } } addMinuteEffect() { const countdownContainer = document.querySelector('.countdown'); if (countdownContainer) { countdownContainer.style.animation = 'none'; setTimeout(() => { countdownContainer.style.animation = 'pulse 0.5s ease-in-out'; }, 10); setTimeout(() => { countdownContainer.style.animation = ''; }, 500); } } addHourEffect() { // Add a more pronounced effect for hours const countdownNumbers = document.querySelectorAll('.countdown-number'); countdownNumbers.forEach(number => { number.style.animation = 'bounce 0.6s ease-in-out'; setTimeout(() => { number.style.animation = ''; }, 600); }); } addDayEffect() { // Add special effect for days const daysElement = this.elements.days; if (daysElement) { daysElement.style.color = '#B89B5F'; daysElement.style.textShadow = '0 0 10px #B89B5F'; setTimeout(() => { daysElement.style.color = ''; daysElement.style.textShadow = ''; }, 2000); } } addNearNewYearEffect() { const countdownItems = document.querySelectorAll('.countdown-item'); countdownItems.forEach(item => { item.style.border = '1px solid #B89B5F'; item.style.boxShadow = '0 0 15px rgba(184, 155, 95, 0.3)'; }); } handleCountdownComplete() { this.stop(); this.displayNewYearMessage(); this.addCelebrationEffect(); } displayNewYearMessage() { const countdownContainer = document.querySelector('.countdown-container'); if (countdownContainer) { const message = document.createElement('div'); message.className = 'new-year-message'; message.innerHTML = `

🎉 Happy New Year! 🎉

Wishing you innovation and success in ${this.targetDate.getFullYear()}!

`; countdownContainer.appendChild(message); // Remove countdown const countdown = document.getElementById('countdown'); if (countdown) { countdown.style.display = 'none'; } } } addCelebrationEffect() { // Add confetti effect (simplified version) this.createConfetti(); // Update page title temporarily const originalTitle = document.title; document.title = '🎊 Happy New Year - LeafBox Technologies! 🎊'; setTimeout(() => { document.title = originalTitle; }, 10000); } createConfetti() { const confettiContainer = document.createElement('div'); confettiContainer.style.position = 'fixed'; confettiContainer.style.top = '0'; confettiContainer.style.left = '0'; confettiContainer.style.width = '100%'; confettiContainer.style.height = '100%'; confettiContainer.style.pointerEvents = 'none'; confettiContainer.style.zIndex = '9999'; document.body.appendChild(confettiContainer); // Create confetti pieces for (let i = 0; i < 50; i++) { const confetti = document.createElement('div'); confetti.style.position = 'absolute'; confetti.style.width = '10px'; confetti.style.height = '10px'; confetti.style.backgroundColor = this.getRandomColor(); confetti.style.left = Math.random() * 100 + '%'; confetti.style.top = '-10px'; confetti.style.borderRadius = '50%'; confetti.style.animation = `confettiFall ${Math.random() * 3 + 2}s linear forwards`; confettiContainer.appendChild(confetti); } // Add confetti animation if (!document.getElementById('confetti-styles')) { const style = document.createElement('style'); style.id = 'confetti-styles'; style.textContent = ` @keyframes confettiFall { to { transform: translateY(100vh) rotate(360deg); opacity: 0; } } `; document.head.appendChild(style); } // Remove confetti after animation setTimeout(() => { confettiContainer.remove(); }, 5000); } getRandomColor() { const colors = ['#B89B5F', '#2A4B3A', '#FDFDFC', '#5F87B8']; return colors[Math.floor(Math.random() * colors.length)]; } // Public methods pause() { this.stop(); } resume() { this.start(); } setTargetDate(date) { this.targetDate = date; if (this.isActive) { this.stop(); this.start(); } } destroy() { this.stop(); // Clean up DOM const newYearMessage = document.querySelector('.new-year-message'); if (newYearMessage) { newYearMessage.remove(); } const countdown = document.getElementById('countdown'); if (countdown) { countdown.style.display = ''; } } // Utility method to format time for display formatTime(ms) { const components = this.calculateTimeComponents(ms); return `${this.padNumber(components.days)}d ${this.padNumber(components.hours)}h ${this.padNumber(components.minutes)}m ${this.padNumber(components.seconds)}s`; } // Get time remaining getTimeRemaining() { const now = new Date().getTime(); const timeLeft = this.targetDate.getTime() - now; return Math.max(0, timeLeft); } // Check if countdown is complete isComplete() { return this.getTimeRemaining() <= 0; } } // Initialize countdown when DOM is loaded document.addEventListener('DOMContentLoaded', function() { // Check if we're close to New Year const now = new Date(); const newYear = new Date(now.getFullYear() + 1, 0, 1); const daysUntilNewYear = Math.floor((newYear.getTime() - now.getTime()) / (1000 * 60 * 60 * 24)); // Only show countdown if we're within 60 days of New Year if (daysUntilNewYear <= 60) { const countdownTimer = new CountdownTimer(); // Make it globally accessible for debugging window.countdownTimer = countdownTimer; // Add keyboard controls for accessibility document.addEventListener('keydown', (e) => { if (e.key === ' ') { // Spacebar e.preventDefault(); if (countdownTimer.isActive) { countdownTimer.pause(); } else { countdownTimer.resume(); } } }); // Handle visibility change for performance document.addEventListener('visibilitychange', () => { if (document.hidden) { countdownTimer.pause(); } else { countdownTimer.resume(); } }); } else { // Hide countdown if we're too far from New Year const countdownContainer = document.querySelector('.countdown-container'); if (countdownContainer) { countdownContainer.style.display = 'none'; } } }); // Export for module systems if (typeof module !== 'undefined' && module.exports) { module.exports = CountdownTimer; }