import { Page } from "./Page"; import { PageState } from "../PageState"; import { getObjectKeys } from "../utils"; type pageList = { [key: string]: Page; }; const PageDoesNotExistError = new Error("Page does not exist."); const PageHasNotBeenSetError = new Error("Page has not been set."); export class PageRouter extends EventTarget { constructor( pages: pageList, state: PageState, pageContentElement: HTMLElement, pageTitleElement: HTMLElement, ) { super(); this.pages = pages; this.state = state; this.pageContentElement = pageContentElement; this.pageTitleElement = pageTitleElement; } private pages: pageList; private currentPageID: string; private currentPage: Page; public state: PageState; public pageContentElement: HTMLElement; public pageTitleElement: HTMLElement; public async getPageIDs(): Promise<string[]> { return getObjectKeys(this.pages); } public async getCurrentPage(): Promise<Page> { return this.currentPage; } public async getCurrentPageID(): Promise<string> { return this.currentPageID; } public async setPageContent(content: string | HTMLElement): Promise<void> { if (typeof content === "string") { this.pageContentElement.innerHTML = content; } else { this.pageContentElement.innerHTML = ""; this.pageContentElement.appendChild(content); } } public async changePage(pageID: string): Promise<void> { if (!(await this.getPageIDs()).includes(pageID)) throw PageDoesNotExistError; // Do cleanup on current page. if (this.currentPage) { await this.currentPage.cleanup(); } // Set the current page to the new page this.currentPageID = pageID; this.currentPage = this.pages[pageID]; await this.currentPage.setRouterAndState(this, this.state); // Dispatch an event saying the page has been changed. this.dispatchEvent(new CustomEvent("pageChanged")); // Render the page. await this.renderPage(); } public async renderPage(): Promise<void> { if (!this.currentPage) throw PageHasNotBeenSetError; // Reset back to blank. this.pageContentElement.innerHTML = ""; this.pageTitleElement.innerHTML = ""; const pageTitle = await this.currentPage.getPageTitle(); if (typeof pageTitle === "string") { this.pageTitleElement.innerText = pageTitle; } else { this.pageTitleElement.appendChild(pageTitle); } await this.currentPage.render(); } public async refresh(): Promise<void> { await this.renderPage(); } public async goBack(): Promise<void> { if (!this.currentPage) throw PageHasNotBeenSetError; await this.currentPage.goBack(); } }