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
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);
}
);
}
});
