##// END OF EJS Templates
@on decorator registers handlers directry on domNode, added support to multiple events in one decorator...
cin -
r85:35a7b6319ebe v1.2.6 default
parent child
Show More
@@ -1,113 +1,114
1 import { djbase, djclass } from "../declare";
1 import { djbase, djclass } from "../declare";
2 import _WidgetBase = require("dijit/_WidgetBase");
2 import _WidgetBase = require("dijit/_WidgetBase");
3 import _AttachMixin = require("dijit/_AttachMixin");
3 import _AttachMixin = require("dijit/_AttachMixin");
4 import { Rendition, isNode } from "./traits";
4 import { Rendition, isNode } from "./traits";
5 import registry = require("dijit/registry");
5 import registry = require("dijit/registry");
6 import on = require("dojo/on");
6
7
7 // type Handle = dojo.Handle;
8 // type Handle = dojo.Handle;
8
9
9 export interface EventArgs {
10 export interface EventArgs {
10 bubbles?: boolean;
11 bubbles?: boolean;
11
12
12 cancelable?: boolean;
13 cancelable?: boolean;
13
14
14 composed?: boolean;
15 composed?: boolean;
15 }
16 }
16
17
17 export interface DjxWidgetBase<Attrs = {}, Events extends { [name in keyof Events]: Event } = {}> extends
18 export interface DjxWidgetBase<Attrs = {}, Events extends { [name in keyof Events]: Event } = {}> extends
18 _WidgetBase<Events> {
19 _WidgetBase<Events> {
19
20
20 /** This property is declared only for type inference to work, it is never assigned
21 /** This property is declared only for type inference to work, it is never assigned
21 * and should not be used.
22 * and should not be used.
22 */
23 */
23 readonly _eventMap: Events & GlobalEventHandlersEventMap;
24 readonly _eventMap: Events & GlobalEventHandlersEventMap;
24
25
25 /** The list of pairs of event and method names. When the widget is created all methods from
26 /** The list of pairs of event and method names. When the widget is created all methods from
26 * this list will be connected to corresponding events.
27 * this list will be connected to corresponding events.
27 *
28 *
28 * This property is maintained in the prototype
29 * This property is maintained in the prototype
29 */
30 */
30 _eventHandlers: Array<{
31 _eventHandlers: Array<{
31 eventName: string,
32 eventName: string,
32 handlerMethod: keyof any;
33 handlerMethod: keyof any;
33 }>;
34 }>;
34 }
35 }
35
36
36 type _super = {
37 type _super = {
37 startup(): void;
38 startup(): void;
38 };
39 };
39
40
40 @djclass
41 @djclass
41 export abstract class DjxWidgetBase<Attrs = {}, Events = {}> extends djbase<_super, _AttachMixin>(_WidgetBase, _AttachMixin) {
42 export abstract class DjxWidgetBase<Attrs = {}, Events = {}> extends djbase<_super, _AttachMixin>(_WidgetBase, _AttachMixin) {
42
43
43 buildRendering() {
44 buildRendering() {
44 this.domNode = this.render().getDomNode();
45 this.domNode = this.render().getDomNode();
45 super.buildRendering();
46 super.buildRendering();
46
47
47 // now we should get assigned data-dojo-attach-points
48 // now we should get assigned data-dojo-attach-points
48 // place the contents of the original srcNode to the containerNode
49 // place the contents of the original srcNode to the containerNode
49 const src = this.srcNodeRef;
50 const src = this.srcNodeRef;
50 const dest = this.containerNode;
51 const dest = this.containerNode;
51
52
52 // the donNode is constructed now we need to connect event handlers
53 // the donNode is constructed now we need to connect event handlers
53 this._connectEventHandlers();
54 this._connectEventHandlers();
54
55
55 if (src && dest) {
56 if (src && dest) {
56 while (src.firstChild)
57 while (src.firstChild)
57 dest.appendChild(src.firstChild);
58 dest.appendChild(src.firstChild);
58 }
59 }
59 }
60 }
60
61
61 abstract render(): Rendition<HTMLElement>;
62 abstract render(): Rendition<HTMLElement>;
62
63
63 private _connectEventHandlers() {
64 private _connectEventHandlers() {
64 if (this._eventHandlers)
65 if (this._eventHandlers)
65 this._eventHandlers.forEach(({ eventName, handlerMethod }) => {
66 this._eventHandlers.forEach(({ eventName, handlerMethod }) => {
66 const handler = this[handlerMethod as keyof this];
67 const handler = this[handlerMethod as keyof this];
67 if (typeof handler === "function")
68 if (typeof handler === "function")
68 this.on(eventName, handler.bind(this));
69 on(this.domNode, eventName, handler.bind(this));
69 });
70 });
70 }
71 }
71
72
72 _processTemplateNode<T extends (Element | Node | _WidgetBase)>(
73 _processTemplateNode<T extends (Element | Node | _WidgetBase)>(
73 baseNode: T,
74 baseNode: T,
74 getAttrFunc: (baseNode: T, attr: string) => any,
75 getAttrFunc: (baseNode: T, attr: string) => any,
75 // tslint:disable-next-line: ban-types
76 // tslint:disable-next-line: ban-types
76 attachFunc: (node: T, type: string, func?: Function) => dojo.Handle
77 attachFunc: (node: T, type: string, func?: Function) => dojo.Handle
77 ): boolean {
78 ): boolean {
78 if (isNode(baseNode)) {
79 if (isNode(baseNode)) {
79 const w = registry.byNode(baseNode);
80 const w = registry.byNode(baseNode);
80 if (w) {
81 if (w) {
81 // from dijit/_WidgetsInTemplateMixin
82 // from dijit/_WidgetsInTemplateMixin
82 this._processTemplateNode(w,
83 this._processTemplateNode(w,
83 (n, p) => n.get(p as any), // callback to get a property of a widget
84 (n, p) => n.get(p as any), // callback to get a property of a widget
84 (widget, type, callback) => {
85 (widget, type, callback) => {
85 if (!callback)
86 if (!callback)
86 throw new Error("The callback must be specified");
87 throw new Error("The callback must be specified");
87
88
88 // callback to do data-dojo-attach-event to a widget
89 // callback to do data-dojo-attach-event to a widget
89 if (type in widget) {
90 if (type in widget) {
90 // back-compat, remove for 2.0
91 // back-compat, remove for 2.0
91 return widget.connect(widget, type, callback as EventListener);
92 return widget.connect(widget, type, callback as EventListener);
92 } else {
93 } else {
93 // 1.x may never hit this branch, but it's the default for 2.0
94 // 1.x may never hit this branch, but it's the default for 2.0
94 return widget.on(type, callback);
95 return widget.on(type, callback);
95 }
96 }
96
97
97 });
98 });
98 // don't process widgets internals
99 // don't process widgets internals
99 return false;
100 return false;
100 }
101 }
101 }
102 }
102 return super._processTemplateNode(baseNode, getAttrFunc, attachFunc);
103 return super._processTemplateNode(baseNode, getAttrFunc, attachFunc);
103 }
104 }
104
105
105 /** Starts current widget and all its supporting widgets (placed outside
106 /** Starts current widget and all its supporting widgets (placed outside
106 * `containerNode`) and child widgets (placed inside `containerNode`)
107 * `containerNode`) and child widgets (placed inside `containerNode`)
107 */
108 */
108 startup() {
109 startup() {
109 // startup supporting widgets
110 // startup supporting widgets
110 registry.findWidgets(this.domNode, this.containerNode).forEach(w => w.startup());
111 registry.findWidgets(this.domNode, this.containerNode).forEach(w => w.startup());
111 super.startup();
112 super.startup();
112 }
113 }
113 }
114 }
@@ -1,230 +1,228
1 import { IDestroyable, IRemovable } from "@implab/core-amd/interfaces";
1 import { IDestroyable, IRemovable } 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 import Stateful = require("dojo/Stateful");
6 import Stateful = require("dojo/Stateful");
7 import { FunctionRendition } from "./FunctionRendition";
7 import { FunctionRendition } from "./FunctionRendition";
8 import { DjxWidgetBase } from "./DjxWidgetBase";
8 import { DjxWidgetBase } from "./DjxWidgetBase";
9
9
10 type _WidgetBaseConstructor = typeof _WidgetBase;
10 type _WidgetBaseConstructor = typeof _WidgetBase;
11
11
12 export type DojoNodePosition = "first" | "after" | "before" | "last" | "replace" | "only" | number;
12 export type DojoNodePosition = "first" | "after" | "before" | "last" | "replace" | "only" | number;
13
13
14 export interface Rendition<TNode extends Node = Node> {
14 export interface Rendition<TNode extends Node = Node> {
15 getDomNode(): TNode;
15 getDomNode(): TNode;
16
16
17 placeAt(refNode: string | Node, position?: DojoNodePosition): void;
17 placeAt(refNode: string | Node, position?: DojoNodePosition): void;
18 }
18 }
19
19
20 /**
20 /**
21 * @deprecated use Rendition
21 * @deprecated use Rendition
22 */
22 */
23 export type BuildContext<TNode extends Node = Node> = Rendition<TNode>;
23 export type BuildContext<TNode extends Node = Node> = Rendition<TNode>;
24
24
25 export interface IRecursivelyDestroyable {
25 export interface IRecursivelyDestroyable {
26 destroyRecursive(): void;
26 destroyRecursive(): void;
27 }
27 }
28
28
29 export function isNode(el: any): el is Node {
29 export function isNode(el: any): el is Node {
30 return el && el.nodeName && el.nodeType;
30 return el && el.nodeName && el.nodeType;
31 }
31 }
32
32
33 export function isElementNode(el: any): el is Element {
33 export function isElementNode(el: any): el is Element {
34 return isNode(el) && el.nodeType === 1;
34 return isNode(el) && el.nodeType === 1;
35 }
35 }
36
36
37 export function isTextNode(el: any): el is Text {
37 export function isTextNode(el: any): el is Text {
38 return isNode(el) && el.nodeType === 3;
38 return isNode(el) && el.nodeType === 3;
39 }
39 }
40
40
41 export function isProcessingInstructionNode(el: any): el is ProcessingInstruction {
41 export function isProcessingInstructionNode(el: any): el is ProcessingInstruction {
42 return isNode(el) && el.nodeType === 7;
42 return isNode(el) && el.nodeType === 7;
43 }
43 }
44
44
45 export function isCommentNode(el: any): el is Comment {
45 export function isCommentNode(el: any): el is Comment {
46 return isNode(el) && el.nodeType === 8;
46 return isNode(el) && el.nodeType === 8;
47 }
47 }
48
48
49 export function isDocumentNode(el: any): el is Document {
49 export function isDocumentNode(el: any): el is Document {
50 return isNode(el) && el.nodeType === 9;
50 return isNode(el) && el.nodeType === 9;
51 }
51 }
52
52
53 export function isDocumentTypeNode(el: any): el is DocumentType {
53 export function isDocumentTypeNode(el: any): el is DocumentType {
54 return isNode(el) && el.nodeType === 10;
54 return isNode(el) && el.nodeType === 10;
55 }
55 }
56
56
57 export function isDocumentFragmentNode(el: any): el is DocumentFragment {
57 export function isDocumentFragmentNode(el: any): el is DocumentFragment {
58 return isNode(el) && el.nodeType === 11;
58 return isNode(el) && el.nodeType === 11;
59 }
59 }
60
60
61 export function isWidget(v: any): v is _WidgetBase {
61 export function isWidget(v: any): v is _WidgetBase {
62 return v && "domNode" in v;
62 return v && "domNode" in v;
63 }
63 }
64
64
65 export function isRendition(v: any): v is Rendition {
65 export function isRendition(v: any): v is Rendition {
66 return typeof v === "object" && typeof v.getDomElement === "function";
66 return typeof v && typeof v.getDomElement === "function";
67 }
67 }
68
68
69 /**
69 /**
70 * @deprecated use isRendition
70 * @deprecated use isRendition
71 */
71 */
72 export const isBuildContext = isRendition;
72 export const isBuildContext = isRendition;
73
73
74 export function isPlainObject(v: object) {
74 export function isPlainObject(v: object) {
75 if (typeof v !== "object")
75 if (typeof v !== "object")
76 return false;
76 return false;
77
77
78 const vp = Object.getPrototypeOf(v);
78 const vp = Object.getPrototypeOf(v);
79 return !vp || vp === Object.prototype;
79 return !vp || vp === Object.prototype;
80 }
80 }
81
81
82 export function isWidgetConstructor(v: any): v is _WidgetBaseConstructor {
82 export function isWidgetConstructor(v: any): v is _WidgetBaseConstructor {
83 return typeof v === "function" && v.prototype && (
83 return typeof v === "function" && v.prototype && (
84 "domNode" in v.prototype ||
84 "domNode" in v.prototype ||
85 "buildRendering" in v.prototype
85 "buildRendering" in v.prototype
86 );
86 );
87 }
87 }
88
88
89 /** Tests whether the specified node is placed in visible dom.
89 /** Tests whether the specified node is placed in visible dom.
90 * @param {Node} node The node to test
90 * @param {Node} node The node to test
91 */
91 */
92 export function isInPage(node: Node) {
92 export function isInPage(node: Node) {
93 return (node === document.body) ? false : document.body.contains(node);
93 return (node === document.body) ? false : document.body.contains(node);
94 }
94 }
95
95
96 export function isRecursivelyDestroyable(target: any): target is IRecursivelyDestroyable {
96 export function isRecursivelyDestroyable(target: any): target is IRecursivelyDestroyable {
97 return target && typeof target.destroyRecursive === "function";
97 return target && typeof target.destroyRecursive === "function";
98 }
98 }
99
99
100
100
101 /** Destroys DOM Node with all contained widgets.
101 /** Destroys DOM Node with all contained widgets.
102 * If the specified node is the root node of a widget, then the
102 * If the specified node is the root node of a widget, then the
103 * widget will be destroyed.
103 * widget will be destroyed.
104 *
104 *
105 * @param target DOM Node or widget to destroy
105 * @param target DOM Node or widget to destroy
106 */
106 */
107 export function destroy(target: Node | IDestroyable | IRecursivelyDestroyable) {
107 export function destroy(target: Node | IDestroyable | IRecursivelyDestroyable) {
108 if (isRecursivelyDestroyable(target)) {
108 if (isRecursivelyDestroyable(target)) {
109 target.destroyRecursive();
109 target.destroyRecursive();
110 } else if (isDestroyable(target)) {
110 } else if (isDestroyable(target)) {
111 target.destroy();
111 target.destroy();
112 } else if (isNode(target)) {
112 } else if (isNode(target)) {
113 const w = isElementNode(target) ? registry.byNode(target) : undefined;
113 const w = isElementNode(target) ? registry.byNode(target) : undefined;
114 if (w) {
114 if (w) {
115 w.destroyRecursive();
115 w.destroyRecursive();
116 } else {
116 } else {
117 registry.findWidgets(target).forEach(destroy);
117 registry.findWidgets(target).forEach(destroy);
118 dom.destroy(target);
118 dom.destroy(target);
119 }
119 }
120 }
120 }
121 }
121 }
122
122
123 /** Empties a content of the specified node and destroys all contained widgets.
123 /** Empties a content of the specified node and destroys all contained widgets.
124 *
124 *
125 * @param target DOM node to .
125 * @param target DOM node to .
126 */
126 */
127 export function emptyNode(target: Node) {
127 export function emptyNode(target: Node) {
128 registry.findWidgets(target).forEach(destroy);
128 registry.findWidgets(target).forEach(destroy);
129 dom.empty(target);
129 dom.empty(target);
130 }
130 }
131
131
132 /** This function starts all widgets inside the DOM node if the target is a node
132 /** This function starts all widgets inside the DOM node if the target is a node
133 * or starts widget itself if the target is the widget. If the specified node
133 * or starts widget itself if the target is the widget. If the specified node
134 * associated with the widget that widget will be started.
134 * associated with the widget that widget will be started.
135 *
135 *
136 * @param target DOM node to find and start widgets or the widget itself.
136 * @param target DOM node to find and start widgets or the widget itself.
137 */
137 */
138 export function startupWidgets(target: Node | _WidgetBase, skipNode?: Node) {
138 export function startupWidgets(target: Node | _WidgetBase, skipNode?: Node) {
139 if (isNode(target)) {
139 if (isNode(target)) {
140 const w = isElementNode(target) ? registry.byNode(target) : undefined;
140 const w = isElementNode(target) ? registry.byNode(target) : undefined;
141 if (w) {
141 if (w) {
142 if (w.startup)
142 if (w.startup)
143 w.startup();
143 w.startup();
144 } else {
144 } else {
145 registry.findWidgets(target, skipNode).forEach(x => x.startup());
145 registry.findWidgets(target, skipNode).forEach(x => x.startup());
146 }
146 }
147 } else {
147 } else {
148 if (target.startup)
148 if (target.startup)
149 target.startup();
149 target.startup();
150 }
150 }
151 }
151 }
152
152
153
153
154 type StatefulProps<T> = T extends Stateful<infer A> ? A : never;
154 type StatefulProps<T> = T extends Stateful<infer A> ? A : never;
155
155
156 type CleanFn = (instance: IRemovable | IDestroyable) => void;
156 type CleanFn = (instance: IRemovable | IDestroyable) => void;
157
157
158 /**
158 /**
159 * Observers the property and calls render callback each change.
159 * Observers the property and calls render callback each change.
160 *
160 *
161 * @param target The target object which property will be observed.
161 * @param target The target object which property will be observed.
162 * @param prop The name of the property.
162 * @param prop The name of the property.
163 * @param render The callback which will be called every time the value is changed
163 * @param render The callback which will be called every time the value is changed
164 * @param cleanupOrOwner The object with method `own` or an callback to register lifecycle for the observer.
164 * @param cleanupOrOwner The object with method `own` or an callback to register lifecycle for the observer.
165 * @returns Rendition which is created instantly
165 * @returns Rendition which is created instantly
166 */
166 */
167 export function watch<W extends _WidgetBase, K extends keyof W>(
167 export function watch<W extends _WidgetBase, K extends keyof W>(
168 target: W,
168 target: W,
169 prop: K,
169 prop: K,
170 render: (model: W[K]) => any,
170 render: (model: W[K]) => any,
171 cleanupOrOwner?: { own: CleanFn } | CleanFn
171 cleanupOrOwner?: { own: CleanFn } | CleanFn
172 ): Rendition;
172 ): Rendition;
173 /**
173 /**
174 * Observers the property and calls render callback each change.
174 * Observers the property and calls render callback each change.
175 *
175 *
176 * @param target The target object which property will be observed.
176 * @param target The target object which property will be observed.
177 * @param prop The name of the property.
177 * @param prop The name of the property.
178 * @param render The callback which will be called every time the value is changed
178 * @param render The callback which will be called every time the value is changed
179 * @param cleanupOrOwner The object with method `own` or an callback to register lifecycle for the observer.
179 * @param cleanupOrOwner The object with method `own` or an callback to register lifecycle for the observer.
180 * @returns Rendition which is created instantly
180 * @returns Rendition which is created instantly
181 */
181 */
182 export function watch<T extends Stateful, K extends keyof StatefulProps<T>>(
182 export function watch<T extends Stateful, K extends keyof StatefulProps<T>>(
183 target: T,
183 target: T,
184 prop: K,
184 prop: K,
185 render: (model: StatefulProps<T>[K]) => any,
185 render: (model: StatefulProps<T>[K]) => any,
186 cleanupOrOwner?: { own: CleanFn } | CleanFn
186 cleanupOrOwner?: { own: CleanFn } | CleanFn
187 ): Rendition;
187 ): Rendition;
188 export function watch<T extends Stateful, K extends keyof StatefulProps<T> & string>(
188 export function watch<T extends Stateful, K extends keyof StatefulProps<T> & string>(
189 target: T,
189 target: T,
190 prop: K,
190 prop: K,
191 render: (model: StatefulProps<T>[K]) => any,
191 render: (model: StatefulProps<T>[K]) => any,
192 cleanupOrOwner: { own: CleanFn } | CleanFn = () => { }
192 cleanupOrOwner: { own: CleanFn } | CleanFn = () => { }
193 ) {
193 ) {
194 let rendition = new FunctionRendition(() => render(target.get(prop)));
194 let rendition = new FunctionRendition(() => render(target.get(prop)));
195 const _own = cleanupOrOwner instanceof Function ? cleanupOrOwner : (x: IRemovable) => cleanupOrOwner.own(x);
195 const _own = cleanupOrOwner instanceof Function ? cleanupOrOwner : (x: IRemovable) => cleanupOrOwner.own(x);
196 _own(target.watch(prop, (_name, oldValue, newValue) => {
196 _own(target.watch(prop, (_name, oldValue, newValue) => {
197 if (oldValue !== newValue) {
197 if (oldValue !== newValue) {
198 const newRendition = new FunctionRendition(() => render(newValue));
198 const newRendition = new FunctionRendition(() => render(newValue));
199 newRendition.placeAt(rendition.getDomNode(), "replace");
199 newRendition.placeAt(rendition.getDomNode(), "replace");
200 destroy(rendition.getDomNode());
200 destroy(rendition.getDomNode());
201 rendition = newRendition;
201 rendition = newRendition;
202 }
202 }
203 }));
203 }));
204 return rendition;
204 return rendition;
205 }
205 }
206
206
207 /** Decorates the method which will be registered as the handle for the specified event.
207 /** Decorates the method which will be registered as the handle for the specified event.
208 * This decorator can be applied to DjxWidgetBase subclass methods.
208 * This decorator can be applied to DjxWidgetBase subclass methods.
209 *
209 *
210 * ```
210 * ```
211 * @on("click")
211 * @on("click")
212 * _onClick(eventObj: MouseEvent) {
212 * _onClick(eventObj: MouseEvent) {
213 * // ...
213 * // ...
214 * }
214 * }
215 * ```
215 * ```
216 */
216 */
217 export const on = <E extends string>(eventName: E) =>
217 export const on = <E extends string>(...eventNames: E[]) =>
218 <K extends string,
218 <K extends string,
219 T extends DjxWidgetBase<any, { [p in E]: EV }>,
219 T extends DjxWidgetBase<any, { [p in E]: EV }>,
220 EV extends Event
220 EV extends Event
221 >(
221 >(
222 target: T,
222 target: T,
223 key: K,
223 key: K,
224 _descriptor: TypedPropertyDescriptor<(eventObj: EV) => void> | TypedPropertyDescriptor<() => void>
224 _descriptor: TypedPropertyDescriptor<(eventObj: EV) => void> | TypedPropertyDescriptor<() => void>
225 ): any => {
225 ): any => {
226 if(!target._eventHandlers)
226 const handlers = eventNames.map(eventName => ({ eventName, handlerMethod: key }))
227 target._eventHandlers = [{ eventName, handlerMethod: key }];
227 target._eventHandlers = target._eventHandlers ? target._eventHandlers.concat(handlers) : handlers;
228 else
229 target._eventHandlers.push({ eventName, handlerMethod: key });
230 };
228 };
@@ -1,71 +1,71
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 } from "../tsx";
4 import { createElement } from "../tsx";
5 import { on } from "../tsx/traits";
5 import { on } from "../tsx/traits";
6
6
7 interface MyWidgetAttrs {
7 interface MyWidgetAttrs {
8 title: string;
8 title: string;
9
9
10 counter: number;
10 counter: number;
11 }
11 }
12
12
13 interface MyWidgetEvents {
13 interface MyWidgetEvents {
14 "count-inc": Event & {
14 "count-inc": Event & {
15 detail: number;
15 detail: number;
16 };
16 };
17
17
18 "count-dec": Event & {
18 "count-dec": Event & {
19 detail: number;
19 detail: number;
20 };
20 };
21 }
21 }
22
22
23
23
24 @djclass
24 @djclass
25 export class MyWidget extends djbase(DjxWidgetBase as AbstractConstructor<DjxWidgetBase<MyWidgetAttrs, MyWidgetEvents>>) {
25 export class MyWidget extends djbase(DjxWidgetBase as AbstractConstructor<DjxWidgetBase<MyWidgetAttrs, MyWidgetEvents>>) {
26
26
27 @bind({ node: "titleNode", type: "innerHTML" })
27 @bind({ node: "titleNode", type: "innerHTML" })
28 title = "";
28 title = "";
29
29
30 @prototype()
30 @prototype()
31 counter = 0;
31 counter = 0;
32
32
33 render() {
33 render() {
34 const Frame = (props: any) => <div>{props.children}</div>;
34 const Frame = (props: any) => <div>{props.children}</div>;
35 return <div className="myWidget" onsubmit={e => this._onSubmit(e)} tabIndex={3} style={{ alignContent: "center", border: "1px solid" }} >
35 return <div className="myWidget" onsubmit={e => this._onSubmit(e)} tabIndex={3} style={{ alignContent: "center", border: "1px solid" }} >
36 <h1 data-dojo-attach-point="titleNode"></h1>
36 <h1 data-dojo-attach-point="titleNode"></h1>
37 <Frame>
37 <Frame>
38 <span class="up-button" onclick={e => this._onIncClick(e)}>[+]</span>
38 <span class="up-button" onclick={e => this._onIncClick(e)}>[+]</span>
39 <span class="down-button" onclick={() => this._onDecClick()}>[-]</span>
39 <span class="down-button" onclick={() => this._onDecClick()}>[-]</span>
40 </Frame>
40 </Frame>
41 </div>;
41 </div>;
42 }
42 }
43
43
44 postCreate() {
44 postCreate() {
45 super.postCreate();
45 super.postCreate();
46
46
47 this.on("click", () => {});
47 this.on("click", () => {});
48 }
48 }
49
49
50 _onSubmit(e: Event) {
50 _onSubmit(e: Event) {
51 }
51 }
52
52
53 _onIncClick(e: MouseEvent) {
53 _onIncClick(e: MouseEvent) {
54 this.set("counter", this.counter + 1);
54 this.set("counter", this.counter + 1);
55
55
56 this.emit("count-inc", { bubbles: false });
56 this.emit("count-inc", { bubbles: false });
57 }
57 }
58
58
59 _onDecClick() {
59 _onDecClick() {
60 this.emit("count-dec", { bubbles: false, detail: this.counter });
60 this.emit("count-dec", { bubbles: false, detail: this.counter });
61 }
61 }
62
62
63 @on("count-inc")
63 @on("count-inc")
64 _onCounterInc(evt: Event & { detail: number; x?: number; }) {
64 _onCounterInc(evt: Event & { detail: number; x?: number; }) {
65 }
65 }
66
66
67 @on("click")
67 @on("click", "keydown")
68 protected _onClick() {
68 protected _onClick(event: MouseEvent | KeyboardEvent) {
69
69
70 }
70 }
71 } No newline at end of file
71 }
General Comments 0
You need to be logged in to leave comments. Login now