|
|
@@ -30,12 +30,9 @@ this.lazyLoader = this.lazyLoader || (() => {
|
|
|
|
|
|
function process(options) {
|
|
|
return new Promise(async resolve => {
|
|
|
- let timeoutId, loadingImages;
|
|
|
- setAsyncTimeout(() => {
|
|
|
- clearAsyncTimeout(timeoutId);
|
|
|
- lazyLoadEnd(idleTimeoutId, observer, cleanupAndResolve);
|
|
|
- }, options.loadDeferredImagesMaxIdleTime * 5);
|
|
|
- const observer = new MutationObserver(async mutations => {
|
|
|
+ let timeoutId, idleTimeoutId, maxTimeoutId, loadingImages, observer, pendingImages = new Set();
|
|
|
+ maxTimeoutId = await deferForceLazyLoadEnd(timeoutId, idleTimeoutId, maxTimeoutId, observer, options, cleanupAndResolve);
|
|
|
+ observer = new MutationObserver(async mutations => {
|
|
|
mutations = mutations.filter(mutation => mutation.type == ATTRIBUTES_MUTATION_TYPE);
|
|
|
if (mutations.length) {
|
|
|
const updated = mutations.filter(mutation => {
|
|
|
@@ -48,32 +45,46 @@ this.lazyLoader = this.lazyLoader || (() => {
|
|
|
});
|
|
|
if (updated.length) {
|
|
|
loadingImages = true;
|
|
|
- timeoutId = await deferLazyLoadEnd(timeoutId, idleTimeoutId, observer, options, cleanupAndResolve);
|
|
|
+ maxTimeoutId = await deferForceLazyLoadEnd(timeoutId, idleTimeoutId, maxTimeoutId, observer, options, cleanupAndResolve);
|
|
|
+ if (!pendingImages.size) {
|
|
|
+ timeoutId = await deferLazyLoadEnd(timeoutId, idleTimeoutId, observer, options, cleanupAndResolve);
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
});
|
|
|
observer.observe(document, { subtree: true, childList: true, attributes: true });
|
|
|
- const idleTimeoutId = await setAsyncTimeout(() => {
|
|
|
+ idleTimeoutId = await setAsyncTimeout(() => {
|
|
|
if (!loadingImages) {
|
|
|
clearAsyncTimeout(timeoutId);
|
|
|
lazyLoadEnd(idleTimeoutId, observer, cleanupAndResolve);
|
|
|
}
|
|
|
}, options.loadDeferredImagesMaxIdleTime * 1.2);
|
|
|
+ addEventListener(hooksFrame.LOAD_IMAGE_EVENT, onImageLoadEvent);
|
|
|
+ addEventListener(hooksFrame.IMAGE_LOADED_EVENT, onImageLoadedEvent);
|
|
|
if (typeof hooksFrame != "undefined") {
|
|
|
hooksFrame.loadDeferredImagesStart();
|
|
|
}
|
|
|
- addEventListener(hooksFrame.LOAD_IMAGE_EVENT, onImageEvent);
|
|
|
- addEventListener(hooksFrame.IMAGE_LOADED_EVENT, onImageEvent);
|
|
|
|
|
|
- async function onImageEvent() {
|
|
|
+ async function onImageLoadEvent(event) {
|
|
|
loadingImages = true;
|
|
|
- timeoutId = await deferLazyLoadEnd(timeoutId, idleTimeoutId, observer, options, cleanupAndResolve);
|
|
|
+ maxTimeoutId = await deferForceLazyLoadEnd(timeoutId, idleTimeoutId, maxTimeoutId, observer, options, cleanupAndResolve);
|
|
|
+ if (event.detail) {
|
|
|
+ pendingImages.add(event.detail);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ async function onImageLoadedEvent(event) {
|
|
|
+ maxTimeoutId = await deferForceLazyLoadEnd(timeoutId, idleTimeoutId, maxTimeoutId, observer, options, cleanupAndResolve);
|
|
|
+ pendingImages.delete(event.detail);
|
|
|
+ if (!pendingImages.size) {
|
|
|
+ timeoutId = await deferLazyLoadEnd(timeoutId, idleTimeoutId, observer, options, cleanupAndResolve);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
function cleanupAndResolve(value) {
|
|
|
observer.disconnect();
|
|
|
- removeEventListener(hooksFrame.LOAD_IMAGE_EVENT, onImageEvent);
|
|
|
- removeEventListener(hooksFrame.IMAGE_LOADED_EVENT, onImageEvent);
|
|
|
+ removeEventListener(hooksFrame.LOAD_IMAGE_EVENT, onImageLoadEvent);
|
|
|
+ removeEventListener(hooksFrame.IMAGE_LOADED_EVENT, onImageLoadedEvent);
|
|
|
resolve(value);
|
|
|
}
|
|
|
});
|
|
|
@@ -84,6 +95,14 @@ this.lazyLoader = this.lazyLoader || (() => {
|
|
|
return setAsyncTimeout(async () => await lazyLoadEnd(idleTimeoutId, observer, resolve), options.loadDeferredImagesMaxIdleTime);
|
|
|
}
|
|
|
|
|
|
+ async function deferForceLazyLoadEnd(timeoutId, idleTimeoutId, maxTimeoutId, observer, options, resolve) {
|
|
|
+ clearAsyncTimeout(maxTimeoutId);
|
|
|
+ return setAsyncTimeout(() => {
|
|
|
+ clearAsyncTimeout(timeoutId);
|
|
|
+ lazyLoadEnd(idleTimeoutId, observer, resolve);
|
|
|
+ }, options.loadDeferredImagesMaxIdleTime * 10);
|
|
|
+ }
|
|
|
+
|
|
|
function lazyLoadEnd(idleTimeoutId, observer, resolve) {
|
|
|
clearAsyncTimeout(idleTimeoutId);
|
|
|
if (typeof hooksFrame != "undefined") {
|