added fallback mechanic to imageviewer.js
This commit is contained in:
parent
5881fa76e0
commit
d8ebe94657
3 changed files with 207 additions and 189 deletions
174
static/js/dynamicscrollingimages.js
Normal file
174
static/js/dynamicscrollingimages.js
Normal file
|
@ -0,0 +1,174 @@
|
|||
(function() {
|
||||
// Configuration
|
||||
const imageStatusInterval = 500; // Interval in milliseconds to check image status
|
||||
const scrollThreshold = 500; // Distance from bottom of the page to trigger loading
|
||||
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; // Flag to indicate if there are no more images to load
|
||||
|
||||
let imageElements = [];
|
||||
let imageIds = [];
|
||||
|
||||
/**
|
||||
* Function to handle image load errors with retry logic
|
||||
* @param {HTMLElement} imgElement - The image element that failed to load
|
||||
* @param {number} retryCount - Number of retries left
|
||||
* @param {number} retryDelay - Delay between retries in milliseconds
|
||||
*/
|
||||
function handleImageError(imgElement, retryCount = 3, retryDelay = 1000) {
|
||||
if (retryCount > 0) {
|
||||
setTimeout(() => {
|
||||
imgElement.src = imgElement.getAttribute('data-full');
|
||||
imgElement.onerror = function() {
|
||||
handleImageError(imgElement, retryCount - 1, retryDelay);
|
||||
};
|
||||
}, retryDelay);
|
||||
} else {
|
||||
// After retries, hide the image container or set a fallback image
|
||||
console.warn('Image failed to load after retries:', imgElement.getAttribute('data-full'));
|
||||
imgElement.parentElement.style.display = 'none'; // Hide the image container
|
||||
// Alternatively, set a fallback image:
|
||||
// imgElement.src = '/static/images/fallback.svg';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to ensure the page is scrollable by loading more images if necessary
|
||||
*/
|
||||
function ensureScrollable() {
|
||||
if (noMoreImages) return; // Do not attempt if no more images are available
|
||||
// Check if the page is not scrollable
|
||||
if (document.body.scrollHeight <= window.innerHeight) {
|
||||
// If not scrollable, fetch the next page
|
||||
fetchNextPage();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to fetch the next page of images
|
||||
*/
|
||||
function fetchNextPage() {
|
||||
if (isFetching || noMoreImages) return;
|
||||
isFetching = true;
|
||||
page += 1;
|
||||
|
||||
fetch(`/search?q=${encodeURIComponent(query)}&t=image&p=${page}&ajax=true`)
|
||||
.then(response => response.text())
|
||||
.then(html => {
|
||||
// Parse the returned HTML and extract image elements
|
||||
let parser = new DOMParser();
|
||||
let doc = parser.parseFromString(html, 'text/html');
|
||||
let newImages = doc.querySelectorAll('.image');
|
||||
|
||||
if (newImages.length > 0) {
|
||||
let resultsContainer = document.querySelector('.images');
|
||||
newImages.forEach(imageDiv => {
|
||||
// Append new images to the container
|
||||
resultsContainer.appendChild(imageDiv);
|
||||
|
||||
// Get the img element
|
||||
let img = imageDiv.querySelector('img');
|
||||
if (img) {
|
||||
if (hardCacheEnabled) {
|
||||
// Replace image with placeholder
|
||||
img.src = '/static/images/placeholder.svg';
|
||||
img.onerror = function() {
|
||||
handleImageError(img);
|
||||
};
|
||||
|
||||
let id = img.getAttribute('data-id');
|
||||
if (id) { // Only include if ID is not empty
|
||||
imageElements.push(img);
|
||||
imageIds.push(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
if (hardCacheEnabled) {
|
||||
checkImageStatus();
|
||||
}
|
||||
// After appending new images, ensure the page is scrollable
|
||||
ensureScrollable();
|
||||
} else {
|
||||
// No more images to load
|
||||
noMoreImages = true;
|
||||
}
|
||||
isFetching = false;
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error fetching next page:', error);
|
||||
isFetching = false;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to check image status via AJAX
|
||||
*/
|
||||
function checkImageStatus() {
|
||||
if (!hardCacheEnabled) return;
|
||||
if (imageIds.length === 0) {
|
||||
// No images to check, do nothing
|
||||
return;
|
||||
}
|
||||
|
||||
// Send AJAX request to check image status
|
||||
fetch(`/image_status?image_ids=${imageIds.join(',')}`)
|
||||
.then(response => response.json())
|
||||
.then(statusMap => {
|
||||
imageElements = imageElements.filter(img => {
|
||||
let id = img.getAttribute('data-id');
|
||||
if (statusMap[id]) {
|
||||
// Image is ready, update src
|
||||
img.src = statusMap[id];
|
||||
img.onerror = function() {
|
||||
handleImageError(img);
|
||||
};
|
||||
// Remove the image id from the list
|
||||
imageIds = imageIds.filter(imageId => imageId !== id);
|
||||
return false; // Remove img from imageElements
|
||||
}
|
||||
return true; // Keep img in imageElements
|
||||
});
|
||||
// After updating images, ensure the page is scrollable
|
||||
ensureScrollable();
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error checking image status:', error);
|
||||
});
|
||||
}
|
||||
|
||||
// Initialize imageElements and imageIds
|
||||
if (hardCacheEnabled) {
|
||||
imageElements = Array.from(document.querySelectorAll('img[data-id]'));
|
||||
imageIds = imageElements
|
||||
.map(img => img.getAttribute('data-id'))
|
||||
.filter(id => id); // Exclude empty IDs
|
||||
|
||||
// Replace images with placeholders
|
||||
imageElements.forEach(img => {
|
||||
img.src = '/static/images/placeholder.svg';
|
||||
});
|
||||
|
||||
// Start checking image status
|
||||
let imageStatusTimer = setInterval(checkImageStatus, imageStatusInterval);
|
||||
checkImageStatus(); // Initial check
|
||||
|
||||
// After initial images are loaded, ensure the page is scrollable
|
||||
window.addEventListener('load', ensureScrollable);
|
||||
}
|
||||
|
||||
// Infinite scrolling
|
||||
window.addEventListener('scroll', function() {
|
||||
if (isFetching || noMoreImages) return;
|
||||
|
||||
if (window.innerHeight + window.scrollY >= document.body.offsetHeight - scrollThreshold) {
|
||||
// User scrolled near the bottom
|
||||
fetchNextPage();
|
||||
}
|
||||
});
|
||||
|
||||
// Remove 'js-enabled' class from content
|
||||
document.getElementById('content').classList.remove('js-enabled');
|
||||
})();
|
Loading…
Add table
Add a link
Reference in a new issue