Personal Website, vers. 1 (pushed far to late)
This commit is contained in:
commit
c8df66d3da
103 files changed
+8977
No files matched your search
@@ -0,0 +1,98 @@
|
||||
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 = `<svg class="icon" viewBox="0 0 24 24" aria-hidden="true"><path d="${paths[name]}"/></svg>`;
|
||||
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));
|
||||
}
|
||||
Reference in new issue
Block a user