@wroud/navigation
Version:
A flexible, pattern-matching navigation system for JavaScript applications with built-in routing, browser integration, and navigation state management
63 lines • 2.44 kB
JavaScript
/// <reference lib="dom" />
/// <reference lib="dom.iterable" />
import { NavigationType } from "../NavigationListener.js";
export class BrowserNavigation {
navigation;
ignoreNextPopState;
constructor(navigation) {
this.navigation = navigation;
this.ignoreNextPopState = false;
this.popStateHandler = this.popStateHandler.bind(this);
this.hashChangeHandler = this.hashChangeHandler.bind(this);
this.handleNavigation = this.handleNavigation.bind(this);
}
async registerRoutes() {
this.addBrowserNavigation();
await this.restoreNavigation();
}
addBrowserNavigation() {
window.addEventListener("popstate", this.popStateHandler);
window.addEventListener("hashchange", this.hashChangeHandler);
this.navigation.addListener(this.handleNavigation);
}
async restoreNavigation() {
await this.popStateHandler();
}
handleNavigation(type, from, to) {
switch (type) {
case NavigationType.Navigate:
window.history.pushState(to, "", this.navigation.router.matcher?.stateToUrl(to));
break;
case NavigationType.Replace:
window.history.replaceState(to, "", this.navigation.router.matcher?.stateToUrl(to));
break;
case NavigationType.Back:
this.ignoreNextPopState = true;
window.history.back();
break;
case NavigationType.Forward:
this.ignoreNextPopState = true;
window.history.forward();
break;
}
}
async popStateHandler() {
if (this.ignoreNextPopState) {
this.ignoreNextPopState = false;
return;
}
const state = this.navigation.router.matcher?.urlToState(decodeURIComponent(window.location.pathname) + window.location.search);
if (state) {
this.navigation.removeListener(this.handleNavigation);
await this.navigation.navigate(state);
this.navigation.addListener(this.handleNavigation);
}
}
hashChangeHandler() { }
dispose() {
window.removeEventListener("popstate", this.popStateHandler);
window.removeEventListener("hashchange", this.hashChangeHandler);
this.navigation.removeListener(this.handleNavigation);
}
}
//# sourceMappingURL=BrowserNavigation.js.map