129 lines
4.3 KiB
JavaScript
129 lines
4.3 KiB
JavaScript
(function () {
|
|
window.initAlbum = function () {
|
|
var old = document.getElementById('lightbox')
|
|
if (old) old.remove()
|
|
|
|
var grid = document.getElementById('album-grid')
|
|
if (!grid) return
|
|
|
|
var items = Array.from(grid.children)
|
|
if (!items.length) return
|
|
|
|
var lastFocus = null
|
|
|
|
var lb = document.createElement('div')
|
|
lb.id = 'lightbox'
|
|
lb.setAttribute('role', 'dialog')
|
|
lb.setAttribute('aria-modal', 'true')
|
|
lb.innerHTML =
|
|
'<button id="lb-close" aria-label="Zamknij"><svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M18 6 6 18"/><path d="m6 6 12 12"/></svg></button>' +
|
|
'<button id="lb-prev" aria-label="Poprzednie"><svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m15 18-6-6 6-6"/></svg></button>' +
|
|
'<img src="" alt="">' +
|
|
'<button id="lb-next" aria-label="Następne"><svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m9 18 6-6-6-6"/></svg></button>'
|
|
document.body.appendChild(lb)
|
|
|
|
var lbImg = lb.querySelector('img')
|
|
var current = -1
|
|
|
|
function open(idx) {
|
|
lastFocus = document.activeElement
|
|
current = idx
|
|
var img = items[current].querySelector('img')
|
|
lbImg.removeAttribute('src')
|
|
lbImg.alt = ''
|
|
lb.classList.add('open')
|
|
lbImg.src = img.dataset.fullsrc
|
|
lbImg.alt = img.alt
|
|
lb.querySelector('#lb-close').focus()
|
|
}
|
|
|
|
function close() {
|
|
lb.classList.remove('open')
|
|
current = -1
|
|
if (lastFocus) lastFocus.focus()
|
|
}
|
|
|
|
function prev() {
|
|
if (current < 0) return
|
|
open((current - 1 + items.length) % items.length)
|
|
}
|
|
|
|
function next() {
|
|
if (current < 0) return
|
|
open((current + 1) % items.length)
|
|
}
|
|
|
|
function trapFocus(e) {
|
|
if (!lb.classList.contains('open')) return
|
|
var focusable = lb.querySelectorAll('button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])')
|
|
if (!focusable.length) return
|
|
var first = focusable[0]
|
|
var last = focusable[focusable.length - 1]
|
|
if (e.key === 'Tab') {
|
|
if (e.shiftKey) {
|
|
if (document.activeElement === first) {
|
|
e.preventDefault()
|
|
last.focus()
|
|
}
|
|
} else {
|
|
if (document.activeElement === last) {
|
|
e.preventDefault()
|
|
first.focus()
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
items.forEach(function (item, i) {
|
|
item.addEventListener('click', function () { open(i) })
|
|
item.addEventListener('keydown', function (e) {
|
|
if (e.key === 'Enter' || e.key === ' ') {
|
|
e.preventDefault()
|
|
open(i)
|
|
}
|
|
})
|
|
})
|
|
|
|
lb.querySelector('#lb-close').addEventListener('click', close)
|
|
lb.querySelector('#lb-prev').addEventListener('click', function (e) {
|
|
e.stopPropagation()
|
|
prev()
|
|
})
|
|
lb.querySelector('#lb-next').addEventListener('click', function (e) {
|
|
e.stopPropagation()
|
|
next()
|
|
})
|
|
|
|
document.addEventListener('keydown', function (e) {
|
|
trapFocus(e)
|
|
if (!lb.classList.contains('open')) return
|
|
if (e.key === 'Escape') { close(); e.preventDefault() }
|
|
if (e.key === 'ArrowLeft') { prev(); e.preventDefault() }
|
|
if (e.key === 'ArrowRight') { next(); e.preventDefault() }
|
|
})
|
|
|
|
lb.addEventListener('click', function (e) {
|
|
if (e.target === lb) close()
|
|
})
|
|
|
|
var touchStartX = 0
|
|
var touchStartY = 0
|
|
lb.addEventListener('touchstart', function (e) {
|
|
touchStartX = e.changedTouches[0].screenX
|
|
touchStartY = e.changedTouches[0].screenY
|
|
}, { passive: true })
|
|
|
|
lb.addEventListener('touchend', function (e) {
|
|
var dx = e.changedTouches[0].screenX - touchStartX
|
|
var dy = e.changedTouches[0].screenY - touchStartY
|
|
if (Math.abs(dx) > Math.abs(dy) && Math.abs(dx) > 50) {
|
|
if (dx < 0) next()
|
|
else prev()
|
|
}
|
|
}, { passive: true })
|
|
}
|
|
|
|
window.initAlbum()
|
|
|
|
document.addEventListener('htmx:afterSwap', window.initAlbum)
|
|
})()
|