2022-05-13 04:21:08 +00:00
|
|
|
const ACTIVE_ITEM_CLASS = 'toc__item--active';
|
|
|
|
|
2020-06-17 03:16:45 +00:00
|
|
|
/**
|
2021-04-21 19:07:55 +00:00
|
|
|
* Toggle active HTML class to items in table of content based on user viewport.
|
2020-07-05 21:07:36 +00:00
|
|
|
*
|
2022-05-13 04:21:08 +00:00
|
|
|
* @param {Element} toc TOC element
|
2021-04-21 19:07:55 +00:00
|
|
|
* @return {void}
|
2020-06-17 03:16:45 +00:00
|
|
|
*/
|
2022-05-13 04:21:08 +00:00
|
|
|
function initToC( toc ) {
|
|
|
|
const
|
|
|
|
headlines = document.querySelectorAll( '.mw-headline' ),
|
2021-04-21 19:07:55 +00:00
|
|
|
marginTop = '-' + window.getComputedStyle( document.documentElement ).getPropertyValue( 'scroll-padding-top' );
|
2021-04-02 19:42:56 +00:00
|
|
|
|
2021-04-21 19:07:55 +00:00
|
|
|
for ( let i = 0; i < headlines.length; i++ ) {
|
|
|
|
/* eslint-disable compat/compat */
|
2021-04-02 19:42:56 +00:00
|
|
|
const observer = new IntersectionObserver( ( entry ) => {
|
2021-04-21 19:07:55 +00:00
|
|
|
/* eslint-enable compat/compat */
|
2021-04-02 19:42:56 +00:00
|
|
|
if ( entry[ 0 ].isIntersecting ) {
|
2022-05-13 04:21:08 +00:00
|
|
|
const
|
|
|
|
headlineId = headlines[ i ].id,
|
2021-04-21 19:07:55 +00:00
|
|
|
// 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,
|
2022-05-13 04:21:08 +00:00
|
|
|
activeLink = toc.querySelector( '.' + ACTIVE_ITEM_CLASS );
|
2021-04-21 19:07:55 +00:00
|
|
|
|
|
|
|
if ( activeLink !== null ) {
|
2022-05-13 04:21:08 +00:00
|
|
|
activeLink.classList.remove( ACTIVE_ITEM_CLASS );
|
2020-02-15 22:56:29 +00:00
|
|
|
}
|
2021-04-21 19:07:55 +00:00
|
|
|
if ( targetLink !== null ) {
|
2022-05-13 04:21:08 +00:00
|
|
|
targetLink.classList.add( ACTIVE_ITEM_CLASS );
|
2020-02-15 22:56:29 +00:00
|
|
|
}
|
|
|
|
}
|
2021-04-02 19:42:56 +00:00
|
|
|
}, {
|
|
|
|
// Will break in viewport with short height
|
|
|
|
// But calculating bottom margin on the fly is too costly
|
2021-04-21 19:07:55 +00:00
|
|
|
rootMargin: marginTop + ' 0px -85% 0px'
|
2021-04-02 19:42:56 +00:00
|
|
|
} );
|
2021-04-21 19:07:55 +00:00
|
|
|
observer.observe( headlines[ i ] );
|
2020-02-15 22:56:29 +00:00
|
|
|
}
|
2020-02-15 22:55:31 +00:00
|
|
|
}
|
2019-12-30 14:53:22 +00:00
|
|
|
|
2022-05-12 21:18:39 +00:00
|
|
|
module.exports = {
|
2022-05-13 03:24:32 +00:00
|
|
|
init: initToC
|
2022-05-12 21:18:39 +00:00
|
|
|
};
|