Jump to content

User:Andrybak/Scripts/Vectron.js

From Wikipedia, the free encyclopedia
This is an old revision of this page, as edited by Andrybak (talk | contribs) at 20:57, 7 June 2024 (By Vectron's eyes, I'm glad to hear that the linked section is now always shown to the user after change of the width). The present address (URL) is a permanent link to this revision, which may differ significantly from the current revision.
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.
// <nowiki>
(function() {
	'use strict';

	const USERSCRIPT_NAME = 'Vectron';
	const config = {
		wikipage: '[[:en:User:Andrybak/${USERSCRIPT_NAME}|${USERSCRIPT_NAME}]]',
		version: '2'
	};
	const LOG_PREFIX = `[${USERSCRIPT_NAME} v${config.version}]:`;
	const mw = window.mw; // a hack to trick my JS editor into believing that `mw` exists

	function error(...toLog) {
		console.error(LOG_PREFIX, ...toLog);
	}

	function warn(...toLog) {
		console.warn(LOG_PREFIX, ...toLog);
	}

	function info(...toLog) {
		console.info(LOG_PREFIX, ...toLog);
	}

	function debug(...toLog) {
		console.debug(LOG_PREFIX, ...toLog);
	}

	function getLimitedWidthToggleButton() {
		return document.querySelector('#p-dock-bottom button.vector-limited-width-toggle');
	}

	function isWideVector(button) {
		return button.getAttribute('data-event-name').endsWith('on');
	}

	function isNarrowVector(button) {
		return !isWideVector(button);
	}

	function maybeShowHashTarget() {
		/*
		 * Because we are messing with the layout of the page
		 * on the fly, we need to ensure that the user sees
		 * the linked section.
		 */
		if (document.location.hash === "") {
			return;
		}
		const targetId = document.location.hash.slice(1).replaceAll(' ', '_');
		document.getElementById(targetId).scrollIntoView();
	}

	function ensureWide() {
		const button = getLimitedWidthToggleButton();
		if (isWideVector(button)) {
			debug('Already wide.');
			return;
		}
		info('Widening.');
		button.click();
		maybeShowHashTarget();
	}

	function ensureNarrow() {
		const button = getLimitedWidthToggleButton();
		if (isNarrowVector(button)) {
			debug('Already narrow.');
			return;
		}
		info('Narrowing.');
		button.click();
		maybeShowHashTarget();
	}

	/*
	 * The main function of the script.
	 */
	function runScript() {
		/*
		 * Reference documentation about keys and values in mw.config:
		 * https://www.mediawiki.org/wiki/Manual:Interface/JavaScript#mw.config
		 */
		if (!mw.config.get('wgIsArticle')) { // This variable is badly named -- it is not related to a page being a main namespace "article".
			info('Not a wiki page.');
			ensureWide();
			return;
		}
		if (mw.config.get('wgDiffNewId') != null || mw.config.get('wgDiffOldId') != null) {
			info('Diff view.');
			ensureWide();
			return;
		}
		const namespaceNumber = mw.config.get('wgNamespaceNumber');
		if (namespaceNumber == -1) {
			info('This is a "Special:" page.');
			ensureWide();
			return;
		}
		const contentModel = mw.config.get("wgPageContentModel");
		// ['javascript', 'css', 'sanitized-css', 'Scribunto'].includes(contentModel)
		if (contentModel !== 'wikitext') {
			info('Content model of the page is for source code (Lua, JS, CSS, etc).');
			ensureWide();
			return;
		}
		info('Assuming wiki page.');
		ensureNarrow();
	}

	function wait(message) {
		info(message);
		setTimeout(lazyLoadVectron, 200);
	}

	/*
	 * Infrastructure to ensure the script can run.
	 */
	function lazyLoadVectron() {
		debug('Loading...');
		const skinId = mw.config.get("skin");
		if (skinId === null) {
			wait('Skin is not loaded yet. Waiting...');
			return;
		}
		if (skinId !== 'vector-2022') {
			warn(`Skin ${skinId} is not supported by the script. Aborting.`);
			return;
		}
		const button = getLimitedWidthToggleButton();
		if (button == null) {
			wait('The toggle button is not loaded yet. Waiting...');
			return;
		}
		const theAttribute = button.getAttribute('data-event-name');
		if (theAttribute == null) {
			wait('Attribute "data-event-name" is not loaded yet. Waiting...');
			return;
		}
		runScript();
	}

	if (document.readyState !== 'loading') {
		lazyLoadVectron();
	} else {
		warn('Cannot load yet. Setting up a listener...');
		document.addEventListener('DOMContentLoaded', lazyLoadVectron);
	}
})();
// </nowiki>