mirror of
https://github.com/StarCitizenTools/mediawiki-skins-Citizen.git
synced 2024-11-28 16:21:11 +00:00
Merge pull request #332 from StarCitizenTools/dev
ToC performance improvements
This commit is contained in:
commit
17bdc97c9a
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue