UNPKG

web-atoms-mvvm

Version:

MVVM, REST Json Service, Message Subscriptions for Web Atoms

178 lines (135 loc) 4.88 kB
namespace WebAtoms { export class AtomPageView extends AtomControl { @bindableProperty url: string; private disposables: AtomDisposable[] = []; stack:AtomControl[] = []; @bindableProperty keepStack: boolean = true; @bindableProperty current:AtomControl = null; currentDisposable:AtomDisposable = null; backCommand: Function; constructor(e:HTMLElement) { super(e); e.style.position = "relative"; this.backCommand = () => { this.onBackCommand(); }; } onBackCommand(): void { if(!this.stack.length) { console.warn(`FrameStack is empty !!`); return; } var ctrl:AtomControl = this.current; var e:HTMLElement = ctrl._element; ctrl.dispose(); e.remove(); this.current = this.stack.pop(); this.current._element.style.display = ""; } async canChange(): Promise<boolean> { if(!this.current) { return true; } var ctrl:AtomControl = this.current; var vm:AtomPageViewModel = ctrl.viewModel; if(vm.closeWarning) { if( await WindowService.instance.confirm(vm.closeWarning,"Are you sure?")) { return true; } return false; } return true; } push(ctrl:AtomControl): void { if(this.current) { if(this.keepStack) { this.current._element.style.display = "none"; this.stack.push(this.current); } else { var c1:AtomControl = this.current; var e:HTMLElement = c1._element; c1.dispose(); e.remove(); } } var element:HTMLElement = ctrl._element; element.style.position = "absolute"; element.style.top = element.style.bottom = element.style.left = element.style.right = "0"; this._element.appendChild(element); this.current = ctrl; } init(): void { super.init(); this.disposables.push(Atom.watch(this,"url", () => { this.load(this.url); })); } dispose(e?:HTMLElement): void { super.dispose(e); if(!e) { for(var d of this.disposables) { d.dispose(); } this.disposables = []; } } createControl(c: {new(e:HTMLElement)}, vmt: {new(q?:any)}, q?:any): AtomControl { var div:HTMLElement = document.createElement("div"); div.id = `${this._element.id}_${this.stack.length + 1}`; var ctrl:any = AtomUI.createControl(div,c); div.setAttribute("atom-local-scope","true"); var vm:any = null; if(vmt) { vm = new (vmt)(q); ctrl.viewModel = vm; } ctrl.init(); return ctrl; } async load(url: string): Promise<any> { if(! await this.canChange()) { return; } var uri:AtomUri = new AtomUri(url); var fragments:string[] = uri.path.split(".") .map(f => this.toUpperCase(f)); var scope:any = window; var vm:any = null; for(var f of fragments) { vm = scope[f + "ViewModel"]; if(!vm) { vm = scope[f + "Model"]; } scope = scope[f]; if(!scope) { throw new Error(`No ${f} in ${url} found.`); } } var q:any = uri.query; var ctrl:AtomControl = this.createControl(scope,vm, q); Atom.post(() => { vm = ctrl.viewModel; if(vm) { if(vm instanceof AtomPageViewModel) { var pvm:AtomPageViewModel = vm as AtomPageViewModel; pvm.pageId = ctrl._element.id; } } }); this.push(ctrl); } toUpperCase(s:string):string { return s.split("-") .filter(t => t) .map(t => t.substr(0,1).toUpperCase() + t.substr(1)) .join(""); } } }