mirror of
https://github.com/StarCitizenTools/mediawiki-skins-Citizen.git
synced 2024-11-23 22:13:38 +00:00
refactor(core): ♻️ set up scroll direction observer in setupObservers
This is needed for centralizing the observers.
This commit is contained in:
parent
241ef66893
commit
3b8022c3c1
|
@ -4,36 +4,47 @@
|
||||||
* @param {Function} onScrollDown - Function to be called when scrolling down.
|
* @param {Function} onScrollDown - Function to be called when scrolling down.
|
||||||
* @param {Function} onScrollUp - Function to be called when scrolling up.
|
* @param {Function} onScrollUp - Function to be called when scrolling up.
|
||||||
* @param {number} threshold - The threshold for significant scroll position change.
|
* @param {number} threshold - The threshold for significant scroll position change.
|
||||||
|
* @return {Object}
|
||||||
*/
|
*/
|
||||||
function initDirectionObserver( onScrollDown, onScrollUp, threshold ) {
|
function initDirectionObserver( onScrollDown, onScrollUp, threshold = 0 ) {
|
||||||
let lastScrollTop = 0;
|
let lastScrollTop = 0;
|
||||||
let lastScrollDirection = '';
|
let lastScrollDirection = '';
|
||||||
let isScrolling = false;
|
let isScrolling = false;
|
||||||
|
|
||||||
window.addEventListener( 'scroll', () => {
|
const handleScroll = () => {
|
||||||
|
const currentScrollTop = window.scrollY;
|
||||||
|
|
||||||
|
if ( Math.abs( currentScrollTop - lastScrollTop ) < threshold ) {
|
||||||
|
isScrolling = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( currentScrollTop > lastScrollTop && lastScrollDirection !== 'down' ) {
|
||||||
|
lastScrollDirection = 'down';
|
||||||
|
onScrollDown();
|
||||||
|
} else if ( currentScrollTop < lastScrollTop && lastScrollDirection !== 'up' ) {
|
||||||
|
lastScrollDirection = 'up';
|
||||||
|
onScrollUp();
|
||||||
|
}
|
||||||
|
lastScrollTop = currentScrollTop <= 0 ? 0 : currentScrollTop;
|
||||||
|
isScrolling = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
const onScroll = () => {
|
||||||
if ( !isScrolling ) {
|
if ( !isScrolling ) {
|
||||||
window.requestAnimationFrame( () => {
|
window.requestAnimationFrame( handleScroll );
|
||||||
const currentScrollTop = window.scrollY;
|
|
||||||
|
|
||||||
if ( Math.abs( currentScrollTop - lastScrollTop ) < threshold ) {
|
|
||||||
isScrolling = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( currentScrollTop > lastScrollTop && lastScrollDirection !== 'down' ) {
|
|
||||||
lastScrollDirection = 'down';
|
|
||||||
onScrollDown();
|
|
||||||
} else if ( currentScrollTop < lastScrollTop && lastScrollDirection !== 'up' ) {
|
|
||||||
lastScrollDirection = 'up';
|
|
||||||
onScrollUp();
|
|
||||||
}
|
|
||||||
// For Mobile or negative scrolling
|
|
||||||
lastScrollTop = currentScrollTop <= 0 ? 0 : currentScrollTop;
|
|
||||||
isScrolling = false;
|
|
||||||
} );
|
|
||||||
isScrolling = true;
|
isScrolling = true;
|
||||||
}
|
}
|
||||||
} );
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
resume: () => {
|
||||||
|
window.addEventListener( 'scroll', onScroll );
|
||||||
|
},
|
||||||
|
pause: () => {
|
||||||
|
window.removeEventListener( 'scroll', onScroll );
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -3,6 +3,7 @@ const
|
||||||
scrollObserver = require( './scrollObserver.js' ),
|
scrollObserver = require( './scrollObserver.js' ),
|
||||||
resizeObserver = require( './resizeObserver.js' ),
|
resizeObserver = require( './resizeObserver.js' ),
|
||||||
initSectionObserver = require( './sectionObserver.js' ),
|
initSectionObserver = require( './sectionObserver.js' ),
|
||||||
|
stickyHeader = require( './stickyHeader.js' ),
|
||||||
initTableOfContents = require( './tableOfContents.js' ),
|
initTableOfContents = require( './tableOfContents.js' ),
|
||||||
deferUntilFrame = require( './deferUntilFrame.js' ),
|
deferUntilFrame = require( './deferUntilFrame.js' ),
|
||||||
TOC_ID = 'citizen-toc',
|
TOC_ID = 'citizen-toc',
|
||||||
|
@ -16,7 +17,9 @@ const
|
||||||
.map( ( sel ) => `.mw-parser-output ${ sel }` ).join( ', ' ),
|
.map( ( sel ) => `.mw-parser-output ${ sel }` ).join( ', ' ),
|
||||||
HEADLINE_SELECTOR = [ '.mw-headline', ...HEADING_TAGS.map( ( tag ) => `${ tag }[id]` ) ]
|
HEADLINE_SELECTOR = [ '.mw-headline', ...HEADING_TAGS.map( ( tag ) => `${ tag }[id]` ) ]
|
||||||
.map( ( sel ) => `.mw-parser-output ${ sel }` ).join( ', ' ),
|
.map( ( sel ) => `.mw-parser-output ${ sel }` ).join( ', ' ),
|
||||||
TOC_SECTION_ID_PREFIX = 'toc-';
|
TOC_SECTION_ID_PREFIX = 'toc-',
|
||||||
|
SCROLL_DOWN_CLASS = 'citizen-scroll--down',
|
||||||
|
SCROLL_UP_CLASS = 'citizen-scroll--up';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @callback OnIntersection
|
* @callback OnIntersection
|
||||||
|
@ -194,7 +197,27 @@ const main = () => {
|
||||||
const tableOfContents = isToCUpdatingAllowed ?
|
const tableOfContents = isToCUpdatingAllowed ?
|
||||||
setupTableOfContents( tocElement, bodyContent, initSectionObserver ) : null;
|
setupTableOfContents( tocElement, bodyContent, initSectionObserver ) : null;
|
||||||
|
|
||||||
const pagetitleObserver = scrollObserver.initScrollObserver(
|
const stickyIntersection = document.getElementById( 'citizen-page-header-sticky-sentinel' );
|
||||||
|
const isStickyHeaderAllowed = !!stickyIntersection;
|
||||||
|
|
||||||
|
const scrollDirectionObserver = scrollObserver.initDirectionObserver(
|
||||||
|
() => {
|
||||||
|
document.body.classList.remove( SCROLL_UP_CLASS );
|
||||||
|
document.body.classList.add( SCROLL_DOWN_CLASS );
|
||||||
|
},
|
||||||
|
() => {
|
||||||
|
document.body.classList.remove( SCROLL_DOWN_CLASS );
|
||||||
|
document.body.classList.add( SCROLL_UP_CLASS );
|
||||||
|
},
|
||||||
|
50
|
||||||
|
);
|
||||||
|
|
||||||
|
if ( isStickyHeaderAllowed ) {
|
||||||
|
stickyHeader.init();
|
||||||
|
scrollDirectionObserver.resume();
|
||||||
|
}
|
||||||
|
|
||||||
|
const pageHeaderObserver = scrollObserver.initScrollObserver(
|
||||||
() => {
|
() => {
|
||||||
// TODO: Below page header
|
// TODO: Below page header
|
||||||
},
|
},
|
||||||
|
@ -203,15 +226,20 @@ const main = () => {
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
pageHeaderObserver.observe( stickyIntersection );
|
||||||
|
|
||||||
const bodyObserver = resizeObserver.initResizeObserver(
|
const bodyObserver = resizeObserver.initResizeObserver(
|
||||||
() => {
|
() => {
|
||||||
// Disable all CSS transition during resize
|
// Disable all CSS animation during resize
|
||||||
if ( document.documentElement.classList.contains( 'citizen-animations-ready' ) ) {
|
if ( document.documentElement.classList.contains( 'citizen-animations-ready' ) ) {
|
||||||
document.documentElement.classList.remove( 'citizen-animations-ready' );
|
document.documentElement.classList.remove( 'citizen-animations-ready' );
|
||||||
}
|
}
|
||||||
|
scrollDirectionObserver.pause();
|
||||||
},
|
},
|
||||||
() => {
|
() => {
|
||||||
|
// Enable CSS animation after resize is finished
|
||||||
document.documentElement.classList.add( 'citizen-animations-ready' );
|
document.documentElement.classList.add( 'citizen-animations-ready' );
|
||||||
|
scrollDirectionObserver.resume();
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
bodyObserver.observe( document.body );
|
bodyObserver.observe( document.body );
|
||||||
|
|
|
@ -50,14 +50,12 @@ function main( window ) {
|
||||||
search = require( './search.js' ),
|
search = require( './search.js' ),
|
||||||
dropdown = require( './dropdown.js' ),
|
dropdown = require( './dropdown.js' ),
|
||||||
setupObservers = require( './setupObservers.js' ),
|
setupObservers = require( './setupObservers.js' ),
|
||||||
stickyHeader = require( './stickyHeader.js' ),
|
|
||||||
lastModified = require( './lastModified.js' ),
|
lastModified = require( './lastModified.js' ),
|
||||||
share = require( './share.js' );
|
share = require( './share.js' );
|
||||||
|
|
||||||
dropdown.init();
|
dropdown.init();
|
||||||
search.init( window );
|
search.init( window );
|
||||||
echo();
|
echo();
|
||||||
stickyHeader.init();
|
|
||||||
lastModified.init();
|
lastModified.init();
|
||||||
share.init();
|
share.init();
|
||||||
|
|
||||||
|
|
|
@ -1,25 +1,5 @@
|
||||||
const SCROLL_DOWN_CLASS = 'citizen-scroll--down';
|
|
||||||
const SCROLL_UP_CLASS = 'citizen-scroll--up';
|
|
||||||
const STICKY_CLASS = 'citizen-page-header--sticky';
|
const STICKY_CLASS = 'citizen-page-header--sticky';
|
||||||
const { initDirectionObserver, initScrollObserver } = require( './scrollObserver.js' );
|
const { initScrollObserver } = require( './scrollObserver.js' );
|
||||||
|
|
||||||
/**
|
|
||||||
* Observes the scroll direction and adds/removes corresponding classes to the body element.
|
|
||||||
*
|
|
||||||
* @return {void}
|
|
||||||
*/
|
|
||||||
function observeScrollDirection() {
|
|
||||||
const toggleScrollClass = ( removeClass, addClass ) => () => {
|
|
||||||
window.requestAnimationFrame( () => {
|
|
||||||
document.body.classList.remove( removeClass );
|
|
||||||
document.body.classList.add( addClass );
|
|
||||||
} );
|
|
||||||
};
|
|
||||||
const addScrollDownClass = toggleScrollClass( SCROLL_UP_CLASS, SCROLL_DOWN_CLASS );
|
|
||||||
const addScrollUpClass = toggleScrollClass( SCROLL_DOWN_CLASS, SCROLL_UP_CLASS );
|
|
||||||
|
|
||||||
initDirectionObserver( addScrollDownClass, addScrollUpClass, 50 );
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes the sticky header functionality for Citizen
|
* Initializes the sticky header functionality for Citizen
|
||||||
|
@ -27,13 +7,6 @@ function observeScrollDirection() {
|
||||||
* @return {void}
|
* @return {void}
|
||||||
*/
|
*/
|
||||||
function init() {
|
function init() {
|
||||||
const sentinel = document.getElementById( 'citizen-page-header-sticky-sentinel' );
|
|
||||||
const shouldStickyHeader = getComputedStyle( sentinel ).getPropertyValue( 'display' ) !== 'none';
|
|
||||||
if ( !shouldStickyHeader ) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
observeScrollDirection();
|
|
||||||
const header = document.querySelector( '.citizen-page-header' );
|
const header = document.querySelector( '.citizen-page-header' );
|
||||||
const placeholder = document.getElementById( 'citizen-page-header-sticky-placeholder' );
|
const placeholder = document.getElementById( 'citizen-page-header-sticky-placeholder' );
|
||||||
let staticHeaderHeight = header.getBoundingClientRect().height;
|
let staticHeaderHeight = header.getBoundingClientRect().height;
|
||||||
|
@ -89,6 +62,7 @@ function init() {
|
||||||
window.removeEventListener( 'resize', onResizeEnd );
|
window.removeEventListener( 'resize', onResizeEnd );
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
const sentinel = document.getElementById( 'citizen-page-header-sticky-sentinel' );
|
||||||
observer.observe( sentinel );
|
observer.observe( sentinel );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue