Marhaban ya Ramadhan

Ruang Berbagi dan Informasi
`; shadow.appendChild(tpl.content.cloneNode(true)); // ELEMENTS (shadow-scoped) const $ = sel => shadow.querySelector(sel); const frame = $('.wf2-frame'); const shell = $('.wf2-shell'); const toggle = $('.wf2-toggle'); const badge = $('.wf2-badge'); const articlesWrap = $('#wf2Articles'); const filterInput = $('#wf2Filter'); const preview = $('#wf2Preview'); const previewTitle = $('#wf2PreviewTitle'); const previewExcerpt = $('#wf2PreviewExcerpt'); const previewRead = $('#wf2PreviewRead'); const collapseBtn = shadow.querySelector('[data-action="collapse"]'); const statusEl = $('#wf2Status'); const welcomeEl = $('#wf2Welcome'); // CONFIG const CONFIG = { feedUrl: 'https://www.warkasa1919.com/feeds/posts/default?alt=json-in-script&max-results=8', pollIntervalMs: 30000, localKeys: { state: 'wf2_state_v2', lastRead: 'wf2_lastread_v2' }, initialCollapsed: true, maxArticles: 8, jsonpTimeout: 8000 }; let ARTICLES = []; let lastRead = new Date(0); let pollTimer = null; let activeJsonp = null; // {cbName, script} // Utilities const esc = s => String(s).replace(/[&<>'"`]/g, c=>({"&":"&","<":"<",">":">","'":"'","\"":""","`":"`"})[c]); const safeDate = s => { try{ const d = new Date(s); return isNaN(d.getTime()) ? new Date(0) : d; }catch(e){ return new Date(0); } }; function cleanupJsonp(cbName, script){ if(script) script.remove(); if(cbName) try{ delete window[cbName]; }catch(e){ window[cbName] = undefined; } activeJsonp = null; } // JSONP helper (unique callback) function jsonpFetch(url, timeout=CONFIG.jsonpTimeout){ return new Promise((resolve, reject)=>{ if(activeJsonp) cleanupJsonp(activeJsonp.cbName, activeJsonp.script); const cbName = '__wf2_cb_' + Math.random().toString(36).slice(2); const script = document.createElement('script'); let timer = null; const finish = (data, err) => { clearTimeout(timer); cleanupJsonp(cbName, script); if(err) reject(err); else resolve(data); }; window[cbName] = data => finish(data); timer = setTimeout(()=> finish(null, new Error('timeout')), timeout); script.src = url + (url.includes('?') ? '&' : '?') + 'callback=' + cbName; script.async = true; script.onerror = ()=> finish(null, new Error('error')); document.head.appendChild(script); activeJsonp = { cbName, script }; }); } // parse blogger JSON -> simple items function parseBlogger(json){ try{ const posts = (json.feed && json.feed.entry) ? json.feed.entry.slice(0, CONFIG.maxArticles) : []; return posts.map((e, i)=>{ const title = e.title && e.title.$t ? e.title.$t : ('Artikel ' + (i+1)); const content = e.content ? e.content.$t : (e.summary ? e.summary.$t : ''); const excerpt = content.replace(/<[^>]+>/g,'').slice(0,140).trim(); let url = ''; if (e.link && e.link.length){ const alt = e.link.find(l=>l.rel==='alternate'); url = alt ? alt.href : e.link[0].href; } const date = e.published ? safeDate(e.published.$t || e.published) : new Date(); return { id: e.id ? (e.id.$t||('p'+i)) : ('p'+i), title, excerpt, url, date }; }); }catch(e){ return []; } } // render function render(filter=''){ articlesWrap.innerHTML = ''; const q = (filter||'').toLowerCase().trim(); const frag = document.createDocumentFragment(); let shown = 0; ARTICLES.forEach(a=>{ if (q && !(a.title.toLowerCase().includes(q) || a.excerpt.toLowerCase().includes(q))) return; const el = document.createElement('div'); el.className = 'wf2-article'; el.tabIndex = 0; el.dataset.url = a.url; el.innerHTML = '

' + esc(a.title) + '

' + esc(a.excerpt) + '

'; if (a.date > lastRead){ const n = document.createElement('span'); n.className = 'wf2-badge'; n.textContent = 'BARU'; n.style.cssText = 'position:absolute; right:8px; top:8px; background:#47ff57;'; // badge BARU hijau el.appendChild(n); } frag.appendChild(el); shown++; }); if (!shown){ const m=document.createElement('div'); m.style.padding='8px'; m.style.color='var(--c4)'; m.textContent='Tidak ditemukan artikel.'; articlesWrap.appendChild(m); } else { articlesWrap.appendChild(frag); } } // open preview function openPreview(item){ previewTitle.textContent = item.title; previewExcerpt.textContent = item.excerpt; previewRead.href = item.url; preview.setAttribute('aria-hidden','false'); previewRead.focus(); } function closePreview(){ preview.setAttribute('aria-hidden','true'); filterInput.focus(); } // badge update function updateBadge(){ const unread = ARTICLES.filter(a=>a.date>lastRead).length; badge.textContent = unread || ''; badge.setAttribute('aria-hidden', unread ? 'false' : 'true'); } // persistence function loadState(){ try{ const s = localStorage.getItem(CONFIG.localKeys.state); const lr = localStorage.getItem(CONFIG.localKeys.lastRead); if (lr) lastRead = safeDate(lr); let state = CONFIG.initialCollapsed ? 'collapsed' : (s||'expanded'); if (s === 'closed') state = 'collapsed'; frame.setAttribute('data-state', state); updateAriaExpanded(state === 'expanded'); }catch(e){} } function saveLastRead(){ try{ localStorage.setItem(CONFIG.localKeys.lastRead, new Date().toISOString()); }catch(e){} } function saveState(s){ try{ localStorage.setItem(CONFIG.localKeys.state, s); }catch(e){} } // UI helpers function updateAriaExpanded(isExpanded){ const state = isExpanded ? 'true' : 'false'; toggle.setAttribute('aria-expanded', state); collapseBtn.setAttribute('aria-expanded', state); shell.setAttribute('aria-hidden', isExpanded ? 'false' : 'true'); } function expand(){ if(frame.getAttribute('data-state') === 'expanded') return; frame.setAttribute('data-state','expanded'); lastRead = new Date(); saveLastRead(); updateBadge(); render(filterInput.value); saveState('expanded'); updateAriaExpanded(true); // Fokuskan input filter untuk pengalaman seluler yang lebih cepat setTimeout(() => filterInput.focus(), 250); } function collapse(){ if(frame.getAttribute('data-state') === 'collapsed') return; frame.setAttribute('data-state','collapsed'); closePreview(); saveState('collapsed'); updateAriaExpanded(false); } function close(){ frame.setAttribute('aria-hidden','true'); saveState('closed'); stopPolling(); } // polling with visibility pause function startPolling(){ stopPolling(); pollTimer = setInterval(()=> { if (document.hidden) return; fetchAndUpdate(true).catch(()=>{}); }, CONFIG.pollIntervalMs); } function stopPolling(){ if (pollTimer){ clearInterval(pollTimer); pollTimer = null; } if(activeJsonp) cleanupJsonp(activeJsonp.cbName, activeJsonp.script); } // fetch and update async function fetchAndUpdate(isPoll=false){ statusEl.textContent = 'Mencari...'; try{ const json = await jsonpFetch(CONFIG.feedUrl); const items = parseBlogger(json); if (items.length){ ARTICLES = items.map(it=>({...it, date: safeDate(it.date)})); render(filterInput.value); updateBadge(); statusEl.textContent = 'Online'; return; } }catch(e){ statusEl.textContent = 'Offline / Feed error'; } if (!ARTICLES.length && !isPoll) { ARTICLES = [ {id:'f1',title:'Nusantara',excerpt:'Baca artikel menarik seputar Nusantara.',url:'/p/nusantara.html',date:safeDate('2025-12-10T10:00:00Z')}, {id:'f2',title:'Teknologi Canggih',excerpt:'Update informasi terkait Teknologi terkini.',url:'/p/teknologi.html',date:safeDate('2025-12-12T12:00:00Z')} ]; } render(filterInput.value); updateBadge(); } // filter debounce function debounce(func, delay){ let timeoutId; return function(...args){ clearTimeout(timeoutId); timeoutId = setTimeout(() => func.apply(this, args), delay); }; } // init function boot(){ if (!frame) return; loadState(); // greeting const h = new Date().getHours(); let g='Halo'; if (h>=4 && h<11) g='Selamat pagi'; else if (h<15) g='Selamat siang'; else if (h<18) g='Selamat sore'; else g='Selamat malam'; welcomeEl.textContent = g + '!'; // event delegation shadow.addEventListener('click', (ev)=>{ const t = ev.target; // Toggle if (t === toggle || t.closest('.wf2-toggle')) { frame.getAttribute('data-state') === 'collapsed' ? expand() : collapse(); } // Actions const act = t.closest('[data-action]'); if (act){ const a = act.dataset.action; if (a==='collapse') collapse(); else if (a==='close') close(); else if (a==='top') { window.scrollTo({top:0,behavior:'smooth'}); // Tutup widget setelah men-scroll ke atas di mobile if (window.innerWidth <= 720) collapse(); } } // Article Click const article = t.closest('.wf2-article'); if (article){ const item = ARTICLES.find(a => a.url === article.dataset.url); if (item) openPreview(item); } // Preview Close if (t.id === 'wf2PreviewClose') closePreview(); }); // keyboard support for Enter/Space on article & Escape shadow.addEventListener('keydown', (e)=>{ const t = e.target; if ((e.key==='Enter' || e.key===' ') && t.classList.contains('wf2-article')){ e.preventDefault(); t.click(); } if (e.key==='Escape'){ if (preview.getAttribute('aria-hidden') === 'false') closePreview(); else if (frame.getAttribute('data-state') === 'expanded') collapse(); } }); // filter debounce filterInput.addEventListener('input', debounce(()=> render(filterInput.value), 200)); // visibility change -> pause polling document.addEventListener('visibilitychange', ()=>{ if (document.hidden) stopPolling(); else startPolling(); }); // initial fetch fetchAndUpdate().then(()=> startPolling()).catch(()=> startPolling()); } // start boot(); // exposed minimal API (on host element only) rootHost.WF2 = { refresh: ()=> fetchAndUpdate(), open: expand, close: collapse, getArticles: ()=> ARTICLES.slice() }; })();

Dukung Warkasa1919

Bantu kami terus menghadirkan artikel premium, fitur canggih & projek digital berkualitas.

Tutup