/* Falah Shortcodes — Client Logic */ (function () { 'use strict'; const cfg = window.FalahSC || {}; // ── Prayer Times ───────────────────────────────────────────────────────── const prayerWidget = document.querySelector('.falah-prayer-times'); if (prayerWidget) { const city = prayerWidget.dataset.city || cfg.prayerCity || 'Kuala Lumpur'; const country = prayerWidget.dataset.country || cfg.prayerCountry || 'Malaysia'; const today = new Date(); const dd = String(today.getDate()).padStart(2, '0'); const mm = String(today.getMonth() + 1).padStart(2, '0'); const yyyy = today.getFullYear(); fetch(`https://api.aladhan.com/v1/timingsByCity/${dd}-${mm}-${yyyy}?city=${encodeURIComponent(city)}&country=${encodeURIComponent(country)}&method=3`) .then(r => r.json()) .then(data => { if (data.code !== 200) throw new Error('API error'); const t = data.data.timings; const h = data.data.date.hijri; const prayers = [ { key: 'Fajr', label: 'Fajr' }, { key: 'Sunrise', label: 'Sunrise' }, { key: 'Dhuhr', label: 'Dhuhr' }, { key: 'Asr', label: 'Asr' }, { key: 'Maghrib', label: 'Maghrib' }, { key: 'Isha', label: 'Isha' }, ]; const now = today.getHours() * 60 + today.getMinutes(); const grid = document.getElementById('falah-prayer-grid'); let nextName = '', nextTime = ''; grid.innerHTML = prayers.map(p => { const raw = t[p.key] || ''; const parts = raw.split(' ')[0].split(':'); const pMin = parseInt(parts[0], 10) * 60 + parseInt(parts[1], 10); const isNext = !nextName && pMin > now && p.key !== 'Sunrise'; if (isNext) { nextName = p.label; nextTime = raw.split(' ')[0]; } return `
${p.label}
${raw.split(' ')[0]}
`; }).join(''); const nextEl = document.getElementById('falah-next-prayer'); if (nextEl && nextName) { nextEl.textContent = `⏰ Next: ${nextName} at ${nextTime}`; } const hijriEl = document.getElementById('falah-hijri'); if (hijriEl) { hijriEl.textContent = `${h.day} ${h.month.en} ${h.year} AH`; } // Also update dashboard updateDashboardPrayer(nextName, nextTime); }) .catch(() => { const grid = document.getElementById('falah-prayer-grid'); if (grid) grid.innerHTML = '
Unable to load prayer times. Check your connection.
'; }); } function updateDashboardPrayer(name, time) { const np = document.getElementById('falah-dash-next-prayer'); const nt = document.getElementById('falah-dash-next-time'); if (np) np.textContent = name || '—'; if (nt) nt.textContent = time ? `at ${time}` : ''; } // ── Daily Verse ────────────────────────────────────────────────────────── const verseWidget = document.getElementById('falah-daily-verse'); if (verseWidget) { const verseNum = parseInt(verseWidget.dataset.verse, 10) || 1; fetch(`https://api.alquran.cloud/v1/ayah/${verseNum}/editions/quran-uthmani,en.asad`) .then(r => r.json()) .then(data => { if (data.code !== 200) throw new Error('API error'); const arabic = data.data[0]; const english = data.data[1]; document.getElementById('falah-verse-loading').style.display = 'none'; const content = document.getElementById('falah-verse-content'); content.style.display = 'block'; document.getElementById('falah-verse-arabic').textContent = arabic.text; document.getElementById('falah-verse-translation').textContent = `"${english.text}"`; document.getElementById('falah-verse-ref').textContent = `Surah ${arabic.surah.englishName} (${arabic.surah.number}:${arabic.numberInSurah})`; // Update dashboard const dv = document.getElementById('falah-dash-verse'); if (dv) dv.textContent = `${arabic.surah.englishName} ${arabic.surah.number}:${arabic.numberInSurah}`; }) .catch(() => { const loading = document.getElementById('falah-verse-loading'); if (loading) loading.innerHTML = '

Unable to load verse. Please try again.

'; }); } // ── Dhikr Counter ──────────────────────────────────────────────────────── const dhikrWidget = document.getElementById('falah-dhikr-widget'); if (dhikrWidget) { let list = []; try { list = JSON.parse(dhikrWidget.dataset.list || '[]'); } catch (e) {} const arabicMap = { 'SubhanAllah': 'سُبْحَانَ اللَّهِ', 'Alhamdulillah': 'الْحَمْدُ لِلَّهِ', 'Allahu Akbar': 'اللَّهُ أَكْبَرُ', 'La ilaha illallah': 'لَا إِلَٰهَ إِلَّا اللَّهُ', 'Astaghfirullah': 'أَسْتَغْفِرُ اللَّهَ', }; const storageKey = 'falah_dhikr_' + new Date().toDateString(); let state = JSON.parse(localStorage.getItem(storageKey) || '{"idx":0,"counts":[0,0,0,0,0],"total":0}'); const ring = document.getElementById('falah-ring'); const numEl = document.getElementById('falah-counter-number'); const targetEl = document.getElementById('falah-counter-target'); const arabicEl = document.getElementById('falah-dhikr-arabic'); const meaningEl = document.getElementById('falah-dhikr-meaning'); const sessionEl = document.getElementById('falah-session-total'); const tapBtn = document.getElementById('falah-btn-tap'); const resetBtn = document.getElementById('falah-btn-reset'); const circumference = 2 * Math.PI * 50; // r=50 function render() { const d = list[state.idx]; const cnt = state.counts[state.idx] || 0; const tgt = d ? d.target : 33; const pct = Math.min(cnt / tgt, 1); numEl.textContent = cnt; targetEl.textContent = `/ ${tgt}`; arabicEl.textContent = (d && arabicMap[d.text]) || ''; meaningEl.textContent = (d && d.meaning) || ''; ring.style.strokeDashoffset = circumference * (1 - pct); const total = state.counts.reduce((a, b) => a + b, 0); sessionEl.textContent = total > 0 ? `Session total: ${total} counts` : ''; // Dashboard const dd = document.getElementById('falah-dash-dhikr-count'); if (dd) dd.textContent = total; } function save() { localStorage.setItem(storageKey, JSON.stringify(state)); } // Button handlers document.querySelectorAll('.falah-dhikr-btn').forEach(btn => { btn.addEventListener('click', () => { state.idx = parseInt(btn.dataset.index, 10); document.querySelectorAll('.falah-dhikr-btn').forEach(b => b.classList.remove('active')); btn.classList.add('active'); save(); render(); }); }); tapBtn.addEventListener('click', () => { const d = list[state.idx]; const tgt = d ? d.target : 33; state.counts[state.idx] = (state.counts[state.idx] || 0) + 1; if (state.counts[state.idx] === tgt) { setTimeout(() => { // Flash completion numEl.style.color = '#1a7a4a'; setTimeout(() => { numEl.style.color = ''; }, 1000); }, 10); } save(); render(); }); resetBtn.addEventListener('click', () => { state.counts[state.idx] = 0; save(); render(); }); ring.style.strokeDasharray = circumference; render(); } // ── Qibla Compass ──────────────────────────────────────────────────────── const qiblaBtn = document.getElementById('falah-qibla-locate'); if (qiblaBtn) { qiblaBtn.addEventListener('click', () => { if (!navigator.geolocation) { qiblaBtn.textContent = '⚠️ Geolocation not supported'; return; } qiblaBtn.textContent = '📍 Getting location…'; qiblaBtn.disabled = true; navigator.geolocation.getCurrentPosition(pos => { const lat = pos.coords.latitude; const lon = pos.coords.longitude; const qiblaAngle = calcQibla(lat, lon); document.getElementById('falah-qibla-status').style.display = 'none'; document.getElementById('falah-qibla-display').style.display = 'block'; document.getElementById('falah-qibla-angle').textContent = `Qibla: ${Math.round(qiblaAngle)}° from North`; document.getElementById('falah-qibla-location').textContent = `Your location: ${lat.toFixed(4)}°, ${lon.toFixed(4)}°`; const needle = document.getElementById('falah-qibla-needle'); // Try device orientation if (window.DeviceOrientationEvent && typeof DeviceOrientationEvent.requestPermission === 'function') { DeviceOrientationEvent.requestPermission().then(perm => { if (perm === 'granted') listenOrientation(needle, qiblaAngle); }); } else if (window.DeviceOrientationEvent) { listenOrientation(needle, qiblaAngle); } else { needle.style.transform = `rotate(${qiblaAngle}deg)`; } }, () => { qiblaBtn.textContent = '⚠️ Location denied. Enable location access and try again.'; qiblaBtn.disabled = false; }); }); } function listenOrientation(needle, qiblaAngle) { window.addEventListener('deviceorientationabsolute', e => { const heading = e.alpha ? (360 - e.alpha) : 0; needle.style.transform = `rotate(${qiblaAngle - heading}deg)`; }, true); } function calcQibla(lat, lon) { // Kaaba coordinates const kLat = 21.3891; const kLon = 39.8579; const φ1 = lat * Math.PI / 180; const φ2 = kLat * Math.PI / 180; const Δλ = (kLon - lon) * Math.PI / 180; const y = Math.sin(Δλ) * Math.cos(φ2); const x = Math.cos(φ1) * Math.sin(φ2) - Math.sin(φ1) * Math.cos(φ2) * Math.cos(Δλ); const θ = Math.atan2(y, x); return ((θ * 180 / Math.PI) + 360) % 360; } // ── Dashboard ───────────────────────────────────────────────────────────── const dashDate = document.getElementById('falah-dash-date'); if (dashDate) { const opts = { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' }; dashDate.textContent = new Date().toLocaleDateString('en-GB', opts); } // Hijri date on dashboard fetch('https://api.aladhan.com/v1/gToH?date=' + new Date().toLocaleDateString('en-GB', { day: '2-digit', month: '2-digit', year: 'numeric' })) .then(r => r.json()) .then(data => { const h = data?.data?.hijri; if (!h) return; const dashHijri = document.getElementById('falah-dash-hijri'); if (dashHijri) dashHijri.textContent = `${h.day} ${h.month.en} ${h.year} AH`; const hijriEl = document.getElementById('falah-hijri'); if (hijriEl) hijriEl.textContent = `${h.day} ${h.month.en} ${h.year} AH`; }) .catch(() => {}); })();