Jump to content

User:Phlsph7/ClassicalTOC(Vector2022).js

From Wikipedia, the free encyclopedia
The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.
Note: After saving, you have to bypass your browser's cache to see the changes. Google Chrome, Firefox, Microsoft Edge and Safari: Hold down the ⇧ Shift key and click the Reload toolbar button. For details and instructions about other browsers, see Wikipedia:Bypass your cache.
/* Classical table of contents for Vector 2022 */

// utility function to get the URL of the current page and apply the parameter for the legacy vector skin
function getURL(){
	let url = window.location.href.split('#')[0] + "?useskin=vector";
	if(window.location.href.split('#').length > 1){
		url += "#" + window.location.href.split('#').slice(1).join("#");
	}
	
	return url;
}

// uses the html text of the page with the legacy vector skin as input, extracts the TOC, and places it into the current page
function getTOCfromHTML(html){
	// adjust the style of the extracted TOC
	function adjustStyle(){
		// remove bullet points and fix margin for unordered lists
		let ulElements = toc.getElementsByTagName('ul');
		for(let ulElement of ulElements){
			ulElement.style.listStyle = "none";
			ulElement.style.marginTop = "0em";
		}

		// fix left margin for the main unordered list
		let masterUl = toc.getElementsByTagName('ul')[0];
		masterUl.style.marginLeft = "0.5em";
		masterUl.style.fontSize = "95%";

		// adjust font-size and font-family for the TOC heading ("Contents")
		let tocHeading = document.getElementById('mw-toc-heading');
		tocHeading.style.fontWeight = 'bold';

		// button used to fold and unfold the TOC
		let foldButton = document.createElement('a');
		
		// button style
		foldButton.style.fontSize = '80%';
		foldButton.style.marginLeft = '0.5em';
		foldButton.style.fontFamily = 'sans-serif';
		foldButton.style.fontWeight = 'normal';
		foldButton.style.verticalAlign = 'text-bottom';
		tocHeading.appendChild(foldButton);
		foldButton.innerHTML = '<span style="color: #202122">[</span>hide<span style="color: #202122">]</span>';
		
		// when clicked: fold/unfold the TOC and change the button text
		foldButton.onclick = function(event){
			if(foldButton.innerText.includes('hide')){
				foldButton.innerHTML = foldButton.innerHTML.split('hide').join('show');
				masterUl.style.display = 'none';
			}
			else{
				foldButton.innerHTML = foldButton.innerHTML.split('show').join('hide');
				masterUl.style.display = '';
			}
		};

		// adjust colors and spaces per entry
		const styleSheet = document.createElement('style');
		styleSheet.innerHTML = `
		.tocnumber{
			color: #202122;
			padding-right: 0.2em;
		}
		
		.toctext{
			color: #0645ad;
		}
		`;
		document.head.append(styleSheet);
	}
	
	// change the look into a grey box
	function setClassicalBoxLook(){
		toc.style.border = "1px solid #a2a9b1";
		toc.style.backgroundColor = "#f8f9fa";
		toc.style.display = "inline-block";
		toc.style.paddingRight = "0.5em";
		let tocHeading = document.getElementById('mw-toc-heading');
		tocHeading.style.textAlign = "center";
		tocHeading.style.borderBottom = "none";
		tocHeading.style.marginTop = "0.3em";
		tocHeading.style.marginLeft = "0.3em";
		firstSectionHeadline.style.clear = "left";
	}
	
	// fix for pages that use the template "clear" before the first section
	function fixClearTemplate(){
		let neighbor =  toc.previousElementSibling;
		if(neighbor != null && neighbor.style.clear === 'both' && neighbor.innerText == ''){
			neighbor.parentNode.insertBefore(toc, neighbor);
		}
	}
	
	// scroll to the right position for section links in case the loading takes too long
	function scrollToRightPosition(){
		if(window.location.hash){
			let hashValue = window.location.hash.substring(1);
			let selectedHeadline = document.getElementById(hashValue);
			if(selectedHeadline != null){
				selectedHeadline.scrollIntoView();
			}
		}
	}
	
	// parse the html file
	var parser = new DOMParser();
	var htmlDoc = parser.parseFromString(html, "text/html");
	
	// extract the TOC and place it before the first headline
	var toc = htmlDoc.getElementById("toc");
	var firstSectionHeadline = getFirstSectionHeadline();
	if(toc != null && firstSectionHeadline != null){
		// insert before the first section
		firstSectionHeadline.parentElement.insertBefore(toc, firstSectionHeadline);
	
		// adjust the general style
		adjustStyle();
		
		// apply the box layout
		setClassicalBoxLook();
		
		// fix for the template "clear"
		fixClearTemplate();
		
		// scroll to the right position for section links in case the loading takes too long
		scrollToRightPosition();
	}
}
	
// utility function to get the headline of the first section, the TOC should be inserted before it
function getFirstSectionHeadline(){
	var mainContainer = document.getElementById('mw-content-text');
	var firstSectionHeadline = mainContainer.getElementsByTagName('h2')[0].parentElement;
	return firstSectionHeadline;
}

// main function
(function(){
	// check whether the Vector 2022 skin is used
	if (document.body.classList.contains("skin-vector-2022")){
		// does not work when editing pages, so only show the TOC when viewing pages
		if(mw.config.get("wgAction") === "view"){
			// load the legacy html to extract their TOC
			fetch(getURL())
				.then(response => response.text())
				.then(getTOCfromHTML);
		}
	}
})();