0 images

Your gallery is empty

Click + Add Images to load from URLs or drag & drop local files. Images from a GitHub repo path can be added as a list of raw URLs.

if (window.GALLERY_IMAGES && Array.isArray(window.GALLERY_IMAGES)) { window.GALLERY_IMAGES.forEach(img => addImage(img.src, img.name || img.src.split('/').pop())); } // ─── GRID COLUMNS ─── function setGrid(n) { currentCols = n; document.getElementById('gallery').style.setProperty('--cols', n); document.querySelectorAll('.grid-toggle button').forEach((b, i) => { b.classList.toggle('active', [2,3,4,6][i] === n); }); } // ─── ADD IMAGE ─── function addImage(src, name) { const idx = images.length; images.push({ src, name: name || src.split('/').pop() }); renderCard(idx); updateCount(); document.getElementById('empty').classList.remove('visible'); } function renderCard(idx) { const { src, name } = images[idx]; const gallery = document.getElementById('gallery'); const card = document.createElement('div'); card.className = 'card skeleton'; card.style.animationDelay = `${(idx % 20) * 30}ms`; const img = document.createElement('img'); img.alt = name; img.loading = 'lazy'; const overlay = document.createElement('div'); overlay.className = 'card-overlay'; overlay.innerHTML = `${name}`; img.onload = () => card.classList.remove('skeleton'); img.onerror = () => { card.classList.remove('skeleton'); card.style.background = '#1a1a1a'; card.innerHTML = `
Could not load image
`; }; img.src = src; card.appendChild(img); card.appendChild(overlay); card.addEventListener('click', () => openLightbox(idx)); gallery.appendChild(card); } function updateCount() { document.getElementById('count-num').textContent = images.length; } // ─── LIGHTBOX ─── function openLightbox(idx) { lbIndex = idx; showLightboxImage(); document.getElementById('lightbox').classList.add('open'); document.body.style.overflow = 'hidden'; } function closeLightbox() { document.getElementById('lightbox').classList.remove('open'); document.body.style.overflow = ''; } function showLightboxImage() { const { src, name } = images[lbIndex]; document.getElementById('lb-img').src = src; document.getElementById('lb-name').textContent = name; document.getElementById('lb-pos').textContent = `${lbIndex + 1} / ${images.length}`; } function navLightbox(dir) { lbIndex = (lbIndex + dir + images.length) % images.length; showLightboxImage(); } // ─── KEYBOARD ─── document.addEventListener('keydown', e => { const lb = document.getElementById('lightbox'); if (lb.classList.contains('open')) { if (e.key === 'ArrowRight') navLightbox(1); if (e.key === 'ArrowLeft') navLightbox(-1); if (e.key === 'Escape') closeLightbox(); } else if (e.key === 'Escape') { closeModal(); } }); document.getElementById('lightbox').addEventListener('click', e => { if (e.target === document.getElementById('lightbox')) closeLightbox(); }); // ─── MODAL ─── function openModal() { document.getElementById('modal').classList.add('open'); } function closeModal() { document.getElementById('modal').classList.remove('open'); document.getElementById('urlInput').value = ''; document.getElementById('fileInput').value = ''; } function loadFromInputs() { const urls = document.getElementById('urlInput').value .split('\n') .map(u => u.trim()) .filter(u => u.length > 0); urls.forEach(url => addImage(url, url.split('/').pop().split('?')[0])); closeModal(); } // ─── FILE UPLOAD ─── function handleFiles(files) { Array.from(files).forEach(file => { const reader = new FileReader(); reader.onload = e => addImage(e.target.result, file.name); reader.readAsDataURL(file); }); } // ─── DRAG & DROP ─── const dropZone = document.getElementById('dropZone'); document.getElementById('modal').addEventListener('dragover', e => { e.preventDefault(); dropZone.classList.add('drag'); }); document.getElementById('modal').addEventListener('dragleave', () => { dropZone.classList.remove('drag'); }); document.getElementById('modal').addEventListener('drop', e => { e.preventDefault(); dropZone.classList.remove('drag'); if (e.dataTransfer.files.length) handleFiles(e.dataTransfer.files); });