##// END OF EJS Templates
Corrected _addChild behavior for WidgetRendition when the content is FunctionRendition which returns a widget instance
cin -
r91:a842d051d227 default
parent child
Show More
@@ -1,121 +1,128
1 import dom = require("dojo/dom-construct");
1 import dom = require("dojo/dom-construct");
2 import { argumentNotNull } from "@implab/core-amd/safe";
2 import { argumentNotNull } from "@implab/core-amd/safe";
3 import { RenditionBase } from "./RenditionBase";
3 import { RenditionBase } from "./RenditionBase";
4 import { DojoNodePosition, isInPage, isWidget } from "./traits";
4 import { DojoNodePosition, isElementNode, isInPage, isWidget } from "./traits";
5 import registry = require("dijit/registry");
5 import registry = require("dijit/registry");
6 import ContentPane = require("dijit/layout/ContentPane");
6 import ContentPane = require("dijit/layout/ContentPane");
7
7
8 // tslint:disable-next-line: class-name
8 // tslint:disable-next-line: class-name
9 export interface _Widget {
9 export interface _Widget {
10 domNode: Node;
10 domNode: Node;
11
11
12 containerNode?: Node;
12 containerNode?: Node;
13
13
14 placeAt?(refNode: string | Node, position?: DojoNodePosition): void;
14 placeAt?(refNode: string | Node, position?: DojoNodePosition): void;
15 startup?(): void;
15 startup?(): void;
16
16
17 addChild?(widget: any, index?: number): void;
17 addChild?(widget: any, index?: number): void;
18 }
18 }
19
19
20 export type _WidgetCtor = new (attrs: any, srcNode?: string | Node) => _Widget;
20 export type _WidgetCtor = new (attrs: any, srcNode?: string | Node) => _Widget;
21
21
22 export class WidgetRendition extends RenditionBase<Node> {
22 export class WidgetRendition extends RenditionBase<Node> {
23 readonly widgetClass: _WidgetCtor;
23 readonly widgetClass: _WidgetCtor;
24
24
25 _instance: _Widget | undefined;
25 _instance: _Widget | undefined;
26
26
27 constructor(widgetClass: _WidgetCtor) {
27 constructor(widgetClass: _WidgetCtor) {
28 super();
28 super();
29 argumentNotNull(widgetClass, "widgetClass");
29 argumentNotNull(widgetClass, "widgetClass");
30
30
31 this.widgetClass = widgetClass;
31 this.widgetClass = widgetClass;
32 }
32 }
33
33
34 _addChild(child: any): void {
34 _addChild(child: any): void {
35 const instance = this._getInstance();
35 const instance = this._getInstance();
36
36
37 if (instance.addChild) {
37 if (instance.addChild) {
38 if (child instanceof WidgetRendition) {
38 if (child instanceof WidgetRendition) {
39 // layout containers add custom logic to addChild methods
39 // layout containers add custom logic to addChild methods
40 instance.addChild(child.getWidgetInstance());
40 instance.addChild(child.getWidgetInstance());
41 } else if (isWidget(child)) {
41 } else if (isWidget(child)) {
42 instance.addChild(child);
42 instance.addChild(child);
43 } else {
43 } else {
44 if (!instance.containerNode)
44 const childDom = this.getItemDom(child);
45 throw new Error("The widget doesn't have neither addChild nor containerNode");
45 const w = isElementNode(childDom) ? registry.byNode(childDom) : undefined;
46
46
47 // the current widget isn't started, it's children shouldn't start too
47 if (w) {
48 dom.place(this.getItemDom(child), instance.containerNode);
48 instance.addChild(w);
49 } else {
50 if (!instance.containerNode)
51 throw new Error("Failed to add DOM content. The widget doesn't have a containerNode");
52
53 // the current widget isn't started, it's children shouldn't start too
54 dom.place(this.getItemDom(child), instance.containerNode);
55 }
49 }
56 }
50 } else {
57 } else {
51 if (!instance.containerNode)
58 if (!instance.containerNode)
52 throw new Error("The widget doesn't have neither addChild nor containerNode");
59 throw new Error("The widget doesn't have neither addChild nor containerNode");
53
60
54 // the current widget isn't started, it's children shouldn't start too
61 // the current widget isn't started, it's children shouldn't start too
55 dom.place(this.getItemDom(child), instance.containerNode);
62 dom.place(this.getItemDom(child), instance.containerNode);
56 }
63 }
57 }
64 }
58
65
59 protected _create(attrs: any, children: any[]) {
66 protected _create(attrs: any, children: any[]) {
60 if (this.widgetClass.prototype instanceof ContentPane) {
67 if (this.widgetClass.prototype instanceof ContentPane) {
61 // a special case for the ContentPane this is for
68 // a special case for the ContentPane this is for
62 // the compatibility with this heavy widget, all
69 // the compatibility with this heavy widget, all
63 // regular containers could be easily manipulated
70 // regular containers could be easily manipulated
64 // through `containerNode` property or `addChild` method.
71 // through `containerNode` property or `addChild` method.
65
72
66 // render children to the DocumentFragment
73 // render children to the DocumentFragment
67 const content = document.createDocumentFragment();
74 const content = document.createDocumentFragment();
68 children.forEach(child => content.appendChild(this.getItemDom(child)));
75 children.forEach(child => content.appendChild(this.getItemDom(child)));
69
76
70 // set the content property to the parameters of the widget
77 // set the content property to the parameters of the widget
71 const _attrs = { ...attrs, content };
78 const _attrs = { ...attrs, content };
72 this._instance = new this.widgetClass(_attrs);
79 this._instance = new this.widgetClass(_attrs);
73 } else {
80 } else {
74 this._instance = new this.widgetClass(attrs);
81 this._instance = new this.widgetClass(attrs);
75 children.forEach(x => this._addChild(x));
82 children.forEach(x => this._addChild(x));
76 }
83 }
77
84
78 }
85 }
79
86
80 private _getInstance() {
87 private _getInstance() {
81 if (!this._instance)
88 if (!this._instance)
82 throw new Error("The instance of the widget isn't created");
89 throw new Error("The instance of the widget isn't created");
83 return this._instance;
90 return this._instance;
84 }
91 }
85
92
86 protected _getDomNode() {
93 protected _getDomNode() {
87 if (!this._instance)
94 if (!this._instance)
88 throw new Error("The instance of the widget isn't created");
95 throw new Error("The instance of the widget isn't created");
89 return this._instance.domNode;
96 return this._instance.domNode;
90 }
97 }
91
98
92 /** Overrides default placeAt implementation. Calls placeAt of the
99 /** Overrides default placeAt implementation. Calls placeAt of the
93 * widget and then starts it.
100 * widget and then starts it.
94 *
101 *
95 * @param refNode A node or id of the node where the widget should be placed.
102 * @param refNode A node or id of the node where the widget should be placed.
96 * @param position A position relative to refNode.
103 * @param position A position relative to refNode.
97 */
104 */
98 placeAt(refNode: string | Node, position?: DojoNodePosition) {
105 placeAt(refNode: string | Node, position?: DojoNodePosition) {
99 this.ensureCreated();
106 this.ensureCreated();
100 const instance = this._getInstance();
107 const instance = this._getInstance();
101 if (typeof instance.placeAt === "function") {
108 if (typeof instance.placeAt === "function") {
102 instance.placeAt(refNode, position);
109 instance.placeAt(refNode, position);
103
110
104 // fix the dojo startup behavior when the widget is placed
111 // fix the dojo startup behavior when the widget is placed
105 // directly to the document and doesn't have any enclosing widgets
112 // directly to the document and doesn't have any enclosing widgets
106 const parentWidget = instance.domNode.parentNode ?
113 const parentWidget = instance.domNode.parentNode ?
107 registry.getEnclosingWidget(instance.domNode.parentNode) : null
114 registry.getEnclosingWidget(instance.domNode.parentNode) : null
108 if (!parentWidget && isInPage(instance.domNode) && typeof instance.startup === "function")
115 if (!parentWidget && isInPage(instance.domNode) && typeof instance.startup === "function")
109 instance.startup();
116 instance.startup();
110 } else {
117 } else {
111 // the widget doesn't have a placeAt method, strange but whatever
118 // the widget doesn't have a placeAt method, strange but whatever
112 super.placeAt(refNode, position);
119 super.placeAt(refNode, position);
113 }
120 }
114 }
121 }
115
122
116 getWidgetInstance() {
123 getWidgetInstance() {
117 this.ensureCreated();
124 this.ensureCreated();
118 return this._getInstance();
125 return this._getInstance();
119 }
126 }
120
127
121 }
128 }
General Comments 0
You need to be logged in to leave comments. Login now