Fix dynamic scroll height sync
This commit is contained in:
parent
bc0da49506
commit
26f9e5daeb
|
|
@ -12,8 +12,15 @@
|
|||
const MEDIA_HANDLE_BOUND_FLAG = "__nodedcMediaHandleBound";
|
||||
const DOCK_LINK_BOUND_FLAG = "__nodedcDockLinkBound";
|
||||
const ORDERED_SLIDER_BOUND_FLAG = "__nodedcOrderedSliderBound";
|
||||
const SCROLL_HEIGHT_SYNC_FLAG = "__nodedcScrollHeightSyncBound";
|
||||
const SCROLL_HEIGHT_SYNC_WARMUP_MS = 14000;
|
||||
const SCROLL_HEIGHT_SYNC_INTERVAL_MS = 90;
|
||||
const IMAGE_EXTENSIONS = new Set(["avif", "gif", "jpeg", "jpg", "png", "svg", "webp"]);
|
||||
const VIDEO_EXTENSIONS = new Set(["m4v", "mov", "mp4", "webm"]);
|
||||
let lastDocumentScrollHeight = 0;
|
||||
let scrollHeightSyncFrame = 0;
|
||||
let scrollHeightSyncShouldForce = false;
|
||||
let scrollHeightDeferredSync = 0;
|
||||
|
||||
function isDesktopPointer() {
|
||||
return window.matchMedia?.("(pointer: fine)").matches ?? true;
|
||||
|
|
@ -55,6 +62,99 @@
|
|||
return Math.min(max, Math.max(min, value));
|
||||
}
|
||||
|
||||
function getDocumentScrollHeight() {
|
||||
return Math.max(document.documentElement.scrollHeight, document.body?.scrollHeight || 0);
|
||||
}
|
||||
|
||||
function notifyScrollHeightChange(force = false) {
|
||||
const nextHeight = getDocumentScrollHeight();
|
||||
if (!nextHeight) return;
|
||||
if (!force && nextHeight === lastDocumentScrollHeight) return;
|
||||
|
||||
lastDocumentScrollHeight = nextHeight;
|
||||
window.dispatchEvent(new Event("resize"));
|
||||
|
||||
if (scrollHeightDeferredSync) {
|
||||
window.clearTimeout(scrollHeightDeferredSync);
|
||||
}
|
||||
|
||||
scrollHeightDeferredSync = window.setTimeout(() => {
|
||||
scrollHeightDeferredSync = 0;
|
||||
if (getDocumentScrollHeight() === lastDocumentScrollHeight) {
|
||||
window.dispatchEvent(new Event("resize"));
|
||||
} else {
|
||||
scheduleScrollHeightSync();
|
||||
}
|
||||
}, 320);
|
||||
}
|
||||
|
||||
function scheduleScrollHeightSync(force = false) {
|
||||
scrollHeightSyncShouldForce = scrollHeightSyncShouldForce || force;
|
||||
if (scrollHeightSyncFrame) return;
|
||||
|
||||
scrollHeightSyncFrame = window.requestAnimationFrame(() => {
|
||||
const shouldForce = scrollHeightSyncShouldForce;
|
||||
|
||||
scrollHeightSyncShouldForce = false;
|
||||
scrollHeightSyncFrame = 0;
|
||||
notifyScrollHeightChange(shouldForce);
|
||||
});
|
||||
}
|
||||
|
||||
function bindScrollHeightSync() {
|
||||
if (document[SCROLL_HEIGHT_SYNC_FLAG]) return;
|
||||
document[SCROLL_HEIGHT_SYNC_FLAG] = true;
|
||||
|
||||
scheduleScrollHeightSync(true);
|
||||
|
||||
const resizeObserver =
|
||||
typeof ResizeObserver === "function"
|
||||
? new ResizeObserver(() => {
|
||||
scheduleScrollHeightSync();
|
||||
})
|
||||
: null;
|
||||
|
||||
resizeObserver?.observe(document.documentElement);
|
||||
if (document.body) resizeObserver?.observe(document.body);
|
||||
|
||||
const mutationObserver =
|
||||
typeof MutationObserver === "function"
|
||||
? new MutationObserver(() => {
|
||||
scheduleScrollHeightSync();
|
||||
})
|
||||
: null;
|
||||
|
||||
mutationObserver?.observe(document.documentElement, {
|
||||
attributes: true,
|
||||
childList: true,
|
||||
subtree: true,
|
||||
});
|
||||
|
||||
const interval = window.setInterval(() => {
|
||||
scheduleScrollHeightSync();
|
||||
}, SCROLL_HEIGHT_SYNC_INTERVAL_MS);
|
||||
|
||||
window.setTimeout(() => {
|
||||
window.clearInterval(interval);
|
||||
mutationObserver?.disconnect();
|
||||
}, SCROLL_HEIGHT_SYNC_WARMUP_MS);
|
||||
|
||||
window.addEventListener("load", () => scheduleScrollHeightSync(true), { once: true });
|
||||
if (document.fonts?.ready) {
|
||||
document.fonts.ready.then(() => scheduleScrollHeightSync(true)).catch(() => {});
|
||||
}
|
||||
|
||||
document.addEventListener(
|
||||
"load",
|
||||
(event) => {
|
||||
if (event.target instanceof HTMLImageElement || event.target instanceof HTMLVideoElement) {
|
||||
scheduleScrollHeightSync();
|
||||
}
|
||||
},
|
||||
true,
|
||||
);
|
||||
}
|
||||
|
||||
function getScrollSpeed(surface) {
|
||||
const rawValue = surface?.dataset?.scrollSpeed ?? surface?.closest?.("[data-scroll-speed]")?.dataset?.scrollSpeed;
|
||||
const value = Number.parseFloat(rawValue);
|
||||
|
|
@ -358,40 +458,48 @@
|
|||
document.querySelectorAll("[data-adaptive-video] video").forEach(bindAdaptiveVideo);
|
||||
}
|
||||
|
||||
bindScrollHeightSync();
|
||||
hydrateMediaHandles();
|
||||
|
||||
if (document.readyState === "loading") {
|
||||
document.addEventListener(
|
||||
"DOMContentLoaded",
|
||||
() => {
|
||||
bindScrollHeightSync();
|
||||
hydrateMediaHandles();
|
||||
bindInteractiveScroll();
|
||||
bindOrderedSliders();
|
||||
bindDockLinks();
|
||||
bindAdaptiveVideos();
|
||||
scheduleScrollHeightSync(true);
|
||||
},
|
||||
{ once: true },
|
||||
);
|
||||
} else {
|
||||
bindScrollHeightSync();
|
||||
hydrateMediaHandles();
|
||||
bindInteractiveScroll();
|
||||
bindOrderedSliders();
|
||||
bindDockLinks();
|
||||
bindAdaptiveVideos();
|
||||
scheduleScrollHeightSync(true);
|
||||
}
|
||||
|
||||
window.addEventListener("load", () => {
|
||||
bindScrollHeightSync();
|
||||
hydrateMediaHandles();
|
||||
bindInteractiveScroll();
|
||||
bindOrderedSliders();
|
||||
bindDockLinks();
|
||||
bindAdaptiveVideos();
|
||||
scheduleScrollHeightSync(true);
|
||||
window.setTimeout(() => {
|
||||
hydrateMediaHandles();
|
||||
bindInteractiveScroll();
|
||||
bindOrderedSliders();
|
||||
bindDockLinks();
|
||||
bindAdaptiveVideos();
|
||||
scheduleScrollHeightSync(true);
|
||||
}, 500);
|
||||
});
|
||||
})();
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue