Blogger — PDF List & Viewer
PDF Series Manager — Blogger
यह पेज आपको PDF URLs या लोकल फाइल्स को सीरियली जोड़कर एक सूची बनाने और उन्हें रेस्पॉन्सिव तरीके से देखने देता है। Blogger में HTML मोड में चिपकाएँ।
Tip: Use public PDF links (Google Drive / Dropbox direct link) for persistent embedding.
How to host on Google Drive: upload → Share → Anyone with link can view → use that share URL as PDF URL.
`;
// Use srcdoc if supported
try{ pdfViewer.srcdoc = wrapper; }catch(e){ pdfViewer.src = fallback; }
}
// smooth scroll to viewer
setTimeout(()=> viewerWrap.scrollIntoView({behavior:'smooth'}),120);
}
// Add button handler
addBtn.addEventListener('click', async ()=>{
const title = titleEl.value.trim();
const url = urlEl.value.trim();
const file = fileEl.files && fileEl.files[0];
if(!url && !file){ alert('PDF का URL डालें या local PDF अपलोड करें'); return }
if(file){
const blobUrl = URL.createObjectURL(file);
items.push({ title: title || file.name, blobName: file.name, blobUrl, created: Date.now() });
// note: blobUrl will only work in this browser session/device
} else {
// normalize Dropbox share links (common pattern) to direct link if possible
let norm = url;
if(norm.includes('dropbox.com') && !norm.includes('dl=1')){
norm = norm.replace('?dl=0','') + (norm.includes('?')?'&dl=1':'?dl=1');
}
items.push({ title: title || ('PDF ' + (items.length+1)), url: norm, created: Date.now() });
}
titleEl.value=''; urlEl.value=''; fileEl.value=''; save(); renderList();
});
// Export
document.getElementById('exportBtn').addEventListener('click', ()=>{
const exportItems = items.map(it=>({title:it.title,url:it.url,created:it.created,blobName:it.blobName}));
const blob = new Blob([JSON.stringify(exportItems, null, 2)], {type:'application/json'});
const a = document.createElement('a'); a.href = URL.createObjectURL(blob); a.download = 'pdf_list.json'; document.body.appendChild(a); a.click(); a.remove();
});
// Import
document.getElementById('importBtn').addEventListener('click', ()=>{
const inp = document.createElement('input'); inp.type='file'; inp.accept='.json,application/json'; inp.onchange = e=>{
const f = e.target.files[0]; if(!f) return; const r = new FileReader(); r.onload = ev=>{
try{
const arr = JSON.parse(ev.target.result);
if(!Array.isArray(arr)) throw new Error('Invalid file');
// imported entries will not have blobUrl; user should add local files manually if needed
arr.forEach(it=> items.push({title: it.title, url: it.url, created: it.created || Date.now()}));
save(); renderList();
}catch(err){ alert('Import failed: ' + err.message) }
}; r.readAsText(f);
}; inp.click();
});
document.getElementById('clearBtn').addEventListener('click', ()=>{ if(confirm('Clear entire list?')){ items=[]; save(); renderList(); }});
// initial render
renderList();
// Optional: allow double-click on list item to view
listEl.addEventListener('dblclick', e=>{
const node = e.target.closest('.item'); if(!node) return; const idx = Array.from(listEl.children).indexOf(node); if(idx>=0) openViewer(idx);
});
// Accessibility: keyboard 'Enter' to add when focused in URL or title
[titleEl,urlEl].forEach(el=> el.addEventListener('keydown', ev=>{ if(ev.key==='Enter'){ addBtn.click(); ev.preventDefault(); }}));