##// END OF EJS Templates
minor code cleanups
cin -
r93:d99e2014cea4 default
parent child
Show More
@@ -1,78 +1,78
1 plugins {
1 plugins {
2 id "org.implab.gradle-typescript" version "1.3.3"
2 id "org.implab.gradle-typescript" version "1.3.3"
3 id "ivy-publish"
3 id "ivy-publish"
4 }
4 }
5
5
6 typescript {
6 typescript {
7 compilerOptions {
7 compilerOptions {
8 lib = ["es5", "dom", "scripthost", "es2015.promise", "es2015.symbol", "es2015.iterable"]
8 lib = ["es5", "dom", "scripthost", "es2015.promise", "es2015.symbol", "es2015.iterable"]
9 //listFiles = true
9 // listFiles = true
10 declaration = true
10 declaration = true
11 strict = true
11 strict = true
12 types = []
12 types = []
13 module = "amd"
13 module = "amd"
14 it.target = "es5"
14 it.target = "es5"
15 experimentalDecorators = true
15 experimentalDecorators = true
16 noUnusedLocals = true
16 noUnusedLocals = false
17 jsx = "react"
17 jsx = "react"
18 jsxFactory = "createElement"
18 jsxFactory = "createElement"
19 moduleResolution = "node"
19 moduleResolution = "node"
20 // dojo-typings are sick
20 // dojo-typings are sick
21 skipLibCheck = true
21 skipLibCheck = true
22 // traceResolution = true
22 // traceResolution = true
23 // baseUrl = "./"
23 // baseUrl = "./"
24 // paths = [ "*": [ "$projectDir/src/typings/*" ] ]
24 // paths = [ "*": [ "$projectDir/src/typings/*" ] ]
25 // baseUrl = "$projectDir/src/typings"
25 // baseUrl = "$projectDir/src/typings"
26 // typeRoots = ["$projectDir/src/typings"]
26 // typeRoots = ["$projectDir/src/typings"]
27 }
27 }
28
28
29 tscCmd = "$projectDir/node_modules/.bin/tsc"
29 tscCmd = "$projectDir/node_modules/.bin/tsc"
30 tsLintCmd = "$projectDir/node_modules/.bin/tslint"
30 tsLintCmd = "$projectDir/node_modules/.bin/tslint"
31 esLintCmd = "$projectDir/node_modules/.bin/eslint"
31 esLintCmd = "$projectDir/node_modules/.bin/eslint"
32 }
32 }
33
33
34 configureTsMain {
34 configureTsMain {
35 sourceFiles {
35 sourceFiles {
36 from sources.main.typings
36 from sources.main.typings
37 }
37 }
38 compilerOptions {
38 compilerOptions {
39 // baseUrl = "$projectDir/src"
39 // baseUrl = "$projectDir/src"
40 /*paths = [
40 /*paths = [
41 "dojo/*" : [ "typings/dojo/*" ],
41 "dojo/*" : [ "typings/dojo/*" ],
42 "dijit/*" : [ "typings/dijit/*" ]
42 "dijit/*" : [ "typings/dijit/*" ]
43 ]*/
43 ]*/
44 types = ["requirejs", "@implab/dojo-typings"]
44 types = ["requirejs", "@implab/dojo-typings"]
45 }
45 }
46 }
46 }
47
47
48 configureTsTest {
48 configureTsTest {
49 compilerOptions {
49 compilerOptions {
50 typeRoots = []
50 typeRoots = []
51 types = ["requirejs", sources.main.output.typingsDir.get().toString() ]
51 types = ["requirejs", sources.main.output.typingsDir.get().toString() ]
52 }
52 }
53 }
53 }
54
54
55 npmPackMeta {
55 npmPackMeta {
56 meta {
56 meta {
57 name = "@$npmScope/$project.name"
57 name = "@$npmScope/$project.name"
58 }
58 }
59 }
59 }
60
60
61 task npmPackTypings(type: Copy) {
61 task npmPackTypings(type: Copy) {
62 dependsOn typings
62 dependsOn typings
63
63
64 npmPackContents.dependsOn it
64 npmPackContents.dependsOn it
65
65
66 from typescript.typingsDir
66 from typescript.typingsDir
67 into npm.packageDir
67 into npm.packageDir
68 }
68 }
69
69
70 task printVersion {
70 task printVersion {
71 doLast {
71 doLast {
72 println "packageName: ${npmPackMeta.metadata.get().name}";
72 println "packageName: ${npmPackMeta.metadata.get().name}";
73 println "version: $version";
73 println "version: $version";
74 println "target: $typescript.compilerOptions.target";
74 println "target: $typescript.compilerOptions.target";
75 println "module: $typescript.compilerOptions.module";
75 println "module: $typescript.compilerOptions.module";
76 println "symbols: $symbols";
76 println "symbols: $symbols";
77 }
77 }
78 } No newline at end of file
78 }
@@ -1,119 +1,119
1 import { Constructor, IDestroyable, IRemovable } from "@implab/core-amd/interfaces";
1 import { Constructor, IDestroyable, IRemovable } from "@implab/core-amd/interfaces";
2 import { HtmlRendition } from "./tsx/HtmlRendition";
2 import { HtmlRendition } from "./tsx/HtmlRendition";
3 import { WidgetRendition } from "./tsx/WidgetRendition";
3 import { WidgetRendition } from "./tsx/WidgetRendition";
4 import { destroy, isWidgetConstructor, Rendition } from "./tsx/traits";
4 import { destroy, isWidgetConstructor, Rendition } from "./tsx/traits";
5 import { FunctionRendition } from "./tsx/FunctionRendition";
5 import { FunctionRendition } from "./tsx/FunctionRendition";
6 import Stateful = require("dojo/Stateful");
6 import Stateful = require("dojo/Stateful");
7 import _WidgetBase = require("dijit/_WidgetBase");
7 import _WidgetBase = require("dijit/_WidgetBase");
8 import { DjxWidgetBase } from "./tsx/DjxWidgetBase";
8 import { DjxWidgetBase } from "./tsx/DjxWidgetBase";
9
9
10 export function createElement<T extends Constructor | string | ((props: any) => Element)>(elementType: T, ...args: any[]): Rendition {
10 export function createElement<T extends Constructor | string | ((props: any) => Element)>(elementType: T, ...args: any[]): Rendition {
11 if (typeof elementType === "string") {
11 if (typeof elementType === "string") {
12 const ctx = new HtmlRendition(elementType);
12 const ctx = new HtmlRendition(elementType);
13 if (args)
13 if (args)
14 args.forEach(x => ctx.visitNext(x));
14 args.forEach(x => ctx.visitNext(x));
15
15
16 return ctx;
16 return ctx;
17 } else if (isWidgetConstructor(elementType)) {
17 } else if (isWidgetConstructor(elementType)) {
18 const ctx = new WidgetRendition(elementType);
18 const ctx = new WidgetRendition(elementType);
19 if (args)
19 if (args)
20 args.forEach(x => ctx.visitNext(x));
20 args.forEach(x => ctx.visitNext(x));
21
21
22 return ctx;
22 return ctx;
23 } else if (typeof elementType === "function") {
23 } else if (typeof elementType === "function") {
24 const ctx = new FunctionRendition(elementType as (props: any) => Element);
24 const ctx = new FunctionRendition(elementType as (props: any) => Element);
25 if (args)
25 if (args)
26 args.forEach(x => ctx.visitNext(x));
26 args.forEach(x => ctx.visitNext(x));
27
27
28 return ctx;
28 return ctx;
29 } else {
29 } else {
30 throw new Error(`The element type '${elementType}' is unsupported`);
30 throw new Error(`The element type '${elementType}' is unsupported`);
31 }
31 }
32 }
32 }
33
33
34 export interface EventDetails<T = any> {
34 export interface EventDetails<T = any> {
35 detail: T;
35 detail: T;
36 }
36 }
37
37
38 export interface EventSelector {
38 export interface EventSelector {
39 selectorTarget: HTMLElement;
39 selectorTarget: HTMLElement;
40 target: HTMLElement;
40 target: HTMLElement;
41 }
41 }
42
42
43 export type DojoMouseEvent<T = any> = MouseEvent & EventSelector & EventDetails<T>;
43 export type DojoMouseEvent<T = any> = MouseEvent & EventSelector & EventDetails<T>;
44
44
45 type StatefulProps<T> = T extends Stateful<infer A> ? A : never;
45 type StatefulProps<T> = T extends Stateful<infer A> ? A : never;
46
46
47 type CleanFn = (instance: IRemovable | IDestroyable) => void;
47 type CleanFn = (instance: IRemovable | IDestroyable) => void;
48
48
49 /**
49 /**
50 * Observers the property and calls render callback each change.
50 * Observers the property and calls render callback each change.
51 *
51 *
52 * @param target The target object which property will be observed.
52 * @param target The target object which property will be observed.
53 * @param prop The name of the property.
53 * @param prop The name of the property.
54 * @param render The callback which will be called every time the value is changed
54 * @param render The callback which will be called every time the value is changed
55 * @param cleanupOrOwner The object with method `own` or an callback to register lifecycle for the observer.
55 * @param cleanupOrOwner The object with method `own` or an callback to register lifecycle for the observer.
56 * @returns Rendition which is created instantly
56 * @returns Rendition which is created instantly
57 */
57 */
58 export function watch<W extends _WidgetBase, K extends keyof W>(
58 export function watch<W extends _WidgetBase, K extends keyof W>(
59 target: W,
59 target: W,
60 prop: K,
60 prop: K,
61 render: (model: W[K]) => any,
61 render: (model: W[K]) => any,
62 cleanupOrOwner?: { own: CleanFn } | CleanFn
62 cleanupOrOwner?: { own: CleanFn } | CleanFn
63 ): Rendition;
63 ): Rendition;
64 /**
64 /**
65 * Observers the property and calls render callback each change.
65 * Observers the property and calls render callback each change.
66 *
66 *
67 * @param target The target object which property will be observed.
67 * @param target The target object which property will be observed.
68 * @param prop The name of the property.
68 * @param prop The name of the property.
69 * @param render The callback which will be called every time the value is changed
69 * @param render The callback which will be called every time the value is changed
70 * @param cleanupOrOwner The object with method `own` or an callback to register lifecycle for the observer.
70 * @param cleanupOrOwner The object with method `own` or an callback to register lifecycle for the observer.
71 * @returns Rendition which is created instantly
71 * @returns Rendition which is created instantly
72 */
72 */
73 export function watch<T extends Stateful, K extends keyof StatefulProps<T>>(
73 export function watch<T extends Stateful, K extends keyof StatefulProps<T>>(
74 target: T,
74 target: T,
75 prop: K,
75 prop: K,
76 render: (model: StatefulProps<T>[K]) => any,
76 render: (model: StatefulProps<T>[K]) => any,
77 cleanupOrOwner?: { own: CleanFn } | CleanFn
77 cleanupOrOwner?: { own: CleanFn } | CleanFn
78 ): Rendition;
78 ): Rendition;
79 export function watch<T extends Stateful, K extends keyof StatefulProps<T> & string>(
79 export function watch<T extends Stateful, K extends keyof StatefulProps<T> & string>(
80 target: T,
80 target: T,
81 prop: K,
81 prop: K,
82 render: (model: StatefulProps<T>[K]) => any,
82 render: (model: StatefulProps<T>[K]) => any,
83 cleanupOrOwner: { own: CleanFn } | CleanFn = () => { }
83 cleanupOrOwner: { own: CleanFn } | CleanFn = () => { }
84 ) {
84 ) {
85 let rendition = new FunctionRendition(() => render(target.get(prop)));
85 let rendition = new FunctionRendition(() => render(target.get(prop)));
86 const _own = cleanupOrOwner instanceof Function ? cleanupOrOwner : (x: IRemovable) => cleanupOrOwner.own(x);
86 const _own = cleanupOrOwner instanceof Function ? cleanupOrOwner : (x: IRemovable) => cleanupOrOwner.own(x);
87 _own(target.watch(prop, (_name, oldValue, newValue) => {
87 _own(target.watch(prop, (_name, oldValue, newValue) => {
88 if (oldValue !== newValue) {
88 if (oldValue !== newValue) {
89 const newRendition = new FunctionRendition(() => render(newValue));
89 const newRendition = new FunctionRendition(() => render(newValue));
90 newRendition.placeAt(rendition.getDomNode(), "replace");
90 newRendition.placeAt(rendition.getDomNode(), "replace");
91 destroy(rendition.getDomNode());
91 destroy(rendition.getDomNode());
92 rendition = newRendition;
92 rendition = newRendition;
93 }
93 }
94 }));
94 }));
95 return rendition;
95 return rendition;
96 }
96 }
97
97
98 /** Decorates the method which will be registered as the handle for the specified event.
98 /** Decorates the method which will be registered as the handle for the specified event.
99 * This decorator can be applied to DjxWidgetBase subclass methods.
99 * This decorator can be applied to DjxWidgetBase subclass methods.
100 *
100 *
101 * ```
101 * ```
102 * @on("click")
102 * @on("click")
103 * _onClick(eventObj: MouseEvent) {
103 * _onClick(eventObj: MouseEvent) {
104 * // ...
104 * // ...
105 * }
105 * }
106 * ```
106 * ```
107 */
107 */
108 export const on = <E extends string>(...eventNames: E[]) =>
108 export const on = <E extends string>(...eventNames: E[]) =>
109 <K extends string,
109 <K extends string,
110 T extends DjxWidgetBase<any, { [p in E]: EV }>,
110 T extends DjxWidgetBase<any, { [p in E]: EV }>,
111 EV extends Event
111 EV extends Event
112 >(
112 >(
113 target: T,
113 target: T,
114 key: K,
114 key: K,
115 _descriptor: TypedPropertyDescriptor<(eventObj: EV) => void> | TypedPropertyDescriptor<() => void>
115 _descriptor: TypedPropertyDescriptor<(eventObj: EV) => void> | TypedPropertyDescriptor<() => void>
116 ): any => {
116 ): any => {
117 const handlers = eventNames.map(eventName => ({ eventName, handlerMethod: key }))
117 const handlers = eventNames.map(eventName => ({ eventName, handlerMethod: key }));
118 target._eventHandlers = target._eventHandlers ? target._eventHandlers.concat(handlers) : handlers;
118 target._eventHandlers = target._eventHandlers ? target._eventHandlers.concat(handlers) : handlers;
119 };
119 };
@@ -1,37 +1,36
1 import dom = require("dojo/dom-construct");
1 import dom = require("dojo/dom-construct");
2 import { argumentNotEmptyString } from "@implab/core-amd/safe";
2 import { argumentNotEmptyString } from "@implab/core-amd/safe";
3 import { RenditionBase } from "./RenditionBase";
3 import { RenditionBase } from "./RenditionBase";
4
4
5 export class HtmlRendition extends RenditionBase<HTMLElement> {
5 export class HtmlRendition extends RenditionBase<HTMLElement> {
6 elementType: string;
6 elementType: string;
7
7
8 _element: HTMLElement | undefined;
8 _element: HTMLElement | undefined;
9
9
10 constructor(elementType: string) {
10 constructor(elementType: string) {
11 argumentNotEmptyString(elementType, "elementType");
11 argumentNotEmptyString(elementType, "elementType");
12 super();
12 super();
13
13
14 this.elementType = elementType;
14 this.elementType = elementType;
15 }
15 }
16
16
17 _addChild(child: any): void {
17 _addChild(child: any): void {
18 if (!this._element)
18 if (!this._element)
19 throw new Error("The HTML element isn't created");
19 throw new Error("The HTML element isn't created");
20 dom.place(this.getItemDom(child), this._element);
20 dom.place(this.getItemDom(child), this._element);
21 }
21 }
22
22
23 _create(attrs: object, children: any[]) {
23 _create(attrs: object, children: any[]) {
24 this._element = dom.create(this.elementType, attrs);
24 this._element = dom.create(this.elementType, attrs);
25
25
26 if (children)
26 children.forEach(v => this._addChild(v));
27 children.forEach(v => this._addChild(v));
28 }
27 }
29
28
30 _getDomNode() {
29 _getDomNode() {
31 if (!this._element)
30 if (!this._element)
32 throw new Error("The HTML element isn't created");
31 throw new Error("The HTML element isn't created");
33
32
34 return this._element;
33 return this._element;
35 }
34 }
36
35
37 }
36 }
@@ -1,116 +1,117
1 import { isNull, mixin } from "@implab/core-amd/safe";
1 import { isNull, mixin } from "@implab/core-amd/safe";
2 import { isPlainObject, isNode, isRendition, DojoNodePosition, Rendition, isInPage, isWidget, isDocumentFragmentNode, startupWidgets } from "./traits";
2 import { isPlainObject, isNode, isRendition, DojoNodePosition, Rendition, isInPage, isWidget, isDocumentFragmentNode, startupWidgets } from "./traits";
3
3
4 import dom = require("dojo/dom-construct");
4 import dom = require("dojo/dom-construct");
5 import registry = require("dijit/registry");
5 import registry = require("dijit/registry");
6
6
7
7
8 export abstract class RenditionBase<TNode extends Node> implements Rendition<TNode> {
8 export abstract class RenditionBase<TNode extends Node> implements Rendition<TNode> {
9 private _attrs = {};
9 private _attrs = {};
10
10
11 private _children = new Array();
11 private _children = new Array();
12
12
13 private _created: boolean = false;
13 private _created: boolean = false;
14
14
15 visitNext(v: any) {
15 visitNext(v: any) {
16 if (this._created)
16 if (this._created)
17 throw new Error("The Element is already created");
17 throw new Error("The Element is already created");
18
18
19 if (isNull(v) || typeof v === "boolean")
19 if (isNull(v) || typeof v === "boolean")
20 // skip null, undefined, booleans ( this will work: {value && <span>{value}</span>} )
20 // skip null, undefined, booleans ( this will work: {value && <span>{value}</span>} )
21 return;
21 return;
22
22
23 if (isPlainObject(v)) {
23 if (isPlainObject(v)) {
24 mixin(this._attrs, v);
24 mixin(this._attrs, v);
25 } else if (v instanceof Array) {
25 } else if (v instanceof Array) {
26 v.forEach(x => this.visitNext(x));
26 v.forEach(x => this.visitNext(x));
27 } else {
27 } else {
28 this._children.push(v);
28 this._children.push(v);
29 }
29 }
30 }
30 }
31
31
32 /** Renders DOM element for different types of the argument. */
32 protected getItemDom(v: any) {
33 protected getItemDom(v: any) {
33 const tv = typeof v;
34 const tv = typeof v;
34
35
35 if (tv === "string" || tv === "number" || v instanceof RegExp || v instanceof Date) {
36 if (tv === "string" || tv === "number" || v instanceof RegExp || v instanceof Date) {
36 // primitive types converted to the text nodes
37 // primitive types converted to the text nodes
37 return document.createTextNode(v.toString());
38 return document.createTextNode(v.toString());
38 } else if (isNode(v)) {
39 } else if (isNode(v)) {
39 // nodes are kept as is
40 // nodes are kept as is
40 return v;
41 return v;
41 } else if (isRendition(v)) {
42 } else if (isRendition(v)) {
42 // renditions as instantinated
43 // renditions are instantiated
43 return v.getDomNode();
44 return v.getDomNode();
44 } else if (isWidget(v)) {
45 } else if (isWidget(v)) {
45 // widgets are converted to it's markup
46 // widgets are converted to it's markup
46 return v.domNode;
47 return v.domNode;
47 } else if (tv === "boolean" || v === null || v === undefined) {
48 } else if (tv === "boolean" || v === null || v === undefined) {
48 // null | undefined | boolean are removed, converted to comments
49 // null | undefined | boolean are removed, converted to comments
49 return document.createComment(`[${tv} ${String(v)}]`);
50 return document.createComment(`[${tv} ${String(v)}]`);
50 } else {
51 } else {
51 // bug: explicit error otherwise
52 // bug: explicit error otherwise
52 throw new Error("Invalid parameter: " + v);
53 throw new Error("Invalid parameter: " + v);
53 }
54 }
54 }
55 }
55
56
56 ensureCreated() {
57 ensureCreated() {
57 if (!this._created) {
58 if (!this._created) {
58 this._create(this._attrs, this._children);
59 this._create(this._attrs, this._children);
59 this._children = [];
60 this._children = [];
60 this._attrs = {};
61 this._attrs = {};
61 this._created = true;
62 this._created = true;
62 }
63 }
63 }
64 }
64
65
65 /** @deprecated will be removed in 1.0.0, use getDomNode() */
66 /** Is rendition was instantiated to the DOM node */
66 getDomElement() {
67 isCreated() {
67 return this.getDomNode();
68 return this._created;
68 }
69 }
69
70
70 /** Creates DOM node if not created. No additional actions are taken. */
71 /** Creates DOM node if not created. No additional actions are taken. */
71 getDomNode() {
72 getDomNode() {
72 this.ensureCreated();
73 this.ensureCreated();
73 return this._getDomNode();
74 return this._getDomNode();
74 }
75 }
75
76
76 /** Creates DOM node if not created, places it to the specified position
77 /** Creates DOM node if not created, places it to the specified position
77 * and calls startup() method for all widgets contained by this node.
78 * and calls startup() method for all widgets contained by this node.
78 *
79 *
79 * @param {string | Node} refNode The reference node where the created
80 * @param {string | Node} refNode The reference node where the created
80 * DOM should be placed.
81 * DOM should be placed.
81 * @param {DojoNodePosition} position Optional parameter, specifies the
82 * @param {DojoNodePosition} position Optional parameter, specifies the
82 * position relative to refNode. Default is "last" (i.e. last child).
83 * position relative to refNode. Default is "last" (i.e. last child).
83 */
84 */
84 placeAt(refNode: string | Node, position?: DojoNodePosition) {
85 placeAt(refNode: string | Node, position?: DojoNodePosition) {
85 const domNode = this.getDomNode();
86 const domNode = this.getDomNode();
86
87
87 const collect = (collection: HTMLCollection) => {
88 const collect = (collection: HTMLCollection) => {
88 const items = [];
89 const items = [];
89 for (let i = 0, n = collection.length; i < n; i++) {
90 for (let i = 0, n = collection.length; i < n; i++) {
90 items.push(collection[i]);
91 items.push(collection[i]);
91 }
92 }
92 return items;
93 return items;
93 };
94 };
94
95
95 const startup = (node: Node) => {
96 const startup = (node: Node) => {
96 if (node.parentNode) {
97 if (node.parentNode) {
97 const parentWidget = registry.getEnclosingWidget(node.parentNode);
98 const parentWidget = registry.getEnclosingWidget(node.parentNode);
98 if (parentWidget && parentWidget._started)
99 if (parentWidget && parentWidget._started)
99 return startupWidgets(node);
100 return startupWidgets(node);
100 }
101 }
101 if (isInPage(node))
102 if (isInPage(node))
102 startupWidgets(node);
103 startupWidgets(node);
103 };
104 };
104
105
105 const startupPending = isDocumentFragmentNode(domNode) ? collect(domNode.children) : [domNode];
106 const startupPending = isDocumentFragmentNode(domNode) ? collect(domNode.children) : [domNode];
106
107
107 dom.place(domNode, refNode, position);
108 dom.place(domNode, refNode, position);
108
109
109 startupPending.forEach(startup);
110 startupPending.forEach(startup);
110
111
111 }
112 }
112
113
113 protected abstract _create(attrs: object, children: any[]): void;
114 protected abstract _create(attrs: object, children: any[]): void;
114
115
115 protected abstract _getDomNode(): TNode;
116 protected abstract _getDomNode(): TNode;
116 }
117 }
@@ -1,148 +1,152
1 import { IDestroyable } from "@implab/core-amd/interfaces";
1 import { IDestroyable } from "@implab/core-amd/interfaces";
2 import { isDestroyable } from "@implab/core-amd/safe";
2 import { isDestroyable } from "@implab/core-amd/safe";
3 import _WidgetBase = require("dijit/_WidgetBase");
3 import _WidgetBase = require("dijit/_WidgetBase");
4 import registry = require("dijit/registry");
4 import registry = require("dijit/registry");
5 import dom = require("dojo/dom-construct");
5 import dom = require("dojo/dom-construct");
6
6
7 type _WidgetBaseConstructor = typeof _WidgetBase;
7 type _WidgetBaseConstructor = typeof _WidgetBase;
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 interface Rendition<TNode extends Node = Node> {
11 export interface Rendition<TNode extends Node = Node> {
12 getDomNode(): TNode;
12 getDomNode(): TNode;
13
13
14 placeAt(refNode: string | Node, position?: DojoNodePosition): void;
14 placeAt(refNode: string | Node, position?: DojoNodePosition): void;
15 }
15 }
16
16
17 /**
17 /**
18 * @deprecated use Rendition
18 * @deprecated use Rendition
19 */
19 */
20 export type BuildContext<TNode extends Node = Node> = Rendition<TNode>;
20 export type BuildContext<TNode extends Node = Node> = Rendition<TNode>;
21
21
22 export interface IRecursivelyDestroyable {
22 export interface IRecursivelyDestroyable {
23 destroyRecursive(): void;
23 destroyRecursive(): void;
24 }
24 }
25
25
26 export function isNode(el: any): el is Node {
26 export function isNode(el: any): el is Node {
27 return el && el.nodeName && el.nodeType;
27 return el && el.nodeName && el.nodeType;
28 }
28 }
29
29
30 export function isElementNode(el: any): el is Element {
30 export function isElementNode(el: any): el is Element {
31 return isNode(el) && el.nodeType === 1;
31 return isNode(el) && el.nodeType === 1;
32 }
32 }
33
33
34 export function isTextNode(el: any): el is Text {
34 export function isTextNode(el: any): el is Text {
35 return isNode(el) && el.nodeType === 3;
35 return isNode(el) && el.nodeType === 3;
36 }
36 }
37
37
38 export function isProcessingInstructionNode(el: any): el is ProcessingInstruction {
38 export function isProcessingInstructionNode(el: any): el is ProcessingInstruction {
39 return isNode(el) && el.nodeType === 7;
39 return isNode(el) && el.nodeType === 7;
40 }
40 }
41
41
42 export function isCommentNode(el: any): el is Comment {
42 export function isCommentNode(el: any): el is Comment {
43 return isNode(el) && el.nodeType === 8;
43 return isNode(el) && el.nodeType === 8;
44 }
44 }
45
45
46 export function isDocumentNode(el: any): el is Document {
46 export function isDocumentNode(el: any): el is Document {
47 return isNode(el) && el.nodeType === 9;
47 return isNode(el) && el.nodeType === 9;
48 }
48 }
49
49
50 export function isDocumentTypeNode(el: any): el is DocumentType {
50 export function isDocumentTypeNode(el: any): el is DocumentType {
51 return isNode(el) && el.nodeType === 10;
51 return isNode(el) && el.nodeType === 10;
52 }
52 }
53
53
54 export function isDocumentFragmentNode(el: any): el is DocumentFragment {
54 export function isDocumentFragmentNode(el: any): el is DocumentFragment {
55 return isNode(el) && el.nodeType === 11;
55 return isNode(el) && el.nodeType === 11;
56 }
56 }
57
57
58 export function isWidget(v: any): v is _WidgetBase {
58 export function isWidget(v: any): v is _WidgetBase {
59 return v && "domNode" in v;
59 return v && "domNode" in v;
60 }
60 }
61
61
62 export function isRendition(v: any): v is Rendition {
62 export function isRendition(v: any): v is Rendition {
63 return v && typeof v.getDomElement === "function";
63 return v && typeof v.getDomElement === "function";
64 }
64 }
65
65
66 /**
66 /**
67 * @deprecated use isRendition
67 * @deprecated use isRendition
68 */
68 */
69 export const isBuildContext = isRendition;
69 export const isBuildContext = isRendition;
70
70
71 export function isPlainObject(v: object) {
71 export function isPlainObject(v: object) {
72 if (typeof v !== "object")
72 if (typeof v !== "object")
73 return false;
73 return false;
74
74
75 const vp = Object.getPrototypeOf(v);
75 const vp = Object.getPrototypeOf(v);
76 return !vp || vp === Object.prototype;
76 return !vp || vp === Object.prototype;
77 }
77 }
78
78
79 export function isWidgetConstructor(v: any): v is _WidgetBaseConstructor {
79 export function isWidgetConstructor(v: any): v is _WidgetBaseConstructor {
80 return typeof v === "function" && v.prototype && (
80 return typeof v === "function" && v.prototype && (
81 "domNode" in v.prototype ||
81 "domNode" in v.prototype ||
82 "buildRendering" in v.prototype
82 "buildRendering" in v.prototype
83 );
83 );
84 }
84 }
85
85
86 /** Tests whether the specified node is placed in visible dom.
86 /** Tests whether the specified node is placed in visible dom.
87 * @param {Node} node The node to test
87 * @param {Node} node The node to test
88 */
88 */
89 export function isInPage(node: Node) {
89 export function isInPage(node: Node) {
90 return (node === document.body) ? false : document.body.contains(node);
90 return (node === document.body) ? false : document.body.contains(node);
91 }
91 }
92
92
93 export function isRecursivelyDestroyable(target: any): target is IRecursivelyDestroyable {
93 export function isRecursivelyDestroyable(target: any): target is IRecursivelyDestroyable {
94 return target && typeof target.destroyRecursive === "function";
94 return target && typeof target.destroyRecursive === "function";
95 }
95 }
96
96
97
97
98 /** Destroys DOM Node with all contained widgets.
98 /** Destroys DOM Node with all contained widgets.
99 * If the specified node is the root node of a widget, then the
99 * If the specified node is the root node of a widget, then the
100 * widget will be destroyed.
100 * widget will be destroyed.
101 *
101 *
102 * @param target DOM Node or widget to destroy
102 * @param target DOM Node or widget to destroy
103 */
103 */
104 export function destroy(target: Node | IDestroyable | IRecursivelyDestroyable) {
104 export function destroy(target: Node | IDestroyable | IRecursivelyDestroyable) {
105 if (isRecursivelyDestroyable(target)) {
105 if (isRecursivelyDestroyable(target)) {
106 target.destroyRecursive();
106 target.destroyRecursive();
107 } else if (isDestroyable(target)) {
107 } else if (isDestroyable(target)) {
108 target.destroy();
108 target.destroy();
109 } else if (isNode(target)) {
109 } else if (isNode(target)) {
110 const w = isElementNode(target) ? registry.byNode(target) : undefined;
110 if (isElementNode(target)) {
111 if (w) {
111 const w = registry.byNode(target);
112 w.destroyRecursive();
112 if (w) {
113 } else {
113 w.destroyRecursive();
114 registry.findWidgets(target).forEach(destroy);
114 } else {
115 dom.destroy(target);
115 registry.findWidgets(target).forEach(destroy);
116 dom.destroy(target);
117 }
116 }
118 }
117 }
119 }
118 }
120 }
119
121
120 /** Empties a content of the specified node and destroys all contained widgets.
122 /** Empties a content of the specified node and destroys all contained widgets.
121 *
123 *
122 * @param target DOM node to .
124 * @param target DOM node to .
123 */
125 */
124 export function emptyNode(target: Node) {
126 export function emptyNode(target: Node) {
125 registry.findWidgets(target).forEach(destroy);
127 registry.findWidgets(target).forEach(destroy);
126 dom.empty(target);
128 dom.empty(target);
127 }
129 }
128
130
129 /** This function starts all widgets inside the DOM node if the target is a node
131 /** This function starts all widgets inside the DOM node if the target is a node
130 * or starts widget itself if the target is the widget. If the specified node
132 * or starts widget itself if the target is the widget. If the specified node
131 * associated with the widget that widget will be started.
133 * associated with the widget that widget will be started.
132 *
134 *
133 * @param target DOM node to find and start widgets or the widget itself.
135 * @param target DOM node to find and start widgets or the widget itself.
134 */
136 */
135 export function startupWidgets(target: Node | _WidgetBase, skipNode?: Node) {
137 export function startupWidgets(target: Node | _WidgetBase, skipNode?: Node) {
136 if (isNode(target)) {
138 if (isNode(target)) {
137 const w = isElementNode(target) ? registry.byNode(target) : undefined;
139 if (isElementNode(target)) {
138 if (w) {
140 const w = registry.byNode(target);
139 if (w.startup)
141 if (w) {
140 w.startup();
142 if (w.startup)
141 } else {
143 w.startup();
142 registry.findWidgets(target, skipNode).forEach(x => x.startup());
144 } else {
145 registry.findWidgets(target, skipNode).forEach(x => x.startup());
146 }
143 }
147 }
144 } else {
148 } else {
145 if (target.startup)
149 if (target.startup)
146 target.startup();
150 target.startup();
147 }
151 }
148 }
152 }
@@ -1,70 +1,70
1 import { djbase, djclass, bind, prototype, AbstractConstructor } from "../declare";
1 import { djbase, djclass, bind, prototype, AbstractConstructor } from "../declare";
2
2
3 import { DjxWidgetBase } from "../tsx/DjxWidgetBase";
3 import { DjxWidgetBase } from "../tsx/DjxWidgetBase";
4 import { createElement, on } from "../tsx";
4 import { createElement, on } from "../tsx";
5
5
6 interface MyWidgetAttrs {
6 interface MyWidgetAttrs {
7 title: string;
7 title: string;
8
8
9 counter: number;
9 counter: number;
10 }
10 }
11
11
12 interface MyWidgetEvents {
12 interface MyWidgetEvents {
13 "count-inc": Event & {
13 "count-inc": Event & {
14 detail: number;
14 detail: number;
15 };
15 };
16
16
17 "count-dec": Event & {
17 "count-dec": Event & {
18 detail: number;
18 detail: number;
19 };
19 };
20 }
20 }
21
21
22
22
23 @djclass
23 @djclass
24 export class MyWidget extends djbase(DjxWidgetBase as AbstractConstructor<DjxWidgetBase<MyWidgetAttrs, MyWidgetEvents>>) {
24 export class MyWidget extends djbase(DjxWidgetBase as AbstractConstructor<DjxWidgetBase<MyWidgetAttrs, MyWidgetEvents>>) {
25
25
26 @bind({ node: "titleNode", type: "innerHTML" })
26 @bind({ node: "titleNode", type: "innerHTML" })
27 title = "";
27 title = "";
28
28
29 @prototype()
29 @prototype()
30 counter = 0;
30 counter = 0;
31
31
32 render() {
32 render() {
33 const Frame = (props: any) => <div>{props.children}</div>;
33 const Frame = (props: any) => <div>{props.children}</div>;
34 return <div className="myWidget" onsubmit={e => this._onSubmit(e)} tabIndex={3} style={{ alignContent: "center", border: "1px solid" }} >
34 return <div className="myWidget" onsubmit={e => this._onSubmit(e)} tabIndex={3} style={{ alignContent: "center", border: "1px solid" }} >
35 <h1 data-dojo-attach-point="titleNode"></h1>
35 <h1 data-dojo-attach-point="titleNode"></h1>
36 <Frame>
36 <Frame>
37 <span class="up-button" onclick={e => this._onIncClick(e)}>[+]</span>
37 <span class="up-button" onclick={e => this._onIncClick(e)}>[+]</span>
38 <span class="down-button" onclick={() => this._onDecClick()}>[-]</span>
38 <span class="down-button" onclick={() => this._onDecClick()}>[-]</span>
39 </Frame>
39 </Frame>
40 </div>;
40 </div>;
41 }
41 }
42
42
43 postCreate() {
43 postCreate() {
44 super.postCreate();
44 super.postCreate();
45
45
46 this.on("click", () => {});
46 this.on("click", () => {});
47 }
47 }
48
48
49 _onSubmit(e: Event) {
49 _onSubmit(e: Event) {
50 }
50 }
51
51
52 _onIncClick(e: MouseEvent) {
52 _onIncClick(e: MouseEvent) {
53 this.set("counter", this.counter + 1);
53 this.set("counter", this.counter + 1);
54
54
55 this.emit("count-inc", { bubbles: false });
55 this.emit("count-inc", { bubbles: false });
56 }
56 }
57
57
58 _onDecClick() {
58 _onDecClick() {
59 this.emit("count-dec", { bubbles: false, detail: this.counter });
59 this.emit("count-dec", { bubbles: false, detail: this.counter });
60 }
60 }
61
61
62 @on("count-inc")
62 @on("count-inc")
63 _onCounterInc(evt: Event & { detail: number; x?: number; }) {
63 private _onCounterInc(evt: Event & { detail: number; x?: number; }) {
64 }
64 }
65
65
66 @on("click", "keydown")
66 @on("click", "keydown")
67 protected _onClick(event: MouseEvent | KeyboardEvent) {
67 protected _onClick(event: MouseEvent | KeyboardEvent) {
68
68
69 }
69 }
70 } No newline at end of file
70 }
@@ -1,13 +1,14
1 {
1 {
2 "extends": "../tsconfig",
2 "extends": "../tsconfig",
3 "compilerOptions": {
3 "compilerOptions": {
4 "noUnusedLocals": false,
4 //"rootDir": "ts",
5 //"rootDir": "ts",
5 "rootDirs": [
6 "rootDirs": [
6 "ts",
7 "ts",
7 "typings",
8 "typings",
8 "../main/ts",
9 "../main/ts",
9 "../main/typings"
10 "../main/typings"
10 ],
11 ],
11 "types": ["requirejs", "../main/typings", "@implab/dojo-typings"]
12 "types": ["requirejs", "../main/typings", "@implab/dojo-typings"]
12 }
13 }
13 } No newline at end of file
14 }
General Comments 0
You need to be logged in to leave comments. Login now