Files
ESP32-WijiBoard/web/js/router.js
T
PROFERIS - Mi³osz Stocki 67b4eda6aa Initial commit
2026-07-06 11:34:03 +02:00

92 lines
3.0 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* WijiBoard Hash-based SPA Router
* web/js/router.js
*
* Usage:
* Router.register('home', homeModule);
* Router.register('stepper-test', stepperModule);
* Router.init('#view', '#home'); // outlet element id, default route
*
* Each section module must export:
* { mount(containerEl), unmount() }
*/
const Router = (() => {
const routes = new Map(); // hash → module
let outlet = null; // DOM element to render into
let current = null; // currently active route key
let currentMod = null; // currently mounted module
// ── Register a route ─────────────────────────────────────────
function register(hash, module) {
routes.set(hash, module);
}
// ── Navigate to a route ──────────────────────────────────────
async function navigate(hash) {
const key = hash.replace(/^#/, '');
if (!routes.has(key)) {
console.warn(`[Router] Unknown route: "${key}"`);
return;
}
if (key === current) return; // already there
// Unmount old section
if (currentMod?.unmount) {
try { await currentMod.unmount(); } catch (e) { console.error('[Router] unmount error', e); }
}
// Clear outlet
outlet.innerHTML = '';
// Mount new section
const mod = routes.get(key);
currentMod = mod;
current = key;
try {
await mod.mount(outlet);
} catch (e) {
console.error('[Router] mount error', e);
outlet.innerHTML = `<p style="color:var(--accent-red);padding:24px">
Failed to load section: ${e.message}</p>`;
}
// Update sidebar active state
document.querySelectorAll('.sidebar-nav-item').forEach(el => {
el.classList.toggle('active', el.dataset.route === key);
});
// Update URL hash (without re-triggering hashchange)
if (location.hash.replace('#','') !== key) {
history.replaceState(null, '', `#${key}`);
}
}
// ── Init: wire up outlet + default route ─────────────────────
function init(outletSelector, defaultHash = '#home') {
outlet = document.querySelector(outletSelector);
if (!outlet) throw new Error(`[Router] Outlet "${outletSelector}" not found`);
// Listen for hash changes
window.addEventListener('hashchange', () => {
navigate(location.hash || defaultHash);
});
// Handle initial load
const initial = location.hash && location.hash.length > 1
? location.hash
: defaultHash;
// Small defer to let the page fully render first
requestAnimationFrame(() => navigate(initial));
}
// ── Active route getter ───────────────────────────────────────
function getActive() { return current; }
return { register, navigate, init, getActive };
})();
export default Router;