MediaWiki:Common.js: Difference between revisions
Appearance
Created page with "→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).tex..." |
No edit summary |
||
(3 intermediate revisions by the same user not shown) | |||
Line 1: | Line 1: | ||
/* 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 */ | /* Quick facts: collapse infobox under first paragraph on touch devices */ | ||
mw.hook('wikipage.content').add(function ($content) { | mw.hook('wikipage.content').add(function ($content) { |
Latest revision as of 19:19, 2 October 2025
/* 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); });