MediaWiki:Gadget-EtytreeZoom.js

From Linguifex
Jump to navigation Jump to search

Note: After publishing, you may have to bypass your browser's cache to see the changes.

  • Firefox / Safari: Hold Shift while clicking Reload, or press either Ctrl-F5 or Ctrl-R (⌘-R on a Mac)
  • Google Chrome: Press Ctrl-Shift-R (⌘-Shift-R on a Mac)
  • Internet Explorer / Edge: Hold Ctrl while clicking Refresh, or press Ctrl-F5
  • Opera: Press Ctrl-F5.
// <nowiki>
const elem = s => document.createRange().createContextualFragment(s).firstChild; // helper

mw.util.addCSS(`
	.etytree-scale {
		position: absolute;
		right: 0;
		padding: 0.5em;
		z-index: 100;
	}

	.etytree {
		position: relative;
	}

	.etytree-body {
		transform-origin: top left;
	}
`);

function zoomOut(tree) {
	let navContent = tree.parentElement;
	let scale = navContent.clientWidth / tree.scrollWidth;

	tree.style.transform = `scale(${scale})`;
	navContent.style.overflow = "hidden"; // hide scrollbars
	navContent.scrollLeft = 0;
	navContent.style.height = `${tree.scrollHeight * scale}px`;
}

function resetZoom(tree) {
	let navContent = tree.parentElement;
	tree.style.transform = "";
	navContent.style.overflow = "auto";
	navContent.style.height = "";
}

for (let etytree of document.querySelectorAll(".etytree")) {
	let navContent = etytree.querySelector(".NavContent");
	let tree = navContent.firstElementChild;
	let etytreeScale = elem(`<div class="etytree-scale"><button class="etytree-scale-toggle cdx-button">Zoom out</button></div>`.trim());
	let toggle = etytreeScale.querySelector(".etytree-scale-toggle");

	navContent.prepend(etytreeScale);
	etytree.treeZoomedOut = false;

	toggle.addEventListener("click", () => {
		if (toggle.textContent === "Zoom out") {
			zoomOut(tree);
			etytree.treeZoomedOut = true;
			toggle.textContent = "Zoom in";
		} else {
			resetZoom(tree);
			etytree.treeZoomedOut = false;
			toggle.textContent = "Zoom out";
		}
	});

	// The button is hidden if there's no horizontal scrollbar.
	etytreeScale.style.display = navContent.scrollWidth > navContent.clientWidth ? "" : "none";

	(new ResizeObserver(() => {
		for (let etytree of document.querySelectorAll(".etytree")) {
			if (etytree.treeZoomedOut) // redo the zoom out
				zoomOut(etytree.querySelector(".etytree-body"));
			let etytreeScale = etytree.querySelector(".etytree-scale");
			etytreeScale.style.display = navContent.scrollWidth > navContent.clientWidth ? "" : "none";
		}
	})).observe(navContent);
}
// </nowiki>