##// END OF EJS Templates
linting
cin -
r108:d644dced936e default
parent child
Show More

The requested changes are too big and content was truncated. Show full diff

@@ -1,33 +1,35
1 {
1 {
2 "root": true,
2 "root": true,
3 "extends": [
3 "extends": [
4 "plugin:react/recommended",
4 "plugin:react/recommended",
5 "eslint:recommended",
5 "eslint:recommended",
6 "plugin:@typescript-eslint/eslint-recommended",
6 "plugin:@typescript-eslint/eslint-recommended",
7 "plugin:@typescript-eslint/recommended",
7 "plugin:@typescript-eslint/recommended",
8 "plugin:@typescript-eslint/recommended-requiring-type-checking"
8 "plugin:@typescript-eslint/recommended-requiring-type-checking"
9 ],
9 ],
10 "parser": "@typescript-eslint/parser",
10 "parser": "@typescript-eslint/parser",
11 "parserOptions": {
11 "parserOptions": {
12 "ecmaFeatures": {
12 "ecmaFeatures": {
13 "jsx": true
13 "jsx": true
14 },
14 },
15 "ecmaVersion": 5,
15 "ecmaVersion": 5,
16 "tsconfigRootDir": "djx/src",
16 "tsconfigRootDir": "djx/src",
17 "project": ["tsconfig.eslint.json", "*/tsconfig.json"]
17 "project": ["tsconfig.eslint.json", "*/tsconfig.json"]
18 },
18 },
19 "plugins": [
19 "plugins": [
20 "@typescript-eslint"
20 "@typescript-eslint"
21 ],
21 ],
22 "rules": {
22 "rules": {
23 "react/react-in-jsx-scope": "off",
24 "react/no-unknown-property": "off",
23 "@typescript-eslint/no-empty-function": "off",
25 "@typescript-eslint/no-empty-function": "off",
24 "max-classes-per-file": [
26 "max-classes-per-file": [
25 "error",
27 "error",
26 { "ignoreExpressions": true, "max": 1 }
28 { "ignoreExpressions": true, "max": 1 }
27 ],
29 ],
28 "@typescript-eslint/prefer-readonly": ["error"],
30 "@typescript-eslint/prefer-readonly": ["error"],
29 "semi": "off",
31 "semi": "off",
30 "@typescript-eslint/semi": ["error"]
32 "@typescript-eslint/semi": ["error"]
31
33
32 }
34 }
33 }
35 }
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
@@ -1,258 +1,254
1 import declare = require("dojo/_base/declare");
1 import declare = require("dojo/_base/declare");
2 import { each } from "@implab/core-amd/safe";
2 import { each } from "@implab/core-amd/safe";
3 import { Constructor } from "@implab/core-amd/interfaces";
3 import { Constructor } from "@implab/core-amd/interfaces";
4
4
5 // declare const declare: any;
5 // declare const declare: any;
6
6
7 type DeclareConstructor<T> = dojo._base.DeclareConstructor<T>;
7 type DeclareConstructor<T> = dojo._base.DeclareConstructor<T>;
8
8
9 export interface AbstractConstructor<T = object> {
9 export interface AbstractConstructor<T = object> {
10 prototype: T;
10 prototype: T;
11 }
11 }
12
12
13 interface DjMockConstructor<T = object> {
13 interface DjMockConstructor<T = object> {
14 new(...args: unknown[]): T;
14 new(...args: unknown[]): T;
15 mock: boolean;
15 mock: boolean;
16 bases: AbstractConstructor[];
16 bases: AbstractConstructor[];
17 }
17 }
18
18
19 export function djbase<T>(): DeclareConstructor<T>;
19 export function djbase<T>(): DeclareConstructor<T>;
20 export function djbase<T>(
20 export function djbase<T>(
21 b0: AbstractConstructor<T>
21 b0: AbstractConstructor<T>
22 ): DeclareConstructor<T>;
22 ): DeclareConstructor<T>;
23
23
24 export function djbase<T0, T1>(
24 export function djbase<T0, T1>(
25 b0: AbstractConstructor<T0>,
25 b0: AbstractConstructor<T0>,
26 b1: AbstractConstructor<T1>
26 b1: AbstractConstructor<T1>
27 ): DeclareConstructor<T0 & T1>;
27 ): DeclareConstructor<T0 & T1>;
28
28
29 export function djbase<T0, T1, T2>(
29 export function djbase<T0, T1, T2>(
30 b0: AbstractConstructor<T0>,
30 b0: AbstractConstructor<T0>,
31 b1: AbstractConstructor<T1>,
31 b1: AbstractConstructor<T1>,
32 b2: AbstractConstructor<T2>
32 b2: AbstractConstructor<T2>
33 ): DeclareConstructor<T0 & T1 & T2>;
33 ): DeclareConstructor<T0 & T1 & T2>;
34
34
35 export function djbase<T0, T1, T2, T3>(
35 export function djbase<T0, T1, T2, T3>(
36 b0: AbstractConstructor<T0>,
36 b0: AbstractConstructor<T0>,
37 b1: AbstractConstructor<T1>,
37 b1: AbstractConstructor<T1>,
38 b2: AbstractConstructor<T2>,
38 b2: AbstractConstructor<T2>,
39 b3: AbstractConstructor<T3>
39 b3: AbstractConstructor<T3>
40 ): DeclareConstructor<T0 & T1 & T2 & T3>;
40 ): DeclareConstructor<T0 & T1 & T2 & T3>;
41
41
42 export function djbase<T0, T1, T2, T3, T4>(
42 export function djbase<T0, T1, T2, T3, T4>(
43 b0: AbstractConstructor<T0>,
43 b0: AbstractConstructor<T0>,
44 b1: AbstractConstructor<T1>,
44 b1: AbstractConstructor<T1>,
45 b2: AbstractConstructor<T2>,
45 b2: AbstractConstructor<T2>,
46 b3: AbstractConstructor<T3>,
46 b3: AbstractConstructor<T3>,
47 b4: AbstractConstructor<T4>
47 b4: AbstractConstructor<T4>
48 ): DeclareConstructor<T0 & T1 & T2 & T3 & T4>;
48 ): DeclareConstructor<T0 & T1 & T2 & T3 & T4>;
49
49
50 export function djbase<T0, T1, T2, T3, T4, T5>(
50 export function djbase<T0, T1, T2, T3, T4, T5>(
51 b0: AbstractConstructor<T0>,
51 b0: AbstractConstructor<T0>,
52 b1: AbstractConstructor<T1>,
52 b1: AbstractConstructor<T1>,
53 b2: AbstractConstructor<T2>,
53 b2: AbstractConstructor<T2>,
54 b3: AbstractConstructor<T3>,
54 b3: AbstractConstructor<T3>,
55 b4: AbstractConstructor<T4>,
55 b4: AbstractConstructor<T4>,
56 b5: AbstractConstructor<T5>
56 b5: AbstractConstructor<T5>
57 ): DeclareConstructor<T0 & T1 & T2 & T3 & T4 & T5>;
57 ): DeclareConstructor<T0 & T1 & T2 & T3 & T4 & T5>;
58
58
59 export function djbase<T0, T1, T2, T3, T4, T5, T6>(
59 export function djbase<T0, T1, T2, T3, T4, T5, T6>(
60 b0: AbstractConstructor<T0>,
60 b0: AbstractConstructor<T0>,
61 b1: AbstractConstructor<T1>,
61 b1: AbstractConstructor<T1>,
62 b2: AbstractConstructor<T2>,
62 b2: AbstractConstructor<T2>,
63 b3: AbstractConstructor<T3>,
63 b3: AbstractConstructor<T3>,
64 b4: AbstractConstructor<T4>,
64 b4: AbstractConstructor<T4>,
65 b5: AbstractConstructor<T5>,
65 b5: AbstractConstructor<T5>,
66 b6: AbstractConstructor<T6>
66 b6: AbstractConstructor<T6>
67 ): DeclareConstructor<T0 & T1 & T2 & T3 & T4 & T5 & T6>;
67 ): DeclareConstructor<T0 & T1 & T2 & T3 & T4 & T5 & T6>;
68
68
69 export function djbase<T0, T1, T2, T3, T4, T5, T6, T7>(
69 export function djbase<T0, T1, T2, T3, T4, T5, T6, T7>(
70 b0: AbstractConstructor<T0>,
70 b0: AbstractConstructor<T0>,
71 b1: AbstractConstructor<T1>,
71 b1: AbstractConstructor<T1>,
72 b2: AbstractConstructor<T2>,
72 b2: AbstractConstructor<T2>,
73 b3: AbstractConstructor<T3>,
73 b3: AbstractConstructor<T3>,
74 b4: AbstractConstructor<T4>,
74 b4: AbstractConstructor<T4>,
75 b5: AbstractConstructor<T5>,
75 b5: AbstractConstructor<T5>,
76 b6: AbstractConstructor<T6>,
76 b6: AbstractConstructor<T6>,
77 b7: AbstractConstructor<T7>
77 b7: AbstractConstructor<T7>
78 ): DeclareConstructor<T0 & T1 & T2 & T3 & T4 & T5 & T6 & T7>;
78 ): DeclareConstructor<T0 & T1 & T2 & T3 & T4 & T5 & T6 & T7>;
79
79
80 /** Создает конструктор-заглушку из списка базовых классов, используется
80 /** Создает конструктор-заглушку из списка базовых классов, используется
81 * для объявления классов при помощи `dojo/_base/declare`.
81 * для объявления классов при помощи `dojo/_base/declare`.
82 *
82 *
83 * Создает пустой конструктор, с пустым стандартным прототипом, это нужно,
83 * Создает пустой конструктор, с пустым стандартным прототипом, это нужно,
84 * поскольку в унаследованном классе конструктор обязательно должен вызвать
84 * поскольку в унаследованном классе конструктор обязательно должен вызвать
85 * `super(...)`, таким образом он вызовет пустую функцию.
85 * `super(...)`, таким образом он вызовет пустую функцию.
86 *
86 *
87 * Созданный конструктор хранит в себе список базовых классов, который будет
87 * Созданный конструктор хранит в себе список базовых классов, который будет
88 * использован декоратором `djclass`, который вернет класс, объявленный при
88 * использован декоратором `djclass`, который вернет класс, объявленный при
89 * помощи `dojo/_base/declare`.
89 * помощи `dojo/_base/declare`.
90 *
90 *
91 * @param bases список базовых классов, от которых требуется унаследовать
91 * @param bases список базовых классов, от которых требуется унаследовать
92 * новый класс.
92 * новый класс.
93 *
93 *
94 */
94 */
95 export function djbase(...bases: AbstractConstructor[]): Constructor {
95 export function djbase(...bases: AbstractConstructor[]): Constructor {
96
96
97 const t = class {
97 const t = class {
98 static mock: boolean;
98 static mock: boolean;
99 static bases: AbstractConstructor[];
99 static bases: AbstractConstructor[];
100 };
100 };
101
101
102 t.mock = true;
102 t.mock = true;
103 t.bases = bases;
103 t.bases = bases;
104
104
105 return t as Constructor;
105 return t as Constructor;
106 }
106 }
107
107
108 function isMockConstructor<T extends object>(v: AbstractConstructor<T>): v is DjMockConstructor<T> {
108 function isMockConstructor<T extends object>(v: AbstractConstructor<T>): v is DjMockConstructor<T> {
109 return v && "mock" in v;
109 return v && "mock" in v;
110 }
110 }
111
111
112 /** Создает класс при помощи `dojo/_base/declare`. Для этого исходный класс
112 /** Создает класс при помощи `dojo/_base/declare`. Для этого исходный класс
113 * должен быть унаследован от `djbase(...)`.
113 * должен быть унаследован от `djbase(...)`.
114 *
114 *
115 * @param target Класс, который нужно объявить при помощи `dojo/_base/declare`
115 * @param target Класс, который нужно объявить при помощи `dojo/_base/declare`
116 */
116 */
117 export function djclass<T extends AbstractConstructor>(target: T): T {
117 export function djclass<T extends AbstractConstructor>(target: T): T {
118 // получаем базовый конструктор и его прототип
118 // получаем базовый конструктор и его прототип
119 const bp = target && !!target.prototype && Object.getPrototypeOf(target.prototype) as object;
119 const bp = target && !!target.prototype && Object.getPrototypeOf(target.prototype) as object;
120 const bc = bp && bp.constructor;
120 const bc = bp && bp.constructor;
121
121
122 // проверка того, что класс унаследован от специальной заглушки
122 // проверка того, что класс унаследован от специальной заглушки
123 if (isMockConstructor(bc)) {
123 if (isMockConstructor(bc)) {
124 // bc.bases - базовый класс, объявленный при помощи dojo/_base/declare
124 // bc.bases - базовый класс, объявленный при помощи dojo/_base/declare
125 const cls = declare(bc.bases, target.prototype) as unknown as T;
125 const cls = declare(bc.bases, target.prototype) as unknown as T;
126
126
127 // bc - базовый класс, bc.prototype используется как super
127 // bc - базовый класс, bc.prototype используется как super
128 // при вызове базовых методов. Нужно создать bc.prototype
128 // при вызове базовых методов. Нужно создать bc.prototype
129 // таким образом, чтобы он вызывал this.inherited().
129 // таким образом, чтобы он вызывал this.inherited().
130
130
131 // создаем новый прототип, он не в цепочке прототипов у текущего
131 // создаем новый прототип, он не в цепочке прототипов у текущего
132 // класса, но super.some_method будет использовать именно его.
132 // класса, но super.some_method будет использовать именно его.
133 // в этом объекте будут размещены прокси для переопределенных
133 // в этом объекте будут размещены прокси для переопределенных
134 // методов.
134 // методов.
135 const nbp = bc.prototype = Object.create(cls.prototype) as Record<string, unknown>;
135 const nbp = bc.prototype = Object.create(cls.prototype) as Record<string, unknown>;
136 nbp.constructor = bc;
136 nbp.constructor = bc;
137
137
138 // proxy - фабрика для создания прокси-методов, которые внутри
138 // proxy - фабрика для создания прокси-методов, которые внутри
139 // себя вызовут this.inherited с правильными параметрами.
139 // себя вызовут this.inherited с правильными параметрами.
140 const proxy = (m: (...args: unknown[]) => unknown) => function (this: dojo._base.DeclareCreatedObject, ...args: unknown[]) {
140 const proxy = (m: (...args: unknown[]) => unknown) => function (this: dojo._base.DeclareCreatedObject, ...args: unknown[]) {
141 const f = this.getInherited({ callee: m, ...args, length: args.length});
141 const f = this.getInherited({ callee: m, ...args, length: args.length });
142 return f ? f.apply(this, args) as unknown : undefined;
142 return f ? f.apply(this, args) as unknown : undefined;
143
143
144 // так сделать можно только dojo 1.15+
144 // так сделать можно только dojo 1.15+
145 // return this.inherited(m, arguments);
145 // return this.inherited(m, arguments);
146 };
146 };
147
147
148 // у текущего класса прототип содержит методы, объявленные в этом
148 // у текущего класса прототип содержит методы, объявленные в этом
149 // классе и его конструктор. Нужно пройти по всем методам и
149 // классе и его конструктор. Нужно пройти по всем методам и
150 // создать для них прокси.
150 // создать для них прокси.
151 // При этом только те, методы, которые есть в базовых классах
151 // При этом только те, методы, которые есть в базовых классах
152 // могут быть переопределены.
152 // могут быть переопределены.
153 each(target.prototype, (m: unknown, p: string) => {
153 each(target.prototype, (m: unknown, p: string) => {
154 if (typeof m === "function" &&
154 if (typeof m === "function" &&
155 p !== "constructor" &&
155 p !== "constructor" &&
156 Object.prototype.hasOwnProperty.call(target, p)
156 Object.prototype.hasOwnProperty.call(target, p)
157 ) {
157 ) {
158 nbp[p] = proxy(m as (...args: unknown[]) => unknown);
158 nbp[p] = proxy(m as (...args: unknown[]) => unknown);
159 }
159 }
160 });
160 });
161
161
162 // TODO mixin static members
162 // TODO mixin static members
163 return cls;
163 return cls;
164 } else {
164 } else {
165 return target;
165 return target;
166 }
166 }
167 }
167 }
168
168
169 function makeSetterName(prop: string) {
169 function makeSetterName(prop: string) {
170 return [
170 return [
171 "_set",
171 "_set",
172 prop.replace(/^./, x => x.toUpperCase()),
172 prop.replace(/^./, x => x.toUpperCase()),
173 "Attr"
173 "Attr"
174 ].join("");
174 ].join("");
175 }
175 }
176
176
177 function makeGetterName(prop: string) {
177 function makeGetterName(prop: string) {
178 return [
178 return [
179 "_get",
179 "_get",
180 prop.replace(/^./, x => x.toUpperCase()),
180 prop.replace(/^./, x => x.toUpperCase()),
181 "Attr"
181 "Attr"
182 ].join("");
182 ].join("");
183 }
183 }
184
184
185 interface NodeBindSpec {
185 interface NodeBindSpec {
186 node: string;
186 node: string;
187 type: "attribute" | "innerText" | "textContent" | "innerHTML" | "class" | "toggleClass";
187 type: "attribute" | "innerText" | "textContent" | "innerHTML" | "class" | "toggleClass";
188 attribute?: string;
188 attribute?: string;
189
189
190 className?: string;
190 className?: string;
191 }
191 }
192
192
193 /**
193 /**
194 * Описание привязки свойства виджета к свойству внутреннего объекта.
194 * Описание привязки свойства виджета к свойству внутреннего объекта.
195 */
195 */
196 interface MemberBindSpec {
196 interface MemberBindSpec {
197 /**
197 /**
198 * Имя свойства со ссылкой на объект, к которому .
198 * Имя свойства со ссылкой на объект, к которому .
199 */
199 */
200 member: string;
200 member: string;
201 /**
201 /**
202 * Свойство объекта к которому нужно осуществить привязку.
202 * Свойство объекта к которому нужно осуществить привязку.
203 */
203 */
204 property: string;
204 property: string;
205
205
206 /**
206 /**
207 * Привязка осуществляется не только на запись но и на чтение свойства.
207 * Привязка осуществляется не только на запись но и на чтение свойства.
208 */
208 */
209 getter?: boolean;
209 getter?: boolean;
210 }
210 }
211
211
212 function isNodeBindSpec(v: object): v is NodeBindSpec {
212 function isNodeBindSpec(v: object): v is NodeBindSpec {
213 return "node" in v;
213 return "node" in v;
214 }
214 }
215
215
216 /** Декорирует свойства виджета для привязки их к внутренним членам, либо DOM
216 /** Декорирует свойства виджета для привязки их к внутренним членам, либо DOM
217 * элементам, либо свойству внутреннего объекта.
217 * элементам, либо свойству внутреннего объекта.
218 *
218 *
219 * @param {NodeBindSpec | MemberBindSpec} params Параметры связывания.
219 * @param {NodeBindSpec | MemberBindSpec} params Параметры связывания.
220 */
220 */
221 export function bind(params: NodeBindSpec | MemberBindSpec) {
221 export function bind(params: NodeBindSpec | MemberBindSpec) {
222 if (isNodeBindSpec(params)) {
222 if (isNodeBindSpec(params)) {
223 return (target: Record<string, unknown>, name: string) => {
223 return <K extends string>(target: Record<K, unknown>, name: K) => {
224 target[makeSetterName(name)] = params;
224 target[makeSetterName(name) as K /** hack to not go insane) */] = params;
225 };
225 };
226 } else {
226 } else {
227 return (target: Record<string, unknown> & { _set(name: string, v: unknown): void }, name: string) => {
227 return <K extends string,
228 target[name] = null;
228 T extends { [p in K]: p extends "_set" ? (name: p, v: unknown) => void : unknown; }> (target: T, name: K) => {
229 target[makeSetterName(name)] = function (v: unknown) {
229 target[name] = undefined as T[K];
230 target[makeSetterName(name) as K] = function (this: T, v: unknown) {
230 this._set(name, v);
231 this._set(name, v);
231 const inner = this[params.member] as Record<string, unknown>;
232 const inner = this[params.member] as Record<string, unknown>;
232 if (typeof inner.set === "function")
233 if (typeof inner.set === "function")
233 inner.set(params.property, v);
234 inner.set(params.property, v);
234 };
235 } as T[K];
235 if (params.getter)
236 if (params.getter)
236 target[makeGetterName(name)] = function () {
237 target[makeGetterName(name)] = function () {
237 const inner = this[params.member] as Record<string, unknown>;
238 const inner = this[params.member] as Record<string, unknown>;
238 if (typeof inner.get === "function")
239 if (typeof inner.get === "function")
239 return inner.get(params.property) as unknown;
240 return inner.get(params.property) as unknown;
240 };
241 };
241 };
242 };
242 }
243 }
243 }
244 }
244
245
245 /** Создает в прототипе указанное свойство со значение `undefined`, данный
246 * декоратор следует использовать для свойств, у которых нет значения по-умолчанию
247 * и они не могут быть `null | undefined`
248 */
249 export function prototype(): (p: object, name: string) => void;
250 /** Создает в прототипе свойство с указанным значением.
246 /** Создает в прототипе свойство с указанным значением.
251 * @param value Значение, которое будет указано в прототипе
247 * @param value Значение, которое будет указано в прототипе
252 */
248 */
253 export function prototype<T>(value: T): <P extends { [m in K]: T }, K extends keyof P>(p: P, name: K) => void;
249 export function prototype<T>(value: T): <P extends { [m in K]: T }, K extends keyof P>(p: P, name: K) => void;
254 export function prototype<T>(value?: T) {
250 export function prototype<T>(value?: T) {
255 return <P extends { [m in K]: T }, K extends keyof P>(p: P, name: K) => {
251 return (p: { [m in string]: T | undefined }, name: string) => {
256 p[name] = value as any;
252 p[name] = value;
257 };
253 };
258 }
254 }
@@ -1,215 +1,215
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
5
6 interface _WidgetBaseConstructor {
6 interface _WidgetBaseConstructor {
7 new <E extends { [k in keyof E]: Event } = {}>(params?: Partial<_WidgetBase<E>> & ThisType<_WidgetBase<E>>, srcNodeRef?: string | Node): _WidgetBase<E> & dojo._base.DeclareCreatedObject;
7 new <E extends { [k in keyof E]: Event } = object>(params?: Partial<_WidgetBase<E>> & ThisType<_WidgetBase<E>>, srcNodeRef?: string | Node): _WidgetBase<E> & dojo._base.DeclareCreatedObject;
8 prototype: _WidgetBase;
8 prototype: _WidgetBase;
9 }
9 }
10
10
11 export type DojoNodePosition = "first" | "after" | "before" | "last" | "replace" | "only" | number;
11 export type DojoNodePosition = "first" | "after" | "before" | "last" | "replace" | "only" | number;
12
12
13 export type DojoNodeLocation = [Node, DojoNodePosition];
13 export type DojoNodeLocation = [Node, DojoNodePosition];
14
14
15 export interface Rendition<TNode extends Node = Node> {
15 export interface Rendition<TNode extends Node = Node> {
16 getDomNode(): TNode;
16 getDomNode(): TNode;
17
17
18 placeAt(refNode: string | Node, position?: DojoNodePosition): void;
18 placeAt(refNode: string | Node, position?: DojoNodePosition): void;
19 }
19 }
20
20
21 /**
21 /**
22 * @deprecated use Rendition
22 * @deprecated use Rendition
23 */
23 */
24 export type BuildContext<TNode extends Node = Node> = Rendition<TNode>;
24 export type BuildContext<TNode extends Node = Node> = Rendition<TNode>;
25
25
26 export interface IRecursivelyDestroyable {
26 export interface IRecursivelyDestroyable {
27 destroyRecursive(): void;
27 destroyRecursive(): void;
28 }
28 }
29
29
30 export const isNode = (el: unknown): el is Node => !!(el && (el as Node).nodeName && (el as Node).nodeType);
30 export const isNode = (el: unknown): el is Node => !!(el && (el as Node).nodeName && (el as Node).nodeType);
31
31
32 export const isElementNode = (el: unknown): el is Element => isNode(el) && el.nodeType === 1;
32 export const isElementNode = (el: unknown): el is Element => isNode(el) && el.nodeType === 1;
33
33
34 export const isTextNode = (el: unknown): el is Text => isNode(el) && el.nodeType === 3;
34 export const isTextNode = (el: unknown): el is Text => isNode(el) && el.nodeType === 3;
35
35
36 export const isProcessingInstructionNode = (el: unknown): el is ProcessingInstruction => isNode(el) && el.nodeType === 7;
36 export const isProcessingInstructionNode = (el: unknown): el is ProcessingInstruction => isNode(el) && el.nodeType === 7;
37
37
38 export const isCommentNode = (el: unknown): el is Comment => isNode(el) && el.nodeType === 8;
38 export const isCommentNode = (el: unknown): el is Comment => isNode(el) && el.nodeType === 8;
39
39
40 export const isDocumentNode = (el: unknown): el is Document => isNode(el) && el.nodeType === 9;
40 export const isDocumentNode = (el: unknown): el is Document => isNode(el) && el.nodeType === 9;
41
41
42 export const isDocumentTypeNode = (el: unknown): el is DocumentType => isNode(el) && el.nodeType === 10;
42 export const isDocumentTypeNode = (el: unknown): el is DocumentType => isNode(el) && el.nodeType === 10;
43
43
44 export const isDocumentFragmentNode = (el: unknown): el is DocumentFragment => isNode(el) && el.nodeType === 11;
44 export const isDocumentFragmentNode = (el: unknown): el is DocumentFragment => isNode(el) && el.nodeType === 11;
45
45
46 export const isWidget = (v: unknown): v is _WidgetBase => !!(v && "domNode" in (v as _WidgetBase));
46 export const isWidget = (v: unknown): v is _WidgetBase => !!(v && "domNode" in (v as _WidgetBase));
47
47
48 export const isRendition = (v: unknown): v is Rendition => !!(v && typeof (v as Rendition).getDomNode === "function");
48 export const isRendition = (v: unknown): v is Rendition => !!(v && typeof (v as Rendition).getDomNode === "function");
49
49
50 /**
50 /**
51 * @deprecated use isRendition
51 * @deprecated use isRendition
52 */
52 */
53 export const isBuildContext = isRendition;
53 export const isBuildContext = isRendition;
54
54
55 export const isPlainObject = (v: object) => {
55 export const isPlainObject = (v: object) => {
56 if (typeof v !== "object")
56 if (typeof v !== "object")
57 return false;
57 return false;
58
58
59 const vp = Object.getPrototypeOf(v) as object;
59 const vp = Object.getPrototypeOf(v) as object;
60 return !vp || vp === Object.prototype;
60 return !vp || vp === Object.prototype;
61 };
61 };
62
62
63 export const isWidgetConstructor = (v: unknown): v is _WidgetBaseConstructor =>
63 export const isWidgetConstructor = (v: unknown): v is _WidgetBaseConstructor =>
64 typeof v === "function" && !!v.prototype && (
64 typeof v === "function" && !!v.prototype && (
65 "domNode" in v.prototype ||
65 "domNode" in v.prototype ||
66 "buildRendering" in v.prototype
66 "buildRendering" in v.prototype
67 );
67 );
68
68
69
69
70 /** Tests whether the specified node is placed in visible dom.
70 /** Tests whether the specified node is placed in visible dom.
71 * @param {Node} node The node to test
71 * @param {Node} node The node to test
72 */
72 */
73 export const isInPage = (node: Node) => node === document.body ? false : document.body.contains(node);
73 export const isInPage = (node: Node) => node === document.body ? false : document.body.contains(node);
74
74
75 export const isRecursivelyDestroyable = (target: unknown): target is IRecursivelyDestroyable =>
75 export const isRecursivelyDestroyable = (target: unknown): target is IRecursivelyDestroyable =>
76 !!(target && typeof (target as IRecursivelyDestroyable).destroyRecursive === "function");
76 !!(target && typeof (target as IRecursivelyDestroyable).destroyRecursive === "function");
77
77
78
78
79
79
80 /** Destroys DOM Node with all contained widgets.
80 /** Destroys DOM Node with all contained widgets.
81 * If the specified node is the root node of a widget, then the
81 * If the specified node is the root node of a widget, then the
82 * widget will be destroyed.
82 * widget will be destroyed.
83 *
83 *
84 * @param target DOM Node or widget to destroy
84 * @param target DOM Node or widget to destroy
85 */
85 */
86 export const destroy = (target: Node | IDestroyable | IRecursivelyDestroyable) => {
86 export const destroy = (target: Node | IDestroyable | IRecursivelyDestroyable) => {
87 if (isRecursivelyDestroyable(target)) {
87 if (isRecursivelyDestroyable(target)) {
88 target.destroyRecursive();
88 target.destroyRecursive();
89 } else if (isDestroyable(target)) {
89 } else if (isDestroyable(target)) {
90 target.destroy();
90 target.destroy();
91 } else if (isNode(target)) {
91 } else if (isNode(target)) {
92 if (isElementNode(target)) {
92 if (isElementNode(target)) {
93 const w = registry.byNode(target);
93 const w = registry.byNode(target);
94 if (w) {
94 if (w) {
95 w.destroyRecursive();
95 w.destroyRecursive();
96 return;
96 return;
97 } else {
97 } else {
98 emptyNode(target);
98 emptyNode(target);
99 }
99 }
100 }
100 }
101 const parent = target.parentNode;
101 const parent = target.parentNode;
102 if (parent)
102 if (parent)
103 parent.removeChild(target);
103 parent.removeChild(target);
104
104
105 }
105 }
106 };
106 };
107
107
108 /** Empties a content of the specified node and destroys all contained widgets.
108 /** Empties a content of the specified node and destroys all contained widgets.
109 *
109 *
110 * @param target DOM node to empty.
110 * @param target DOM node to empty.
111 */
111 */
112 export const emptyNode = (target: Node) => {
112 export const emptyNode = (target: Node) => {
113 registry.findWidgets(target).forEach(destroy);
113 registry.findWidgets(target).forEach(destroy);
114
114
115 // eslint-disable-next-line no-cond-assign
115 // eslint-disable-next-line no-cond-assign
116 for (let c; c = target.lastChild;) { // intentional assignment
116 for (let c; c = target.lastChild;) { // intentional assignment
117 target.removeChild(c);
117 target.removeChild(c);
118 }
118 }
119 };
119 };
120
120
121 /** This function starts all widgets inside the DOM node if the target is a node
121 /** This function starts all widgets inside the DOM node if the target is a node
122 * or starts widget itself if the target is the widget. If the specified node
122 * or starts widget itself if the target is the widget. If the specified node
123 * associated with the widget that widget will be started.
123 * associated with the widget that widget will be started.
124 *
124 *
125 * @param target DOM node to find and start widgets or the widget itself.
125 * @param target DOM node to find and start widgets or the widget itself.
126 */
126 */
127 export const startupWidgets = (target: Node | _WidgetBase, skipNode?: Node) => {
127 export const startupWidgets = (target: Node | _WidgetBase, skipNode?: Node) => {
128 if (isNode(target)) {
128 if (isNode(target)) {
129 if (isElementNode(target)) {
129 if (isElementNode(target)) {
130 const w = registry.byNode(target);
130 const w = registry.byNode(target);
131 if (w) {
131 if (w) {
132 if (w.startup)
132 if (w.startup)
133 w.startup();
133 w.startup();
134 } else {
134 } else {
135 registry.findWidgets(target, skipNode).forEach(x => x.startup());
135 registry.findWidgets(target, skipNode).forEach(x => x.startup());
136 }
136 }
137 }
137 }
138 } else {
138 } else {
139 if (target.startup)
139 if (target.startup)
140 target.startup();
140 target.startup();
141 }
141 }
142 };
142 };
143
143
144 /** Places the specified DOM node at the specified location.
144 /** Places the specified DOM node at the specified location.
145 *
145 *
146 * @param node The node which should be placed
146 * @param node The node which should be placed
147 * @param refNodeOrId The reference node where the created
147 * @param refNodeOrId The reference node where the created
148 * DOM should be placed.
148 * DOM should be placed.
149 * @param position Optional parameter, specifies the
149 * @param position Optional parameter, specifies the
150 * position relative to refNode. Default is "last" (i.e. last child).
150 * position relative to refNode. Default is "last" (i.e. last child).
151 */
151 */
152 export const placeAt = (node: Node, refNodeOrId: string | Node, position: DojoNodePosition = "last") => {
152 export const placeAt = (node: Node, refNodeOrId: string | Node, position: DojoNodePosition = "last") => {
153 const ref = typeof refNodeOrId == "string" ? document.getElementById(refNodeOrId) : refNodeOrId;
153 const ref = typeof refNodeOrId == "string" ? document.getElementById(refNodeOrId) : refNodeOrId;
154 if (!ref)
154 if (!ref)
155 return;
155 return;
156
156
157 const parent = ref.parentNode;
157 const parent = ref.parentNode;
158
158
159 if (typeof position == "number") {
159 if (typeof position == "number") {
160 if (ref.childNodes.length <= position) {
160 if (ref.childNodes.length <= position) {
161 ref.appendChild(node);
161 ref.appendChild(node);
162 } else {
162 } else {
163 ref.insertBefore(node, ref.childNodes[position]);
163 ref.insertBefore(node, ref.childNodes[position]);
164 }
164 }
165 } else {
165 } else {
166 switch (position) {
166 switch (position) {
167 case "before":
167 case "before":
168 parent && parent.insertBefore(node, ref);
168 parent && parent.insertBefore(node, ref);
169 break;
169 break;
170 case "after":
170 case "after":
171 parent && parent.insertBefore(node, ref.nextSibling);
171 parent && parent.insertBefore(node, ref.nextSibling);
172 break;
172 break;
173 case "first":
173 case "first":
174 ref.insertBefore(node, ref.firstChild);
174 ref.insertBefore(node, ref.firstChild);
175 break;
175 break;
176 case "last":
176 case "last":
177 ref.appendChild(node);
177 ref.appendChild(node);
178 break;
178 break;
179 case "only":
179 case "only":
180 emptyNode(ref);
180 emptyNode(ref);
181 ref.appendChild(node);
181 ref.appendChild(node);
182 break;
182 break;
183 case "replace":
183 case "replace":
184 if (parent)
184 if (parent)
185 parent.replaceChild(node, ref);
185 parent.replaceChild(node, ref);
186 destroy(ref);
186 destroy(ref);
187 break;
187 break;
188 }
188 }
189 }
189 }
190 };
190 };
191
191
192 /** Collects nodes from collection to an array.
192 /** Collects nodes from collection to an array.
193 *
193 *
194 * @param collection The collection of nodes.
194 * @param collection The collection of nodes.
195 * @returns The array of nodes.
195 * @returns The array of nodes.
196 */
196 */
197 export const collectNodes = (collection: NodeListOf<ChildNode>) => {
197 export const collectNodes = (collection: NodeListOf<ChildNode>) => {
198 const items = [];
198 const items = [];
199 for (let i = 0, n = collection.length; i < n; i++) {
199 for (let i = 0, n = collection.length; i < n; i++) {
200 items.push(collection[i]);
200 items.push(collection[i]);
201 }
201 }
202 return items;
202 return items;
203 };
203 };
204
204
205
205
206 export const isMounted = (node: Node) => {
206 export const isMounted = (node: Node) => {
207 if (node.parentNode) {
207 if (node.parentNode) {
208 const parentWidget = registry.getEnclosingWidget(node.parentNode);
208 const parentWidget = registry.getEnclosingWidget(node.parentNode);
209 if (parentWidget && parentWidget._started)
209 if (parentWidget && parentWidget._started)
210 return true;
210 return true;
211 }
211 }
212 if (isInPage(node))
212 if (isInPage(node))
213 return true;
213 return true;
214 return false;
214 return false;
215 }; No newline at end of file
215 };
@@ -1,52 +1,52
1 import { observe } from "./observable";
1 import { observe } from "./observable";
2 import * as t from "tap";
2 import * as t from "tap";
3
3
4 const subj1 = observe<number>(({ next, complete }) => {
4 const subj1 = observe<number>(({ next, complete }) => {
5 next(1);
5 next(1);
6 complete();
6 complete();
7 next(2);
7 next(2);
8 });
8 });
9
9
10 const consumer1 = {
10 const consumer1 = {
11 sum: 0,
11 sum: 0,
12 next(v: number) {
12 next(v: number) {
13 this.sum += v;
13 this.sum += v;
14 }
14 }
15 }
15 };
16
16
17 subj1.subscribe(consumer1);
17 subj1.subscribe(consumer1);
18 t.equal(consumer1.sum, 1, "Should get only one value");
18 t.equal(consumer1.sum, 1, "Should get only one value");
19
19
20 subj1.subscribe(consumer1);
20 subj1.subscribe(consumer1);
21 t.equal(consumer1.sum, 2, "Should get the value again");
21 t.equal(consumer1.sum, 2, "Should get the value again");
22
22
23 const consumer2 = {
23 const consumer2 = {
24 value: 0,
24 value: 0,
25 completed: false,
25 completed: false,
26 next(v: number) { this.value = v; },
26 next(v: number) { this.value = v; },
27 complete() { this.completed = true; }
27 complete() { this.completed = true; }
28 };
28 };
29
29
30 let maps = 0;
30 let maps = 0;
31
31
32 subj1
32 subj1
33 .map(v => {
33 .map(v => {
34 t.comment("map1: " + v * 2);
34 t.comment(`map1: ${v * 2}`);
35 maps++;
35 maps++;
36 return v * 2;
36 return v * 2;
37 })
37 })
38 .map (v => {
38 .map (v => {
39 t.comment("map2: " + v * 2);
39 t.comment(`map2: ${v * 2}`);
40 maps++;
40 maps++;
41 return v * 2;
41 return v * 2;
42 })
42 })
43 .map(v => {
43 .map(v => {
44 t.comment("map3: " + v * 2);
44 t.comment(`map3: ${v * 2}`);
45 maps++;
45 maps++;
46 return v * 2
46 return v * 2;
47 })
47 })
48 .subscribe(consumer2);
48 .subscribe(consumer2);
49
49
50 t.equal(consumer2.value, 8, "Should map");
50 t.equal(consumer2.value, 8, "Should map");
51 t.equal(maps, 3, "The map chain should not be executed after completion");
51 t.equal(maps, 3, "The map chain should not be executed after completion");
52 t.ok(consumer2.completed, "The completion signal should pass through"); No newline at end of file
52 t.ok(consumer2.completed, "The completion signal should pass through");
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
General Comments 0
You need to be logged in to leave comments. Login now