MediaWiki:Gadget-minitoc.js
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>
// Initialize preferred languages from local storage.
let preferredLanguages = new Set(JSON.parse(localStorage.getItem("minitocLangs")));
// Empty and filled-in bookmark icons.
const unselectedIcon = `<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="18" height="17" viewBox="0 0 20 20" aria-hidden="true" fill="currentColor"><g><path d="M5 1a2 2 0 00-2 2v16l7-5 7 5V3a2 2 0 00-2-2zm10 14.25-5-3.5-5 3.5V3h10z"></path></g></svg>`;
const selectedIcon = `<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="18" height="17" viewBox="0 0 20 20" aria-hidden="true" fill="currentColor"><g><path d="M5 1a2 2 0 00-2 2v16l7-5 7 5V3a2 2 0 00-2-2z"></path></g></svg>`;
mw.util.addCSS(`
.minitoc-icon-selected, .minitoc-icon-unselected {
cursor: pointer;
vertical-align: sub;
}
`);
function displayLanguages() {
// Clear out previously displayed languages.
document.querySelectorAll(".minitoc-linked-languages").forEach(elem => elem.remove());
for (let minitoc of document.querySelectorAll(".minitoc")) {
let linkedLanguages = document.createElement("span");
linkedLanguages.className = "minitoc-linked-languages";
for (let languageLink of minitoc.querySelectorAll(`.NavContent > a:not([href="#catlinks"]`)) {
if (preferredLanguages.has(languageLink.textContent)) {
let link = document.createElement("a");
link.textContent = `→ ${languageLink.textContent}`;
link.href = languageLink.href;
link.style.whiteSpace = "nowrap";
linkedLanguages.append(" ", link);
}
}
if (linkedLanguages.childElementCount)
minitoc.querySelector(".NavHead").append(linkedLanguages);
}
}
// Setup.
// Note: the code is generic and can handle multiple miniTOCs on one page, although this probably isn't necessary.
for (let minitoc of document.querySelectorAll(".minitoc")) {
minitoc.querySelector(".NavContent").insertAdjacentHTML("beforeend",
`<span style="font-size: 85%" class="minitoc-button-container">
 
[<a class="minitoc-button-select" role="button">
Select preferred languages
</a>]
<span style="display: none">
 
[<a class="minitoc-button-clear" role="button">
Clear all
</a>]
</span>
</span>`
.replace(/[\n\t]/g, "")
);
let selectButton = minitoc.querySelector(".minitoc-button-select");
let clearButton = minitoc.querySelector(".minitoc-button-clear");
selectButton.addEventListener("click", () => {
// The button can be in two states: "select" and "save".
if (selectButton.textContent === "Select preferred languages") {
clearButton.parentElement.style.display = "";
// Make sure you can't have multiple miniTOCs in "select" mode simultaneously.
for (let button of document.querySelectorAll(".minitoc-button-select")) {
if (button.textContent === "Save preferred languages") {
// Trigger the saving procedure.
button.click();
}
}
selectButton.textContent = "Save preferred languages";
for (let languageLink of minitoc.querySelectorAll(`.NavContent > a:not([href="#catlinks"]`)) {
let iconContainer = document.createElement("span");
iconContainer.role = "button";
languageLink.insertAdjacentElement("beforebegin", iconContainer);
if (preferredLanguages.has(languageLink.textContent)) {
iconContainer.className = "minitoc-icon-selected";
iconContainer.innerHTML = selectedIcon;
} else {
iconContainer.className = "minitoc-icon-unselected";
iconContainer.innerHTML = unselectedIcon;
}
iconContainer.addEventListener("click", () => {
if (preferredLanguages.has(languageLink.textContent)) {
preferredLanguages.delete(languageLink.textContent);
iconContainer.className = "minitoc-icon-unselected";
iconContainer.innerHTML = unselectedIcon;
} else {
preferredLanguages.add(languageLink.textContent);
iconContainer.className = "minitoc-icon-selected";
iconContainer.innerHTML = selectedIcon;
}
});
}
} else {
// Save to local storage.
localStorage.setItem("minitocLangs", JSON.stringify(Array.from(preferredLanguages)));
// Reset state.
minitoc.querySelectorAll(".minitoc-icon-selected, .minitoc-icon-unselected").forEach(elem => elem.remove());
selectButton.textContent = "Select preferred languages";
clearButton.parentElement.style.display = "none";
displayLanguages();
}
});
clearButton.addEventListener("click", () => {
preferredLanguages.clear();
for (let iconContainer of minitoc.querySelectorAll(".minitoc-icon-selected")) {
iconContainer.innerHTML = unselectedIcon;
iconContainer.className = "minitoc-icon-unselected";
}
});
}
displayLanguages();
// </nowiki>