Search/static/js/imageviewer.js

169 lines
6.9 KiB
JavaScript
Raw Normal View History

2024-10-22 21:58:06 +02:00
document.addEventListener('DOMContentLoaded', function() {
let viewerOpen = false;
let currentIndex = -1;
let imageList = [];
// Initialize imageList with all images on the page
function initializeImageList() {
imageList = Array.from(document.querySelectorAll('.image img.clickable'));
}
2024-10-22 21:58:06 +02:00
const viewerOverlay = document.getElementById('image-viewer-overlay');
2024-12-02 14:36:08 +01:00
// Set the innerHTML of viewerOverlay
2024-10-22 21:58:06 +02:00
viewerOverlay.innerHTML = `
<div id="image-viewer" class="image_view image_hide">
<div class="btn-nostyle">
<button class="btn-nostyle" id="viewer-prev-button">
<div class="material-icons-round icon_visibility clickable image-before">&#xe408;</div> <!-- navigate_before -->
</button>
<button class="btn-nostyle" id="viewer-next-button">
<div class="material-icons-round icon_visibility clickable image-next">&#xe409;</div> <!-- navigate_next -->
2024-10-22 21:58:06 +02:00
</button>
<button class="btn-nostyle" id="viewer-close-button">
<div class="material-icons-round icon_visibility clickable image-close">&#xe5cd;</div> <!-- close -->
2024-10-22 21:58:06 +02:00
</button>
</div>
2024-12-02 14:36:08 +01:00
<div class="view-image" id="viewer-image-container">
<img id="viewer-image" class="view-image-img" src="" alt="">
</div>
2024-10-22 21:58:06 +02:00
<p class="image-alt" id="viewer-title"></p>
2025-04-19 21:24:27 +02:00
<br>
2025-04-23 12:26:05 +02:00
<div class="search-type-icons" style="display:flex; justify-content:center; flex-wrap: wrap;">
2025-04-19 21:24:27 +02:00
<div class="icon-button">
<button class="material-icons-round clickable btn-nostyle" id="viewer-copy-link">
<span class="material-icons-round">&#xe37c;</span>
<p>Copy link</p>
</button>
</div>
<div class="icon-button">
<button class="material-icons-round clickable btn-nostyle" id="viewer-open-image">
<span class="material-icons-round">&#xe193;</span>
<p>Open image</p>
</button>
</div>
<div class="icon-button">
<button class="material-icons-round clickable btn-nostyle" id="viewer-open-source">
<span class="material-icons-round">&#xe366;</span>
<p>Go to source</p>
</button>
</div>
<div class="icon-button">
<button class="material-icons-round clickable btn-nostyle" id="viewer-download-image">
<span class="material-icons-round">&#xe2d1;</span>
<p>Download</p>
</button>
</div>
</div>
2024-10-22 21:58:06 +02:00
</div>
`;
2024-12-02 14:36:08 +01:00
const imageView = viewerOverlay.querySelector('#image-viewer');
const imagesContainer = document.querySelector('.images');
2024-10-22 21:58:06 +02:00
function openImageViewer(element) {
2025-04-19 21:24:27 +02:00
initializeImageList();
2024-10-22 21:58:06 +02:00
const parentImageDiv = element.closest('.image');
if (!parentImageDiv) return;
currentIndex = imageList.findIndex(img => img === parentImageDiv.querySelector('img.clickable'));
if (currentIndex === -1) return;
2024-10-22 21:58:06 +02:00
displayImage(currentIndex);
2024-10-22 21:58:06 +02:00
viewerOpen = true;
2024-12-02 14:36:08 +01:00
imagesContainer.classList.remove('images_viewer_hidden');
document.body.classList.add('viewer-open');
viewerOverlay.style.display = 'block';
2025-04-19 21:24:27 +02:00
imageView.classList.replace('image_hide', 'image_show');
}
2025-04-19 21:24:27 +02:00
let fullImageUrl, sourceUrl, proxyFullUrl;
function displayImage(index) {
if (index < 0 || index >= imageList.length) return;
2024-12-02 14:36:08 +01:00
imageList.forEach(img => {
const parentImageDiv = img.closest('.image');
2025-04-19 21:24:27 +02:00
parentImageDiv?.classList.remove('image_selected');
});
2025-04-19 21:24:27 +02:00
const imgElement = imageList[index];
const parentImageDiv = imgElement.closest('.image');
2025-04-19 21:24:27 +02:00
parentImageDiv?.classList.add('image_selected');
2024-12-02 14:36:08 +01:00
2025-04-19 21:24:27 +02:00
fullImageUrl = imgElement.getAttribute('data-full') || imgElement.src;
sourceUrl = imgElement.getAttribute('data-source');
proxyFullUrl = imgElement.getAttribute('data-proxy-full') || fullImageUrl;
2024-12-02 14:36:08 +01:00
2024-10-22 21:58:06 +02:00
const viewerImage = document.getElementById('viewer-image');
const viewerTitle = document.getElementById('viewer-title');
2025-04-19 21:24:27 +02:00
viewerTitle.textContent = imgElement.alt || 'Untitled';
viewerImage.onerror = () => viewerImage.src = proxyFullUrl;
viewerImage.onload = () => {};
viewerImage.src = fullImageUrl;
}
2024-10-22 21:58:06 +02:00
2025-04-19 21:24:27 +02:00
document.getElementById('viewer-copy-link').onclick = () => {
navigator.clipboard.writeText(window.location.origin + fullImageUrl).catch(console.error);
};
document.getElementById('viewer-open-image').onclick = () => {
window.open(fullImageUrl, '_blank');
};
document.getElementById('viewer-open-source').onclick = () => {
window.open(sourceUrl || proxyFullUrl, '_blank');
};
document.getElementById('viewer-download-image').onclick = (event) => {
event.stopPropagation();
const a = document.createElement('a');
a.href = fullImageUrl;
a.download = fullImageUrl.split('/').pop();
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
};
document.body.addEventListener('click', e => {
const clickableElement = e.target.closest('img.clickable, .img_title.clickable');
2024-10-22 21:58:06 +02:00
if (clickableElement) {
e.preventDefault();
openImageViewer(clickableElement);
}
});
function closeImageViewer() {
2025-04-19 21:24:27 +02:00
imageView.classList.replace('image_show', 'image_hide');
2024-10-22 21:58:06 +02:00
viewerOpen = false;
currentIndex = -1;
2024-12-02 14:36:08 +01:00
imagesContainer.classList.add('images_viewer_hidden');
document.body.classList.remove('viewer-open');
viewerOverlay.style.display = 'none';
2024-10-22 21:58:06 +02:00
2025-04-19 21:24:27 +02:00
imageList.forEach(img => img.closest('.image')?.classList.remove('image_selected'));
}
2025-04-19 21:24:27 +02:00
document.getElementById('viewer-close-button').onclick = closeImageViewer;
document.getElementById('viewer-prev-button').onclick = () => currentIndex > 0 && displayImage(--currentIndex);
document.getElementById('viewer-next-button').onclick = () => currentIndex < imageList.length - 1 && displayImage(++currentIndex);
2025-04-19 21:24:27 +02:00
document.addEventListener('click', e => {
if (viewerOpen && !viewerOverlay.contains(e.target) && !e.target.closest('.image')) {
closeImageViewer();
2024-10-22 21:58:06 +02:00
}
});
2025-04-19 21:24:27 +02:00
document.addEventListener('keydown', e => {
if (!viewerOpen) return;
if (e.key === 'Escape') closeImageViewer();
if (e.key === 'ArrowLeft' && currentIndex > 0) displayImage(--currentIndex);
if (e.key === 'ArrowRight' && currentIndex < imageList.length - 1) displayImage(++currentIndex);
});
});