User:Ioaxxere/minitoc.js

From Wiktionary, the free dictionary
Jump to navigation Jump to search

Note: You may have to bypass your browser’s cache to see the changes. In addition, after saving a sitewide CSS file such as MediaWiki:Common.css, it will take 5-10 minutes before the changes take effect, even if you clear your cache.

  • Mozilla / Firefox / Safari: hold Shift while clicking Reload, or press either Ctrl-F5 or Ctrl-R (Command-R on a Macintosh);
  • Konqueror and Chrome: click Reload or press F5;
  • Opera: clear the cache in Tools → Preferences;
  • Internet Explorer: hold Ctrl while clicking Refresh, or press Ctrl-F5.

// This script gives {{minitoc}} some cool new functionality.

let selectionEnabled = false;

// Try to initialize preferredLanguagesArray from saved cookie.
let preferredLanguagesArray = JSON.parse(mw.storage.get("miniTOC_langs")) || [];

document.querySelectorAll("[data-minitoc-length]").forEach(miniTOC => {
	const NavHead = miniTOC.children[0];
	const NavContent = miniTOC.children[1];
	const languageLinks = NavContent.querySelectorAll("span");

	// Create language selector.
	const langSelector = document.createElement("a");
	langSelector.textContent = "[select preferred language(s)]";
	langSelector.style.fontSize = "85%";

	// Create clear button (initially hidden).
	const clearButton = document.createElement("a");
	clearButton.textContent = "[clear all]";
	clearButton.style.fontSize = "85%";
	clearButton.style.display = "none";

	NavContent.appendChild(document.createTextNode(" "));
	NavContent.appendChild(langSelector);
	NavContent.appendChild(document.createTextNode(" "));
	NavContent.appendChild(clearButton);

	// This function is called whenever headerLinks needs to be updated and displayed.
	function updateHeaderLinks() {
		headerLinks.innerHTML = "";
		Array.from(languageLinks).filter(item => preferredLanguagesArray.includes(item.textContent)).forEach(item => {
			let headerLink = document.createElement("a");
			headerLink.setAttribute("href", item.children[0].getAttribute("href"));
			headerLink.style.whiteSpace = "nowrap";
			headerLink.textContent = "→ " + item.textContent + " ";
			// Prevent NavFrame from opening or closing.
			headerLink.addEventListener("click", (event) => {
				event.stopPropagation();
			})
			headerLinks.appendChild(document.createTextNode(" "));
			headerLinks.appendChild(headerLink);
		})
		headerLinks.style.display = "inline"
	}

	// Create header links to preferred languages.
	const headerLinks = document.createElement("span");
	updateHeaderLinks();
	NavHead.appendChild(document.createTextNode(" "));
	NavHead.appendChild(headerLinks);

	// Clear all languages when clearButton is clicked.
	clearButton.addEventListener("click", () => {
		preferredLanguagesArray = [];
		languageLinks.forEach(languageLink => {
			languageLink.style.backgroundColor = "palegoldenrod";
		});
	});

	// This function is called whenever a user adds or removes a preferred language.
	function togglePreferredLanguage(event) {
		// Temporarily disable the link from functioning.
		event.preventDefault();
		if (this.style.backgroundColor == "lightgreen") {
			// Remove language.
			preferredLanguagesArray = preferredLanguagesArray.filter(item => item !== this.textContent);
			this.style.backgroundColor = "palegoldenrod";
		} else {
			// Add language.
			preferredLanguagesArray.push(this.textContent);
			this.style.backgroundColor = "lightgreen";
		}
	}
	
	// Do stuff when langSelector is clicked.
	langSelector.addEventListener("click", (event) => {
		selectionEnabled = !selectionEnabled;
		if (selectionEnabled) {
			langSelector.textContent = "[save preferred language(s)]";
			clearButton.style.display = "inline";
			headerLinks.style.display = "none"
		} else {
			langSelector.textContent = "[select preferred language(s)]";
			clearButton.style.display = "none";
			updateHeaderLinks();
		}

		if (selectionEnabled) {
			// Add highlighting.
			languageLinks.forEach(languageLink => {
				languageLink.addEventListener("click", togglePreferredLanguage);
				if (preferredLanguagesArray.includes(languageLink.textContent)) {
					languageLink.style.backgroundColor = "lightgreen";
				} else {
					languageLink.style.backgroundColor = "palegoldenrod";
				}
			});	
		} else {
			// Save list as a cookie and remove highlighting.
			preferredLanguagesArray.sort();
			mw.storage.set("miniTOC_langs", JSON.stringify(preferredLanguagesArray));
			languageLinks.forEach(languageLink => {
				languageLink.removeEventListener("click", togglePreferredLanguage);
				languageLink.style.backgroundColor = "";
			});
		}
	});
});