/** * Exchange Rates Ticker — Frontend entrypoint. * * Measures the ticker content width and computes the CSS animation * duration based on the user-configured speed (px/sec), then sets * --crtoday-ticker-duration on each ticker widget. * * Also handles resize / mutation to recalculate when content changes. */ function initTickers(): void { const tickers = document.querySelectorAll('.crtoday-ticker'); tickers.forEach((ticker) => calibrate(ticker)); if (typeof ResizeObserver !== 'undefined') { const ro = new ResizeObserver((entries) => { for (const entry of entries) { const el = entry.target as HTMLElement; const ticker = el.closest('.crtoday-ticker'); if (ticker) { calibrate(ticker); } } }); tickers.forEach((ticker) => { const content = ticker.querySelector('.crtoday-ticker-content'); if (content) { ro.observe(content); } }); } } function calibrate(ticker: HTMLElement): void { const content = ticker.querySelector('.crtoday-ticker-content'); if (!content) return; const speed = parseInt(ticker.getAttribute('data-ticker-speed') || '40', 10); const clampedSpeed = Math.max(10, Math.min(200, speed)); const contentWidth = content.scrollWidth; if (contentWidth <= 0) return; const duration = contentWidth / clampedSpeed; ticker.style.setProperty('--crtoday-ticker-duration', `${duration.toFixed(2)}s`); } if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', initTickers); } else { initTickers(); }