mediawiki-skins-Citizen/resources/skins.citizen.scripts/scrollObserver.js
2024-05-25 19:26:38 -04:00

56 lines
1.6 KiB
JavaScript

/**
* Create an observer based vertical scroll direction with debouncing
*
* @param {Function} onScrollDown functionality for when viewport is scrolled down
* @param {Function} onScrollUp functionality for when viewport is scrolled up
* @param {number} threshold minimum scrolled px to trigger the function
* @return {void}
*/
function initDirectionObserver( onScrollDown, onScrollUp, threshold ) {
let lastScrollTop = window.scrollY;
const onScroll = () => {
const scrollTop = window.scrollY;
if ( Math.abs( scrollTop - lastScrollTop ) < threshold ) {
return;
}
if ( scrollTop > lastScrollTop ) {
onScrollDown();
} else {
onScrollUp();
}
lastScrollTop = scrollTop;
};
const debouncedOnScroll = mw.util.debounce( onScroll, 100 );
window.addEventListener( 'scroll', mw.util.throttle( debouncedOnScroll, 250 ) );
}
/**
* Create an observer based on element visiblity.
* Based on Vector
*
* @param {Function} onHidden functionality for when the element is visible
* @param {Function} onVisible functionality for when the element is hidden
* @return {IntersectionObserver}
*/
function initIntersectionObserver( onHidden, onVisible ) {
/* eslint-disable-next-line compat/compat */
return new IntersectionObserver( ( entries ) => {
if ( !entries[ 0 ].isIntersecting && entries[ 0 ].boundingClientRect.top < 0 ) {
// Viewport has crossed the bottom edge of the target element.
onHidden();
} else {
// Viewport is above the bottom edge of the target element.
onVisible();
}
} );
}
module.exports = {
initDirectionObserver,
initIntersectionObserver
};