Rework lazy loading as js controlled fetches
This commit is contained in:
@@ -8,15 +8,101 @@
|
||||
// ============================================================
|
||||
// Gallery Thumbnails Module
|
||||
// ============================================================
|
||||
// Thumbnail loading now relies on native loading="lazy" attribute.
|
||||
// The browser handles deferred loading, connection limits, and
|
||||
// automatic cancellation on navigation.
|
||||
//
|
||||
// This module is kept as a stub for potential future enhancements.
|
||||
// Uses fetch() with AbortController to load thumbnails.
|
||||
// This allows true HTTP request cancellation on navigation,
|
||||
// unlike native loading="lazy" where queued requests block.
|
||||
Luxtools.GalleryThumbnails = (function () {
|
||||
var controller = null;
|
||||
var maxConcurrent = 4;
|
||||
var activeCount = 0;
|
||||
var queue = [];
|
||||
|
||||
function abortAll() {
|
||||
if (controller) {
|
||||
controller.abort();
|
||||
controller = null;
|
||||
}
|
||||
queue = [];
|
||||
activeCount = 0;
|
||||
}
|
||||
|
||||
function processQueue() {
|
||||
if (!controller) return;
|
||||
while (activeCount < maxConcurrent && queue.length > 0) {
|
||||
var img = queue.shift();
|
||||
loadThumb(img);
|
||||
}
|
||||
}
|
||||
|
||||
function loadThumb(img) {
|
||||
if (!controller) return;
|
||||
|
||||
var src = img.getAttribute('data-src');
|
||||
if (!src) {
|
||||
processQueue();
|
||||
return;
|
||||
}
|
||||
|
||||
activeCount++;
|
||||
|
||||
fetch(src, { signal: controller.signal })
|
||||
.then(function (response) {
|
||||
if (!response.ok) throw new Error('HTTP ' + response.status);
|
||||
return response.blob();
|
||||
})
|
||||
.then(function (blob) {
|
||||
img.src = URL.createObjectURL(blob);
|
||||
img.removeAttribute('data-src');
|
||||
})
|
||||
.catch(function (err) {
|
||||
// Aborted or failed - ignore
|
||||
if (err.name !== 'AbortError') {
|
||||
// Keep data-src for potential retry, just log
|
||||
}
|
||||
})
|
||||
.finally(function () {
|
||||
activeCount--;
|
||||
processQueue();
|
||||
});
|
||||
}
|
||||
|
||||
function queueThumb(img) {
|
||||
if (!controller) return;
|
||||
if (!img.getAttribute('data-src')) return;
|
||||
if (img.getAttribute('data-queued') === '1') return;
|
||||
img.setAttribute('data-queued', '1');
|
||||
queue.push(img);
|
||||
processQueue();
|
||||
}
|
||||
|
||||
function init() {
|
||||
// Native lazy loading handles everything.
|
||||
// No JavaScript intervention needed.
|
||||
var imgs = document.querySelectorAll(
|
||||
'div.luxtools-gallery img.luxtools-thumb[data-src], div.luxtools-imagebox img[data-src]'
|
||||
);
|
||||
if (!imgs || !imgs.length) return;
|
||||
|
||||
// Create abort controller for all requests
|
||||
controller = new AbortController();
|
||||
|
||||
// Abort all pending requests on navigation
|
||||
window.addEventListener('beforeunload', abortAll);
|
||||
window.addEventListener('pagehide', abortAll);
|
||||
|
||||
// Use IntersectionObserver to trigger loading
|
||||
if ('IntersectionObserver' in window) {
|
||||
var io = new IntersectionObserver(function (entries) {
|
||||
entries.forEach(function (entry) {
|
||||
if (!entry.isIntersecting) return;
|
||||
queueThumb(entry.target);
|
||||
io.unobserve(entry.target);
|
||||
});
|
||||
}, { rootMargin: '200px' });
|
||||
|
||||
imgs.forEach(function (img) { io.observe(img); });
|
||||
} else {
|
||||
// Fallback: queue all
|
||||
imgs.forEach(queueThumb);
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
|
||||
@@ -88,7 +88,7 @@ class Output
|
||||
$caption = $label;
|
||||
}
|
||||
|
||||
// Build thumbnail URL - rely on native loading="lazy" for deferred loading
|
||||
// Build thumbnail URL - JavaScript will load via fetch() for cancellability
|
||||
$thumbUrl = $this->withQueryParams($url, [
|
||||
'thumb' => 1,
|
||||
'w' => $genThumbW,
|
||||
@@ -107,12 +107,10 @@ class Output
|
||||
. '>';
|
||||
$renderer->doc .= '<img'
|
||||
. ' class="luxtools-thumb"'
|
||||
. ' src="' . $thumbSrc . '"'
|
||||
. ' data-src="' . $thumbSrc . '"'
|
||||
. ' alt=""'
|
||||
. ' width="' . $thumbW . '"'
|
||||
. ' height="' . $thumbH . '"'
|
||||
. ' loading="lazy"'
|
||||
. ' decoding="async"'
|
||||
. ' />';
|
||||
$renderer->doc .= '<span class="luxtools-gallery-caption">' . $caption . '</span>';
|
||||
$renderer->doc .= '</a>';
|
||||
|
||||
Reference in New Issue
Block a user