@@ -1,8 +1,11 | |||
|
1 | import { Constructor } from "@implab/core-amd/interfaces"; | |
|
1 | import { Constructor, IDestroyable, IRemovable } from "@implab/core-amd/interfaces"; | |
|
2 | 2 | import { HtmlRendition } from "./tsx/HtmlRendition"; |
|
3 | 3 | import { WidgetRendition } from "./tsx/WidgetRendition"; |
|
4 | import { isWidgetConstructor, Rendition } from "./tsx/traits"; | |
|
4 | import { destroy, isWidgetConstructor, Rendition } from "./tsx/traits"; | |
|
5 | 5 | import { FunctionRendition } from "./tsx/FunctionRendition"; |
|
6 | import Stateful = require("dojo/Stateful"); | |
|
7 | import _WidgetBase = require("dijit/_WidgetBase"); | |
|
8 | import { DjxWidgetBase } from "./tsx/DjxWidgetBase"; | |
|
6 | 9 | |
|
7 | 10 | export function createElement<T extends Constructor | string | ((props: any) => Element)>(elementType: T, ...args: any[]): Rendition { |
|
8 | 11 | if (typeof elementType === "string") { |
@@ -38,3 +41,79 export interface EventSelector { | |||
|
38 | 41 | } |
|
39 | 42 | |
|
40 | 43 | export type DojoMouseEvent<T = any> = MouseEvent & EventSelector & EventDetails<T>; |
|
44 | ||
|
45 | type StatefulProps<T> = T extends Stateful<infer A> ? A : never; | |
|
46 | ||
|
47 | type CleanFn = (instance: IRemovable | IDestroyable) => void; | |
|
48 | ||
|
49 | /** | |
|
50 | * Observers the property and calls render callback each change. | |
|
51 | * | |
|
52 | * @param target The target object which property will be observed. | |
|
53 | * @param prop The name of the property. | |
|
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. | |
|
56 | * @returns Rendition which is created instantly | |
|
57 | */ | |
|
58 | export function watch<W extends _WidgetBase, K extends keyof W>( | |
|
59 | target: W, | |
|
60 | prop: K, | |
|
61 | render: (model: W[K]) => any, | |
|
62 | cleanupOrOwner?: { own: CleanFn } | CleanFn | |
|
63 | ): Rendition; | |
|
64 | /** | |
|
65 | * Observers the property and calls render callback each change. | |
|
66 | * | |
|
67 | * @param target The target object which property will be observed. | |
|
68 | * @param prop The name of the property. | |
|
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. | |
|
71 | * @returns Rendition which is created instantly | |
|
72 | */ | |
|
73 | export function watch<T extends Stateful, K extends keyof StatefulProps<T>>( | |
|
74 | target: T, | |
|
75 | prop: K, | |
|
76 | render: (model: StatefulProps<T>[K]) => any, | |
|
77 | cleanupOrOwner?: { own: CleanFn } | CleanFn | |
|
78 | ): Rendition; | |
|
79 | export function watch<T extends Stateful, K extends keyof StatefulProps<T> & string>( | |
|
80 | target: T, | |
|
81 | prop: K, | |
|
82 | render: (model: StatefulProps<T>[K]) => any, | |
|
83 | cleanupOrOwner: { own: CleanFn } | CleanFn = () => { } | |
|
84 | ) { | |
|
85 | let rendition = new FunctionRendition(() => render(target.get(prop))); | |
|
86 | const _own = cleanupOrOwner instanceof Function ? cleanupOrOwner : (x: IRemovable) => cleanupOrOwner.own(x); | |
|
87 | _own(target.watch(prop, (_name, oldValue, newValue) => { | |
|
88 | if (oldValue !== newValue) { | |
|
89 | const newRendition = new FunctionRendition(() => render(newValue)); | |
|
90 | newRendition.placeAt(rendition.getDomNode(), "replace"); | |
|
91 | destroy(rendition.getDomNode()); | |
|
92 | rendition = newRendition; | |
|
93 | } | |
|
94 | })); | |
|
95 | return rendition; | |
|
96 | } | |
|
97 | ||
|
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. | |
|
100 | * | |
|
101 | * ``` | |
|
102 | * @on("click") | |
|
103 | * _onClick(eventObj: MouseEvent) { | |
|
104 | * // ... | |
|
105 | * } | |
|
106 | * ``` | |
|
107 | */ | |
|
108 | export const on = <E extends string>(...eventNames: E[]) => | |
|
109 | <K extends string, | |
|
110 | T extends DjxWidgetBase<any, { [p in E]: EV }>, | |
|
111 | EV extends Event | |
|
112 | >( | |
|
113 | target: T, | |
|
114 | key: K, | |
|
115 | _descriptor: TypedPropertyDescriptor<(eventObj: EV) => void> | TypedPropertyDescriptor<() => void> | |
|
116 | ): any => { | |
|
117 | const handlers = eventNames.map(eventName => ({ eventName, handlerMethod: key })) | |
|
118 | target._eventHandlers = target._eventHandlers ? target._eventHandlers.concat(handlers) : handlers; | |
|
119 | }; |
@@ -1,11 +1,8 | |||
|
1 |
import { IDestroyable |
|
|
1 | import { IDestroyable } from "@implab/core-amd/interfaces"; | |
|
2 | 2 | import { isDestroyable } from "@implab/core-amd/safe"; |
|
3 | 3 | import _WidgetBase = require("dijit/_WidgetBase"); |
|
4 | 4 | import registry = require("dijit/registry"); |
|
5 | 5 | import dom = require("dojo/dom-construct"); |
|
6 | import Stateful = require("dojo/Stateful"); | |
|
7 | import { FunctionRendition } from "./FunctionRendition"; | |
|
8 | import { DjxWidgetBase } from "./DjxWidgetBase"; | |
|
9 | 6 | |
|
10 | 7 | type _WidgetBaseConstructor = typeof _WidgetBase; |
|
11 | 8 | |
@@ -149,80 +146,3 export function startupWidgets(target: N | |||
|
149 | 146 | target.startup(); |
|
150 | 147 | } |
|
151 | 148 | } |
|
152 | ||
|
153 | ||
|
154 | type StatefulProps<T> = T extends Stateful<infer A> ? A : never; | |
|
155 | ||
|
156 | type CleanFn = (instance: IRemovable | IDestroyable) => void; | |
|
157 | ||
|
158 | /** | |
|
159 | * Observers the property and calls render callback each change. | |
|
160 | * | |
|
161 | * @param target The target object which property will be observed. | |
|
162 | * @param prop The name of the property. | |
|
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. | |
|
165 | * @returns Rendition which is created instantly | |
|
166 | */ | |
|
167 | export function watch<W extends _WidgetBase, K extends keyof W>( | |
|
168 | target: W, | |
|
169 | prop: K, | |
|
170 | render: (model: W[K]) => any, | |
|
171 | cleanupOrOwner?: { own: CleanFn } | CleanFn | |
|
172 | ): Rendition; | |
|
173 | /** | |
|
174 | * Observers the property and calls render callback each change. | |
|
175 | * | |
|
176 | * @param target The target object which property will be observed. | |
|
177 | * @param prop The name of the property. | |
|
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. | |
|
180 | * @returns Rendition which is created instantly | |
|
181 | */ | |
|
182 | export function watch<T extends Stateful, K extends keyof StatefulProps<T>>( | |
|
183 | target: T, | |
|
184 | prop: K, | |
|
185 | render: (model: StatefulProps<T>[K]) => any, | |
|
186 | cleanupOrOwner?: { own: CleanFn } | CleanFn | |
|
187 | ): Rendition; | |
|
188 | export function watch<T extends Stateful, K extends keyof StatefulProps<T> & string>( | |
|
189 | target: T, | |
|
190 | prop: K, | |
|
191 | render: (model: StatefulProps<T>[K]) => any, | |
|
192 | cleanupOrOwner: { own: CleanFn } | CleanFn = () => { } | |
|
193 | ) { | |
|
194 | let rendition = new FunctionRendition(() => render(target.get(prop))); | |
|
195 | const _own = cleanupOrOwner instanceof Function ? cleanupOrOwner : (x: IRemovable) => cleanupOrOwner.own(x); | |
|
196 | _own(target.watch(prop, (_name, oldValue, newValue) => { | |
|
197 | if (oldValue !== newValue) { | |
|
198 | const newRendition = new FunctionRendition(() => render(newValue)); | |
|
199 | newRendition.placeAt(rendition.getDomNode(), "replace"); | |
|
200 | destroy(rendition.getDomNode()); | |
|
201 | rendition = newRendition; | |
|
202 | } | |
|
203 | })); | |
|
204 | return rendition; | |
|
205 | } | |
|
206 | ||
|
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. | |
|
209 | * | |
|
210 | * ``` | |
|
211 | * @on("click") | |
|
212 | * _onClick(eventObj: MouseEvent) { | |
|
213 | * // ... | |
|
214 | * } | |
|
215 | * ``` | |
|
216 | */ | |
|
217 | export const on = <E extends string>(...eventNames: E[]) => | |
|
218 | <K extends string, | |
|
219 | T extends DjxWidgetBase<any, { [p in E]: EV }>, | |
|
220 | EV extends Event | |
|
221 | >( | |
|
222 | target: T, | |
|
223 | key: K, | |
|
224 | _descriptor: TypedPropertyDescriptor<(eventObj: EV) => void> | TypedPropertyDescriptor<() => void> | |
|
225 | ): any => { | |
|
226 | const handlers = eventNames.map(eventName => ({ eventName, handlerMethod: key })) | |
|
227 | target._eventHandlers = target._eventHandlers ? target._eventHandlers.concat(handlers) : handlers; | |
|
228 | }; |
@@ -1,8 +1,7 | |||
|
1 | 1 | import { djbase, djclass, bind, prototype, AbstractConstructor } from "../declare"; |
|
2 | 2 | |
|
3 | 3 | import { DjxWidgetBase } from "../tsx/DjxWidgetBase"; |
|
4 | import { createElement } from "../tsx"; | |
|
5 | import { on } from "../tsx/traits"; | |
|
4 | import { createElement, on } from "../tsx"; | |
|
6 | 5 | |
|
7 | 6 | interface MyWidgetAttrs { |
|
8 | 7 | title: string; |
General Comments 0
You need to be logged in to leave comments.
Login now