Merge pull request #332 from StarCitizenTools/dev

ToC performance improvements
This commit is contained in:
alistair3149 2021-04-02 15:48:12 -04:00 committed by GitHub
commit 17bdc97c9a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 29 additions and 91 deletions

View file

@ -9,3 +9,4 @@ resources/skins.citizen.scripts.search/typeahead-init.js
resources/skins.citizen.scripts.search/underscore.partial.js
resources/skins.citizen.scripts.search/wm-typeahead.js
resources/skins.citizen.scripts.theme/inline.js
resources/skins.citizen.scripts.toc/skins.citizen.scripts.toc.js

View file

@ -1,77 +1,28 @@
/*
* Citizen - ToC JS
* https://starcitizen.tools
*
* Smooth scroll fallback and Scrollspy
*/
/**
* Implement smooth scroll when an item in table of content is clicked.
*
* @constructor
*/
function SmoothScroll() {
var navLinks, eventListener, link;
if ( !( 'scrollBehavior' in document.documentElement.style ) ) {
navLinks = document.querySelectorAll( '#toc a' );
eventListener = function clickHandler( e ) {
e.preventDefault();
e.target.scrollIntoView( {
behavior: 'smooth'
} );
};
for ( link in navLinks ) {
if ( Object.prototype.hasOwnProperty.call( navLinks, link ) ) {
navLinks[ link ].addEventListener( 'click', eventListener );
}
}
}
}
/**
* Throttle scroll event
*
* @param {Function} fn - function
* @param {number} wait - wait time in ms
* @return {Function}
*/
function throttle( fn, wait ) {
var time = Date.now();
return function () {
if ( ( time + wait - Date.now() ) < 0 ) {
fn();
time = Date.now();
}
};
}
/**
* Add active HTML class to items in table of content based on user viewport.
*
* @constructor
*/
function ScrollSpy() {
function intersectionHandler() {
var sections = document.querySelectorAll( '.mw-headline' ),
mwbody = document.querySelector( '.mw-body' ),
mwbodyStyle = window.getComputedStyle( mwbody ),
scrollOffset = parseInt( mwbodyStyle.marginTop, 10 ) + 1;
htmlStyles = window.getComputedStyle( document.documentElement ),
scrollPaddingTop = htmlStyles.getPropertyValue( 'scroll-padding-top' ),
// Align with scroll offset set in CSS
marginTop = "-" + scrollPaddingTop,
id, id2, toclink, node, active;
window.addEventListener( 'scroll', throttle( function () {
var scrollPos = document.documentElement.scrollTop || document.body.scrollTop,
section, id, id2, toclink, node, active;
scrollPos += scrollOffset;
for ( section in sections ) {
if (
Object.prototype.hasOwnProperty.call( sections, section ) &&
sections[ section ].offsetTop <= scrollPos
) {
id = sections[ section ].id;
for (let i = 0; i < sections.length; i++) {
const observer = new IntersectionObserver( ( entry ) => {
if ( entry[ 0 ].isIntersecting ) {
id = sections[i].id;
// Try the ID of the span before
if ( sections[ section ].previousSibling !== null ) {
id2 = sections[ section ].previousSibling.id || '';
if ( sections[i].previousSibling !== null ) {
id2 = sections[i].previousSibling.id || '';
}
toclink = document.querySelector( "a[href='#" + id + "']" ) || document.querySelector( "a[href='#" + id2 + "']" );
node = toclink.parentNode;
@ -83,35 +34,19 @@ function ScrollSpy() {
node.classList.add( 'active' );
}
}
}
}, 10 ), { passive: true } );
}
/**
* Run SmoothScroll() and ScrollSpy() when table of content is present.
*
* @constructor
*/
function CheckToC() {
if ( document.getElementById( 'toc' ) ) {
SmoothScroll();
ScrollSpy();
}, {
// Will break in viewport with short height
// But calculating bottom margin on the fly is too costly
rootMargin: marginTop + " 0px -85% 0px"
} );
observer.observe( sections[i] );
}
}
function main() {
if ( document.readyState !== 'loading' ) {
CheckToC();
} else if ( document.addEventListener ) {
// All modern browsers to register DOMContentLoaded
document.addEventListener( 'DOMContentLoaded', CheckToC );
} else {
// Old IE browsers
document.attachEvent( 'onreadystatechange', function () {
if ( document.readyState === 'complete' ) {
CheckToC();
}
} );
// Check for has-toc class since it is loaded way before #toc is present
if ( document.body.classList.contains( 'skin-citizen-has-toc' ) ) {
intersectionHandler();
}
}

View file

@ -253,11 +253,6 @@ video {
max-width: 100%; // Prevent overflow
}
html.citizen-animations-ready {
// So that the delay scroll animation won't happen on load
scroll-behavior: smooth; // not supported by IE, Edge, Safari, and Opera, use JQuery as fallback
}
.skin-citizen-dark {
.mw-editsection > a:before {
filter: invert( 1 );
@ -272,4 +267,11 @@ html.citizen-animations-ready {
table {
display: table;
}
// Delay scroll animation won't happen on load
// Use it only for larger viewport as it is very costly
// on mobile devices
html.citizen-animations-ready {
scroll-behavior: smooth;
}
}