##// END OF EJS Templates
Added Renderer, WatchRendition
cin -
r94:131e369d1143 default
parent child
Show More
@@ -0,0 +1,26
1 import { Scope } from "./Scope";
2 import { destroy, Rendition } from "./traits";
3
4 let _scope = Scope.dummy;
5
6 const beginRender = async () => {
7 }
8
9 const endRender = () => {
10 }
11
12 export const getScope = () => _scope;
13
14 export const render = async (rendition: () => Rendition, scope = Scope.dummy) => {
15 await beginRender();
16 const prev = _scope;
17 _scope = scope;
18 try {
19 const node = rendition().getDomNode();
20 scope.own(() => destroy(node));
21 return node;
22 } finally {
23 _scope = prev;
24 endRender();
25 }
26 }
@@ -0,0 +1,40
1 import { IDestroyable, IRemovable } from "@implab/core-amd/interfaces";
2 import { isDestroyable, isRemovable } from "@implab/core-amd/safe";
3
4 export interface IScope {
5 own(target: (() => void) | IDestroyable | IRemovable): void;
6 }
7
8 export class Scope implements IDestroyable, IScope {
9 private readonly _cleanup: (() => void)[] = [];
10
11 static readonly dummy: IScope = { own() { } };
12
13 own(target: (() => void) | IDestroyable | IRemovable) {
14 if (target instanceof Function) {
15 this._cleanup.push(target);
16 } else if (isDestroyable(target)) {
17 this._cleanup.push(() => target.destroy());
18 } else if (isRemovable(target)) {
19 this._cleanup.push(() => target.remove());
20 }
21 }
22
23 clean() {
24 const guard = (cb: () => void) => {
25 try {
26 cb();
27 } catch {
28 // guard
29 }
30 }
31
32 this._cleanup.forEach(guard);
33 this._cleanup.length = 0;
34 }
35
36 destroy() {
37 this.clean();
38 }
39
40 } No newline at end of file
@@ -0,0 +1,58
1 import { id as mid } from "module";
2 import { TraceSource } from "@implab/core-amd/log/TraceSource";
3 import { argumentNotNull } from "@implab/core-amd/safe";
4 import { place } from "dojo/dom-construct";
5 import { getScope, render } from "./Renderer";
6 import { RenditionBase } from "./RenditionBase";
7 import { Scope } from "./Scope";
8 import { locateNode } from "./traits";
9
10 const trace = TraceSource.get(mid);
11
12 export class WatchRendition<T> extends RenditionBase<Node> {
13 private readonly _factory: (arg: T) => any;
14
15 private _node: Node;
16
17 private readonly _scope = new Scope();
18
19 constructor(component: (arg: T) => any, subject: any) {
20 super();
21 argumentNotNull(component, "component");
22
23 this._factory = component;
24
25 this._node = document.createComment("WatchRendition placeholder");
26 }
27
28 protected _create(attrs: object, children: any[]) {
29 const _attrs: any = attrs || {};
30 const _children = children.map(x => this.getItemDom(x));
31 this._node = this.getItemDom(
32 this._factory.call(null, { ..._attrs, children: _children })
33 );
34
35 const scope = getScope();
36 scope.own(this._scope);
37
38 // если отрендерили текст? или DocumentFragment
39 }
40
41 private async _render(value: T) {
42 const [refNode, position] = locateNode(this._node);
43 this._scope.clean();
44
45 this._node = await render(() => this._factory(value), this._scope);
46
47 if (refNode)
48 place(this._node, refNode, position);
49 }
50
51 protected _getDomNode() {
52 if (!this._node)
53 throw new Error("The instance of the widget isn't created");
54 return this._node;
55 }
56
57
58 }
@@ -8,6 +8,8 type _WidgetBaseConstructor = typeof _Wi
8
8
9 export type DojoNodePosition = "first" | "after" | "before" | "last" | "replace" | "only" | number;
9 export type DojoNodePosition = "first" | "after" | "before" | "last" | "replace" | "only" | number;
10
10
11 export type DojoNodeLocation = [Node | null, DojoNodePosition];
12
11 export interface Rendition<TNode extends Node = Node> {
13 export interface Rendition<TNode extends Node = Node> {
12 getDomNode(): TNode;
14 getDomNode(): TNode;
13
15
@@ -150,3 +152,10 export function startupWidgets(target: N
150 target.startup();
152 target.startup();
151 }
153 }
152 }
154 }
155
156 export function locateNode(node: Node): DojoNodeLocation {
157 const next = node.nextSibling;
158 return next ?
159 [next, "before"] :
160 [node.parentNode, "last"];
161 } No newline at end of file
General Comments 0
You need to be logged in to leave comments. Login now