##// END OF EJS Templates
Added support for ContentPane, corrected widget startup calls
cin -
r48:030ea350f98b v1.0.3 default
parent child
Show More
@@ -1,74 +1,74
1 1 plugins {
2 2 id "org.implab.gradle-typescript" version "1.3.3"
3 3 id "ivy-publish"
4 4 }
5 5
6 6 typescript {
7 7 compilerOptions {
8 8 lib = ["es5", "dom", "scripthost", "es2015.promise", "es2015.symbol", "es2015.iterable"]
9 9 //listFiles = true
10 10 declaration = true
11 11 strict = true
12 12 types = []
13 13 module = "amd"
14 14 it.target = "es5"
15 15 experimentalDecorators = true
16 16 jsx = "react"
17 17 jsxFactory = "createElement"
18 18 moduleResolution = "node"
19 19 // dojo-typings are sick
20 20 skipLibCheck = true
21 21 // traceResolution = true
22 22 // baseUrl = "./"
23 23 // paths = [ "*": [ "$projectDir/src/typings/*" ] ]
24 24 // baseUrl = "$projectDir/src/typings"
25 25 // typeRoots = ["$projectDir/src/typings"]
26 26 }
27 27
28 28 tscCmd = "$projectDir/node_modules/.bin/tsc"
29 29 tsLintCmd = "$projectDir/node_modules/.bin/tslint"
30 30 esLintCmd = "$projectDir/node_modules/.bin/eslint"
31 31 }
32 32
33 33 configureTsMain {
34 34 compilerOptions {
35 /*baseUrl = "$projectDir/src"
36 paths = [
35 //baseUrl = "$projectDir/src"
36 /*paths = [
37 37 "dojo/*" : [ "typings/dojo/*" ],
38 38 "dijit/*" : [ "typings/dijit/*" ]
39 39 ]*/
40 types = ["requirejs", "dojo-typings"]
40 types = ["requirejs", "dojo-typings", "$projectDir/src/main/typings"]
41 41 }
42 42 }
43 43
44 44 configureTsTest {
45 45 compilerOptions {
46 46 typeRoots = []
47 47 types = ["requirejs", sources.main.output.typingsDir.get().toString() ]
48 48 }
49 49 }
50 50
51 51 npmPackMeta {
52 52 meta {
53 53 name = "@$npmScope/$project.name"
54 54 }
55 55 }
56 56
57 57 task npmPackTypings(type: Copy) {
58 58 dependsOn typings
59 59
60 60 npmPackContents.dependsOn it
61 61
62 62 from typescript.typingsDir
63 63 into npm.packageDir
64 64 }
65 65
66 66 task printVersion {
67 67 doLast {
68 68 println "packageName: ${npmPackMeta.metadata.get().name}";
69 69 println "version: $version";
70 70 println "target: $typescript.compilerOptions.target";
71 71 println "module: $typescript.compilerOptions.module";
72 72 println "symbols: $symbols";
73 73 }
74 74 } No newline at end of file
@@ -1,81 +1,89
1 1 import { isNull, mixin } from "@implab/core-amd/safe";
2 import { isPlainObject, isNode, isBuildContext, DojoNodePosition, BuildContext } from "./traits";
2 import { isPlainObject, isNode, isBuildContext, DojoNodePosition, BuildContext, isInPage } from "./traits";
3 3
4 4 import dom = require("dojo/dom-construct");
5 5 import registry = require("dijit/registry");
6 6
7
7 8 export abstract class BuildContextBase<TNode extends Node> implements BuildContext<TNode> {
8 9 private _attrs = {};
9 10
10 11 private _children = new Array();
11 12
12 13 private _created: boolean = false;
13 14
14 15 visitNext(v: any) {
15 16 if (this._created)
16 17 throw new Error("The Element is already created");
17 18
18 19 if (isNull(v) || typeof v === "boolean")
19 20 // skip null, undefined, booleans ( this will work: {value && <span>{value}</span>} )
20 21 return;
21 22
22 23 if (isPlainObject(v)) {
23 24 mixin(this._attrs, v);
24 25 } else if (v instanceof Array) {
25 26 v.forEach(x => this.visitNext(x));
26 27 } else {
27 28 this._children.push(v);
28 29 }
29 30 }
30 31
31 32 getChildDom(v: any) {
32 33 const tv = typeof v;
33 34 if (tv === "string" || tv === "number" || v instanceof RegExp || v instanceof Date) {
34 35 return document.createTextNode(v.toString());
35 36 } else if (isNode(v)) {
36 37 return v;
37 38 } else if (isBuildContext(v)) {
38 39 return v.getDomNode();
39 40 } else {
40 41 throw new Error("Invalid parameter");
41 42 }
42 43 }
43 44
44 45 ensureCreated() {
45 46 if (!this._created) {
46 47 this._create(this._attrs, this._children);
47 48 this._children = [];
48 49 this._attrs = {};
49 50 this._created = true;
50 51 }
51 52 }
52 53
53 54 /** @deprecated will be removed in 1.0.0, use getDomNode() */
54 55 getDomElement() {
55 56 return this.getDomNode();
56 57 }
57 58
58 59 /** Creates DOM node if not created. No additional actions are taken. */
59 60 getDomNode() {
60 61 this.ensureCreated();
61 62 return this._getDomNode();
62 63 }
63 64
64 65 /** Creates DOM node if not created, places it to the specified position
65 66 * and calls startup() method for all widgets contained by this node.
66 67 *
67 68 * @param {string | Node} refNode The reference node where the created
68 69 * DOM should be placed.
69 70 * @param {DojoNodePosition} position Optional parameter, specifies the
70 71 * position relative to refNode. Default is "last" (i.e. last child).
71 72 */
72 73 placeAt(refNode: string | Node, position?: DojoNodePosition) {
73 74 const domNode = this.getDomNode();
74 75 dom.place(domNode, refNode, position);
75 registry.findWidgets(domNode).forEach(w => w.startup());
76 const parentWidget = domNode.parentNode ? registry.getEnclosingWidget(domNode.parentNode) : null;
77
78 if ((parentWidget && parentWidget._started) || isInPage(domNode))
79 this._startup();
80 }
81
82 _startup () {
83 registry.findWidgets(this._getDomNode()).forEach(w => w.startup());
76 84 }
77 85
78 86 abstract _create(attrs: object, children: any[]): void;
79 87
80 88 abstract _getDomNode(): TNode;
81 89 }
@@ -1,32 +1,33
1 1 import dom = require("dojo/dom-construct");
2 2 import attr = require("dojo/dom-attr");
3 3 import { argumentNotNull } from "@implab/core-amd/safe";
4 4 import { BuildContextBase } from "./BuildContextBase";
5 import registry = require("dijit/registry");
5 6
6 7
7 export class FunctionComponentContext extends BuildContextBase<Element> {
8 private _component: (props: any) => Element;
8 export class FunctionComponentContext extends BuildContextBase<Node> {
9 private _component: (props: any) => any;
9 10
10 private _element: Element | undefined;
11 private _node: Node | undefined;
11 12
12 constructor(component: (props: any) => Element) {
13 constructor(component: (props: any) => any) {
13 14 super();
14 15 argumentNotNull(component, "component");
15 16
16 17 this._component = component;
17 18 }
18 19
19 20 _create(attrs: object, children: any[]) {
20 21 const _attrs: any = attrs || {};
21 22 _attrs.children = children.map(x => this.getChildDom(x));
22 23
23 this._element = this._component.call(null, _attrs);
24 this._node = this.getChildDom(this._component.call(null, _attrs));
24 25 }
25 26
26 27 _getDomNode() {
27 if (!this._element)
28 if (!this._node)
28 29 throw new Error("The instance of the widget isn't created");
29 return this._element;
30 return this._node;
30 31 }
31 32
32 33 }
@@ -1,38 +1,39
1 1 import dom = require("dojo/dom-construct");
2 2 import attr = require("dojo/dom-attr");
3 3 import { argumentNotEmptyString } from "@implab/core-amd/safe";
4 4 import { BuildContextBase } from "./BuildContextBase";
5 import registry = require("dijit/registry");
5 6
6 7 export class HtmlElementContext extends BuildContextBase<HTMLElement> {
7 8 elementType: string;
8 9
9 10 _element: HTMLElement | undefined;
10 11
11 12 constructor(elementType: string) {
12 13 argumentNotEmptyString(elementType, "elementType");
13 14 super();
14 15
15 16 this.elementType = elementType;
16 17 }
17 18
18 19 _addChild(child: any): void {
19 20 if (!this._element)
20 21 throw new Error("The HTML element isn't created");
21 22 dom.place(this.getChildDom(child), this._element);
22 23 }
23 24
24 25 _create(attrs: object, children: any[]) {
25 26 this._element = dom.create(this.elementType, attrs);
26 27
27 28 if (children)
28 29 children.forEach(v => this._addChild(v));
29 30 }
30 31
31 32 _getDomNode() {
32 33 if (!this._element)
33 34 throw new Error("The HTML element isn't created");
34 35
35 36 return this._element;
36 37 }
37 38
38 39 }
@@ -1,95 +1,128
1 1 import dom = require("dojo/dom-construct");
2 2 import { argumentNotNull } from "@implab/core-amd/safe";
3 3 import { BuildContextBase } from "./BuildContextBase";
4 import { DojoNodePosition, isWidget } from "./traits";
4 import { DojoNodePosition, isInPage, isWidget } from "./traits";
5 import registry = require("dijit/registry");
6 import ContentPane = require("dijit/layout/ContentPane");
5 7
6 8 // tslint:disable-next-line: class-name
7 9 export interface _Widget {
8 10 domNode: Node;
9 11
10 12 containerNode?: Node;
11 13
12 14 placeAt?(refNode: string | Node, position?: DojoNodePosition): void;
13 15 startup?(): void;
14 16
15 17 addChild?(widget: any, index?: number): void;
16 18 }
17 19
18 20 export type _WidgetCtor = new (attrs: any, srcNode?: string | Node) => _Widget;
19 21
20 22 export class WidgetContext extends BuildContextBase<Node> {
21 23 readonly widgetClass: _WidgetCtor;
22 24
23 25 _instance: _Widget | undefined;
24 26
25 27 constructor(widgetClass: _WidgetCtor) {
26 28 super();
27 29 argumentNotNull(widgetClass, "widgetClass");
28 30
29 31 this.widgetClass = widgetClass;
30 32 }
31 33
32 34 _addChild(child: any): void {
33 35 const instance = this._getInstance();
34 36
35 37 if (instance.addChild) {
36 if (child instanceof WidgetContext)
38 if (child instanceof WidgetContext) {
37 39 // layout containers add custom logic to addChild methods
38 40 instance.addChild(child.getWidgetInstance());
39 else if (isWidget(child))
41 } else if (isWidget(child)) {
40 42 instance.addChild(child);
41 else
42 instance.addChild(this.getChildDom(child));
43 } else {
44 if (!instance.containerNode)
45 throw new Error("The widget doesn't have neither addChild nor containerNode");
46
47 // the current widget isn't started, it's children shouldn't start too
48 dom.place(this.getChildDom(child), instance.containerNode);
49 }
43 50 } else {
44 51 if (!instance.containerNode)
45 52 throw new Error("The widget doesn't have neither addChild nor containerNode");
46 53
47 54 // the current widget isn't started, it's children shouldn't start too
48 55 dom.place(this.getChildDom(child), instance.containerNode);
49 56 }
50 57 }
51 58
52 _create(attrs: object, children: any[]) {
53 this._instance = new this.widgetClass(attrs);
54 if (children)
59 _create(attrs: any, children: any[]) {
60 if (this.widgetClass.prototype instanceof ContentPane) {
61 // a special case for the ContentPane this is for
62 // the compatibility with this heavy widget, all
63 // regular containers could be easily manipulated
64 // through `containerNode` property or `addChild` method.
65
66 // render children to the DocumentFragment
67 const content = document.createDocumentFragment();
68 children.forEach(child => content.appendChild(this.getChildDom(child)));
69
70 // set the content property to the parameters of the widget
71 const _attrs = { ...attrs, content };
72 this._instance = new this.widgetClass(_attrs);
73 } else {
74 this._instance = new this.widgetClass(attrs);
55 75 children.forEach(x => this._addChild(x));
76 }
77
56 78 }
57 79
58 80 private _getInstance() {
59 81 if (!this._instance)
60 82 throw new Error("The instance of the widget isn't created");
61 83 return this._instance;
62 84 }
63 85
64 86 _getDomNode() {
65 87 if (!this._instance)
66 88 throw new Error("The instance of the widget isn't created");
67 89 return this._instance.domNode;
68 90 }
69 91
70 92 /** Overrides default placeAt implementation. Calls placeAt of the
71 93 * widget and then starts it.
72 94 *
73 95 * @param refNode A node or id of the node where the widget should be placed.
74 96 * @param position A position relative to refNode.
75 97 */
76 98 placeAt(refNode: string | Node, position?: DojoNodePosition) {
77 99 this.ensureCreated();
78 100 const instance = this._getInstance();
79 101 if (typeof instance.placeAt === "function") {
80 102 instance.placeAt(refNode, position);
81 103
82 // do we need to force widget startup?
83 if (typeof instance.startup === "function")
84 instance.startup();
104 // fix the dojo startup behavior when the widget is placed
105 // directly to the document and doesn't have any enclosing widgets
106 const parentWidget = instance.domNode.parentNode ?
107 registry.getEnclosingWidget(instance.domNode.parentNode) : null
108 if (!parentWidget && isInPage(instance.domNode))
109 this._startup();
85 110 } else {
111 // the widget doesn't have a placeAt method, strange but whatever
86 112 super.placeAt(refNode, position);
87 113 }
88 114 }
89 115
116 _startup() {
117 const instance = this._getInstance();
118
119 if (typeof instance.startup === "function")
120 instance.startup();
121 }
122
90 123 getWidgetInstance() {
91 124 this.ensureCreated();
92 125 return this._getInstance();
93 126 }
94 127
95 128 }
@@ -1,66 +1,73
1 1 import _WidgetBase = require("dijit/_WidgetBase");
2 2
3 3 type _WidgetBaseConstructor = typeof _WidgetBase;
4 4
5 5 export type DojoNodePosition = "first" | "after" | "before" | "last" | "replace" | "only" | number;
6 6
7 7 export interface BuildContext<TNode extends Node = Node> {
8 8 getDomNode(): TNode;
9 9
10 10 placeAt(refNode: string | Node, position?: DojoNodePosition): void;
11 11 }
12 12
13 13 export function isNode(el: any): el is Node {
14 14 return el && el.nodeName && el.nodeType;
15 15 }
16 16
17 17 export function isElementNode(el: any): el is Element {
18 18 return isNode(el) && el.nodeType === 1;
19 19 }
20 20
21 21 export function isTextNode(el: any): el is Text {
22 22 return isNode(el) && el.nodeType === 3;
23 23 }
24 24
25 25 export function isProcessingInstructionNode(el: any): el is ProcessingInstruction {
26 26 return isNode(el) && el.nodeType === 7;
27 27 }
28 28
29 29 export function isCommentNode(el: any): el is Comment {
30 30 return isNode(el) && el.nodeType === 8;
31 31 }
32 32
33 33 export function isDocumentNode(el: any): el is Document {
34 34 return isNode(el) && el.nodeType === 9;
35 35 }
36 36
37 37 export function isDocumentTypeNode(el: any): el is DocumentType {
38 38 return isNode(el) && el.nodeType === 10;
39 39 }
40 40
41 41 export function isDocumentFragmentNode(el: any): el is DocumentFragment {
42 42 return isNode(el) && el.nodeType === 11;
43 43 }
44 44
45 45 export function isWidget(v: any): v is _WidgetBase {
46 46 return v && "domNode" in v;
47 47 }
48 48
49 49 export function isBuildContext(v: any): v is BuildContext {
50 50 return typeof v === "object" && typeof v.getDomElement === "function";
51 51 }
52 52
53 53 export function isPlainObject(v: object) {
54 54 if (typeof v !== "object")
55 55 return false;
56 56
57 57 const vp = Object.getPrototypeOf(v);
58 58 return !vp || vp === Object.prototype;
59 59 }
60 60
61 61 export function isWidgetConstructor(v: any): v is _WidgetBaseConstructor {
62 62 return typeof v === "function" && v.prototype && (
63 63 "domNode" in v.prototype ||
64 64 "buildRendering" in v.prototype
65 65 );
66 66 }
67
68 /** Tests whether the specified node is placed in visible dom.
69 * @param {Node} node The node to test
70 */
71 export function isInPage(node: Node) {
72 return (node === document.body) ? false : document.body.contains(node);
73 }
General Comments 0
You need to be logged in to leave comments. Login now