📜
gallery.js
Back
📝 Javascript ⚡ Executable Ctrl+S: Save • Ctrl+R: Run • Ctrl+F: Find
/* ---------- Gallery Management ---------- */ /* DOM Elements */ const crumbsEl = document.getElementById('crumbs'); const foldersTrack = document.getElementById('foldersTrack'); const emptyFolders = document.getElementById('emptyFolders'); const galleryTrack = document.getElementById('galleryTrack'); const emptyImages = document.getElementById('emptyImages'); const goUpBtn = document.getElementById('goUpBtn'); const refreshBtn = document.getElementById('refreshBtn'); /* State */ let currentSub = ''; /* ---------- API Communication ---------- */ async function fetchDir(sub = '') { const res = await fetch(`media.php?sub=${encodeURIComponent(sub)}`, {cache:'no-store'}); if(!res.ok) throw new Error(`HTTP ${res.status}`); return await res.json(); } /* ---------- Rendering Functions ---------- */ function renderBreadcrumb(bc) { crumbsEl.innerHTML = ''; bc.forEach((c, i) => { const b = document.createElement('button'); b.textContent = c.label; b.onclick = () => openSub(c.sub); crumbsEl.appendChild(b); if(i < bc.length - 1) { const s = document.createElement('span'); s.className = 'sep'; s.textContent = '›'; crumbsEl.appendChild(s); } }); } function renderFolders(items) { foldersTrack.innerHTML = ''; emptyFolders.hidden = !!items.length; for(const f of items) { const card = document.createElement('div'); card.className = 'folder-card'; card.innerHTML = `<span>📂</span><span>${f.name}</span>`; card.onclick = () => openSub(f.sub); foldersTrack.appendChild(card); } } function renderImages(items) { galleryTrack.innerHTML = ''; emptyImages.hidden = !!items.length; for(const im of items) { const img = document.createElement('img'); img.alt = im.name; img.loading = 'lazy'; img.decoding = 'async'; img.src = im.url; img.onclick = () => window.CoreAPI.setImage(im.url); galleryTrack.appendChild(img); } } /* ---------- Auto Tile Size Detection ---------- */ function inferTileFromPath(sub) { if (!sub) return null; const parts = sub.split('/').filter(Boolean).reverse(); for (const p of parts) { const n = parseInt(p, 10); if (String(n) === p && n > 0) return n; } return null; } /* ---------- Navigation ---------- */ async function openSub(sub) { try { const data = await fetchDir(sub); currentSub = data.cwd || ''; renderBreadcrumb(data.breadcrumb || []); renderFolders(data.folders || []); renderImages(data.images || []); // Auto-detect tile size from folder name const inferred = inferTileFromPath(currentSub); if (inferred) { window.CoreAPI.setTileSize(inferred); } } catch(err) { console.error(err); alert('Failed to load folder.'); } } function parentOf(sub) { if(!sub) return ''; const p = sub.split('/').filter(Boolean); p.pop(); return p.join('/'); } /* ---------- Event Handlers ---------- */ function initGalleryEvents() { goUpBtn.addEventListener('click', () => openSub(parentOf(currentSub))); refreshBtn.addEventListener('click', () => openSub(currentSub)); } /* ---------- Initialization ---------- */ function initializeGallery() { try { // Get DOM elements crumbsEl = document.getElementById('crumbs'); foldersTrack = document.getElementById('foldersTrack'); emptyFolders = document.getElementById('emptyFolders'); galleryTrack = document.getElementById('galleryTrack'); emptyImages = document.getElementById('emptyImages'); goUpBtn = document.getElementById('goUpBtn'); refreshBtn = document.getElementById('refreshBtn'); // Check required DOM elements and dependencies if (!crumbsEl || !foldersTrack || !galleryTrack || !goUpBtn) { throw new Error('Required DOM elements not found'); } if (!window.CoreAPI || typeof window.CoreAPI.setImage !== 'function') { throw new Error('CoreAPI not available'); } initGalleryEvents(); openSub(''); // Load root folder } catch (error) { alert(`Gallery module failed to initialize: ${error.message}\n\nNote: Gallery requires media.php to be present and working.`); // Don't throw here since gallery failure shouldn't break the whole app } } // Export API for other modules window.GalleryAPI = { openSub, currentSub: () => currentSub };