204 lines
6.3 KiB
JavaScript
204 lines
6.3 KiB
JavaScript
// Assume that currentGalleryImages is already declared in app.js.
|
|
// Only declare currentGalleryIndex if it isn't defined already.
|
|
if (typeof currentGalleryIndex === "undefined") {
|
|
var currentGalleryIndex = -1;
|
|
}
|
|
|
|
function openGalleryModal(relUrl) {
|
|
document.body.style.overflow = 'hidden'; // Disable background scrolling.
|
|
currentGalleryIndex = currentGalleryImages.indexOf(relUrl);
|
|
showGalleryImage(relUrl);
|
|
document.getElementById('gallery-modal').style.display = 'flex';
|
|
}
|
|
|
|
function showGalleryImage(relUrl) {
|
|
const fullUrl = '/media/' + relUrl;
|
|
const modal = document.getElementById('gallery-modal');
|
|
const currentImage = document.getElementById('gallery-modal-content');
|
|
const loader = document.getElementById('loader-container');
|
|
const closeBtn = document.getElementById('gallery-close');
|
|
|
|
// Set a timeout for showing the loader after 500ms.
|
|
let loaderTimeout = setTimeout(() => {
|
|
loader.style.display = 'flex';
|
|
}, 500);
|
|
|
|
// Preload the new image.
|
|
const tempImg = new Image();
|
|
tempImg.src = fullUrl;
|
|
|
|
tempImg.onload = function () {
|
|
clearTimeout(loaderTimeout);
|
|
loader.style.display = 'none';
|
|
|
|
// Select all current images in the gallery modal
|
|
const existingImages = document.querySelectorAll('#gallery-modal img');
|
|
|
|
// Create a new image element for the transition
|
|
const newImage = document.createElement('img');
|
|
newImage.src = fullUrl;
|
|
newImage.style.position = 'absolute';
|
|
newImage.style.top = '50%'; // Center vertically
|
|
newImage.style.left = '50%'; // Center horizontally
|
|
newImage.style.transform = 'translate(-50%, -50%)'; // Ensure centering
|
|
newImage.style.maxWidth = '95vw'; // Prevent overflow on large screens
|
|
newImage.style.maxHeight = '95vh'; // Prevent overflow on tall screens
|
|
newImage.style.transition = 'opacity 0.5s ease-in-out';
|
|
newImage.style.opacity = 0; // Start fully transparent
|
|
newImage.id = 'gallery-modal-content';
|
|
|
|
// Append new image on top of existing ones
|
|
modal.appendChild(newImage);
|
|
|
|
// Fade out all old images and fade in the new one
|
|
setTimeout(() => {
|
|
existingImages.forEach(img => {
|
|
img.style.opacity = 0; // Apply fade-out
|
|
});
|
|
newImage.style.opacity = 1; // Fade in the new image
|
|
}, 10);
|
|
|
|
// Wait for fade-out to finish, then remove all old images
|
|
setTimeout(() => {
|
|
existingImages.forEach(img => {
|
|
if (img.parentNode) {
|
|
img.parentNode.removeChild(img); // Remove old images
|
|
}
|
|
});
|
|
}, 510); // 500ms for fade-out + small buffer
|
|
|
|
// Preload the next image
|
|
preloadNextImage();
|
|
};
|
|
|
|
|
|
tempImg.onerror = function() {
|
|
clearTimeout(loaderTimeout);
|
|
loader.style.display = 'none';
|
|
console.error('Error loading image:', fullUrl);
|
|
};
|
|
}
|
|
|
|
function preloadNextImage() {
|
|
if (currentGalleryIndex < currentGalleryImages.length - 1) {
|
|
const nextImage = new Image();
|
|
nextImage.src = '/media/' + currentGalleryImages[currentGalleryIndex + 1];
|
|
}
|
|
}
|
|
|
|
function closeGalleryModal() {
|
|
document.getElementById('gallery-modal').style.display = 'none';
|
|
document.body.style.overflow = ''; // Restore scrolling.
|
|
}
|
|
|
|
function handleGalleryImageClick(e) {
|
|
if (e.target.classList.contains('gallery-next') || e.target.classList.contains('gallery-prev')) {
|
|
return; // Prevent conflict
|
|
}
|
|
|
|
const imgRect = this.getBoundingClientRect();
|
|
if (e.clientX < imgRect.left + imgRect.width / 2) {
|
|
if (currentGalleryIndex > 0) {
|
|
currentGalleryIndex--;
|
|
showGalleryImage(currentGalleryImages[currentGalleryIndex]);
|
|
}
|
|
} else {
|
|
if (currentGalleryIndex < currentGalleryImages.length - 1) {
|
|
currentGalleryIndex++;
|
|
showGalleryImage(currentGalleryImages[currentGalleryIndex]);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
function initGallerySwipe() {
|
|
let touchStartX = 0;
|
|
let touchEndX = 0;
|
|
const galleryModal = document.getElementById('gallery-modal');
|
|
|
|
galleryModal.addEventListener('touchstart', function(e) {
|
|
touchStartX = e.changedTouches[0].screenX;
|
|
}, false);
|
|
|
|
galleryModal.addEventListener('touchend', function(e) {
|
|
touchEndX = e.changedTouches[0].screenX;
|
|
handleSwipe();
|
|
}, false);
|
|
|
|
function handleSwipe() {
|
|
const deltaX = touchEndX - touchStartX;
|
|
if (Math.abs(deltaX) > 50) { // Swipe threshold.
|
|
if (deltaX > 0) { // Swipe right: previous image.
|
|
if (currentGalleryIndex > 0) {
|
|
currentGalleryIndex--;
|
|
showGalleryImage(currentGalleryImages[currentGalleryIndex]);
|
|
}
|
|
} else { // Swipe left: next image.
|
|
if (currentGalleryIndex < currentGalleryImages.length - 1) {
|
|
currentGalleryIndex++;
|
|
showGalleryImage(currentGalleryImages[currentGalleryIndex]);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
function initGalleryControls() {
|
|
const nextButton = document.querySelector('.gallery-next');
|
|
const prevButton = document.querySelector('.gallery-prev');
|
|
const closeButton = document.getElementById('gallery-close');
|
|
|
|
if (nextButton) {
|
|
nextButton.addEventListener('click', function () {
|
|
if (currentGalleryIndex < currentGalleryImages.length - 1) {
|
|
currentGalleryIndex++;
|
|
showGalleryImage(currentGalleryImages[currentGalleryIndex]);
|
|
}
|
|
});
|
|
}
|
|
|
|
if (prevButton) {
|
|
prevButton.addEventListener('click', function () {
|
|
if (currentGalleryIndex > 0) {
|
|
currentGalleryIndex--;
|
|
showGalleryImage(currentGalleryImages[currentGalleryIndex]);
|
|
}
|
|
});
|
|
}
|
|
|
|
if (closeButton) {
|
|
closeButton.addEventListener('click', closeGalleryModal);
|
|
}
|
|
}
|
|
|
|
|
|
function initGallery() {
|
|
const galleryImage = document.getElementById('gallery-modal-content');
|
|
if (galleryImage) {
|
|
galleryImage.addEventListener('click', handleGalleryImageClick);
|
|
}
|
|
initGallerySwipe();
|
|
initGalleryControls();
|
|
|
|
// Close modal when clicking outside the image.
|
|
const galleryModal = document.getElementById('gallery-modal');
|
|
galleryModal.addEventListener('click', function(e) {
|
|
if (e.target === galleryModal) {
|
|
closeGalleryModal();
|
|
}
|
|
});
|
|
|
|
}
|
|
|
|
// Initialize the gallery once the DOM content is loaded.
|
|
if (document.readyState === "loading") {
|
|
document.addEventListener('DOMContentLoaded', initGallery);
|
|
} else {
|
|
initGallery();
|
|
}
|