diff --git a/static/loader.js b/static/loader.js index 7432dca..d3e992b 100644 --- a/static/loader.js +++ b/static/loader.js @@ -7,9 +7,12 @@ 's-llms', 's-conversation', ]; + // Determine which section to show first (same logic as nav.js) + var _savedSection = localStorage.getItem('ttsvc_section'); + var _activeSection = (_savedSection && SECTIONS.indexOf(_savedSection) !== -1) + ? _savedSection : 's-voices'; + // ── Fetch app version once for JS cache-busting ────────────────────────── - // JS files are served with ?v= so the browser can cache them - // aggressively. Sections use Date.now() to always get fresh HTML. var _appVersion = 'dev'; try { var _vr = await fetch('/api/version'); @@ -17,35 +20,50 @@ _appVersion = _vd.version || _appVersion; } catch (_) {} - // ── 1. Fetch all section HTML partials in parallel ──────────────────────── var _ts = Date.now(); // sections always fresh during a session - await Promise.all(SECTIONS.map(async function (id) { - try { - var res = await fetch('/static/sections/' + id + '.html?v=' + _ts); - if (!res.ok) throw new Error(res.status + ' ' + res.statusText); - var el = document.getElementById(id); - if (el) el.innerHTML = await res.text(); - } catch (e) { - console.error('[loader] section', id, 'failed:', e.message); - var el = document.getElementById(id); - if (el) el.innerHTML = - '

Failed to load section ' + - id + ': ' + e.message + '

'; - } - })); - // ── 2. Load JS in parallel batches ──────────────────────────────────────── + function _inject(id, html) { + var el = document.getElementById(id); + if (el) el.innerHTML = html; + } + + // ── 1. Load ONLY the active section before anything else ───────────────── + // Feature modules set up DOM event listeners — the active section's elements + // must exist when JS runs. Other sections are loaded in step 2. + try { + var _ar = await fetch('/static/sections/' + _activeSection + '.html?v=' + _ts); + if (!_ar.ok) throw new Error(_ar.status + ' ' + _ar.statusText); + _inject(_activeSection, await _ar.text()); + } catch (e) { + var _ael = document.getElementById(_activeSection); + if (_ael) _ael.innerHTML = + '

Failed to load section ' + + _activeSection + ': ' + e.message + '

'; + } + + // ── 2. Fetch remaining sections in background (parallel with JS loading) ── + // These run concurrently with utils + settings below. Because section HTML + // files are much smaller than JS, they finish before the feature-module batch + // needs them. + var _bgSections = Promise.all( + SECTIONS.filter(function (id) { return id !== _activeSection; }) + .map(async function (id) { + try { + var res = await fetch('/static/sections/' + id + '.html?v=' + _ts); + if (!res.ok) throw new Error(res.status + ' ' + res.statusText); + _inject(id, await res.text()); + } catch (e) { + var el = document.getElementById(id); + if (el) el.innerHTML = + '

Failed to load section ' + + id + ': ' + e.message + '

'; + } + }) + ); + + // ── 3. Load JS in parallel batches ──────────────────────────────────────── // Scripts with async=false are FETCHED in parallel but EXECUTED in DOM // insertion order — safe for modules that share a global scope. - // - // Batch order: - // A) utils.js — defines $, toast, escHtml; needed by everything - // B) settings.js — declares _appSettings; needed before features read it - // C) Feature modules — parallel fetch + ordered execute - // D) init.js — calls loadSettings() + initBenchmarkSampleControls() - // E) Post-init modules — parallel fetch + ordered execute - // F) nav.js — navigation overrides; must be last - function _load(src) { return new Promise(function (resolve, reject) { var s = document.createElement('script'); @@ -58,8 +76,6 @@ } function _loadBatch(srcs) { - // Append all