======================================================================== // =============================================== // 🔄 FALLBACK CONTENT SYSTEM - Enhanced Cache // =============================================== // Konfigurasi const FALLBACK_CONFIG = { CHECK_INTERVAL: 30000, // 30 detik CACHE_TIMEOUT: 86400000, // 24 jam (expired cache) CACHE_KEY: 'masjid_fallback_cache', DEBUG: true }; let fallbackSystem = { cachedContent: null, cacheTimestamp: null, isUsingFallback: false, checkInterval: null, // Inisialisasi sistem fallback init: function() { this.loadFromCache(); this.setupIframeMonitoring(); this.startPeriodicCheck(); this.log('Fallback system initialized'); }, // Load cache dari localStorage loadFromCache: function() { try { const cached = localStorage.getItem(FALLBACK_CONFIG.CACHE_KEY); if (cached) { const data = JSON.parse(cached); // Check if cache is not expired if (Date.now() - data.timestamp < FALLBACK_CONFIG.CACHE_TIMEOUT) { this.cachedContent = data.content; this.cacheTimestamp = data.timestamp; this.log('Cache loaded from localStorage', data.timestamp); } else { this.log('Cache expired, clearing...'); localStorage.removeItem(FALLBACK_CONFIG.CACHE_KEY); } } } catch (error) { this.log('Error loading cache:', error); } }, // Save content ke cache saveToCache: function(content) { try { const data = { content: content, timestamp: Date.now(), url: window.location.href }; localStorage.setItem(FALLBACK_CONFIG.CACHE_KEY, JSON.stringify(data)); this.cachedContent = content; this.cacheTimestamp = data.timestamp; this.log('Content cached successfully'); } catch (error) { this.log('Error saving cache:', error); } }, // Setup monitoring iframe setupIframeMonitoring: function() { const iframe = document.getElementById('mainFrame'); if (!iframe) return; // Event listener untuk iframe load iframe.addEventListener('load', () => { setTimeout(() => { this.checkIframeContent(); }, 1000); // Delay untuk memastikan content ter-load }); // Event listener untuk iframe error iframe.addEventListener('error', () => { this.log('Iframe error detected'); this.applyFallback(); }); }, // Check content iframe checkIframeContent: function() { try { const iframe = document.getElementById('mainFrame'); if (!iframe || !iframe.contentWindow) return; const iframeDoc = iframe.contentWindow.document; const body = iframeDoc.body; if (!body) { this.log('Iframe body not accessible'); return; } const content = body.innerHTML; const isError = this.isErrorContent(content); if (isError) { this.log('Error content detected in iframe'); this.applyFallback(); } else if (content.trim().length > 100) { // Minimal content check this.log('Valid content detected, updating cache'); this.saveToCache(content); this.isUsingFallback = false; } } catch (error) { this.log('Cannot access iframe content (CORS/Security):', error.message); // Jika tidak bisa akses content iframe (CORS), gunakan fallback this.applyFallback(); } }, // Check apakah content adalah error isErrorContent: function(content) { if (!content || content.trim().length < 50) return true; const errorPatterns = [ '404', 'not found', 'error', 'failed to load', 'connection refused', 'timeout', 'unavailable', 'page not found', 'server error' ]; const lowerContent = content.toLowerCase(); return errorPatterns.some(pattern => lowerContent.includes(pattern)); }, // Apply fallback content applyFallback: function() { if (!this.cachedContent) { this.log('No cached content available for fallback'); this.showNoConnectionMessage(); return; } try { const iframe = document.getElementById('mainFrame'); if (iframe && iframe.contentWindow && iframe.contentWindow.document) { iframe.contentWindow.document.body.innerHTML = this.cachedContent; this.isUsingFallback = true; this.log('Fallback content applied'); this.showFallbackIndicator(); } else { // Jika tidak bisa akses iframe, buat content div this.createFallbackDiv(); } } catch (error) { this.log('Error applying fallback:', error); this.createFallbackDiv(); } }, // Buat div fallback jika iframe tidak accessible createFallbackDiv: function() { const container = document.getElementById('content-container'); if (!container) return; // Hide iframe const iframe = document.getElementById('mainFrame'); if (iframe) iframe.style.display = 'none'; // Create fallback div let fallbackDiv = document.getElementById('fallback-content'); if (!fallbackDiv) { fallbackDiv = document.createElement('div'); fallbackDiv.id = 'fallback-content'; fallbackDiv.style.cssText = ` width: 100%; height: 100%; background: #000; color: #fff; overflow: hidden; `; container.appendChild(fallbackDiv); } fallbackDiv.innerHTML = this.cachedContent || this.getNoConnectionHTML(); this.isUsingFallback = true; this.log('Fallback div created'); this.showFallbackIndicator(); }, // Show "no connection" message showNoConnectionMessage: function() { this.createFallbackDiv(); const fallbackDiv = document.getElementById('fallback-content'); if (fallbackDiv) { fallbackDiv.innerHTML = this.getNoConnectionHTML(); } }, // HTML untuk "no connection" getNoConnectionHTML: function() { return `
📡

Koneksi Terputus

Mencoba menghubungkan kembali...

`; }, // Show fallback indicator showFallbackIndicator: function() { let indicator = document.getElementById('fallback-indicator'); if (!indicator) { indicator = document.createElement('div'); indicator.id = 'fallback-indicator'; indicator.style.cssText = ` position: fixed; top: 15px; left: 15px; background: #ff6b6b; color: white; padding: 8px 12px; border-radius: 15px; font-size: 12px; font-weight: bold; z-index: 10000; animation: pulse 2s infinite; `; indicator.innerHTML = '📄 Mode Offline'; document.body.appendChild(indicator); // Add CSS animation const style = document.createElement('style'); style.textContent = ` @keyframes pulse { 0% { opacity: 0.7; } 50% { opacity: 1; } 100% { opacity: 0.7; } } `; document.head.appendChild(style); } }, // Hide fallback indicator hideFallbackIndicator: function() { const indicator = document.getElementById('fallback-indicator'); if (indicator) { indicator.remove(); } }, // Restore normal iframe restoreNormalMode: function() { // Show iframe const iframe = document.getElementById('mainFrame'); if (iframe) iframe.style.display = 'block'; // Hide fallback div const fallbackDiv = document.getElementById('fallback-content'); if (fallbackDiv) fallbackDiv.style.display = 'none'; this.hideFallbackIndicator(); this.isUsingFallback = false; this.log('Restored to normal mode'); }, // Start periodic check startPeriodicCheck: function() { this.checkInterval = setInterval(() => { this.periodicCheck(); }, FALLBACK_CONFIG.CHECK_INTERVAL); this.log('Periodic check started'); }, // Periodic check function periodicCheck: function() { this.log('Running periodic check...'); // Check connection status const connectionStatus = lastStatus; // Dari sistem yang sudah ada if (connectionStatus === 'disconnected' || connectionStatus === 'degraded') { if (!this.isUsingFallback) { this.log('Connection issue detected, applying fallback'); this.applyFallback(); } } else if (connectionStatus === 'good' && this.isUsingFallback) { this.log('Connection restored, checking iframe content'); setTimeout(() => { this.checkIframeContent(); if (!this.isUsingFallback) { this.restoreNormalMode(); } }, 2000); } }, // Stop periodic check stop: function() { if (this.checkInterval) { clearInterval(this.checkInterval); this.checkInterval = null; } this.log('Fallback system stopped'); }, // Debug logging log: function(...args) { if (FALLBACK_CONFIG.DEBUG) { console.log('[FallbackSystem]', ...args); } } }; // Auto-initialize when DOM is ready if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', () => { setTimeout(() => fallbackSystem.init(), 2000); }); } else { setTimeout(() => fallbackSystem.init(), 2000); } // Cleanup on page unload window.addEventListener('beforeunload', () => { fallbackSystem.stop(); });