vasille 2.0.3 → 2.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -3
- package/cdn/es2015.js +939 -1009
- package/cdn/es5.js +1048 -1029
- package/flow-typed/vasille.js +2641 -832
- package/lib/binding/attribute.js +11 -12
- package/lib/binding/binding.js +9 -19
- package/lib/binding/class.js +34 -42
- package/lib/binding/style.js +5 -11
- package/lib/core/core.js +78 -32
- package/lib/core/destroyable.js +2 -2
- package/lib/core/ivalue.js +15 -13
- package/lib/functional/components.js +17 -0
- package/lib/functional/merge.js +41 -0
- package/lib/functional/models.js +26 -0
- package/lib/functional/options.js +1 -0
- package/lib/functional/reactivity.js +33 -0
- package/lib/functional/stack.js +127 -0
- package/lib/index.js +2 -7
- package/lib/models/array-model.js +9 -0
- package/lib/models/object-model.js +28 -14
- package/lib/node/app.js +23 -14
- package/lib/node/interceptor.js +3 -3
- package/lib/node/node.js +338 -684
- package/lib/node/watch.js +9 -17
- package/lib/spec/html.js +1 -0
- package/lib/spec/react.js +1 -0
- package/lib/spec/svg.js +1 -0
- package/lib/v/index.js +23 -0
- package/lib/value/expression.js +11 -8
- package/lib/value/mirror.js +6 -8
- package/lib/value/reference.js +3 -7
- package/lib/views/array-view.js +6 -10
- package/lib/views/base-view.js +12 -23
- package/lib/views/map-view.js +4 -9
- package/lib/views/object-view.js +5 -8
- package/lib/views/repeat-node.js +20 -60
- package/lib/views/repeater.js +7 -7
- package/lib/views/set-view.js +4 -11
- package/package.json +7 -6
- package/types/binding/attribute.d.ts +2 -8
- package/types/binding/binding.d.ts +4 -13
- package/types/binding/class.d.ts +7 -19
- package/types/binding/style.d.ts +0 -6
- package/types/core/core.d.ts +40 -54
- package/types/core/destroyable.d.ts +2 -2
- package/types/core/ivalue.d.ts +13 -11
- package/types/functional/components.d.ts +4 -0
- package/types/functional/merge.d.ts +1 -0
- package/types/functional/models.d.ts +10 -0
- package/types/functional/options.d.ts +23 -0
- package/types/functional/reactivity.d.ts +11 -0
- package/types/functional/stack.d.ts +24 -0
- package/types/index.d.ts +3 -7
- package/types/models/array-model.d.ts +3 -2
- package/types/models/map-model.d.ts +2 -2
- package/types/models/model.d.ts +3 -1
- package/types/models/object-model.d.ts +4 -2
- package/types/models/set-model.d.ts +2 -2
- package/types/node/app.d.ts +21 -19
- package/types/node/node.d.ts +97 -422
- package/types/node/watch.d.ts +9 -15
- package/types/spec/html.d.ts +975 -0
- package/types/spec/react.d.ts +4 -0
- package/types/spec/svg.d.ts +314 -0
- package/types/v/index.d.ts +32 -0
- package/types/value/expression.d.ts +7 -20
- package/types/value/mirror.d.ts +3 -3
- package/types/value/reference.d.ts +5 -5
- package/types/views/array-view.d.ts +3 -4
- package/types/views/base-view.d.ts +9 -17
- package/types/views/map-view.d.ts +2 -3
- package/types/views/object-view.d.ts +2 -3
- package/types/views/repeat-node.d.ts +8 -9
- package/types/views/set-view.d.ts +2 -3
- package/types/core/executor.d.ts +0 -87
- package/types/core/signal.d.ts +0 -35
- package/types/core/slot.d.ts +0 -45
- package/types/node/interceptor.d.ts +0 -50
- package/types/views/repeater.d.ts +0 -38
package/lib/node/node.js
CHANGED
|
@@ -3,7 +3,7 @@ import { IValue } from "../core/ivalue";
|
|
|
3
3
|
import { Reference } from "../value/reference";
|
|
4
4
|
import { Expression } from "../value/expression";
|
|
5
5
|
import { AttributeBinding } from "../binding/attribute";
|
|
6
|
-
import {
|
|
6
|
+
import { StaticClassBinding, DynamicalClassBinding } from "../binding/class";
|
|
7
7
|
import { StyleBinding } from "../binding/style";
|
|
8
8
|
import { internalError, userError } from "../core/errors";
|
|
9
9
|
/**
|
|
@@ -14,7 +14,7 @@ import { internalError, userError } from "../core/errors";
|
|
|
14
14
|
export class FragmentPrivate extends ReactivePrivate {
|
|
15
15
|
constructor() {
|
|
16
16
|
super();
|
|
17
|
-
this
|
|
17
|
+
this.seal();
|
|
18
18
|
}
|
|
19
19
|
/**
|
|
20
20
|
* Pre-initializes the base of a fragment
|
|
@@ -28,10 +28,10 @@ export class FragmentPrivate extends ReactivePrivate {
|
|
|
28
28
|
/**
|
|
29
29
|
* Unlinks all bindings
|
|
30
30
|
*/
|
|
31
|
-
|
|
31
|
+
destroy() {
|
|
32
32
|
this.next = null;
|
|
33
33
|
this.prev = null;
|
|
34
|
-
super
|
|
34
|
+
super.destroy();
|
|
35
35
|
}
|
|
36
36
|
}
|
|
37
37
|
/**
|
|
@@ -41,16 +41,17 @@ export class FragmentPrivate extends ReactivePrivate {
|
|
|
41
41
|
export class Fragment extends Reactive {
|
|
42
42
|
/**
|
|
43
43
|
* Constructs a Vasille Node
|
|
44
|
+
* @param input
|
|
44
45
|
* @param $ {FragmentPrivate}
|
|
45
46
|
*/
|
|
46
|
-
constructor($) {
|
|
47
|
-
super();
|
|
47
|
+
constructor(input, $) {
|
|
48
|
+
super(input, $ || new FragmentPrivate);
|
|
48
49
|
/**
|
|
49
50
|
* The children list
|
|
50
51
|
* @type Array
|
|
51
52
|
*/
|
|
52
|
-
this
|
|
53
|
-
this
|
|
53
|
+
this.children = new Set;
|
|
54
|
+
this.lastChild = null;
|
|
54
55
|
}
|
|
55
56
|
/**
|
|
56
57
|
* Gets the app of node
|
|
@@ -64,43 +65,16 @@ export class Fragment extends Reactive {
|
|
|
64
65
|
* @param parent {Fragment} parent of node
|
|
65
66
|
* @param data {*} additional data
|
|
66
67
|
*/
|
|
67
|
-
|
|
68
|
+
preinit(app, parent, data) {
|
|
68
69
|
const $ = this.$;
|
|
69
70
|
$.preinit(app, parent);
|
|
70
71
|
}
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
$init() {
|
|
75
|
-
this.$createSignals();
|
|
76
|
-
this.$createWatchers();
|
|
77
|
-
this.$created();
|
|
78
|
-
this.$compose();
|
|
79
|
-
this.$mounted();
|
|
80
|
-
return this;
|
|
81
|
-
}
|
|
82
|
-
/** To be overloaded: created event handler */
|
|
83
|
-
$created() {
|
|
84
|
-
// empty
|
|
85
|
-
}
|
|
86
|
-
/** To be overloaded: mounted event handler */
|
|
87
|
-
$mounted() {
|
|
88
|
-
// empty
|
|
72
|
+
compose(input) {
|
|
73
|
+
super.compose(input);
|
|
74
|
+
input.slot && input.slot(this);
|
|
89
75
|
}
|
|
90
76
|
/** To be overloaded: ready event handler */
|
|
91
|
-
|
|
92
|
-
// empty
|
|
93
|
-
}
|
|
94
|
-
/** To be overloaded: signals creation milestone */
|
|
95
|
-
$createSignals() {
|
|
96
|
-
// empty
|
|
97
|
-
}
|
|
98
|
-
/** To be overloaded: watchers creation milestone */
|
|
99
|
-
$createWatchers() {
|
|
100
|
-
// empty
|
|
101
|
-
}
|
|
102
|
-
/** To be overloaded: DOM creation milestone */
|
|
103
|
-
$compose() {
|
|
77
|
+
ready() {
|
|
104
78
|
// empty
|
|
105
79
|
}
|
|
106
80
|
/**
|
|
@@ -108,27 +82,23 @@ export class Fragment extends Reactive {
|
|
|
108
82
|
* @param node {Fragment} A node to push
|
|
109
83
|
* @protected
|
|
110
84
|
*/
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
lastChild = this.$children[this.$children.length - 1];
|
|
115
|
-
}
|
|
116
|
-
if (lastChild) {
|
|
117
|
-
lastChild.$.next = node;
|
|
85
|
+
pushNode(node) {
|
|
86
|
+
if (this.lastChild) {
|
|
87
|
+
this.lastChild.$.next = node;
|
|
118
88
|
}
|
|
119
|
-
node.$.prev = lastChild;
|
|
120
|
-
|
|
121
|
-
this
|
|
89
|
+
node.$.prev = this.lastChild;
|
|
90
|
+
this.lastChild = node;
|
|
91
|
+
this.children.add(node);
|
|
122
92
|
}
|
|
123
93
|
/**
|
|
124
94
|
* Find first node in element if so exists
|
|
125
95
|
* @return {?Element}
|
|
126
96
|
* @protected
|
|
127
97
|
*/
|
|
128
|
-
|
|
98
|
+
findFirstChild() {
|
|
129
99
|
let first;
|
|
130
|
-
this
|
|
131
|
-
first = first || child
|
|
100
|
+
this.children.forEach(child => {
|
|
101
|
+
first = first || child.findFirstChild();
|
|
132
102
|
});
|
|
133
103
|
return first;
|
|
134
104
|
}
|
|
@@ -136,30 +106,30 @@ export class Fragment extends Reactive {
|
|
|
136
106
|
* Append a node to end of element
|
|
137
107
|
* @param node {Node} node to insert
|
|
138
108
|
*/
|
|
139
|
-
|
|
109
|
+
appendNode(node) {
|
|
140
110
|
const $ = this.$;
|
|
141
111
|
if ($.next) {
|
|
142
|
-
$.next
|
|
112
|
+
$.next.insertAdjacent(node);
|
|
143
113
|
}
|
|
144
114
|
else {
|
|
145
|
-
$.parent
|
|
115
|
+
$.parent.appendNode(node);
|
|
146
116
|
}
|
|
147
117
|
}
|
|
148
118
|
/**
|
|
149
119
|
* Insert a node as a sibling of this
|
|
150
120
|
* @param node {Node} node to insert
|
|
151
121
|
*/
|
|
152
|
-
|
|
153
|
-
const child = this
|
|
122
|
+
insertAdjacent(node) {
|
|
123
|
+
const child = this.findFirstChild();
|
|
154
124
|
const $ = this.$;
|
|
155
125
|
if (child) {
|
|
156
|
-
|
|
126
|
+
child.parentElement.insertBefore(node, child);
|
|
157
127
|
}
|
|
158
128
|
else if ($.next) {
|
|
159
|
-
$.next
|
|
129
|
+
$.next.insertAdjacent(node);
|
|
160
130
|
}
|
|
161
131
|
else {
|
|
162
|
-
$.parent
|
|
132
|
+
$.parent.appendNode(node);
|
|
163
133
|
}
|
|
164
134
|
}
|
|
165
135
|
/**
|
|
@@ -167,60 +137,49 @@ export class Fragment extends Reactive {
|
|
|
167
137
|
* @param text {String | IValue} A text fragment string
|
|
168
138
|
* @param cb {function (TextNode)} Callback if previous is slot name
|
|
169
139
|
*/
|
|
170
|
-
|
|
140
|
+
text(text, cb) {
|
|
171
141
|
const $ = this.$;
|
|
172
142
|
const node = new TextNode();
|
|
173
|
-
|
|
174
|
-
node
|
|
175
|
-
|
|
176
|
-
if (cb) {
|
|
177
|
-
$.app.$run.callCallback(() => {
|
|
178
|
-
cb(node);
|
|
179
|
-
});
|
|
180
|
-
}
|
|
181
|
-
return this;
|
|
143
|
+
node.preinit($.app, this, text);
|
|
144
|
+
this.pushNode(node);
|
|
145
|
+
cb && cb(node);
|
|
182
146
|
}
|
|
183
|
-
|
|
184
|
-
if (this.$.app
|
|
147
|
+
debug(text) {
|
|
148
|
+
if (this.$.app.debugUi) {
|
|
185
149
|
const node = new DebugNode();
|
|
186
|
-
node
|
|
187
|
-
this
|
|
150
|
+
node.preinit(this.$.app, this, text);
|
|
151
|
+
this.pushNode(node);
|
|
188
152
|
}
|
|
189
|
-
return this;
|
|
190
153
|
}
|
|
191
|
-
|
|
154
|
+
/**
|
|
155
|
+
* Defines a tag element
|
|
156
|
+
* @param tagName {String} the tag name
|
|
157
|
+
* @param input
|
|
158
|
+
* @param cb {function(Tag, *)} callback
|
|
159
|
+
*/
|
|
160
|
+
tag(tagName, input, cb) {
|
|
192
161
|
const $ = this.$;
|
|
193
|
-
const node = new Tag();
|
|
194
|
-
|
|
195
|
-
node
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
}
|
|
201
|
-
node.$ready();
|
|
202
|
-
});
|
|
203
|
-
return this;
|
|
162
|
+
const node = new Tag(input);
|
|
163
|
+
input.slot = cb || input.slot;
|
|
164
|
+
node.preinit($.app, this, tagName);
|
|
165
|
+
node.init();
|
|
166
|
+
this.pushNode(node);
|
|
167
|
+
node.ready();
|
|
168
|
+
return node.node;
|
|
204
169
|
}
|
|
205
170
|
/**
|
|
206
171
|
* Defines a custom element
|
|
207
172
|
* @param node {Fragment} vasille element to insert
|
|
208
173
|
* @param callback {function($ : *)}
|
|
209
|
-
* @param callback1 {function($ : *)}
|
|
210
174
|
*/
|
|
211
|
-
|
|
175
|
+
create(node, callback) {
|
|
212
176
|
const $ = this.$;
|
|
213
177
|
node.$.parent = this;
|
|
214
|
-
node
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
callback1(node);
|
|
220
|
-
}
|
|
221
|
-
this.$$pushNode(node);
|
|
222
|
-
node.$init().$ready();
|
|
223
|
-
return this;
|
|
178
|
+
node.preinit($.app, this);
|
|
179
|
+
node.input.slot = callback || node.input.slot;
|
|
180
|
+
this.pushNode(node);
|
|
181
|
+
node.init();
|
|
182
|
+
node.ready();
|
|
224
183
|
}
|
|
225
184
|
/**
|
|
226
185
|
* Defines an if node
|
|
@@ -228,32 +187,29 @@ export class Fragment extends Reactive {
|
|
|
228
187
|
* @param cb {function(Fragment)} callback to run on true
|
|
229
188
|
* @return {this}
|
|
230
189
|
*/
|
|
231
|
-
|
|
232
|
-
|
|
190
|
+
if(cond, cb) {
|
|
191
|
+
const node = new SwitchedNode();
|
|
192
|
+
node.preinit(this.$.app, this);
|
|
193
|
+
node.init();
|
|
194
|
+
this.pushNode(node);
|
|
195
|
+
node.addCase(this.case(cond, cb));
|
|
196
|
+
node.ready();
|
|
233
197
|
}
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
return this.$switch({ cond: ifCond, cb: ifCb }, { cond: trueIValue, cb: elseCb });
|
|
198
|
+
else(cb) {
|
|
199
|
+
if (this.lastChild instanceof SwitchedNode) {
|
|
200
|
+
this.lastChild.addCase(this.default(cb));
|
|
201
|
+
}
|
|
202
|
+
else {
|
|
203
|
+
throw userError('wrong `else` function use', 'logic-error');
|
|
204
|
+
}
|
|
242
205
|
}
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
const node = new SwitchedNode();
|
|
251
|
-
node.$preinit($.app, this);
|
|
252
|
-
node.$init();
|
|
253
|
-
this.$$pushNode(node);
|
|
254
|
-
node.setCases(cases);
|
|
255
|
-
node.$ready();
|
|
256
|
-
return this;
|
|
206
|
+
elif(cond, cb) {
|
|
207
|
+
if (this.lastChild instanceof SwitchedNode) {
|
|
208
|
+
this.lastChild.addCase(this.case(cond, cb));
|
|
209
|
+
}
|
|
210
|
+
else {
|
|
211
|
+
throw userError('wrong `elif` function use', 'logic-error');
|
|
212
|
+
}
|
|
257
213
|
}
|
|
258
214
|
/**
|
|
259
215
|
* Create a case for switch
|
|
@@ -261,22 +217,48 @@ export class Fragment extends Reactive {
|
|
|
261
217
|
* @param cb {function(Fragment) : void}
|
|
262
218
|
* @return {{cond : IValue, cb : (function(Fragment) : void)}}
|
|
263
219
|
*/
|
|
264
|
-
|
|
220
|
+
case(cond, cb) {
|
|
265
221
|
return { cond, cb };
|
|
266
222
|
}
|
|
267
223
|
/**
|
|
268
224
|
* @param cb {(function(Fragment) : void)}
|
|
269
225
|
* @return {{cond : IValue, cb : (function(Fragment) : void)}}
|
|
270
226
|
*/
|
|
271
|
-
|
|
227
|
+
default(cb) {
|
|
272
228
|
return { cond: trueIValue, cb };
|
|
273
229
|
}
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
230
|
+
insertBefore(node) {
|
|
231
|
+
const $ = this.$;
|
|
232
|
+
node.$.prev = $.prev;
|
|
233
|
+
node.$.next = this;
|
|
234
|
+
if ($.prev) {
|
|
235
|
+
$.prev.$.next = node;
|
|
277
236
|
}
|
|
278
|
-
|
|
279
|
-
|
|
237
|
+
$.prev = node;
|
|
238
|
+
}
|
|
239
|
+
insertAfter(node) {
|
|
240
|
+
const $ = this.$;
|
|
241
|
+
node.$.prev = this;
|
|
242
|
+
node.$.next = $.next;
|
|
243
|
+
$.next = node;
|
|
244
|
+
}
|
|
245
|
+
remove() {
|
|
246
|
+
const $ = this.$;
|
|
247
|
+
if ($.next) {
|
|
248
|
+
$.next.$.prev = $.prev;
|
|
249
|
+
}
|
|
250
|
+
if ($.prev) {
|
|
251
|
+
$.prev.$.next = $.next;
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
destroy() {
|
|
255
|
+
this.children.forEach(child => child.destroy());
|
|
256
|
+
this.children.clear();
|
|
257
|
+
this.lastChild = null;
|
|
258
|
+
if (this.$.parent.lastChild === this) {
|
|
259
|
+
this.$.parent.lastChild = this.$.prev;
|
|
260
|
+
}
|
|
261
|
+
super.destroy();
|
|
280
262
|
}
|
|
281
263
|
}
|
|
282
264
|
const trueIValue = new Reference(true);
|
|
@@ -288,26 +270,28 @@ const trueIValue = new Reference(true);
|
|
|
288
270
|
export class TextNodePrivate extends FragmentPrivate {
|
|
289
271
|
constructor() {
|
|
290
272
|
super();
|
|
291
|
-
this
|
|
273
|
+
this.seal();
|
|
292
274
|
}
|
|
293
275
|
/**
|
|
294
276
|
* Pre-initializes a text node
|
|
295
277
|
* @param app {AppNode} the app node
|
|
278
|
+
* @param parent
|
|
296
279
|
* @param text {IValue}
|
|
297
280
|
*/
|
|
298
281
|
preinitText(app, parent, text) {
|
|
299
282
|
super.preinit(app, parent);
|
|
300
|
-
this.node = document.createTextNode(text.$);
|
|
301
|
-
|
|
302
|
-
this.
|
|
303
|
-
|
|
304
|
-
|
|
283
|
+
this.node = document.createTextNode(text instanceof IValue ? text.$ : text);
|
|
284
|
+
if (text instanceof IValue) {
|
|
285
|
+
this.bindings.add(new Expression((v) => {
|
|
286
|
+
this.node.replaceData(0, -1, v);
|
|
287
|
+
}, true, text));
|
|
288
|
+
}
|
|
305
289
|
}
|
|
306
290
|
/**
|
|
307
291
|
* Clear node data
|
|
308
292
|
*/
|
|
309
|
-
|
|
310
|
-
super
|
|
293
|
+
destroy() {
|
|
294
|
+
super.destroy();
|
|
311
295
|
}
|
|
312
296
|
}
|
|
313
297
|
/**
|
|
@@ -316,25 +300,25 @@ export class TextNodePrivate extends FragmentPrivate {
|
|
|
316
300
|
* @extends Fragment
|
|
317
301
|
*/
|
|
318
302
|
export class TextNode extends Fragment {
|
|
319
|
-
constructor() {
|
|
320
|
-
super();
|
|
321
|
-
this
|
|
322
|
-
this.$seal();
|
|
303
|
+
constructor($ = new TextNodePrivate()) {
|
|
304
|
+
super({}, $);
|
|
305
|
+
this.seal();
|
|
323
306
|
}
|
|
324
|
-
|
|
307
|
+
preinit(app, parent, text) {
|
|
325
308
|
const $ = this.$;
|
|
326
309
|
if (!text) {
|
|
327
310
|
throw internalError('wrong TextNode::$preninit call');
|
|
328
311
|
}
|
|
329
312
|
$.preinitText(app, parent, text);
|
|
313
|
+
$.parent.appendNode($.node);
|
|
330
314
|
}
|
|
331
|
-
|
|
315
|
+
findFirstChild() {
|
|
332
316
|
return this.$.node;
|
|
333
317
|
}
|
|
334
|
-
|
|
318
|
+
destroy() {
|
|
335
319
|
this.$.node.remove();
|
|
336
|
-
this
|
|
337
|
-
super
|
|
320
|
+
this.$.destroy();
|
|
321
|
+
super.destroy();
|
|
338
322
|
}
|
|
339
323
|
}
|
|
340
324
|
/**
|
|
@@ -350,10 +334,10 @@ export class INodePrivate extends FragmentPrivate {
|
|
|
350
334
|
* @type {boolean}
|
|
351
335
|
*/
|
|
352
336
|
this.unmounted = false;
|
|
353
|
-
this
|
|
337
|
+
this.seal();
|
|
354
338
|
}
|
|
355
|
-
|
|
356
|
-
super
|
|
339
|
+
destroy() {
|
|
340
|
+
super.destroy();
|
|
357
341
|
}
|
|
358
342
|
}
|
|
359
343
|
/**
|
|
@@ -364,11 +348,12 @@ export class INodePrivate extends FragmentPrivate {
|
|
|
364
348
|
export class INode extends Fragment {
|
|
365
349
|
/**
|
|
366
350
|
* Constructs a base node
|
|
351
|
+
* @param input
|
|
367
352
|
* @param $ {?INodePrivate}
|
|
368
353
|
*/
|
|
369
|
-
constructor($) {
|
|
370
|
-
super($ || new INodePrivate);
|
|
371
|
-
this
|
|
354
|
+
constructor(input, $) {
|
|
355
|
+
super(input, $ || new INodePrivate);
|
|
356
|
+
this.seal();
|
|
372
357
|
}
|
|
373
358
|
/**
|
|
374
359
|
* Get the bound node
|
|
@@ -376,78 +361,55 @@ export class INode extends Fragment {
|
|
|
376
361
|
get node() {
|
|
377
362
|
return this.$.node;
|
|
378
363
|
}
|
|
379
|
-
/**
|
|
380
|
-
* Initialize node
|
|
381
|
-
*/
|
|
382
|
-
$init() {
|
|
383
|
-
this.$createSignals();
|
|
384
|
-
this.$createWatchers();
|
|
385
|
-
this.$createAttrs();
|
|
386
|
-
this.$createStyle();
|
|
387
|
-
this.$created();
|
|
388
|
-
this.$compose();
|
|
389
|
-
this.$mounted();
|
|
390
|
-
return this;
|
|
391
|
-
}
|
|
392
|
-
/** To be overloaded: attributes creation milestone */
|
|
393
|
-
$createAttrs() {
|
|
394
|
-
// empty
|
|
395
|
-
}
|
|
396
|
-
/** To be overloaded: $style attributes creation milestone */
|
|
397
|
-
$createStyle() {
|
|
398
|
-
// empty
|
|
399
|
-
}
|
|
400
364
|
/**
|
|
401
365
|
* Bind attribute value
|
|
402
366
|
* @param name {String} name of attribute
|
|
403
367
|
* @param value {IValue} value
|
|
404
368
|
*/
|
|
405
|
-
|
|
369
|
+
attr(name, value) {
|
|
406
370
|
const $ = this.$;
|
|
407
371
|
const attr = new AttributeBinding(this, name, value);
|
|
408
372
|
$.bindings.add(attr);
|
|
409
|
-
return this;
|
|
410
|
-
}
|
|
411
|
-
$bindAttr(name, calculator, v1, v2, v3, v4, v5, v6, v7, v8, v9) {
|
|
412
|
-
const $ = this.$;
|
|
413
|
-
const expr = this.$bind(calculator, v1, v2, v3, v4, v5, v6, v7, v8, v9);
|
|
414
|
-
$.bindings.add(new AttributeBinding(this, name, expr));
|
|
415
|
-
return this;
|
|
416
373
|
}
|
|
417
374
|
/**
|
|
418
375
|
* Set attribute value
|
|
419
376
|
* @param name {string} name of attribute
|
|
420
377
|
* @param value {string} value
|
|
421
378
|
*/
|
|
422
|
-
|
|
423
|
-
|
|
379
|
+
setAttr(name, value) {
|
|
380
|
+
if (typeof value === 'boolean') {
|
|
381
|
+
if (value) {
|
|
382
|
+
this.$.node.setAttribute(name, "");
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
else {
|
|
386
|
+
this.$.node.setAttribute(name, `${value}`);
|
|
387
|
+
}
|
|
424
388
|
return this;
|
|
425
389
|
}
|
|
426
390
|
/**
|
|
427
391
|
* Adds a CSS class
|
|
428
392
|
* @param cl {string} Class name
|
|
429
393
|
*/
|
|
430
|
-
|
|
431
|
-
this.$.
|
|
394
|
+
addClass(cl) {
|
|
395
|
+
this.$.node.classList.add(cl);
|
|
432
396
|
return this;
|
|
433
397
|
}
|
|
434
398
|
/**
|
|
435
399
|
* Adds some CSS classes
|
|
436
400
|
* @param cls {...string} classes names
|
|
437
401
|
*/
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
this.$.app.$run.addClass(this.$.node, cl);
|
|
441
|
-
});
|
|
402
|
+
removeClasse(cl) {
|
|
403
|
+
this.$.node.classList.remove(cl);
|
|
442
404
|
return this;
|
|
443
405
|
}
|
|
444
406
|
/**
|
|
445
407
|
* Bind a CSS class
|
|
446
408
|
* @param className {IValue}
|
|
447
409
|
*/
|
|
448
|
-
|
|
410
|
+
bindClass(className) {
|
|
449
411
|
const $ = this.$;
|
|
450
|
-
$.bindings.add(new
|
|
412
|
+
$.bindings.add(new DynamicalClassBinding(this, className));
|
|
451
413
|
return this;
|
|
452
414
|
}
|
|
453
415
|
/**
|
|
@@ -455,8 +417,8 @@ export class INode extends Fragment {
|
|
|
455
417
|
* @param cond {IValue} condition
|
|
456
418
|
* @param className {string} class name
|
|
457
419
|
*/
|
|
458
|
-
|
|
459
|
-
this.$.bindings.add(new
|
|
420
|
+
floatingClass(cond, className) {
|
|
421
|
+
this.$.bindings.add(new StaticClassBinding(this, className, cond));
|
|
460
422
|
return this;
|
|
461
423
|
}
|
|
462
424
|
/**
|
|
@@ -464,7 +426,7 @@ export class INode extends Fragment {
|
|
|
464
426
|
* @param name {String} name of style attribute
|
|
465
427
|
* @param value {IValue} value
|
|
466
428
|
*/
|
|
467
|
-
|
|
429
|
+
style(name, value) {
|
|
468
430
|
const $ = this.$;
|
|
469
431
|
if ($.node instanceof HTMLElement) {
|
|
470
432
|
$.bindings.add(new StyleBinding(this, name, value));
|
|
@@ -474,28 +436,17 @@ export class INode extends Fragment {
|
|
|
474
436
|
}
|
|
475
437
|
return this;
|
|
476
438
|
}
|
|
477
|
-
$bindStyle(name, calculator, v1, v2, v3, v4, v5, v6, v7, v8, v9) {
|
|
478
|
-
const $ = this.$;
|
|
479
|
-
const expr = this.$bind(calculator, v1, v2, v3, v4, v5, v6, v7, v8, v9);
|
|
480
|
-
if ($.node instanceof HTMLElement) {
|
|
481
|
-
$.bindings.add(new StyleBinding(this, name, expr));
|
|
482
|
-
}
|
|
483
|
-
else {
|
|
484
|
-
throw userError('style can be applied to HTML elements only', 'non-html-element');
|
|
485
|
-
}
|
|
486
|
-
return this;
|
|
487
|
-
}
|
|
488
439
|
/**
|
|
489
440
|
* Sets a style property value
|
|
490
441
|
* @param prop {string} Property name
|
|
491
442
|
* @param value {string} Property value
|
|
492
443
|
*/
|
|
493
|
-
|
|
444
|
+
setStyle(prop, value) {
|
|
494
445
|
if (this.$.node instanceof HTMLElement) {
|
|
495
|
-
this.$.
|
|
446
|
+
this.$.node.style.setProperty(prop, value);
|
|
496
447
|
}
|
|
497
448
|
else {
|
|
498
|
-
throw userError("Style can be
|
|
449
|
+
throw userError("Style can be set for HTML elements only", "non-html-element");
|
|
499
450
|
}
|
|
500
451
|
return this;
|
|
501
452
|
}
|
|
@@ -505,403 +456,24 @@ export class INode extends Fragment {
|
|
|
505
456
|
* @param handler {function (Event)} Event handler
|
|
506
457
|
* @param options {Object | boolean} addEventListener options
|
|
507
458
|
*/
|
|
508
|
-
|
|
459
|
+
listen(name, handler, options) {
|
|
509
460
|
this.$.node.addEventListener(name, handler, options);
|
|
510
461
|
return this;
|
|
511
462
|
}
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
* @param options {Object | boolean}
|
|
515
|
-
*/
|
|
516
|
-
$oncontextmenu(handler, options) {
|
|
517
|
-
return this.$listen("contextmenu", handler, options);
|
|
518
|
-
}
|
|
519
|
-
/**
|
|
520
|
-
* @param handler {function (MouseEvent)}
|
|
521
|
-
* @param options {Object | boolean}
|
|
522
|
-
*/
|
|
523
|
-
$onmousedown(handler, options) {
|
|
524
|
-
return this.$listen("mousedown", handler, options);
|
|
525
|
-
}
|
|
526
|
-
/**
|
|
527
|
-
* @param handler {function (MouseEvent)}
|
|
528
|
-
* @param options {Object | boolean}
|
|
529
|
-
*/
|
|
530
|
-
$onmouseenter(handler, options) {
|
|
531
|
-
return this.$listen("mouseenter", handler, options);
|
|
532
|
-
}
|
|
533
|
-
/**
|
|
534
|
-
* @param handler {function (MouseEvent)}
|
|
535
|
-
* @param options {Object | boolean}
|
|
536
|
-
*/
|
|
537
|
-
$onmouseleave(handler, options) {
|
|
538
|
-
return this.$listen("mouseleave", handler, options);
|
|
539
|
-
}
|
|
540
|
-
/**
|
|
541
|
-
* @param handler {function (MouseEvent)}
|
|
542
|
-
* @param options {Object | boolean}
|
|
543
|
-
*/
|
|
544
|
-
$onmousemove(handler, options) {
|
|
545
|
-
return this.$listen("mousemove", handler, options);
|
|
546
|
-
}
|
|
547
|
-
/**
|
|
548
|
-
* @param handler {function (MouseEvent)}
|
|
549
|
-
* @param options {Object | boolean}
|
|
550
|
-
*/
|
|
551
|
-
$onmouseout(handler, options) {
|
|
552
|
-
return this.$listen("mouseout", handler, options);
|
|
553
|
-
}
|
|
554
|
-
/**
|
|
555
|
-
* @param handler {function (MouseEvent)}
|
|
556
|
-
* @param options {Object | boolean}
|
|
557
|
-
*/
|
|
558
|
-
$onmouseover(handler, options) {
|
|
559
|
-
return this.$listen("mouseover", handler, options);
|
|
560
|
-
}
|
|
561
|
-
/**
|
|
562
|
-
* @param handler {function (MouseEvent)}
|
|
563
|
-
* @param options {Object | boolean}
|
|
564
|
-
*/
|
|
565
|
-
$onmouseup(handler, options) {
|
|
566
|
-
return this.$listen("mouseup", handler, options);
|
|
567
|
-
}
|
|
568
|
-
/**
|
|
569
|
-
* @param handler {function (MouseEvent)}
|
|
570
|
-
* @param options {Object | boolean}
|
|
571
|
-
*/
|
|
572
|
-
$onclick(handler, options) {
|
|
573
|
-
return this.$listen("click", handler, options);
|
|
574
|
-
}
|
|
575
|
-
/**
|
|
576
|
-
* @param handler {function (MouseEvent)}
|
|
577
|
-
* @param options {Object | boolean}
|
|
578
|
-
*/
|
|
579
|
-
$ondblclick(handler, options) {
|
|
580
|
-
return this.$listen("dblclick", handler, options);
|
|
581
|
-
}
|
|
582
|
-
/**
|
|
583
|
-
* @param handler {function (FocusEvent)}
|
|
584
|
-
* @param options {Object | boolean}
|
|
585
|
-
*/
|
|
586
|
-
$onblur(handler, options) {
|
|
587
|
-
return this.$listen("blur", handler, options);
|
|
588
|
-
}
|
|
589
|
-
/**
|
|
590
|
-
* @param handler {function (FocusEvent)}
|
|
591
|
-
* @param options {Object | boolean}
|
|
592
|
-
*/
|
|
593
|
-
$onfocus(handler, options) {
|
|
594
|
-
return this.$listen("focus", handler, options);
|
|
595
|
-
}
|
|
596
|
-
/**
|
|
597
|
-
* @param handler {function (FocusEvent)}
|
|
598
|
-
* @param options {Object | boolean}
|
|
599
|
-
*/
|
|
600
|
-
$onfocusin(handler, options) {
|
|
601
|
-
return this.$listen("focusin", handler, options);
|
|
602
|
-
}
|
|
603
|
-
/**
|
|
604
|
-
* @param handler {function (FocusEvent)}
|
|
605
|
-
* @param options {Object | boolean}
|
|
606
|
-
*/
|
|
607
|
-
$onfocusout(handler, options) {
|
|
608
|
-
return this.$listen("focusout", handler, options);
|
|
609
|
-
}
|
|
610
|
-
/**
|
|
611
|
-
* @param handler {function (KeyboardEvent)}
|
|
612
|
-
* @param options {Object | boolean}
|
|
613
|
-
*/
|
|
614
|
-
$onkeydown(handler, options) {
|
|
615
|
-
return this.$listen("keydown", handler, options);
|
|
616
|
-
}
|
|
617
|
-
/**
|
|
618
|
-
* @param handler {function (KeyboardEvent)}
|
|
619
|
-
* @param options {Object | boolean}
|
|
620
|
-
*/
|
|
621
|
-
$onkeyup(handler, options) {
|
|
622
|
-
return this.$listen("keyup", handler, options);
|
|
623
|
-
}
|
|
624
|
-
/**
|
|
625
|
-
* @param handler {function (KeyboardEvent)}
|
|
626
|
-
* @param options {Object | boolean}
|
|
627
|
-
*/
|
|
628
|
-
$onkeypress(handler, options) {
|
|
629
|
-
return this.$listen("keypress", handler, options);
|
|
630
|
-
}
|
|
631
|
-
/**
|
|
632
|
-
* @param handler {function (TouchEvent)}
|
|
633
|
-
* @param options {Object | boolean}
|
|
634
|
-
*/
|
|
635
|
-
$ontouchstart(handler, options) {
|
|
636
|
-
return this.$listen("touchstart", handler, options);
|
|
637
|
-
}
|
|
638
|
-
/**
|
|
639
|
-
* @param handler {function (TouchEvent)}
|
|
640
|
-
* @param options {Object | boolean}
|
|
641
|
-
*/
|
|
642
|
-
$ontouchmove(handler, options) {
|
|
643
|
-
return this.$listen("touchmove", handler, options);
|
|
644
|
-
}
|
|
645
|
-
/**
|
|
646
|
-
* @param handler {function (TouchEvent)}
|
|
647
|
-
* @param options {Object | boolean}
|
|
648
|
-
*/
|
|
649
|
-
$ontouchend(handler, options) {
|
|
650
|
-
return this.$listen("touchend", handler, options);
|
|
651
|
-
}
|
|
652
|
-
/**
|
|
653
|
-
* @param handler {function (TouchEvent)}
|
|
654
|
-
* @param options {Object | boolean}
|
|
655
|
-
*/
|
|
656
|
-
$ontouchcancel(handler, options) {
|
|
657
|
-
return this.$listen("touchcancel", handler, options);
|
|
658
|
-
}
|
|
659
|
-
/**
|
|
660
|
-
* @param handler {function (WheelEvent)}
|
|
661
|
-
* @param options {Object | boolean}
|
|
662
|
-
*/
|
|
663
|
-
$onwheel(handler, options) {
|
|
664
|
-
return this.$listen("wheel", handler, options);
|
|
665
|
-
}
|
|
666
|
-
/**
|
|
667
|
-
* @param handler {function (ProgressEvent)}
|
|
668
|
-
* @param options {Object | boolean}
|
|
669
|
-
*/
|
|
670
|
-
$onabort(handler, options) {
|
|
671
|
-
return this.$listen("abort", handler, options);
|
|
672
|
-
}
|
|
673
|
-
/**
|
|
674
|
-
* @param handler {function (ProgressEvent)}
|
|
675
|
-
* @param options {Object | boolean}
|
|
676
|
-
*/
|
|
677
|
-
$onerror(handler, options) {
|
|
678
|
-
return this.$listen("error", handler, options);
|
|
679
|
-
}
|
|
680
|
-
/**
|
|
681
|
-
* @param handler {function (ProgressEvent)}
|
|
682
|
-
* @param options {Object | boolean}
|
|
683
|
-
*/
|
|
684
|
-
$onload(handler, options) {
|
|
685
|
-
return this.$listen("load", handler, options);
|
|
686
|
-
}
|
|
687
|
-
/**
|
|
688
|
-
* @param handler {function (ProgressEvent)}
|
|
689
|
-
* @param options {Object | boolean}
|
|
690
|
-
*/
|
|
691
|
-
$onloadend(handler, options) {
|
|
692
|
-
return this.$listen("loadend", handler, options);
|
|
693
|
-
}
|
|
694
|
-
/**
|
|
695
|
-
* @param handler {function (ProgressEvent)}
|
|
696
|
-
* @param options {Object | boolean}
|
|
697
|
-
*/
|
|
698
|
-
$onloadstart(handler, options) {
|
|
699
|
-
return this.$listen("loadstart", handler, options);
|
|
700
|
-
}
|
|
701
|
-
/**
|
|
702
|
-
* @param handler {function (ProgressEvent)}
|
|
703
|
-
* @param options {Object | boolean}
|
|
704
|
-
*/
|
|
705
|
-
$onprogress(handler, options) {
|
|
706
|
-
return this.$listen("progress", handler, options);
|
|
707
|
-
}
|
|
708
|
-
/**
|
|
709
|
-
* @param handler {function (ProgressEvent)}
|
|
710
|
-
* @param options {Object | boolean}
|
|
711
|
-
*/
|
|
712
|
-
$ontimeout(handler, options) {
|
|
713
|
-
return this.$listen("timeout", handler, options);
|
|
714
|
-
}
|
|
715
|
-
/**
|
|
716
|
-
* @param handler {function (DragEvent)}
|
|
717
|
-
* @param options {Object | boolean}
|
|
718
|
-
*/
|
|
719
|
-
$ondrag(handler, options) {
|
|
720
|
-
return this.$listen("drag", handler, options);
|
|
721
|
-
}
|
|
722
|
-
/**
|
|
723
|
-
* @param handler {function (DragEvent)}
|
|
724
|
-
* @param options {Object | boolean}
|
|
725
|
-
*/
|
|
726
|
-
$ondragend(handler, options) {
|
|
727
|
-
return this.$listen("dragend", handler, options);
|
|
728
|
-
}
|
|
729
|
-
/**
|
|
730
|
-
* @param handler {function (DragEvent)}
|
|
731
|
-
* @param options {Object | boolean}
|
|
732
|
-
*/
|
|
733
|
-
$ondragenter(handler, options) {
|
|
734
|
-
return this.$listen("dragenter", handler, options);
|
|
735
|
-
}
|
|
736
|
-
/**
|
|
737
|
-
* @param handler {function (DragEvent)}
|
|
738
|
-
* @param options {Object | boolean}
|
|
739
|
-
*/
|
|
740
|
-
$ondragexit(handler, options) {
|
|
741
|
-
return this.$listen("dragexit", handler, options);
|
|
742
|
-
}
|
|
743
|
-
/**
|
|
744
|
-
* @param handler {function (DragEvent)}
|
|
745
|
-
* @param options {Object | boolean}
|
|
746
|
-
*/
|
|
747
|
-
$ondragleave(handler, options) {
|
|
748
|
-
return this.$listen("dragleave", handler, options);
|
|
749
|
-
}
|
|
750
|
-
/**
|
|
751
|
-
* @param handler {function (DragEvent)}
|
|
752
|
-
* @param options {Object | boolean}
|
|
753
|
-
*/
|
|
754
|
-
$ondragover(handler, options) {
|
|
755
|
-
return this.$listen("dragover", handler, options);
|
|
756
|
-
}
|
|
757
|
-
/**
|
|
758
|
-
* @param handler {function (DragEvent)}
|
|
759
|
-
* @param options {Object | boolean}
|
|
760
|
-
*/
|
|
761
|
-
$ondragstart(handler, options) {
|
|
762
|
-
return this.$listen("dragstart", handler, options);
|
|
763
|
-
}
|
|
764
|
-
/**
|
|
765
|
-
* @param handler {function (DragEvent)}
|
|
766
|
-
* @param options {Object | boolean}
|
|
767
|
-
*/
|
|
768
|
-
$ondrop(handler, options) {
|
|
769
|
-
return this.$listen("drop", handler, options);
|
|
770
|
-
}
|
|
771
|
-
/**
|
|
772
|
-
* @param handler {function (PointerEvent)}
|
|
773
|
-
* @param options {Object | boolean}
|
|
774
|
-
*/
|
|
775
|
-
$onpointerover(handler, options) {
|
|
776
|
-
return this.$listen("pointerover", handler, options);
|
|
777
|
-
}
|
|
778
|
-
/**
|
|
779
|
-
* @param handler {function (PointerEvent)}
|
|
780
|
-
* @param options {Object | boolean}
|
|
781
|
-
*/
|
|
782
|
-
$onpointerenter(handler, options) {
|
|
783
|
-
return this.$listen("pointerenter", handler, options);
|
|
784
|
-
}
|
|
785
|
-
/**
|
|
786
|
-
* @param handler {function (PointerEvent)}
|
|
787
|
-
* @param options {Object | boolean}
|
|
788
|
-
*/
|
|
789
|
-
$onpointerdown(handler, options) {
|
|
790
|
-
return this.$listen("pointerdown", handler, options);
|
|
791
|
-
}
|
|
792
|
-
/**
|
|
793
|
-
* @param handler {function (PointerEvent)}
|
|
794
|
-
* @param options {Object | boolean}
|
|
795
|
-
*/
|
|
796
|
-
$onpointermove(handler, options) {
|
|
797
|
-
return this.$listen("pointermove", handler, options);
|
|
798
|
-
}
|
|
799
|
-
/**
|
|
800
|
-
* @param handler {function (PointerEvent)}
|
|
801
|
-
* @param options {Object | boolean}
|
|
802
|
-
*/
|
|
803
|
-
$onpointerup(handler, options) {
|
|
804
|
-
return this.$listen("pointerup", handler, options);
|
|
805
|
-
}
|
|
806
|
-
/**
|
|
807
|
-
* @param handler {function (PointerEvent)}
|
|
808
|
-
* @param options {Object | boolean}
|
|
809
|
-
*/
|
|
810
|
-
$onpointercancel(handler, options) {
|
|
811
|
-
return this.$listen("pointercancel", handler, options);
|
|
812
|
-
}
|
|
813
|
-
/**
|
|
814
|
-
* @param handler {function (PointerEvent)}
|
|
815
|
-
* @param options {Object | boolean}
|
|
816
|
-
*/
|
|
817
|
-
$onpointerout(handler, options) {
|
|
818
|
-
return this.$listen("pointerout", handler, options);
|
|
819
|
-
}
|
|
820
|
-
/**
|
|
821
|
-
* @param handler {function (PointerEvent)}
|
|
822
|
-
* @param options {Object | boolean}
|
|
823
|
-
*/
|
|
824
|
-
$onpointerleave(handler, options) {
|
|
825
|
-
return this.$listen("pointerleave", handler, options);
|
|
826
|
-
}
|
|
827
|
-
/**
|
|
828
|
-
* @param handler {function (PointerEvent)}
|
|
829
|
-
* @param options {Object | boolean}
|
|
830
|
-
*/
|
|
831
|
-
$ongotpointercapture(handler, options) {
|
|
832
|
-
return this.$listen("gotpointercapture", handler, options);
|
|
833
|
-
}
|
|
834
|
-
/**
|
|
835
|
-
* @param handler {function (PointerEvent)}
|
|
836
|
-
* @param options {Object | boolean}
|
|
837
|
-
*/
|
|
838
|
-
$onlostpointercapture(handler, options) {
|
|
839
|
-
return this.$listen("lostpointercapture", handler, options);
|
|
840
|
-
}
|
|
841
|
-
/**
|
|
842
|
-
* @param handler {function (AnimationEvent)}
|
|
843
|
-
* @param options {Object | boolean}
|
|
844
|
-
*/
|
|
845
|
-
$onanimationstart(handler, options) {
|
|
846
|
-
return this.$listen("animationstart", handler, options);
|
|
847
|
-
}
|
|
848
|
-
/**
|
|
849
|
-
* @param handler {function (AnimationEvent)}
|
|
850
|
-
* @param options {Object | boolean}
|
|
851
|
-
*/
|
|
852
|
-
$onanimationend(handler, options) {
|
|
853
|
-
return this.$listen("animationend", handler, options);
|
|
854
|
-
}
|
|
855
|
-
/**
|
|
856
|
-
* @param handler {function (AnimationEvent)}
|
|
857
|
-
* @param options {Object | boolean}
|
|
858
|
-
*/
|
|
859
|
-
$onanimationiteraton(handler, options) {
|
|
860
|
-
return this.$listen("animationiteration", handler, options);
|
|
861
|
-
}
|
|
862
|
-
/**
|
|
863
|
-
* @param handler {function (ClipboardEvent)}
|
|
864
|
-
* @param options {Object | boolean}
|
|
865
|
-
*/
|
|
866
|
-
$onclipboardchange(handler, options) {
|
|
867
|
-
return this.$listen("clipboardchange", handler, options);
|
|
868
|
-
}
|
|
869
|
-
/**
|
|
870
|
-
* @param handler {function (ClipboardEvent)}
|
|
871
|
-
* @param options {Object | boolean}
|
|
872
|
-
*/
|
|
873
|
-
$oncut(handler, options) {
|
|
874
|
-
return this.$listen("cut", handler, options);
|
|
875
|
-
}
|
|
876
|
-
/**
|
|
877
|
-
* @param handler {function (ClipboardEvent)}
|
|
878
|
-
* @param options {Object | boolean}
|
|
879
|
-
*/
|
|
880
|
-
$oncopy(handler, options) {
|
|
881
|
-
return this.$listen("copy", handler, options);
|
|
882
|
-
}
|
|
883
|
-
/**
|
|
884
|
-
* @param handler {function (ClipboardEvent)}
|
|
885
|
-
* @param options {Object | boolean}
|
|
886
|
-
*/
|
|
887
|
-
$onpaste(handler, options) {
|
|
888
|
-
return this.$listen("paste", handler, options);
|
|
889
|
-
}
|
|
890
|
-
$$insertAdjacent(node) {
|
|
891
|
-
const $ = this.$;
|
|
892
|
-
$.app.$run.insertBefore($.node, node);
|
|
463
|
+
insertAdjacent(node) {
|
|
464
|
+
this.$.node.parentNode.insertBefore(node, this.$.node);
|
|
893
465
|
}
|
|
894
466
|
/**
|
|
895
467
|
* A v-show & ngShow alternative
|
|
896
468
|
* @param cond {IValue} show condition
|
|
897
469
|
*/
|
|
898
|
-
|
|
470
|
+
bindShow(cond) {
|
|
899
471
|
const $ = this.$;
|
|
900
472
|
const node = $.node;
|
|
901
473
|
if (node instanceof HTMLElement) {
|
|
902
474
|
let lastDisplay = node.style.display;
|
|
903
475
|
const htmlNode = node;
|
|
904
|
-
return this
|
|
476
|
+
return this.bindAlive(cond, () => {
|
|
905
477
|
lastDisplay = htmlNode.style.display;
|
|
906
478
|
htmlNode.style.display = 'none';
|
|
907
479
|
}, () => {
|
|
@@ -916,19 +488,105 @@ export class INode extends Fragment {
|
|
|
916
488
|
* bind HTML
|
|
917
489
|
* @param value {IValue}
|
|
918
490
|
*/
|
|
919
|
-
|
|
491
|
+
bindDomApi(name, value) {
|
|
920
492
|
const $ = this.$;
|
|
921
493
|
const node = $.node;
|
|
922
494
|
if (node instanceof HTMLElement) {
|
|
923
|
-
node
|
|
924
|
-
this
|
|
925
|
-
node
|
|
495
|
+
node[name] = value.$;
|
|
496
|
+
this.watch((v) => {
|
|
497
|
+
node[name] = v;
|
|
926
498
|
}, value);
|
|
927
499
|
}
|
|
928
500
|
else {
|
|
929
501
|
throw userError("HTML can be bound for HTML nodes only", "dom-error");
|
|
930
502
|
}
|
|
931
503
|
}
|
|
504
|
+
applyOptions(options) {
|
|
505
|
+
options["v:attr"] && Object.keys(options["v:attr"]).forEach(name => {
|
|
506
|
+
const value = options["v:attr"][name];
|
|
507
|
+
if (value instanceof IValue) {
|
|
508
|
+
this.attr(name, value);
|
|
509
|
+
}
|
|
510
|
+
else {
|
|
511
|
+
this.setAttr(name, value);
|
|
512
|
+
}
|
|
513
|
+
});
|
|
514
|
+
if (options.class) {
|
|
515
|
+
const handleClass = (name, value) => {
|
|
516
|
+
if (value instanceof IValue) {
|
|
517
|
+
this.floatingClass(value, name);
|
|
518
|
+
}
|
|
519
|
+
else if (value && name !== '$') {
|
|
520
|
+
this.addClass(name);
|
|
521
|
+
}
|
|
522
|
+
else {
|
|
523
|
+
this.removeClasse(name);
|
|
524
|
+
}
|
|
525
|
+
};
|
|
526
|
+
if (Array.isArray(options.class)) {
|
|
527
|
+
options.class.forEach(item => {
|
|
528
|
+
if (item instanceof IValue) {
|
|
529
|
+
this.bindClass(item);
|
|
530
|
+
}
|
|
531
|
+
else if (typeof item == "string") {
|
|
532
|
+
this.addClass(item);
|
|
533
|
+
}
|
|
534
|
+
else {
|
|
535
|
+
Reflect.ownKeys(item).forEach((name) => {
|
|
536
|
+
handleClass(name, item[name]);
|
|
537
|
+
});
|
|
538
|
+
}
|
|
539
|
+
});
|
|
540
|
+
}
|
|
541
|
+
else {
|
|
542
|
+
options.class.$.forEach(item => {
|
|
543
|
+
this.bindClass(item);
|
|
544
|
+
});
|
|
545
|
+
Reflect.ownKeys(options.class).forEach((name) => {
|
|
546
|
+
handleClass(name, options.class[name]);
|
|
547
|
+
});
|
|
548
|
+
}
|
|
549
|
+
}
|
|
550
|
+
options.style && Object.keys(options.style).forEach(name => {
|
|
551
|
+
const value = options.style[name];
|
|
552
|
+
if (value instanceof IValue) {
|
|
553
|
+
this.style(name, value);
|
|
554
|
+
}
|
|
555
|
+
else if (typeof value === "string") {
|
|
556
|
+
this.setStyle(name, value);
|
|
557
|
+
}
|
|
558
|
+
else {
|
|
559
|
+
if (value[0] instanceof IValue) {
|
|
560
|
+
this.style(name, this.expr((v) => v + value[1], value[0]));
|
|
561
|
+
}
|
|
562
|
+
else {
|
|
563
|
+
this.setStyle(name, value[0] + value[1]);
|
|
564
|
+
}
|
|
565
|
+
}
|
|
566
|
+
});
|
|
567
|
+
options["v:events"] && Object.keys(options["v:events"]).forEach(name => {
|
|
568
|
+
this.listen(name, options["v:events"][name]);
|
|
569
|
+
});
|
|
570
|
+
if (options["v:bind"]) {
|
|
571
|
+
const inode = this.node;
|
|
572
|
+
Reflect.ownKeys(options["v:bind"]).forEach((k) => {
|
|
573
|
+
const value = options["v:bind"][k];
|
|
574
|
+
if (k === 'value' && (inode instanceof HTMLInputElement || inode instanceof HTMLTextAreaElement)) {
|
|
575
|
+
inode.oninput = () => value.$ = inode.value;
|
|
576
|
+
}
|
|
577
|
+
else if (k === 'checked' && inode instanceof HTMLInputElement) {
|
|
578
|
+
inode.oninput = () => value.$ = inode.checked;
|
|
579
|
+
}
|
|
580
|
+
else if (k === 'volume' && inode instanceof HTMLMediaElement) {
|
|
581
|
+
inode.onvolumechange = () => value.$ = inode.volume;
|
|
582
|
+
}
|
|
583
|
+
this.bindDomApi(k, value);
|
|
584
|
+
});
|
|
585
|
+
}
|
|
586
|
+
options["v:set"] && Object.keys(options["v:set"]).forEach(key => {
|
|
587
|
+
this.node[key] = options["v:set"][key];
|
|
588
|
+
});
|
|
589
|
+
}
|
|
932
590
|
}
|
|
933
591
|
/**
|
|
934
592
|
* Represents an Vasille.js HTML element node
|
|
@@ -936,11 +594,11 @@ export class INode extends Fragment {
|
|
|
936
594
|
* @extends INode
|
|
937
595
|
*/
|
|
938
596
|
export class Tag extends INode {
|
|
939
|
-
constructor() {
|
|
940
|
-
super();
|
|
941
|
-
this
|
|
597
|
+
constructor(input) {
|
|
598
|
+
super(input);
|
|
599
|
+
this.seal();
|
|
942
600
|
}
|
|
943
|
-
|
|
601
|
+
preinit(app, parent, tagName) {
|
|
944
602
|
if (!tagName || typeof tagName !== "string") {
|
|
945
603
|
throw internalError('wrong Tag::$preinit call');
|
|
946
604
|
}
|
|
@@ -948,55 +606,52 @@ export class Tag extends INode {
|
|
|
948
606
|
const $ = this.$;
|
|
949
607
|
$.preinit(app, parent);
|
|
950
608
|
$.node = node;
|
|
951
|
-
$.parent
|
|
609
|
+
$.parent.appendNode(node);
|
|
610
|
+
}
|
|
611
|
+
compose(input) {
|
|
612
|
+
input.slot && input.slot(this);
|
|
952
613
|
}
|
|
953
|
-
|
|
614
|
+
findFirstChild() {
|
|
954
615
|
return this.$.unmounted ? null : this.$.node;
|
|
955
616
|
}
|
|
956
|
-
|
|
617
|
+
insertAdjacent(node) {
|
|
957
618
|
if (this.$.unmounted) {
|
|
958
619
|
if (this.$.next) {
|
|
959
|
-
this.$.next
|
|
620
|
+
this.$.next.insertAdjacent(node);
|
|
960
621
|
}
|
|
961
622
|
else {
|
|
962
|
-
this.$.parent
|
|
623
|
+
this.$.parent.appendNode(node);
|
|
963
624
|
}
|
|
964
625
|
}
|
|
965
626
|
else {
|
|
966
|
-
super
|
|
627
|
+
super.insertAdjacent(node);
|
|
967
628
|
}
|
|
968
629
|
}
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
$.app.$run.appendChild($.node, node);
|
|
630
|
+
appendNode(node) {
|
|
631
|
+
this.$.node.appendChild(node);
|
|
972
632
|
}
|
|
973
633
|
/**
|
|
974
634
|
* Mount/Unmount a node
|
|
975
635
|
* @param cond {IValue} show condition
|
|
976
636
|
*/
|
|
977
|
-
|
|
637
|
+
bindMount(cond) {
|
|
978
638
|
const $ = this.$;
|
|
979
|
-
|
|
639
|
+
this.bindAlive(cond, () => {
|
|
980
640
|
$.node.remove();
|
|
981
641
|
$.unmounted = true;
|
|
982
642
|
}, () => {
|
|
983
|
-
if (
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
$.next.$$insertAdjacent($.node);
|
|
987
|
-
}
|
|
988
|
-
else {
|
|
989
|
-
$.parent.$$appendNode($.node);
|
|
643
|
+
if ($.unmounted) {
|
|
644
|
+
this.insertAdjacent($.node);
|
|
645
|
+
$.unmounted = false;
|
|
990
646
|
}
|
|
991
|
-
$.unmounted = false;
|
|
992
647
|
});
|
|
993
648
|
}
|
|
994
649
|
/**
|
|
995
650
|
* Runs GC
|
|
996
651
|
*/
|
|
997
|
-
|
|
652
|
+
destroy() {
|
|
998
653
|
this.node.remove();
|
|
999
|
-
super
|
|
654
|
+
super.destroy();
|
|
1000
655
|
}
|
|
1001
656
|
}
|
|
1002
657
|
/**
|
|
@@ -1005,22 +660,22 @@ export class Tag extends INode {
|
|
|
1005
660
|
* @extends INode
|
|
1006
661
|
*/
|
|
1007
662
|
export class Extension extends INode {
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
663
|
+
preinit(app, parent) {
|
|
664
|
+
const $ = this.$;
|
|
665
|
+
let it = parent;
|
|
666
|
+
while (it && !(it instanceof INode)) {
|
|
667
|
+
it = it.parent;
|
|
1013
668
|
}
|
|
1014
|
-
|
|
1015
|
-
|
|
669
|
+
if (it && it instanceof INode) {
|
|
670
|
+
$.node = it.node;
|
|
671
|
+
}
|
|
672
|
+
$.preinit(app, parent);
|
|
673
|
+
if (!it) {
|
|
674
|
+
throw userError("A extension node can be encapsulated only in a tag/extension/component", "virtual-dom");
|
|
1016
675
|
}
|
|
1017
676
|
}
|
|
1018
|
-
|
|
1019
|
-
super(
|
|
1020
|
-
this.$seal();
|
|
1021
|
-
}
|
|
1022
|
-
$destroy() {
|
|
1023
|
-
super.$destroy();
|
|
677
|
+
destroy() {
|
|
678
|
+
super.destroy();
|
|
1024
679
|
}
|
|
1025
680
|
}
|
|
1026
681
|
/**
|
|
@@ -1029,56 +684,60 @@ export class Extension extends INode {
|
|
|
1029
684
|
* @extends Extension
|
|
1030
685
|
*/
|
|
1031
686
|
export class Component extends Extension {
|
|
1032
|
-
|
|
1033
|
-
super();
|
|
1034
|
-
this
|
|
1035
|
-
|
|
1036
|
-
$mounted() {
|
|
1037
|
-
super.$mounted();
|
|
1038
|
-
if (this.$children.length !== 1) {
|
|
1039
|
-
throw userError("UserNode must have a child only", "dom-error");
|
|
687
|
+
ready() {
|
|
688
|
+
super.ready();
|
|
689
|
+
if (this.children.size !== 1) {
|
|
690
|
+
throw userError("Component must have a child only", "dom-error");
|
|
1040
691
|
}
|
|
1041
|
-
const child = this
|
|
692
|
+
const child = this.lastChild;
|
|
1042
693
|
if (child instanceof Tag || child instanceof Component) {
|
|
1043
694
|
const $ = this.$;
|
|
1044
695
|
$.node = child.node;
|
|
1045
696
|
}
|
|
1046
697
|
else {
|
|
1047
|
-
throw userError("
|
|
698
|
+
throw userError("Component child must be Tag or Component", "dom-error");
|
|
1048
699
|
}
|
|
1049
700
|
}
|
|
701
|
+
preinit(app, parent) {
|
|
702
|
+
this.$.preinit(app, parent);
|
|
703
|
+
}
|
|
1050
704
|
}
|
|
1051
705
|
/**
|
|
1052
706
|
* Private part of switch node
|
|
1053
707
|
* @class SwitchedNodePrivate
|
|
1054
708
|
* @extends INodePrivate
|
|
1055
709
|
*/
|
|
1056
|
-
export class SwitchedNodePrivate extends
|
|
710
|
+
export class SwitchedNodePrivate extends FragmentPrivate {
|
|
1057
711
|
constructor() {
|
|
1058
712
|
super();
|
|
1059
|
-
|
|
713
|
+
/**
|
|
714
|
+
* Array of possible cases
|
|
715
|
+
* @type {Array<{cond : IValue<boolean>, cb : function(Fragment)}>}
|
|
716
|
+
*/
|
|
717
|
+
this.cases = [];
|
|
718
|
+
this.seal();
|
|
1060
719
|
}
|
|
1061
720
|
/**
|
|
1062
721
|
* Runs GC
|
|
1063
722
|
*/
|
|
1064
|
-
|
|
723
|
+
destroy() {
|
|
1065
724
|
this.cases.forEach(c => {
|
|
1066
725
|
delete c.cond;
|
|
1067
726
|
delete c.cb;
|
|
1068
727
|
});
|
|
1069
728
|
this.cases.splice(0);
|
|
1070
|
-
super
|
|
729
|
+
super.destroy();
|
|
1071
730
|
}
|
|
1072
731
|
}
|
|
1073
732
|
/**
|
|
1074
733
|
* Defines a node witch can switch its children conditionally
|
|
1075
734
|
*/
|
|
1076
|
-
class SwitchedNode extends Fragment {
|
|
735
|
+
export class SwitchedNode extends Fragment {
|
|
1077
736
|
/**
|
|
1078
737
|
* Constructs a switch node and define a sync function
|
|
1079
738
|
*/
|
|
1080
739
|
constructor() {
|
|
1081
|
-
super(new SwitchedNodePrivate);
|
|
740
|
+
super({}, new SwitchedNodePrivate);
|
|
1082
741
|
this.$.sync = () => {
|
|
1083
742
|
const $ = this.$;
|
|
1084
743
|
let i = 0;
|
|
@@ -1090,10 +749,10 @@ class SwitchedNode extends Fragment {
|
|
|
1090
749
|
if (i === $.index) {
|
|
1091
750
|
return;
|
|
1092
751
|
}
|
|
1093
|
-
if (
|
|
1094
|
-
|
|
1095
|
-
this
|
|
1096
|
-
|
|
752
|
+
if (this.lastChild) {
|
|
753
|
+
this.lastChild.destroy();
|
|
754
|
+
this.children.clear();
|
|
755
|
+
this.lastChild = null;
|
|
1097
756
|
}
|
|
1098
757
|
if (i !== $.cases.length) {
|
|
1099
758
|
$.index = i;
|
|
@@ -1103,43 +762,38 @@ class SwitchedNode extends Fragment {
|
|
|
1103
762
|
$.index = -1;
|
|
1104
763
|
}
|
|
1105
764
|
};
|
|
1106
|
-
this
|
|
765
|
+
this.seal();
|
|
1107
766
|
}
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
setCases(cases) {
|
|
1113
|
-
const $ = this.$;
|
|
1114
|
-
$.cases = [...cases];
|
|
767
|
+
addCase(case_) {
|
|
768
|
+
this.$.cases.push(case_);
|
|
769
|
+
case_.cond.on(this.$.sync);
|
|
770
|
+
this.$.sync();
|
|
1115
771
|
}
|
|
1116
772
|
/**
|
|
1117
773
|
* Creates a child node
|
|
1118
774
|
* @param cb {function(Fragment)} Call-back
|
|
1119
775
|
*/
|
|
1120
776
|
createChild(cb) {
|
|
1121
|
-
const node = new Fragment();
|
|
1122
|
-
node
|
|
1123
|
-
node
|
|
1124
|
-
node
|
|
1125
|
-
this
|
|
1126
|
-
this.$children.push(node);
|
|
777
|
+
const node = new Fragment({});
|
|
778
|
+
node.preinit(this.$.app, this);
|
|
779
|
+
node.init();
|
|
780
|
+
this.lastChild = node;
|
|
781
|
+
this.children.add(node);
|
|
1127
782
|
cb(node);
|
|
1128
783
|
}
|
|
1129
|
-
|
|
784
|
+
ready() {
|
|
1130
785
|
const $ = this.$;
|
|
1131
|
-
super.$ready();
|
|
1132
786
|
$.cases.forEach(c => {
|
|
1133
787
|
c.cond.on($.sync);
|
|
1134
788
|
});
|
|
1135
789
|
$.sync();
|
|
1136
790
|
}
|
|
1137
|
-
|
|
791
|
+
destroy() {
|
|
1138
792
|
const $ = this.$;
|
|
1139
793
|
$.cases.forEach(c => {
|
|
1140
794
|
c.cond.off($.sync);
|
|
1141
795
|
});
|
|
1142
|
-
super
|
|
796
|
+
super.destroy();
|
|
1143
797
|
}
|
|
1144
798
|
}
|
|
1145
799
|
/**
|
|
@@ -1148,7 +802,7 @@ class SwitchedNode extends Fragment {
|
|
|
1148
802
|
export class DebugPrivate extends FragmentPrivate {
|
|
1149
803
|
constructor() {
|
|
1150
804
|
super();
|
|
1151
|
-
this
|
|
805
|
+
this.seal();
|
|
1152
806
|
}
|
|
1153
807
|
/**
|
|
1154
808
|
* Pre-initializes a text node
|
|
@@ -1162,14 +816,14 @@ export class DebugPrivate extends FragmentPrivate {
|
|
|
1162
816
|
this.bindings.add(new Expression((v) => {
|
|
1163
817
|
this.node.replaceData(0, -1, v);
|
|
1164
818
|
}, true, text));
|
|
1165
|
-
this.parent
|
|
819
|
+
this.parent.appendNode(this.node);
|
|
1166
820
|
}
|
|
1167
821
|
/**
|
|
1168
822
|
* Clear node data
|
|
1169
823
|
*/
|
|
1170
|
-
|
|
824
|
+
destroy() {
|
|
1171
825
|
this.node.remove();
|
|
1172
|
-
super
|
|
826
|
+
super.destroy();
|
|
1173
827
|
}
|
|
1174
828
|
}
|
|
1175
829
|
/**
|
|
@@ -1179,15 +833,15 @@ export class DebugPrivate extends FragmentPrivate {
|
|
|
1179
833
|
*/
|
|
1180
834
|
export class DebugNode extends Fragment {
|
|
1181
835
|
constructor() {
|
|
1182
|
-
super();
|
|
836
|
+
super({});
|
|
1183
837
|
/**
|
|
1184
838
|
* private data
|
|
1185
839
|
* @type {DebugNode}
|
|
1186
840
|
*/
|
|
1187
841
|
this.$ = new DebugPrivate();
|
|
1188
|
-
this
|
|
842
|
+
this.seal();
|
|
1189
843
|
}
|
|
1190
|
-
|
|
844
|
+
preinit(app, parent, text) {
|
|
1191
845
|
const $ = this.$;
|
|
1192
846
|
if (!text) {
|
|
1193
847
|
throw internalError('wrong DebugNode::$preninit call');
|
|
@@ -1197,8 +851,8 @@ export class DebugNode extends Fragment {
|
|
|
1197
851
|
/**
|
|
1198
852
|
* Runs garbage collector
|
|
1199
853
|
*/
|
|
1200
|
-
|
|
1201
|
-
this
|
|
1202
|
-
super
|
|
854
|
+
destroy() {
|
|
855
|
+
this.$.destroy();
|
|
856
|
+
super.destroy();
|
|
1203
857
|
}
|
|
1204
858
|
}
|