const paths = { close: 'M6 6l12 12M18 6 6 18', prev: 'M15 5l-7 7 7 7', next: 'M9 5l7 7-7 7', }; function button(className, name, label) { const element = document.createElement('button'); element.type = 'button'; element.className = `lightbox__btn ${className}`; element.setAttribute('aria-label', label); element.innerHTML = ``; return element; } export function initLightbox(gallery) { const links = [...gallery.querySelectorAll('.gallery__link')]; if (!links.length || typeof HTMLDialogElement !== 'function') return; const { labelPrev, labelNext, labelClose } = gallery.dataset; const dialog = document.createElement('dialog'); dialog.className = 'lightbox'; const figure = document.createElement('figure'); figure.className = 'lightbox__figure'; const image = document.createElement('img'); image.className = 'lightbox__img'; image.decoding = 'async'; figure.append(image); const count = document.createElement('p'); count.className = 'lightbox__count'; const close = button('lightbox__close', 'close', labelClose); const prev = button('lightbox__prev', 'prev', labelPrev); const next = button('lightbox__next', 'next', labelNext); dialog.append(figure, count, close, prev, next); document.body.append(dialog); if (links.length < 2) { prev.hidden = true; next.hidden = true; count.hidden = true; } let current = 0; function show(index) { current = (index + links.length) % links.length; const link = links[current]; image.src = link.dataset.full || link.href; image.width = Number(link.dataset.width) || 0; image.height = Number(link.dataset.height) || 0; image.alt = link.querySelector('img')?.alt ?? ''; count.textContent = `${current + 1} / ${links.length}`; } function open(index) { show(index); dialog.showModal(); document.documentElement.classList.add('lightbox-open'); } links.forEach((link, index) => { link.addEventListener('click', (event) => { if (event.metaKey || event.ctrlKey || event.shiftKey) return; event.preventDefault(); open(index); }); }); dialog.addEventListener('close', () => { document.documentElement.classList.remove('lightbox-open'); links[current].focus(); }); close.addEventListener('click', () => dialog.close()); prev.addEventListener('click', () => show(current - 1)); next.addEventListener('click', () => show(current + 1)); // a click on the dark area around the image closes it figure.addEventListener('click', (event) => { if (event.target === figure) dialog.close(); }); dialog.addEventListener('keydown', (event) => { if (event.key === 'ArrowLeft') show(current - 1); if (event.key === 'ArrowRight') show(current + 1); }); let startX = null; figure.addEventListener('pointerdown', (event) => { if (event.pointerType !== 'mouse') startX = event.clientX; }); figure.addEventListener('pointerup', (event) => { if (startX === null) return; const distance = event.clientX - startX; startX = null; if (Math.abs(distance) > 50 && links.length > 1) show(current + (distance < 0 ? 1 : -1)); }); figure.addEventListener('pointercancel', () => (startX = null)); }