MediaWiki:Common.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.
/* Hero image above the title, cloned from infobox (touch devices only) */
(function () {
if (!window.matchMedia || !matchMedia('(pointer: coarse)').matches) return;
if (document.querySelector('.article-hero')) return;
function bestSrc(img) {
// prefer the largest srcset candidate if present
var ss = img.getAttribute('srcset');
if (!ss) return img.currentSrc || img.src || '';
var last = ss.split(',').pop().trim().split(/\s+/)[0];
return last || img.currentSrc || img.src || '';
}
function run() {
var imgCell = document.querySelector('table.infobox .infobox-image-cell');
if (!imgCell) return;
// Prefer cloning a wrapper so link/captions survive if present
var wrapper = imgCell.querySelector('a, span, figure, picture') || imgCell.querySelector('img');
if (!wrapper) return;
var header = document.querySelector('.mw-body-header') || document.getElementById('firstHeading');
if (!header) return;
// Build hero before header (reserves space up-front)
var hero = document.createElement('div');
hero.className = 'article-hero';
header.parentNode.insertBefore(hero, header);
// Clone the wrapper; if we only have <img>, create a fresh <img> with best candidate
var cloneNode;
if (wrapper.tagName.toLowerCase() === 'img') {
cloneNode = document.createElement('img');
cloneNode.src = bestSrc(wrapper);
cloneNode.alt = ''; // decorative hero; alt remains in infobox
cloneNode.decoding = 'async';
cloneNode.loading = 'eager';
cloneNode.fetchPriority = 'high';
cloneNode.sizes = '100vw';
} else {
cloneNode = wrapper.cloneNode(true);
// Ensure nested <img> uses a high-res candidate
var heroImg = cloneNode.querySelector('img');
if (heroImg) {
heroImg.src = bestSrc(heroImg);
heroImg.alt = '';
heroImg.decoding = 'async';
heroImg.loading = 'eager';
heroImg.fetchPriority = 'high';
heroImg.sizes = '100vw';
}
}
hero.appendChild(cloneNode);
// Reveal smoothly on the next frame
requestAnimationFrame(function () {
hero.classList.add('is-ready');
});
}
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', run, { once: true });
} else {
run();
}
})();
/* Quick facts: collapse infobox under first paragraph on touch devices */
mw.hook('wikipage.content').add(function ($content) {
// Only on touch devices
if (!window.matchMedia || !window.matchMedia('(pointer: coarse)').matches) return;
var $ibox = $content.find('table.infobox').first();
if (!$ibox.length) return;
// First real paragraph in article content
var $firstP = $content
.find('.mw-parser-output > p')
.filter(function () { return $(this).text().trim().length > 0; })
.first();
if (!$firstP.length) return;
// Build <details> wrapper
var $details = $('<details>', { 'class': 'quickfacts', 'aria-label': 'Quick facts' });
var $summary = $('<summary>', { 'class': 'quickfacts-summary', text: 'Quick facts' });
$details.append($summary);
// Mark infobox so CSS can remove float/width inside quickfacts
$ibox.addClass('infobox--in-quickfacts');
// Move the infobox inside the details (not cloning; avoids duplicate content for SR)
$details.append($ibox);
// Insert directly after the first paragraph
$details.insertAfter($firstP);
});