widget-router
Version:
Widget Router is another Typescript (also JavaScript) Router, but this one works better if used in widgets inside HTML
202 lines (172 loc) • 8.2 kB
text/typescript
import { IWidgetRouter } from "./IWidgetRouter";
import { RouteResult } from "./RouteResult";
import { RouteConfig } from "./RouteConfig";
import { Utilities } from "./Utilities";
import { ITemplateProvider } from "./ITemplateProvider";
import { TemplateProvider } from "./TemplateProvider";
import { EventHandlerManager } from 'event-handler-manager';
export class WidgetRouter extends EventHandlerManager implements IWidgetRouter {
private readonly containerId: string;
private readonly routeConfig: RouteConfig;
private readonly appScope: object;
private readonly controllerHelper : any;
private readonly pageIdPrefix: string;
private controllersInitiated: any;
private templateProvider: ITemplateProvider;
public activePage: string;
//public templatesCollection: Object;
constructor(containerId: string, routeConfig: RouteConfig, appScope?: Object, controllerHelper?: any) {
super();
const currentContainer = <HTMLElement>document.querySelector(containerId);
if (currentContainer === undefined || currentContainer === null) {
throw new Error(containerId + ' was not found inside document, please set a valid container Id selector.');
}
this.containerId = containerId;
this.routeConfig = routeConfig;
this.appScope = appScope ? appScope : {};
routeConfig.routes.forEach(route => {
this.appScope[route.name] = {};
});
this.controllerHelper = controllerHelper;
this.pageIdPrefix = routeConfig.pageIdPrefix !== undefined && routeConfig.pageIdPrefix !== null ? routeConfig.pageIdPrefix : '';
this.controllersInitiated = {};
this.routeConfig.routes.forEach(route => {
let currentPage = <HTMLElement>document.querySelector(this.containerId).querySelector('#' + this.pageIdPrefix + route.name);
if (currentPage === undefined || currentPage === null) {
document.querySelector(this.containerId).innerHTML += '<div id="' +
this.pageIdPrefix +
route.name +
'" style="display:none;"></div>';
} else {
currentPage.style.display = 'none';
}
});
this.templateProvider = new TemplateProvider();
if (this.routeConfig.usingTemplates) {
if (controllerHelper === undefined && controllerHelper === null) {
controllerHelper = {};
}
controllerHelper.templatesCollection = {};
}
this.attach(['beforego', 'aftergo']);
}
private executeController(routeName, params, templateContent, initController, currentRouteConfig) : Promise<RouteResult> {
const dfd = new Promise<RouteResult>((resolve, reject) => {
let routeResult = {
routeName: routeName,
routeParams: params,
routeScope: this.appScope[routeName],
router: this,
controllerHelper: this.controllerHelper
} as RouteResult;
if (this.routeConfig.usingTemplates) {
if (this.controllerHelper.templatesCollection === undefined ||
this.controllerHelper.templatesCollection === null) {
this.controllerHelper.templatesCollection = {};
}
this.controllerHelper.templatesCollection[routeName] = templateContent;
}
if (initController && Utilities.isFunction(currentRouteConfig.controller)) {
(() => {
try {
let controllerResult = currentRouteConfig.controller(routeResult);
if (controllerResult !== undefined && controllerResult !== null && !!controllerResult.then && typeof controllerResult.then === 'function') {
controllerResult.then(() => {
resolve(routeResult);
}).catch(err => {
console.error(err);
});
} else {
this.controllersInitiated[routeName] = true;
resolve(routeResult);
}
} catch (e) {
console.error(e);
reject(e);
}
})();
} else {
resolve(routeResult);
}
});
return dfd;
}
go(routeName: string, params?: any, noCache?: boolean, initController?: boolean): Promise<RouteResult> {
const dfd = new Promise<RouteResult>((resolve, reject) => {
this.trigger('beforego').then(() => {
const currentRouteConfig = this.routeConfig.routes.find(route => {
return route.name === routeName;
});
if (currentRouteConfig === undefined || currentRouteConfig == null) {
throw new Error('Route Configuration not found for that Route Name');
}
this.routeConfig.afterRouteInitController = this.routeConfig.afterRouteInitController !== undefined &&
this.routeConfig.afterRouteInitController !== null
? this.routeConfig.afterRouteInitController
: true;
initController = initController !== undefined && initController !== null ? initController : this.routeConfig.afterRouteInitController;
initController = currentRouteConfig.controller !== undefined && currentRouteConfig.controller !== null
? initController
: false;
if (this.activePage !== undefined && this.activePage !== null && this.activePage.trim() !== '') {
let activePage = <HTMLElement>document.querySelector(this.containerId).querySelector('#' + this.pageIdPrefix + this.activePage);
activePage.style.display = 'none';
}
let newActivePage = <HTMLElement>document.querySelector(this.containerId).querySelector('#' + this.pageIdPrefix + routeName);
if (newActivePage === undefined || newActivePage === null) {
document.querySelector(this.containerId).innerHTML += '<div id="' + this.pageIdPrefix + routeName + '">';
newActivePage = <HTMLElement>document.querySelector(this.containerId).querySelector('#' + this.pageIdPrefix + routeName);
} else {
newActivePage.style.display = 'block';
}
this.activePage = routeName;
if (currentRouteConfig.templateFile !== undefined &&
currentRouteConfig.templateFile !== null &&
currentRouteConfig.templateFile.trim() !== '') {
this.getTemplateFromFile(currentRouteConfig.templateFile).then(templateContent => {
if (!this.routeConfig.usingTemplates) {
newActivePage.innerHTML = templateContent;
}
this.executeController(routeName, params, templateContent, initController, currentRouteConfig).then(routeResult => {
this.trigger('aftergo').then(() => {
resolve(routeResult);
}).catch(err => reject(err)).catch(err => reject(err));
}).catch(err => {
console.error(err);
reject(err);
});
}).catch(err => {
console.error(err);
reject(err);
});
} else {
if (newActivePage !== undefined && newActivePage !== null && currentRouteConfig.template !== undefined && currentRouteConfig.template !== null && currentRouteConfig.template.trim() !== '' && !this.routeConfig.usingTemplates) {
newActivePage.innerHTML = currentRouteConfig.template;
}
this.executeController(routeName, params, currentRouteConfig.template, initController, currentRouteConfig).then(routeResult => {
this.trigger('aftergo').then(() => {
resolve(routeResult);
}).catch(err => reject(err)).catch(err => reject(err));
}).catch(err => {
console.error(err);
reject(err);
});
}
}).catch(err => {
console.error(err);
});
});
return dfd;
}
private getTemplateFromFile(templateFile) {
const dfd = new Promise<string>((resolve, reject) => {
this.templateProvider.get(templateFile).then((templateContent) => {
resolve(templateContent);
}).catch(error => {
console.log(error);
reject(error);
});
});
return dfd;
}
}