MediaWiki:Gadget-DocTabs.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)
- Edge: Hold Ctrl while clicking Refresh, or press Ctrl-F5.
// Idea: add or remove portlet links as required, using an API query to check what needs to be redlinked beforehand.
// The following page types are unsupported: `Template_talk:XYZ/documentation`, `Module_talk:XYZ/documentation`, `Citations_talk:XYZ`
// as it is not clear whether these pages should exist at all, and if so, what portlets should be shown on them.
// <nowiki>
let portletBar = document.querySelector("#p-associated-pages, #p-namespaces, #p-cactions");
if (portletBar) {
let actionAPI = new mw.Api({ajax: {headers: {"Api-User-Agent": "Gadget developed by [[User:Ioaxxere]]"}}});
let ns = mw.config.values.wgNamespaceNumber;
let title = mw.config.values.wgTitle.replaceAll(" ", "_");
let isDocumentationPage = (ns === 10 || ns === 11 || ns === 828 || ns === 829) && title.endsWith("/documentation");
// Remove /documentation suffix if necessary.
let mainTitle = isDocumentationPage ? title.slice(0, -14) : title;
// Page title, display text, ID, tooltip, access key.
let portletData = {
"mainspace": [mainTitle, "Entry", "ca-nstab-main", "View the content page", "c"],
"talk": [`Talk:${mainTitle}`, "Discussion", "ca-talk", "Discussion about the content page", "t"],
"citations": [`Citations:${mainTitle}`, "Citations", "ca-nstab-citations", "View the citations page", "3"],
"template": [`Template:${mainTitle}`, "Template", "ca-nstab-template", "View the template", "c"],
"template_talk": [`Template_talk:${mainTitle}`, "Discussion", "ca-talk", "Discussion about the content page", "t"],
"template_documentation": [`Template:${mainTitle}/documentation`, "Documentation", "ca-nstab-docs", "View the documentation", "3"],
"module": [`Module:${mainTitle}`, "Module", "ca-nstab-module", "View the module page", "c"],
"module_talk": [`Module_talk:${mainTitle}`, "Discussion", "ca-talk", "Discussion about the content page", "t"],
"module_documentation": [`Module:${mainTitle}/documentation`, "Documentation", "ca-nstab-docs", "View the documentation", "3"]
};
// Given a list of portlet types (see above), return a filtered set of portlets which need to be highlighted as redlinks.
async function checkRedlinkPortlets(...portletList) {
let titleList = portletList.map(portlet => portletData[portlet][0]);
// Check whether the page titles exist.
let response = await actionAPI.get({
action: "query",
titles: titleList.join("|"),
format: "json"
});
// Get page results which have a negative ID (i.e., do not exist).
let redlinks = new Set();
for (let [pageKey, pageData] of Object.entries(response.query.pages)) {
if (pageKey < 0)
redlinks.add(pageData.title.replaceAll(" ", "_"));
}
return new Set(portletList.filter(portlet => redlinks.has(portletData[portlet][0])));
}
// Adds a namespace link of the specified type (see above) on the portlet bar.
// It uses the `redlinkPortlets` list generated by checkRedlinkPortlets().
// `location` should be set to either "beginning" or "end".
// There appears to be no way to create a portlet redlink, so this implementation tries to emulate the default behaviour.
// Note: adding two identical portlets is currently unsupported, as it results in duplicate IDs in the DOM.
// More info: https://doc.wikimedia.org/mediawiki-core/REL1_29/js/#!/api/mw.util-method-addPortletLink
function addNamespaceLink(portletType, redlinkPortlets, location, isSelected) {
let data = portletData[portletType];
// Certain skins that have unrelated portlets in the same bar which we should always be before.
// If none of the selectors match an element, the portlet is placed at the very end as desired.
// If `location` is "beginning", the selector always matches the first element.
let before = location === "beginning" ? "li" : "#ca-edit, #ca-view, #ca-watch";
let isRedlink = redlinkPortlets.has(portletType);
let tooltip = data[3];
let href = `/wiki/${data[0]}`;
if (isRedlink) {
tooltip += " (page does not exist)";
href = `/w/index.php?title=${data[0]}&action=edit&redlink=1`;
}
mw.util.addPortletLink(portletBar.id, href, data[1], data[2], tooltip, data[4], portletBar.querySelector(before));
let portletElem = document.getElementById(data[2]);
if (isSelected) {
portletElem.classList.add("selected");
} else if (isRedlink) {
portletElem.classList.add("new");
portletElem.querySelector("a").classList.add("new");
}
}
(async () => {
if (ns === 0 || ns === 1) { // Mainspace and Talk
// Add a link to the citations page.
let redlinkPortlets = await checkRedlinkPortlets("citations");
addNamespaceLink("citations", redlinkPortlets, "end");
} else if (ns === 114) { // Citations
// Add links to mainspace and talk and remove link to citations talk.
let redlinkPortlets = await checkRedlinkPortlets("mainspace", "talk");
// Remove link to Citations talk.
portletBar.querySelectorAll("li")[1].remove();
// Set access key to "3".
let citationsLink = portletBar.querySelector("li > a");
citationsLink.setAttribute("accesskey", 3);
citationsLink.setAttribute("title", "View the citations page [alt-shift-3]");
addNamespaceLink("talk", redlinkPortlets, "beginning");
addNamespaceLink("mainspace", redlinkPortlets, "beginning");
} else if ((ns === 10 || ns === 11) && !isDocumentationPage) { // Template and Template_talk
// Add a link to the documentation.
let redlinkPortlets = await checkRedlinkPortlets("template_documentation");
addNamespaceLink("template_documentation", redlinkPortlets, "end");
} else if (ns === 10 && isDocumentationPage) { // Template documentation
let redlinkPortlets = await checkRedlinkPortlets("template", "template_talk", "template_documentation");
// Remove existing two portlet links.
portletBar.querySelector("li").remove();
portletBar.querySelector("li").remove();
// Add links to the template, discussion, and current documentation pages.
addNamespaceLink("template", redlinkPortlets, "end");
addNamespaceLink("template_talk", redlinkPortlets, "end");
addNamespaceLink("template_documentation", redlinkPortlets, "end", true);
} else if ((ns === 828 || ns === 829) && !isDocumentationPage) { // Module and Module_talk
// Add a link to the documentation.
let redlinkPortlets = await checkRedlinkPortlets("module_documentation");
addNamespaceLink("module_documentation", redlinkPortlets, "end");
} else if (ns === 828 && isDocumentationPage) { // Module documentation
let redlinkPortlets = await checkRedlinkPortlets("module", "module_talk", "module_documentation");
// Remove existing two portlet links.
portletBar.querySelector("li").remove();
portletBar.querySelector("li").remove();
// Add links to the module, discussion, and current documentation pages.
addNamespaceLink("module", redlinkPortlets, "end");
addNamespaceLink("module_talk", redlinkPortlets, "end");
addNamespaceLink("module_documentation", redlinkPortlets, "end", true);
}
})();
}
// </nowiki>