This repository has been archived on 2026-05-31. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
imagerepo/app/static/js/modal-pagination.js
T
2025-08-03 11:40:32 -04:00

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();
}
});
});