MediaWiki:Common.js: Difference between revisions
Appearance
	
	
| No edit summary | No edit summary | ||
| Line 1: | Line 1: | ||
| /* Promote infobox image to a 10:7 hero  | /* Promote infobox image to a 10:7 hero above the title (touch devices only) */ | ||
| (function () { | |||
|    if (!window.matchMedia || ! |    if (!window.matchMedia || !matchMedia('(pointer: coarse)').matches) return; | ||
|    if (document.querySelector('.article-hero')) return; |    if (document.querySelector('.article-hero')) return; | ||
|    //  |    function run() { | ||
|     // Find the infobox image cell | |||
|     var imgCell = document.querySelector('table.infobox .infobox-image-cell'); | |||
|     if (!imgCell) return; | |||
|     // What we'll move: prefer a wrapper (span/a/figure) so we keep the link | |||
|     var moveNode = | |||
|       imgCell.querySelector('span, figure, a, picture, img') || imgCell.firstElementChild; | |||
|     if (!moveNode) return; | |||
|      var  | |||
|     // Where to put the hero | |||
|     var header = document.querySelector('.mw-body-header') || document.getElementById('firstHeading'); | |||
|     if (!header) return; | |||
|     // Create the hero *first* so space is reserved immediately | |||
|      var hero = document.createElement('div'); | |||
|     hero.className = 'article-hero'; | |||
|     header.parentNode.insertBefore(hero, header); | |||
|     // Batch DOM mutation in the next frame to avoid extra reflows | |||
|     requestAnimationFrame(function () { | |||
|       // Move (not clone) the existing node — avoids a second download/decoding | |||
|       hero.appendChild(moveNode); | |||
|       // Optional: mark infobox for any extra styling you might want later | |||
|       var infobox = imgCell.closest('table.infobox'); | |||
|       if (infobox) infobox.classList.add('infobox--image-promoted'); | |||
|     }); | |||
|    } |    } | ||
|    if (document.readyState === 'loading') { | |||
|      document.addEventListener('DOMContentLoaded', run, { once: true }); | |||
|    } else { |    } else { | ||
|      run(); | |||
|    } |    } | ||
| })(); | |||
Revision as of 19:15, 2 October 2025
/* Promote infobox image to a 10:7 hero above the title (touch devices only) */
(function () {
  if (!window.matchMedia || !matchMedia('(pointer: coarse)').matches) return;
  if (document.querySelector('.article-hero')) return;
  function run() {
    // Find the infobox image cell
    var imgCell = document.querySelector('table.infobox .infobox-image-cell');
    if (!imgCell) return;
    // What we'll move: prefer a wrapper (span/a/figure) so we keep the link
    var moveNode =
      imgCell.querySelector('span, figure, a, picture, img') || imgCell.firstElementChild;
    if (!moveNode) return;
    // Where to put the hero
    var header = document.querySelector('.mw-body-header') || document.getElementById('firstHeading');
    if (!header) return;
    // Create the hero *first* so space is reserved immediately
    var hero = document.createElement('div');
    hero.className = 'article-hero';
    header.parentNode.insertBefore(hero, header);
    // Batch DOM mutation in the next frame to avoid extra reflows
    requestAnimationFrame(function () {
      // Move (not clone) the existing node — avoids a second download/decoding
      hero.appendChild(moveNode);
      // Optional: mark infobox for any extra styling you might want later
      var infobox = imgCell.closest('table.infobox');
      if (infobox) infobox.classList.add('infobox--image-promoted');
    });
  }
  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);
});
