| 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); |
| | + | })(); |