185 lines
No EOL
7 KiB
JavaScript
185 lines
No EOL
7 KiB
JavaScript
// dynamicscrollingimages.js
|
|
(function() {
|
|
// Add loading effects to image and title
|
|
function addLoadingEffects(imgElement) {
|
|
const title = imgElement.closest('.image').querySelector('.img_title');
|
|
imgElement.classList.add('loading-image');
|
|
title.classList.add('title-loading');
|
|
}
|
|
|
|
function removeLoadingEffects(imgElement) {
|
|
const title = imgElement.closest('.image').querySelector('.img_title');
|
|
imgElement.classList.remove('loading-image');
|
|
title.classList.remove('title-loading');
|
|
|
|
if (imgElement.src.endsWith('/images/missing.svg')) {
|
|
imgElement.closest('.image').remove();
|
|
}
|
|
}
|
|
|
|
// Modified handleImageError with theme-consistent error handling
|
|
function handleImageError(imgElement, retryCount = 3, retryDelay = 1000) {
|
|
const container = imgElement.closest('.image');
|
|
const title = container.querySelector('.img_title');
|
|
|
|
if (retryCount > 0) {
|
|
setTimeout(() => {
|
|
imgElement.src = imgElement.getAttribute('data-full');
|
|
imgElement.onerror = () => handleImageError(imgElement, retryCount - 1, retryDelay);
|
|
}, retryDelay);
|
|
} else {
|
|
imgElement.classList.remove('loading-image');
|
|
title.classList.remove('title-loading');
|
|
container.style.display = 'none';
|
|
}
|
|
}
|
|
|
|
// Rest of your existing code with minor additions
|
|
const imageStatusInterval = 500;
|
|
const scrollThreshold = 500;
|
|
const loadingIndicator = document.getElementById('message-bottom-right'); let loadingTimer;
|
|
let isFetching = false;
|
|
let page = parseInt(document.getElementById('template-data').getAttribute('data-page')) || 1;
|
|
let query = document.getElementById('template-data').getAttribute('data-query');
|
|
let hardCacheEnabled = document.getElementById('template-data').getAttribute('data-hard-cache-enabled') === 'true';
|
|
let noMoreImages = false;
|
|
|
|
let imageElements = [];
|
|
let imageIds = [];
|
|
let imageStatusTimer;
|
|
|
|
function showLoadingMessage() {
|
|
loadingIndicator.classList.add('visible');
|
|
}
|
|
|
|
function hideLoadingMessage() {
|
|
loadingIndicator.classList.remove('visible');
|
|
}
|
|
|
|
function ensureScrollable() {
|
|
if (noMoreImages) return;
|
|
if (document.body.scrollHeight <= window.innerHeight) {
|
|
fetchNextPage();
|
|
}
|
|
}
|
|
|
|
function fetchNextPage() {
|
|
if (isFetching || noMoreImages) return;
|
|
loadingTimer = setTimeout(() => {
|
|
showLoadingMessage();
|
|
}, 150);
|
|
isFetching = true;
|
|
page += 1;
|
|
|
|
fetch(`/search?q=${encodeURIComponent(query)}&t=image&p=${page}&ajax=true`)
|
|
.then(response => response.text())
|
|
.then(html => {
|
|
clearTimeout(loadingTimer);
|
|
hideLoadingMessage();
|
|
|
|
let tempDiv = document.createElement('div');
|
|
tempDiv.innerHTML = html;
|
|
let newImages = tempDiv.querySelectorAll('.image');
|
|
|
|
if (newImages.length > 0) {
|
|
let resultsContainer = document.querySelector('.images');
|
|
newImages.forEach(imageDiv => {
|
|
let clonedImageDiv = imageDiv.cloneNode(true);
|
|
resultsContainer.appendChild(clonedImageDiv);
|
|
|
|
let img = clonedImageDiv.querySelector('img');
|
|
if (img && img.getAttribute('data-id')) {
|
|
addLoadingEffects(img);
|
|
if (hardCacheEnabled) {
|
|
img.src = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII=';
|
|
img.onerror = () => handleImageError(img);
|
|
imageElements.push(img);
|
|
imageIds.push(img.getAttribute('data-id'));
|
|
} else {
|
|
img.src = img.getAttribute('data-full');
|
|
img.onload = () => removeLoadingEffects(img);
|
|
img.onerror = () => handleImageError(img);
|
|
}
|
|
}
|
|
});
|
|
|
|
if (hardCacheEnabled) checkImageStatus();
|
|
ensureScrollable();
|
|
} else {
|
|
noMoreImages = true;
|
|
}
|
|
isFetching = false;
|
|
})
|
|
.catch(error => {
|
|
clearTimeout(loadingTimer);
|
|
hideLoadingMessage();
|
|
console.error('Fetch error:', error);
|
|
isFetching = false;
|
|
});
|
|
}
|
|
|
|
function checkImageStatus() {
|
|
if (!hardCacheEnabled || imageIds.length === 0) return;
|
|
|
|
fetch(`/image_status?image_ids=${imageIds.join(',')}`)
|
|
.then(response => response.json())
|
|
.then(statusMap => {
|
|
const pendingImages = [];
|
|
const pendingIds = [];
|
|
|
|
imageElements.forEach(img => {
|
|
const id = img.getAttribute('data-id');
|
|
if (statusMap[id]) {
|
|
img.src = statusMap[id];
|
|
img.onload = () => removeLoadingEffects(img);
|
|
img.onerror = () => handleImageError(img);
|
|
} else {
|
|
pendingImages.push(img);
|
|
pendingIds.push(id);
|
|
}
|
|
});
|
|
|
|
imageElements = pendingImages;
|
|
imageIds = pendingIds;
|
|
ensureScrollable();
|
|
})
|
|
.catch(error => {
|
|
console.error('Status check error:', error);
|
|
});
|
|
}
|
|
|
|
// Initialize with loading effects
|
|
document.querySelectorAll('img[data-id]').forEach(img => {
|
|
const id = img.getAttribute('data-id');
|
|
if (id) {
|
|
addLoadingEffects(img);
|
|
imageElements.push(img);
|
|
imageIds.push(id);
|
|
if (hardCacheEnabled) {
|
|
img.src = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII=';
|
|
} else {
|
|
img.src = img.getAttribute('data-full');
|
|
img.onload = () => removeLoadingEffects(img);
|
|
}
|
|
img.onerror = () => handleImageError(img);
|
|
}
|
|
});
|
|
|
|
// Rest of your existing code remains unchanged
|
|
if (hardCacheEnabled) {
|
|
imageStatusTimer = setInterval(checkImageStatus, imageStatusInterval);
|
|
checkImageStatus();
|
|
}
|
|
|
|
window.addEventListener('load', ensureScrollable);
|
|
window.addEventListener('scroll', () => {
|
|
if (isFetching || noMoreImages) return;
|
|
if (window.innerHeight + window.scrollY >= document.body.offsetHeight - scrollThreshold) {
|
|
fetchNextPage();
|
|
}
|
|
});
|
|
|
|
window.addEventListener('beforeunload', () => {
|
|
if (imageStatusTimer) clearInterval(imageStatusTimer);
|
|
});
|
|
})(); |