178 lines
4.6 KiB
JavaScript
Raw Normal View History

2025-12-04 20:29:35 +01:00
/**
* @fileoverview URL Router Service for Rantii
* @author retoor <retoor@molodetz.nl>
* @description Handles URL routing and navigation state management
* @keywords router, navigation, url, history, routing
*/
class Router {
constructor() {
this.routes = new Map();
this.currentRoute = null;
this.currentParams = {};
this.onRouteChange = null;
this.basePath = this.detectBasePath();
}
detectBasePath() {
const path = window.location.pathname;
const htmlIndex = path.lastIndexOf('.html');
if (htmlIndex !== -1) {
return path.substring(0, path.lastIndexOf('/') + 1);
}
return path.endsWith('/') ? path : path + '/';
}
init() {
window.addEventListener('popstate', () => this.handleRoute());
this.handleRoute();
}
register(name, handler) {
this.routes.set(name, handler);
}
getParams() {
const params = new URLSearchParams(window.location.search);
const result = {};
for (const [key, value] of params) {
result[key] = value;
}
return result;
}
handleRoute() {
const params = this.getParams();
this.currentParams = params;
let routeName = 'home';
if (params.rant) {
routeName = 'rant';
} else if (params.user) {
routeName = 'user';
} else if (params.search !== undefined) {
routeName = 'search';
} else if (params.notifications !== undefined) {
routeName = 'notifications';
} else if (params.settings !== undefined) {
routeName = 'settings';
} else if (params.login !== undefined) {
routeName = 'login';
} else if (params.weekly !== undefined) {
routeName = 'weekly';
} else if (params.collabs !== undefined) {
routeName = 'collabs';
} else if (params.stories !== undefined) {
routeName = 'stories';
}
this.currentRoute = routeName;
const handler = this.routes.get(routeName);
if (handler) {
handler(params);
}
if (this.onRouteChange) {
this.onRouteChange(routeName, params);
}
window.dispatchEvent(new CustomEvent('rantii:route-change', {
detail: { route: routeName, params }
}));
}
navigate(routeName, params = {}) {
const url = this.buildUrl(params);
window.history.pushState({ route: routeName, params }, '', url);
this.handleRoute();
}
replace(routeName, params = {}) {
const url = this.buildUrl(params);
window.history.replaceState({ route: routeName, params }, '', url);
this.handleRoute();
}
buildUrl(params = {}) {
const searchParams = new URLSearchParams();
Object.entries(params).forEach(([key, value]) => {
if (value !== undefined && value !== null && value !== '') {
searchParams.set(key, value);
} else if (value === '') {
searchParams.set(key, '');
}
});
const queryString = searchParams.toString();
const currentPath = window.location.pathname;
return queryString ? `${currentPath}?${queryString}` : currentPath;
}
goHome() {
this.navigate('home', {});
}
goToRant(rantId, commentId = null) {
const params = { rant: rantId };
if (commentId) {
params.comment = commentId;
}
this.navigate('rant', params);
}
goToUser(username) {
this.navigate('user', { user: username });
}
goToSearch(term = '') {
this.navigate('search', { search: term });
}
goToNotifications() {
this.navigate('notifications', { notifications: '' });
}
goToSettings() {
this.navigate('settings', { settings: '' });
}
goToLogin() {
this.navigate('login', { login: '' });
}
goToWeekly() {
this.navigate('weekly', { weekly: '' });
}
goToCollabs() {
this.navigate('collabs', { collabs: '' });
}
goToStories() {
this.navigate('stories', { stories: '' });
}
back() {
window.history.back();
}
forward() {
window.history.forward();
}
getCurrentRoute() {
return this.currentRoute;
}
getCurrentParams() {
return this.currentParams;
}
setRouteChangeCallback(callback) {
this.onRouteChange = callback;
}
isCurrentRoute(routeName) {
return this.currentRoute === routeName;
}
}
export { Router };