class PageBlock { public static useDoubleView: boolean = false; public shown: Signal; public loadPromises: JQueryPromise[]; public defaultSecondaryName: string; public currentPage: string; public currentSecondary: string; public secondaryViews: string[]; public requireAuthentication: boolean = false; constructor(public name: string, public primaryName: string, primaryModel: any) { this.loadPromises = []; this.secondaryViews = []; this.bindSubPage(primaryName, primaryModel); } public addSecondary(name: string, viewModel: any, isDefault: boolean = false): void { if (isDefault) { this.defaultSecondaryName = name; } this.secondaryViews.push(name); this.bindSubPage(name, viewModel); } public showBlock() { if (typeof window !== "undefined") { $(this.getSelector()).show(); } this.showPrimary(); if (PageBlock.useDoubleView) { this.showSecondary(this.defaultSecondaryName); } } public hideBlock() { if (typeof window !== "undefined") { $(this.getSelector()).hide(); } } public showPrimary() { this.showSubPage(this.primaryName); } public showSecondary(name: string) { this.showSubPage(name); } private isSecondary(pageName: string) { return this.secondaryViews.indexOf(pageName) !== -1; } private isPrimary(pageName: string) { return pageName === this.primaryName; } private isSameBlock(pageName: string) { return this.isPrimary(pageName) && this.isSecondary(pageName); } /** * Gets page by it's name * @param subPageName String Name of the sub page to get. */ private getSubPage(subPageName: string) { if (!this.hasOwnProperty(subPageName + "Page")) { return null; } return this[subPageName + "Page"] as Page; } private showSubPage(pageName: string) { const nextPageObject = this.getSubPage(pageName); if (nextPageObject !== null) { if (nextPageObject.canActivate !== undefined) { if (!nextPageObject.canActivate()) { return; } } } let needHidePrevView = this.currentPage != null; if (PageBlock.useDoubleView) { // Add additional logic when previous view should be hidden. // Never hide primary view. needHidePrevView = needHidePrevView && !this.isPrimary(this.currentPage); } if (needHidePrevView) { const pageObject = this.getSubPage(this.currentPage); if (pageObject !== null) { pageObject.deactivate(this.currentPage); } if (typeof window !== "undefined") { $(this.getPageSelector(this.currentPage)).css("display", "none"); } } this.currentPage = pageName; if (nextPageObject !== null) { nextPageObject.activate(this.currentPage); } if (typeof window !== "undefined") { $(this.getPageSelector(pageName)).css("display", "block"); } } private getSelector(): string { return ".page-block." + this.name; } private getPageSelector(pageName: string): string { return this.getSelector() + " .sub-page." + pageName; } private bindSubPage(pageName: string, viewModel: any): void { this[pageName + "Page"] = viewModel; if (typeof window === "undefined") { return; } const pagejElement = $(this.getPageSelector(pageName)); if (pagejElement.length === 0) { // tslint:disable-next-line:no-console console.error("Could not bind sub page " + pageName + " since DOM element not found."); return; } if (pagejElement.length > 1) { // tslint:disable-next-line:no-console console.warn("Page " + pageName + " has more then one element to bind."); return; } const pageElement = pagejElement[0]; if (!pageElement.hasChildNodes()) { const templateSource: string = pagejElement.data("template") as any; const pageLoadPromise = $.get(templateSource, "text/html").then(function (data: string) { pagejElement.html(data); try { ko.applyBindings(viewModel, pageElement); } catch (e) { // tslint:disable-next-line:no-console console.log("Bind page " + pageName + " failed"); } }); this.loadPromises.push(pageLoadPromise); return; } ko.applyBindings(viewModel, pageElement); } }