58 lines
1.5 KiB
JavaScript
58 lines
1.5 KiB
JavaScript
// ── SPA Router ──
|
|
|
|
const routes = {};
|
|
let currentPage = null;
|
|
let isNavigating = false;
|
|
|
|
function registerPage(name, { init, destroy }) {
|
|
routes[name] = { init, destroy };
|
|
}
|
|
|
|
async function navigateTo(page, params = {}, options = {}) {
|
|
const app = document.getElementById('app');
|
|
|
|
// Tooltip verstecken
|
|
if (window.hideTooltip) window.hideTooltip();
|
|
|
|
// Alte Page zerstören
|
|
if (currentPage && routes[currentPage] && routes[currentPage].destroy) {
|
|
routes[currentPage].destroy();
|
|
}
|
|
|
|
// Template klonen und einfügen
|
|
const tpl = document.getElementById(`tpl-${page}`);
|
|
if (!tpl) {
|
|
app.innerHTML = `<div class="placeholder-page"><h2>404</h2><p>Seite "${page}" nicht gefunden.</p></div>`;
|
|
currentPage = null;
|
|
return;
|
|
}
|
|
|
|
app.innerHTML = '';
|
|
app.appendChild(tpl.content.cloneNode(true));
|
|
currentPage = page;
|
|
|
|
// URL Hash setzen
|
|
const hash = params.id ? `${page}/${params.id}` : page;
|
|
if (options.replace) {
|
|
history.replaceState({ page, params }, '', `#${hash}`);
|
|
} else {
|
|
history.pushState({ page, params }, '', `#${hash}`);
|
|
}
|
|
|
|
// Page initialisieren
|
|
if (routes[page] && routes[page].init) {
|
|
await routes[page].init(params);
|
|
}
|
|
|
|
// Back-Buttons verdrahten
|
|
document.querySelectorAll('.back-btn[data-page]').forEach(btn => {
|
|
btn.addEventListener('click', () => history.back());
|
|
});
|
|
}
|
|
|
|
function parseHash() {
|
|
const hash = location.hash.slice(1) || 'dashboard';
|
|
const parts = hash.split('/');
|
|
return { page: parts[0], id: parts[1] || null };
|
|
}
|