1/** 2 * MOE.Loader.js â Page preload overlay controller 3 * Plain IIFE â no module â loads at the start of <body>. 4 * 5 * 1. Immediately injects #moe-page-loader into document.body before any page 6 * content is parsed (script runs synchronously at body start). 7 * Asset path is resolved from window.MOE_FRAGMENT_BASE (set per-page in <head>). 8 * Canonical markup lives in components/fragments/page-loader.html. 9 * 10 * 2. Waits for 5 signals before hiding the overlay: 11 * moe:fragments-loaded â all HTML fragments injected (MOE.LoadComponents.js) 12 * moe:alpine-started â Alpine.start() complete (page entry JS) 13 * moe:nav-loaded â nav API resolved or failed (page entry JS) 14 * moe:footer-loaded â footer API resolved or failed (page entry JS) 15 * fonts â HugeIcons font loaded via document.fonts.load() 16 * 17 * Hard timeout (MAX_WAIT_MS) hides the loader regardless if signals are late. 18 */ 19(function () { 20 "use strict"; 21 22 // ââ 1. Inject loader overlay âââââââââââââââââââââââââââââââââââââââââ 23 // Runs synchronously when the script executes at the start of <body>. 24 // window.MOE_FRAGMENT_BASE is already set in <head> before this script loads. 25 // MOE.LangDir.js (also in <head>) has already read localStorage('moe-lang'), 26 // so we can safely use the same key here to pick the correct label language. 27 (function _inject() { 28 if (document.getElementById("moe-page-loader")) return; // guard against double-run 29 var base = 30 (typeof window.MOE_BASE_PATH === "string" && window.MOE_BASE_PATH) 31 ? window.MOE_BASE_PATH + "/" 32 : (typeof window.MOE_FRAGMENT_BASE === "string" && window.MOE_FRAGMENT_BASE) 33 ? window.MOE_FRAGMENT_BASE 34 : "../"; 35 var logoSrc = base + "assets/images/moe-logo.svg"; 36 var ariaLabel = localStorage.getItem("moe-lang") === "en" 37 ? "Page loading" 38 : "\u062c\u0627\u0631\u064a \u062a\u062d\u0645\u064a\u0644 \u0627\u0644\u0635\u0641\u062d\u0629"; 39 document.body.insertAdjacentHTML( 40 "afterbegin", 41 [ 42 '<div id="moe-page-loader" aria-hidden="true" role="status" aria-label="' + 43 ariaLabel + 44 '">', 45 ' <div class="moe-loader-ring-wrap">', 46 ' <div class="moe-loader-ring"></div>', 47 ' <img src="' + 48 logoSrc + 49 '" alt="" class="moe-loader-logo" width="90" height="60" />', 50 " </div>", 51 "</div>", 52 ].join("\n"), 53 ); 54 })(); 55 56 // ââ 2. Signal system âââââââââââââââââââââââââââââââââââââââââââââââââ 57 58 var MAX_WAIT_MS = 4000; 59 60 var _hidden = false; 61 var _checks = { 62 fragments: false, 63 alpine: false, 64 nav: false, 65 footer: false, 66 fonts: false, 67 }; 68 69 function _tryHide() { 70 if (_hidden) return; 71 if (_checks.fragments && _checks.alpine && _checks.nav && _checks.footer && _checks.fonts) { 72 _hide(); 73 } 74 } 75 76 function _hide() { 77 if (_hidden) return; 78 _hidden = true; 79 80 var el = document.getElementById("moe-page-loader"); 81 if (!el) return; 82 83 el.classList.add("moe-loader--out"); 84 // Remove from DOM after CSS fade-out completes 85 setTimeout(function () { 86 if (el.parentNode) el.parentNode.removeChild(el); 87 }, 500); 88 } 89 90 function _mark(key) { 91 _checks[key] = true; 92 _tryHide(); 93 } 94 95 // ââ Signal listeners âââââââââââââââââââââââââââââââââââââââââââââââââ 96 97 window.addEventListener("moe:fragments-loaded", function () { 98 _mark("fragments"); 99 }); 100 window.addEventListener("moe:alpine-started", function () { 101 _mark("alpine"); 102 }); 103 window.addEventListener("moe:nav-loaded", function () { 104 _mark("nav"); 105 }); 106 window.addEventListener("moe:footer-loaded", function () { 107 _mark("footer"); 108 }); 109 110 // ââ Font loading check ââââââââââââââââââââââââââââââââââââââââââââââââ 111 // Wait for the HugeIcons font before hiding the overlay â prevents icons 112 // from briefly rendering as CJK/tofu fallback glyphs while the font loads. 113 if (document.fonts && typeof document.fonts.load === 'function') { 114 document.fonts.load('1em "hgi-stroke-rounded"').then(function () { 115 _mark('fonts'); 116 }).catch(function () { 117 _mark('fonts'); 118 });
119 } else { 120 _mark('fonts'); // Font Loading API not supported â skip, hard timeout covers it 121 } 122 123 // ââ Hard timeout âââââââââââââââââââââââââââââââââââââââââââââââââââââ 124 125 setTimeout(function () { 126 if (!_hidden) { 127 console.warn( 128 "[MOE] Loader timeout â forcing hide. Missing signals:", 129 JSON.stringify(_checks), 130 ); 131 _hide(); 132 } 133 }, MAX_WAIT_MS); 134 135 // ââ Public debug handle ââââââââââââââââââââââââââââââââââââââââââââââ 136 137 window.MOE = window.MOE || {}; 138 window.MOE.Loader = window.MOE.Loader || { checks: _checks }; 139})();
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.