web-atoms-mvvm
Version:
MVVM, REST Json Service, Message Subscriptions for Web Atoms
178 lines (135 loc) • 4.88 kB
text/typescript
namespace WebAtoms {
export class AtomPageView extends AtomControl {
url: string;
private disposables: AtomDisposable[] = [];
stack:AtomControl[] = [];
keepStack: boolean = true;
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("");
}
}
}