211 lines
7.0 KiB
JavaScript
211 lines
7.0 KiB
JavaScript
// /app/static/js/modal-pagination.js
|
|
document.addEventListener('DOMContentLoaded', () => {
|
|
const modal = document.getElementById('imageModal');
|
|
const modalImage = document.getElementById('modalImage');
|
|
const modalPrev = document.getElementById('modalPrev');
|
|
const modalNext = document.getElementById('modalNext');
|
|
const modalClose = document.getElementById('modalClose');
|
|
const modalImageWrapper = document.querySelector('.modal-image-wrapper');
|
|
|
|
modalImage.setAttribute('draggable', 'false');
|
|
|
|
let images = Array.from(document.querySelectorAll('.img-clickable'));
|
|
let currentIndex = -1;
|
|
let isZoomed = false;
|
|
let isDragging = false;
|
|
let startX, startY, scrollLeft, scrollTop;
|
|
let dragStartX = 0;
|
|
let dragStartY = 0;
|
|
let dragMoved = false;
|
|
|
|
const hasNextPageInput = document.getElementById('hasNextPage');
|
|
const nextPageUrlInput = document.getElementById('nextPageUrl');
|
|
const hasPrevPageInput = document.getElementById('hasPrevPage');
|
|
const prevPageUrlInput = document.getElementById('prevPageUrl');
|
|
|
|
function updateImage(index) {
|
|
const img = images[index];
|
|
modalImage.src = img.dataset.full;
|
|
currentIndex = index;
|
|
resetZoom();
|
|
}
|
|
|
|
function openModal(index) {
|
|
modal.classList.add('active');
|
|
updateImage(index);
|
|
history.replaceState({ modalIndex: index }, '', window.location.href);
|
|
}
|
|
|
|
function closeModal() {
|
|
modal.classList.remove('active');
|
|
modalImage.src = '';
|
|
currentIndex = -1;
|
|
resetZoom();
|
|
history.replaceState({}, '', window.location.pathname + window.location.search);
|
|
}
|
|
|
|
function showNext() {
|
|
if (currentIndex < images.length - 1) {
|
|
updateImage(currentIndex + 1);
|
|
} else if (hasNextPageInput?.value === "true") {
|
|
fetch(nextPageUrlInput.value)
|
|
.then(res => res.text())
|
|
.then(html => {
|
|
const parser = new DOMParser();
|
|
const doc = parser.parseFromString(html, 'text/html');
|
|
const newGallery = doc.querySelector('.gallery-grid');
|
|
const newImages = doc.querySelectorAll('.img-clickable');
|
|
|
|
if (newGallery && newImages.length > 0) {
|
|
const gallery = document.querySelector('.gallery-grid');
|
|
gallery.innerHTML = newGallery.innerHTML;
|
|
|
|
images = Array.from(document.querySelectorAll('.img-clickable'));
|
|
images.forEach((img, i) => {
|
|
img.addEventListener('click', () => openModal(i));
|
|
});
|
|
|
|
const newHasNext = doc.getElementById('hasNextPage')?.value || "false";
|
|
const newNextUrl = doc.getElementById('nextPageUrl')?.value || "";
|
|
const newHasPrev = doc.getElementById('hasPrevPage')?.value || "false";
|
|
const newPrevUrl = doc.getElementById('prevPageUrl')?.value || "";
|
|
|
|
hasNextPageInput.value = newHasNext;
|
|
nextPageUrlInput.value = newNextUrl;
|
|
hasPrevPageInput.value = newHasPrev;
|
|
prevPageUrlInput.value = newPrevUrl;
|
|
|
|
history.pushState({}, '', nextPageUrlInput.value);
|
|
openModal(0);
|
|
}
|
|
});
|
|
}
|
|
}
|
|
|
|
function showPrev() {
|
|
if (currentIndex > 0) {
|
|
updateImage(currentIndex - 1);
|
|
} else if (hasPrevPageInput?.value === "true") {
|
|
fetch(prevPageUrlInput.value)
|
|
.then(res => res.text())
|
|
.then(html => {
|
|
const parser = new DOMParser();
|
|
const doc = parser.parseFromString(html, 'text/html');
|
|
const newGallery = doc.querySelector('.gallery-grid');
|
|
const newImages = doc.querySelectorAll('.img-clickable');
|
|
|
|
if (newGallery && newImages.length > 0) {
|
|
const gallery = document.querySelector('.gallery-grid');
|
|
gallery.innerHTML = newGallery.innerHTML;
|
|
|
|
images = Array.from(document.querySelectorAll('.img-clickable'));
|
|
images.forEach((img, i) => {
|
|
img.addEventListener('click', () => openModal(i));
|
|
});
|
|
|
|
const newHasNext = doc.getElementById('hasNextPage')?.value || "false";
|
|
const newNextUrl = doc.getElementById('nextPageUrl')?.value || "";
|
|
const newHasPrev = doc.getElementById('hasPrevPage')?.value || "false";
|
|
const newPrevUrl = doc.getElementById('prevPageUrl')?.value || "";
|
|
|
|
hasNextPageInput.value = newHasNext;
|
|
nextPageUrlInput.value = newNextUrl;
|
|
hasPrevPageInput.value = newHasPrev;
|
|
prevPageUrlInput.value = newPrevUrl;
|
|
|
|
history.pushState({}, '', prevPageUrlInput.value);
|
|
openModal(images.length - 1);
|
|
}
|
|
});
|
|
}
|
|
}
|
|
|
|
function toggleZoom() {
|
|
isZoomed = !isZoomed;
|
|
modalImageWrapper.classList.toggle('zoomed', isZoomed);
|
|
modalImageWrapper.style.cursor = isZoomed ? 'grab' : '';
|
|
if (!isZoomed) {
|
|
modalImageWrapper.scrollLeft = 0;
|
|
modalImageWrapper.scrollTop = 0;
|
|
}
|
|
}
|
|
|
|
function resetZoom() {
|
|
isZoomed = false;
|
|
modalImageWrapper.classList.remove('zoomed');
|
|
modalImageWrapper.scrollLeft = 0;
|
|
modalImageWrapper.scrollTop = 0;
|
|
modalImageWrapper.style.cursor = '';
|
|
}
|
|
|
|
modalImageWrapper.addEventListener('mousedown', (e) => {
|
|
if (!isZoomed) return;
|
|
isDragging = true;
|
|
dragMoved = false;
|
|
modalImageWrapper.style.cursor = 'grabbing';
|
|
startX = e.pageX - modalImageWrapper.offsetLeft;
|
|
startY = e.pageY - modalImageWrapper.offsetTop;
|
|
scrollLeft = modalImageWrapper.scrollLeft;
|
|
scrollTop = modalImageWrapper.scrollTop;
|
|
dragStartX = e.pageX;
|
|
dragStartY = e.pageY;
|
|
});
|
|
|
|
modalImageWrapper.addEventListener('mouseleave', () => {
|
|
isDragging = false;
|
|
if (isZoomed) modalImageWrapper.style.cursor = 'grab';
|
|
});
|
|
|
|
modalImageWrapper.addEventListener('mouseup', () => {
|
|
isDragging = false;
|
|
if (isZoomed) modalImageWrapper.style.cursor = 'grab';
|
|
});
|
|
|
|
modalImageWrapper.addEventListener('mousemove', (e) => {
|
|
if (!isDragging || !isZoomed) return;
|
|
e.preventDefault();
|
|
dragMoved = true;
|
|
const x = e.pageX - modalImageWrapper.offsetLeft;
|
|
const y = e.pageY - modalImageWrapper.offsetTop;
|
|
const walkX = x - startX;
|
|
const walkY = y - startY;
|
|
modalImageWrapper.scrollLeft = scrollLeft - walkX;
|
|
modalImageWrapper.scrollTop = scrollTop - walkY;
|
|
});
|
|
|
|
modalImageWrapper.addEventListener('click', (e) => {
|
|
if (dragMoved) {
|
|
dragMoved = false;
|
|
return;
|
|
}
|
|
toggleZoom();
|
|
});
|
|
|
|
modalClose?.addEventListener('click', closeModal);
|
|
modalPrev?.addEventListener('click', showPrev);
|
|
modalNext?.addEventListener('click', showNext);
|
|
|
|
modal.addEventListener('click', (e) => {
|
|
if (e.target === modal) closeModal();
|
|
});
|
|
|
|
document.addEventListener('keydown', (e) => {
|
|
if (!modal.classList.contains('active')) return;
|
|
if (e.key === 'ArrowRight') showNext();
|
|
if (e.key === 'ArrowLeft') showPrev();
|
|
if (e.key === 'Escape') closeModal();
|
|
});
|
|
|
|
images.forEach((img, index) => {
|
|
img.addEventListener('click', () => openModal(index));
|
|
});
|
|
|
|
window.addEventListener('popstate', () => {
|
|
if (modal.classList.contains('active')) {
|
|
closeModal();
|
|
} else {
|
|
location.reload();
|
|
}
|
|
});
|
|
});
|