Tip of the day
You can find achievements and obtained collectible items by tapping your character at the top-left.

MediaWiki:Gadget-wswbLanguageSelector.js

From Walkscape Walkthrough
Revision as of 03:21, 30 August 2026 by Bonez565 (talk | contribs) (Created page with "// Move and control the custom WSWB language selector. $(function () { const selector = document.querySelector( ".wswb-language-selector" ); if (!selector) { return; } function markSelectorReady() { selector.classList.add("is-ready"); } const subpages = document.querySelector(".subpages"); if (subpages) { subpages.replaceWith(selector); } const inlineLanguages = selector.querySelector( ".wswb-language-selector__inline" ); const toggle = select...")
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)

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)
  • Edge: Hold Ctrl while clicking Refresh, or press Ctrl-F5.
// Move and control the custom WSWB language selector.
$(function () {
	const selector = document.querySelector(
		".wswb-language-selector"
	);

	if (!selector) {
		return;
	}
	
	function markSelectorReady() {
		selector.classList.add("is-ready");
	}

	const subpages = document.querySelector(".subpages");

	if (subpages) {
		subpages.replaceWith(selector);
	}

	const inlineLanguages = selector.querySelector(
		".wswb-language-selector__inline"
	);
	const toggle = selector.querySelector(
		".wswb-language-selector__toggle"
	);
	const menu = selector.querySelector(
		".wswb-language-selector__menu"
	);
	const toggleSeparator = selector.querySelector(
		".wswb-language-selector__toggle-separator"
	);

	if (!inlineLanguages || !toggle || !toggleSeparator || !menu) {
		markSelectorReady();
		return;
	}

	// Preserve the original language order even when options
	// move between the main bar and dropdown.
	const languageOptions = Array.from(
		inlineLanguages.querySelectorAll(
			".wswb-language-selector__option"
		)
	);
	
	const currentOption = languageOptions.find(
		function (option) {
			return option.classList.contains(
				"wswb-language-selector__current"
			);
		}
	);

	const englishOption = languageOptions.find(
		function (option) {
			return option.getAttribute("lang") === "en";
		}
	);
	
	const movableOptions = languageOptions.filter(
		function (option) {
			return !option.classList.contains(
				"wswb-language-selector__pinned"
			);
		}
	);
	
	function selectorOverflows() {
		return (
			selector.scrollWidth >
			selector.clientWidth + 1
		);
	}
	
	function arrangeLanguages() {
		try {
			setOpen(false);
	
			// Restore every language to its original order.
			languageOptions.forEach(function (option) {
				inlineLanguages.appendChild(option);
			});
	
			setToggleVisible(false);
	
			if (!selectorOverflows()) {
				return;
			}
	
			setToggleVisible(true);
	
			// Move only non-pinned languages, starting
			// from the right side of the row.
			for (
				let index = movableOptions.length - 1;
				index >= 0 && selectorOverflows();
				index -= 1
			) {
				const option = movableOptions[index];

				menu.insertBefore(
					option,
					menu.firstChild
				);
			}

			/*
			 * If the selected language, English and the
			 * dropdown still cannot fit, move English into
			 * the dropdown. The selected language always
			 * remains visible.
			 */
			if (
				selectorOverflows() &&
				englishOption &&
				englishOption !== currentOption
			) {
				menu.insertBefore(
					englishOption,
					menu.firstChild
				);
			}

			setToggleVisible(
				menu.children.length > 0
			);
		
		} finally {
			/*
			 * Reveal the selector after the first layout.
			 * Adding the class again during resize is harmless.
			 */
			markSelectorReady();
		}
	}

	function setOpen(open) {
		// Do not open an empty dropdown.
		if (
			open &&
			menu.children.length === 0
		) {
			open = false;
		}

		toggle.setAttribute(
			"aria-expanded",
			String(open)
		);
		menu.setAttribute(
			"aria-hidden",
			String(!open)
		);
		menu.classList.toggle("is-open", open);
	}

	function setToggleVisible(visible) {
		toggle.classList.toggle(
			"is-hidden",
			!visible
		);
		toggle.setAttribute(
			"aria-hidden",
			String(!visible)
		);
	
		toggleSeparator.classList.toggle(
			"is-hidden",
			!visible
		);
	
		if (!visible) {
			setOpen(false);
		}
	}

	toggle.addEventListener("click", function () {
		const open =
			toggle.getAttribute(
				"aria-expanded"
			) === "true";

		setOpen(!open);
	});

	toggle.addEventListener(
		"keydown",
		function (event) {
			if (
				event.key === "Enter" ||
				event.key === " "
			) {
				event.preventDefault();

				const open =
					toggle.getAttribute(
						"aria-expanded"
					) === "true";

				setOpen(!open);
			}
		}
	);

	// Escape closes the dropdown from anywhere on the page.
	document.addEventListener(
		"keydown",
		function (event) {
			if (
				event.key !== "Escape" &&
				event.key !== "Esc"
			) {
				return;
			}

			const open =
				toggle.getAttribute(
					"aria-expanded"
				) === "true";

			if (open) {
				setOpen(false);
				toggle.focus();
			}
		},
		true
	);

	// Clicking outside the selector closes the dropdown.
	document.addEventListener(
		"pointerdown",
		function (event) {
			if (!selector.contains(event.target)) {
				setOpen(false);
			}
		},
		true
	);

    // Avoid running the layout repeatedly during resizing.

	let resizeFrame = null;
	let lastArrangementWidth = null;

	function getArrangementWidth() {
		const container =
			selector.parentElement || selector;

		return Math.round(
			container.getBoundingClientRect().width
		);
	}

	function scheduleArrangement(force) {
		const width = getArrangementWidth();

		if (
			!force &&
			width === lastArrangementWidth
		) {
			return;
		}

		if (resizeFrame !== null) {
			window.cancelAnimationFrame(
				resizeFrame
			);
		}

		resizeFrame =
			window.requestAnimationFrame(
				function () {
					resizeFrame = null;

					const currentWidth =
						getArrangementWidth();

					if (
						!force &&
						currentWidth ===
							lastArrangementWidth
					) {
						return;
					}

					lastArrangementWidth =
						currentWidth;

					arrangeLanguages();
				}
			);
	}

	window.addEventListener(
		"resize",
		function () {
			scheduleArrangement(false);
		}
	);

	if (
		window.ResizeObserver &&
		selector.parentElement
	) {
		const resizeObserver =
			new ResizeObserver(
				function () {
					scheduleArrangement(false);
				}
			);

		resizeObserver.observe(
			selector.parentElement
		);
	}

	setOpen(false);
	scheduleArrangement(true);

	// Force one recheck after the web fonts load because
	// text widths can change without the container changing width.

	if (document.fonts) {
		document.fonts.ready.then(
			function () {
				scheduleArrangement(true);
			}
		);
	}
});