mediawiki-skins-Citizen/resources/skins.citizen.scripts.toc/skins.citizen.scripts.toc.js
alistair3149 e0d5eb9657
feat(core): set toc-enabled through Mustache template
Since somewhere around MW 1.37, buildSkinFeatures() no longer have access to OutputPage.
That causes $out->isTOCenabled always return null, which makes ToC
broken for any wikis since 1.37. This should fix the issue for now.
More optimizations on the loading behavior will come soon.
2022-05-12 17:01:01 -04:00

52 lines
1.6 KiB
JavaScript

/**
* Toggle active HTML class to items in table of content based on user viewport.
*
* @return {void}
*/
function intersectionHandler() {
const headlines = document.querySelectorAll( '.mw-headline' ),
toc = document.getElementById( 'toc' ),
marginTop = '-' + window.getComputedStyle( document.documentElement ).getPropertyValue( 'scroll-padding-top' );
for ( let i = 0; i < headlines.length; i++ ) {
/* eslint-disable compat/compat */
const observer = new IntersectionObserver( ( entry ) => {
/* eslint-enable compat/compat */
if ( entry[ 0 ].isIntersecting ) {
const headlineId = headlines[ i ].id,
// Get the decoded ID from the span before
decodedId = ( headlines[ i ].previousSibling !== null ) ?
headlines[ i ].previousSibling.id : '',
links = toc.querySelector( "a[href='#" + headlineId + "']" ) ||
toc.querySelector( "a[href='#" + decodedId + "']" ),
targetLink = links.parentNode,
activeLink = toc.querySelector( '.active' );
if ( activeLink !== null ) {
activeLink.classList.remove( 'active' );
}
if ( targetLink !== null ) {
targetLink.classList.add( 'active' );
}
}
}, {
// Will break in viewport with short height
// But calculating bottom margin on the fly is too costly
rootMargin: marginTop + ' 0px -85% 0px'
} );
observer.observe( headlines[ i ] );
}
}
/**
* @return {void}
*/
function initTOC() {
// Check for has-toc class since it is loaded way before #toc is present
if ( document.querySelector( '.citizen-toc-enabled' ) ) {
intersectionHandler();
}
}
initTOC();