// Global scripts that will be used across all pages // Initialize tooltips function initTooltips() { const tooltipTriggers = document.querySelectorAll('[data-tooltip]'); tooltipTriggers.forEach(trigger => { const tooltip = document.createElement('div'); tooltip.className = 'tooltip-text bg-gray-800 text-white text-xs rounded py-1 px-2 absolute z-50 invisible'; tooltip.textContent = trigger.dataset.tooltip; trigger.appendChild(tooltip); trigger.addEventListener('mouseenter', () => { tooltip.classList.remove('invisible'); tooltip.classList.add('visible'); }); trigger.addEventListener('mouseleave', () => { tooltip.classList.remove('visible'); tooltip.classList.add('invisible'); }); }); } // Initialize modals function initModals() { const modalButtons = document.querySelectorAll('[data-modal-toggle]'); modalButtons.forEach(button => { const modalId = button.dataset.modalToggle; const modal = document.getElementById(modalId); const closeButtons = modal.querySelectorAll('[data-modal-hide]'); button.addEventListener('click', () => { modal.classList.remove('hidden'); modal.classList.add('flex'); document.body.classList.add('overflow-hidden'); }); closeButtons.forEach(closeButton => { closeButton.addEventListener('click', () => { modal.classList.remove('flex'); modal.classList.add('hidden'); document.body.classList.remove('overflow-hidden'); }); }); // Close when clicking outside modal.addEventListener('click', (e) => { if (e.target === modal) { modal.classList.remove('flex'); modal.classList.add('hidden'); document.body.classList.remove('overflow-hidden'); } }); }); } // Mobile menu toggle function initMobileMenu() { const mobileMenuButton = document.querySelector('[data-collapse-toggle="mobile-menu"]'); if (!mobileMenuButton) return; const mobileMenu = document.getElementById('mobile-menu'); mobileMenuButton.addEventListener('click', () => { mobileMenu.classList.toggle('hidden'); const expanded = mobileMenuButton.getAttribute('aria-expanded') === 'true'; mobileMenuButton.setAttribute('aria-expanded', !expanded); }); } // Dropdown toggle function initDropdowns() { const dropdownButtons = document.querySelectorAll('[data-dropdown-toggle]'); dropdownButtons.forEach(button => { const dropdownId = button.dataset.dropdownToggle; const dropdown = document.getElementById(dropdownId); button.addEventListener('click', () => { dropdown.classList.toggle('hidden'); }); // Close when clicking outside document.addEventListener('click', (e) => { if (!button.contains(e.target) && !dropdown.contains(e.target)) { dropdown.classList.add('hidden'); } }); }); } // Tab functionality function initTabs() { const tabButtons = document.querySelectorAll('[data-tab-toggle]'); tabButtons.forEach(button => { button.addEventListener('click', () => { const tabId = button.dataset.tabToggle; const tabContainer = button.closest('[data-tab-container]'); // Hide all tabs in the container tabContainer.querySelectorAll('[data-tab-content]').forEach(tab => { tab.classList.add('hidden'); }); // Show the selected tab document.getElementById(tabId).classList.remove('hidden'); // Update active state of buttons tabContainer.querySelectorAll('[data-tab-toggle]').forEach(btn => { btn.classList.remove('active'); btn.classList.add('text-gray-400'); btn.classList.remove('text-white', 'border-purple-500'); }); button.classList.add('active', 'text-white', 'border-purple-500'); button.classList.remove('text-gray-400'); }); }); } // Initialize everything when DOM is loaded document.addEventListener('DOMContentLoaded', () => { initTooltips(); initModals(); initMobileMenu(); initDropdowns(); initTabs(); // Smooth scroll 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' }); } }); }); }); // Price ticker functionality class PriceTicker { constructor() { this.ticker = document.querySelector('custom-price-ticker'); if (!this.ticker) return; this.coins = [ { symbol: 'BTC', name: 'Bitcoin', price: 0, change: 0 }, { symbol: 'ETH', name: 'Ethereum', price: 0, change: 0 }, { symbol: 'XRP', name: 'Ripple', price: 0, change: 0 }, { symbol: 'LTC', name: 'Litecoin', price: 0, change: 0 }, { symbol: 'ADA', name: 'Cardano', price: 0, change: 0 }, { symbol: 'DOGE', name: 'Dogecoin', price: 0, change: 0 }, ]; this.fetchPrices(); } async fetchPrices() { try { // In a real app, you would fetch from a real API // This is a mock implementation this.coins = this.coins.map(coin => { const basePrice = Math.random() * 10000 + 1000; const price = parseFloat(basePrice.toFixed(2)); const change = parseFloat((Math.random() * 10 - 5).toFixed(2)); return { ...coin, price, change }; }); this.render(); // Update prices every 10 seconds setTimeout(() => this.fetchPrices(), 10000); } catch (error) { console.error('Error fetching prices:', error); } } render() { if (!this.ticker) return; this.ticker.innerHTML = `
${this.coins.map(coin => `
${coin.symbol} $${coin.price.toLocaleString()} ${coin.change >= 0 ? '+' : ''}${coin.change}%
`).join('')}
`; } startAnimation() { if (!this.ticker) return; const marquee = this.ticker.querySelector('.animate-marquee'); if (!marquee) return; // Calculate animation duration based on content width const contentWidth = marquee.scrollWidth; const duration = contentWidth / 50; // Adjust speed as needed marquee.style.animationDuration = `${duration}s`; } } // Initialize price ticker when DOM is loaded document.addEventListener('DOMContentLoaded', () => { new PriceTicker(); });