media/js/base/article-toc.es6.js (63 lines of code) (raw):
/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
let isSticky = false;
let resizeTimer;
const stickyTOC = {};
const sidebar = document.querySelector('.mzp-l-sidebar');
/**
* Is the layout large enough to be 2 column?
* @returns {Boolean}
*/
stickyTOC.isTwoColumn = () => {
return getComputedStyle(sidebar).getPropertyValue('float') !== 'none';
};
/**
* Is there enough vertical space for sticky behavior?
* @returns {Boolean}
*/
stickyTOC.isTallEnough = () => {
return sidebar.offsetHeight < window.innerHeight;
};
/**
* Feature detect for sticky navigation
* @returns {Boolean}
*/
stickyTOC.supportsSticky = () => {
if (typeof window.MzpSupports !== 'undefined') {
return (
window.MzpSupports.classList &&
window.MzpSupports.matchMedia &&
CSS.supports('position', 'sticky')
);
} else {
return false;
}
};
/**
* Add class
*/
stickyTOC.createSticky = () => {
if (!isSticky) {
sidebar.classList.add('toc-is-sticky');
isSticky = true;
}
};
/**
* Remove class
*/
stickyTOC.destroySticky = () => {
if (isSticky) {
sidebar.classList.remove('toc-is-sticky');
isSticky = false;
}
};
/**
* Init sticky TOC if conditions are satisfied
*/
stickyTOC.initSticky = () => {
const makeSticky = () => {
if (
stickyTOC.isTallEnough() &&
stickyTOC.isTwoColumn() &&
!matchMedia('(prefers-reduced-motion: reduce)').matches
) {
stickyTOC.createSticky();
} else {
stickyTOC.destroySticky();
return false;
}
};
// react to window resizing
if (stickyTOC.supportsSticky()) {
makeSticky();
window.addEventListener(
'resize',
function () {
clearTimeout(resizeTimer);
resizeTimer = setTimeout(makeSticky, 250);
},
true
);
}
};
window.addEventListener('DOMContentLoaded', () => {
if (sidebar) {
stickyTOC.initSticky();
}
});