From 9fc7cf0c682309da1430523fd6d6c919c9113bd0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A9ry=20Debongnie?= Date: Fri, 25 Jan 2019 14:27:16 +0100 Subject: [PATCH] move internal stuff in _, add unique id for each widget --- web/static/src/ts/core/Widget.ts | 55 ++++++++++++++++++++++---------- web/static/src/ts/core/utils.ts | 5 +++ web/static/src/ts/env.ts | 4 ++- web/static/tests/utils.test.ts | 11 ++++++- web/static/tests/widget.test.ts | 6 ++-- 5 files changed, 60 insertions(+), 21 deletions(-) diff --git a/web/static/src/ts/core/Widget.ts b/web/static/src/ts/core/Widget.ts index 9608f95f..2452d5d5 100644 --- a/web/static/src/ts/core/Widget.ts +++ b/web/static/src/ts/core/Widget.ts @@ -8,17 +8,28 @@ const patch = init([sdListeners, sdAttrs]); export interface WEnv { qweb: QWeb; + getID(): number; +} + +let wl: any[] = []; +(window).wl = wl; + +interface Meta { + id: number; + // name: string; + // template: string; + vnode: VNode | null; + isStarted: boolean; + isMounted: boolean; + parent: Widget | null; + children: Widget[]; } export class Widget { + _: Meta; name: string = "widget"; template: string = "
"; - vnode: VNode | null = null; - isStarted: boolean = false; - isMounted: boolean = false; - parent: Widget | null = null; - children: Widget[] = []; env: T; el: HTMLElement | null = null; state: Object = {}; @@ -29,13 +40,23 @@ export class Widget { //-------------------------------------------------------------------------- constructor(parent: Widget | T, props?: any) { + wl.push(this); + let p: Widget | null = null; if (parent instanceof Widget) { - this.parent = parent; - parent.children.push(this); + p = parent; + parent._.children.push(this); this.env = Object.create(parent.env); } else { this.env = parent; } + this._ = { + id: this.env.getID(), + vnode: null, + isStarted: false, + isMounted: false, + parent: p, + children: [] + }; } async willStart() {} @@ -56,8 +77,8 @@ export class Widget { if (document.body.contains(target)) { this.visitSubTree(w => { - if (!w.isMounted && this.el!.contains(w.el)) { - w.isMounted = true; + if (!w._.isMounted && this.el!.contains(w.el)) { + w._.isMounted = true; w.mounted(); } }); @@ -78,7 +99,7 @@ export class Widget { */ async updateState(newState: Object) { Object.assign(this.state, newState); - if (this.isStarted) { + if (this._.isStarted) { await this.render(); } } @@ -92,14 +113,14 @@ export class Widget { if (!this.el) { this.el = document.createElement(vnode.sel!); } - patch(this.vnode || this.el, vnode); - this.vnode = vnode; + patch(this._.vnode || this.el, vnode); + this._.vnode = vnode; return vnode; } private async _start(): Promise { await this.willStart(); - this.isStarted = true; + this._.isStarted = true; } private async _render(): Promise { @@ -114,9 +135,9 @@ export class Widget { _mount(el: HTMLElement) { this.el = el; - if (this.parent) { - if (this.parent.isMounted) { - this.isMounted = true; + if (this._.parent) { + if (this._.parent._.isMounted) { + this._.isMounted = true; this.mounted(); } } @@ -124,7 +145,7 @@ export class Widget { private visitSubTree(callback: (w: Widget) => void) { callback(this); - for (let child of this.children) { + for (let child of this._.children) { child.visitSubTree(callback); } } diff --git a/web/static/src/ts/core/utils.ts b/web/static/src/ts/core/utils.ts index 29bdb568..74cb005b 100644 --- a/web/static/src/ts/core/utils.ts +++ b/web/static/src/ts/core/utils.ts @@ -26,3 +26,8 @@ export function htmlTrim(s: string): string { } return result; } + +export function idGenerator(): (() => number) { + let nextID = 1; + return () => nextID++; +} diff --git a/web/static/src/ts/env.ts b/web/static/src/ts/env.ts index f1900bc3..082e1455 100644 --- a/web/static/src/ts/env.ts +++ b/web/static/src/ts/env.ts @@ -1,4 +1,5 @@ import { QWeb } from "./core/qweb_vdom"; +import { idGenerator } from "./core/utils"; import { WEnv } from "./core/widget"; import { ActionManager } from "./services/action_manager"; import { Ajax } from "./services/ajax"; @@ -31,6 +32,7 @@ export function makeEnvironment(): Env { ajax, router, actionManager, - menus + menus, + getID: idGenerator() }; } diff --git a/web/static/tests/utils.test.ts b/web/static/tests/utils.test.ts index 0d3aa159..35e7bb26 100644 --- a/web/static/tests/utils.test.ts +++ b/web/static/tests/utils.test.ts @@ -1,4 +1,4 @@ -import { escape, htmlTrim } from "../src/ts/core/utils"; +import { escape, htmlTrim, idGenerator } from "../src/ts/core/utils"; describe("escape", () => { test("normal strings", () => { @@ -25,3 +25,12 @@ describe("htmlTrim", () => { expect(htmlTrim("")).toBe(""); }); }); + +describe("idGenerator", () => { + test("basic use", () => { + let gen = idGenerator(); + expect(gen()).toBe(1); + expect(gen()).toBe(2); + expect(gen()).toBe(3); + }); +}); diff --git a/web/static/tests/widget.test.ts b/web/static/tests/widget.test.ts index 7a0fdfaa..28964c5d 100644 --- a/web/static/tests/widget.test.ts +++ b/web/static/tests/widget.test.ts @@ -1,4 +1,5 @@ import { Widget, WEnv } from "../src/ts/core/widget"; +import { idGenerator } from "../src/ts/core/utils"; import { QWeb } from "../src/ts/core/qweb_vdom"; interface Type extends Function { @@ -9,8 +10,9 @@ type TestEnv = WEnv; type TestWidget = Widget; function makeWidget(W: Type): TestWidget { - const env = { - qweb: new QWeb() + const env: WEnv = { + qweb: new QWeb(), + getID: idGenerator() }; const w = new W(env); return w;