MediaWiki:Gadget-SidebarImages.js
Appearance
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.
// Enables the injection of images into sidebars
// IMPORTANT: Configuration is co-dependent with that of MediaWiki:Common.css
(function ($, mw) {
'use strict';
if (window.ICWSidebarImagesLoaded) return;
window.ICWSidebarImagesLoaded = true;
// Config is loaded dynamically from MediaWiki:SidebarImages.json at runtime.
// Fallback URL builder when API fails
function buildRedirectThumbURL(filename, size) {
const title = `Special:Redirect/file/${filename}`;
return mw.util.getUrl(title, { width: String(size) });
}
function fetchIconURLs(files, size) {
const api = new mw.Api({ timeout: 8000 });
return api.get({
action: 'query',
formatversion: 2,
prop: 'imageinfo',
titles: files,
iiprop: 'url|mime',
iiurlwidth: size
}).then(function (data) {
const out = Object.create(null);
const pages = (data && data.query && data.query.pages) || [];
for (const page of pages) {
if (!page || page.missing || !page.title) continue;
const baseName = page.title.replace(/^File:/i, '');
const info = (page.imageinfo && page.imageinfo[0]) || null;
// Priority: SVG direct URL, then thumbnail, then redirect fallback
if (info && info.mime === 'image/svg+xml' && info.url) {
out[baseName] = info.url;
} else if (info && info.thumburl) {
out[baseName] = info.thumburl;
} else {
out[baseName] = buildRedirectThumbURL(baseName, size);
}
}
return out;
});
}
// Per-skin size selection
function pickSize(sizeCfg) {
if (typeof sizeCfg === 'number') return sizeCfg;
var skin = mw.config.get('skin');
return (sizeCfg && (sizeCfg[skin] || sizeCfg.default)) || 24;
}
// Load shared JSON config from on-wiki page (with fallback)
function getSidebarIconsConfig() {
if (window.ICWSidebarIconsConfigPromise) return window.ICWSidebarIconsConfigPromise;
window.ICWSidebarIconsConfigPromise = mw.loader.using('mediawiki.api').then(function () {
var api = new mw.Api();
return api.get({
action: 'query',
prop: 'revisions',
titles: 'MediaWiki:SidebarImages.json',
rvprop: 'content',
rvslots: '*',
formatversion: 2
}).then(function (data) {
var page = data && data.query && data.query.pages && data.query.pages[0];
var text = page && page.revisions && page.revisions[0] &&
(page.revisions[0].slots ? page.revisions[0].slots.main.content : page.revisions[0].content);
if (!text) throw new Error('No JSON content');
return JSON.parse(text);
}).catch(function () {
// Fallback: return null to trigger simple text fallback
return null;
});
});
return window.ICWSidebarIconsConfigPromise;
}
function insertIconGroups(groups, urlMap) {
for (const group of groups) {
const container = document.getElementById(group.containerId);
if (!container) continue;
const groupWrapper = document.createElement('div');
// Classes required for CSS styling and OpenExternal.js processing
groupWrapper.className = 'sidebar-icon-group link-open-external';
for (const icon of group.icons) {
const src = urlMap[icon.file];
if (!src) continue;
const link = document.createElement('a');
link.href = icon.url;
const img = document.createElement('img');
img.src = src;
img.alt = icon.name;
img.width = pickSize(group.size);
img.height = pickSize(group.size);
img.decoding = 'async';
img.loading = 'eager';
if (icon.className) {
img.classList.add(icon.className);
}
link.appendChild(img);
groupWrapper.appendChild(link);
}
// Replace placeholder content and show icons
container.innerHTML = '';
container.appendChild(groupWrapper);
container.style.opacity = 1;
container.style.pointerEvents = 'auto';
}
}
function insertTextFallback() {
const container = document.getElementById('n-Social-Links');
if (!container) return;
const link = document.createElement('a');
link.href = '/Main_Page';
link.textContent = 'ICANNWiki';
container.innerHTML = '';
container.appendChild(link);
container.style.opacity = 1;
container.style.pointerEvents = 'auto';
}
function initSidebarIcons() {
getSidebarIconsConfig().then(function (cfg) {
const groups = (cfg && cfg.groups) || [];
if (!groups.length) {
insertTextFallback();
return;
}
const allIcons = groups.flatMap(g => g.icons);
const fileTitles = allIcons.map(icon => 'File:' + icon.file);
const maxSize = Math.max.apply(null, groups.map(g => pickSize(g.size)));
fetchIconURLs(fileTitles, maxSize)
.then(urlMap => insertIconGroups(groups, urlMap))
.catch(err => {
console.groupCollapsed('[SidebarImages] API error occurred.');
console.error(err);
console.groupEnd();
insertTextFallback();
});
});
}
$(function () {
if (mw.config.get('skin') === 'minerva') return; // REVIEW: Skip mobile skin
const sidebar = document.getElementById('mw-panel');
if (!sidebar) {
// Wait for sidebar creation on slow-loading pages
new MutationObserver((mutations, obs) => {
if (document.getElementById('mw-panel')) {
obs.disconnect();
initSidebarIcons();
}
}).observe(document.body, { childList: true, subtree: true });
} else {
initSidebarIcons();
}
});
})(jQuery, mediaWiki);