Changes

no edit summary
Line 6: Line 6:     
/* Other JS: */
 
/* Other JS: */
 +
/* Force-load images/media when a MobileFrontend section is expanded */
 +
(function () {
 +
  function forceLoadIn(root) {
 +
    if (!root) return;
 +
 +
    // <img> with native lazy or data-* sources
 +
    var imgs = root.querySelectorAll('img[loading="lazy"], img[data-src], img[data-srcset], img.lazyload');
 +
    imgs.forEach(function (img) {
 +
      try {
 +
        // Promote data-* to real attrs if present
 +
        if (img.dataset) {
 +
          if (img.dataset.src) img.src = img.dataset.src;
 +
          if (img.dataset.srcset) img.srcset = img.dataset.srcset;
 +
          if (img.dataset.sizes) img.sizes = img.dataset.sizes;
 +
        }
 +
        // Disable lazy & decode ASAP
 +
        img.loading = 'eager';
 +
        try { img.decoding = 'sync'; } catch (e) {}
 +
 +
        // Kick browsers that already set src but kept it idle due to prior hidden state
 +
        var s = img.currentSrc || img.src;
 +
        if (s) { img.src = ''; img.src = s; }
 +
      } catch (e) {}
 +
    });
 +
 +
    // Background images deferred via data-bg
 +
    var bgs = root.querySelectorAll('[data-bg]');
 +
    bgs.forEach(function (el) {
 +
      var bg = el.getAttribute('data-bg');
 +
      if (bg) {
 +
        el.style.backgroundImage = 'url("' + bg + '")';
 +
        el.removeAttribute('data-bg');
 +
      }
 +
    });
 +
 +
    // Videos commonly start with preload="none" on mobile
 +
    var vids = root.querySelectorAll('video[preload="none"], video[data-poster]');
 +
    vids.forEach(function (v) {
 +
      try {
 +
        v.preload = 'metadata';
 +
        if (v.dataset && v.dataset.poster && !v.poster) v.poster = v.dataset.poster;
 +
        // Nudge the browser
 +
        if (v.paused) v.load();
 +
      } catch (e) {}
 +
    });
 +
  }
 +
 +
  // On heading click (MobileFrontend/Minerva uses section headings as toggles)
 +
  function onToggle(e) {
 +
    var heading = e.target && e.target.closest &&
 +
      e.target.closest('.section-heading, .mf-section-heading, .toc-mobile__section-heading, h2, h3, h4');
 +
    if (!heading) return;
 +
 +
    // Wait for classes/ARIA to update
 +
    setTimeout(function () {
 +
      var section = heading.closest('.section, .mf-section, .collapsible-block, .mf-collapsible-block, .mobile-collapse');
 +
      if (!section) return;
 +
      var isOpen = section.classList.contains('open-block') ||
 +
                  section.getAttribute('aria-expanded') === 'true';
 +
      if (isOpen) forceLoadIn(section);
 +
    }, 0);
 +
  }
 +
  document.addEventListener('click', onToggle, true);
 +
 +
  // Fallback: observe class/ARIA flips (covers non-click expansions)
 +
  var mo = new MutationObserver(function (mutations) {
 +
    mutations.forEach(function (m) {
 +
      var el = m.target;
 +
      if (!el) return;
 +
      var isOpen = el.classList && el.classList.contains('open-block');
 +
      if (!isOpen && el.getAttribute) {
 +
        isOpen = el.getAttribute('aria-expanded') === 'true';
 +
      }
 +
      if (isOpen) forceLoadIn(el);
 +
    });
 +
  });
 +
 +
  function attachObservers() {
 +
    document.querySelectorAll('.mf-collapsible-block, .collapsible-block, .section, .mf-section, .mobile-collapse')
 +
      .forEach(function (el) {
 +
        mo.observe(el, { attributes: true, attributeFilter: ['class', 'aria-expanded'] });
 +
      });
 +
  }
 +
 +
  if (document.readyState === 'loading') {
 +
    document.addEventListener('DOMContentLoaded', attachObservers);
 +
  } else {
 +
    attachObservers();
 +
  }
 +
 +
  // Ensure lead content eagerly loads as well
 +
  var lead = document.querySelector('#mf-section-0, .lead, #bodyContent, .content');
 +
  if (lead) forceLoadIn(lead);
 +
})();