/** * NewsTicker - Scrolling news/announcement ticker for landscape kiosk mode * Fetches from /api/ticker with fallback to hardcoded messages */ class NewsTicker { constructor(options = {}) { this.options = { containerId: options.containerId || 'news-ticker', fetchUrl: options.fetchUrl || '/api/ticker', refreshInterval: options.refreshInterval || 5 * 60 * 1000, // 5 minutes fallbackMessages: options.fallbackMessages || [ 'Välkommen till Ambassaderna', 'Håll dörren stängd', 'Tvättstugan stänger kl 22:00' ], ...options }; this.container = null; this.contentEl = null; this.messages = []; this.refreshTimer = null; this.init(); } init() { this.container = document.getElementById(this.options.containerId); if (!this.container) return; this.contentEl = this.container.querySelector('.ticker-content'); if (!this.contentEl) { this.contentEl = document.createElement('div'); this.contentEl.className = 'ticker-content'; this.container.appendChild(this.contentEl); } this.fetchMessages(); this.refreshTimer = setInterval(() => this.fetchMessages(), this.options.refreshInterval); } async fetchMessages() { try { const response = await fetch(this.options.fetchUrl); if (response.ok) { const data = await response.json(); if (Array.isArray(data.messages) && data.messages.length > 0) { this.messages = data.messages; } else { this.messages = this.options.fallbackMessages; } } else { this.messages = this.options.fallbackMessages; } } catch { this.messages = this.options.fallbackMessages; } this.render(); } render() { if (!this.contentEl || this.messages.length === 0) return; const separator = ' \u2022 '; // bullet separator const text = this.messages.join(separator); // Duplicate text for seamless infinite scroll loop this.contentEl.textContent = text + separator + text; } stop() { if (this.refreshTimer) { clearInterval(this.refreshTimer); this.refreshTimer = null; } } } // ES module export export { NewsTicker }; // Keep window reference for backward compatibility window.NewsTicker = NewsTicker;