vasille 2.0.4 → 2.2.1
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 +947 -1006
- package/cdn/es5.js +1053 -1023
- package/flow-typed/vasille.js +2646 -838
- 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 +84 -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 +340 -681
- 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 +3 -1
- 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 +42 -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 +99 -423
- 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/cdn/es2015.js
CHANGED
|
@@ -1,4 +1,24 @@
|
|
|
1
1
|
(function(){
|
|
2
|
+
// ./lib/v/index.js
|
|
3
|
+
|
|
4
|
+
const v = Object.assign(Object.assign({ ref(value) {
|
|
5
|
+
return current.ref(value);
|
|
6
|
+
}, expr: expr, of: valueOf, sv: setValue, alwaysFalse: new Reference(false), app,
|
|
7
|
+
component,
|
|
8
|
+
fragment,
|
|
9
|
+
extension,
|
|
10
|
+
text,
|
|
11
|
+
tag,
|
|
12
|
+
create }, vx), { merge,
|
|
13
|
+
destructor() {
|
|
14
|
+
return current.destroy.bind(current);
|
|
15
|
+
},
|
|
16
|
+
runOnDestroy(callback) {
|
|
17
|
+
current.runOnDestroy(callback);
|
|
18
|
+
} });
|
|
19
|
+
|
|
20
|
+
window.v = v;
|
|
21
|
+
|
|
2
22
|
// ./lib/models/model.js
|
|
3
23
|
|
|
4
24
|
|
|
@@ -149,13 +169,14 @@ class ObjectModel extends Object {
|
|
|
149
169
|
*/
|
|
150
170
|
constructor(obj = {}) {
|
|
151
171
|
super();
|
|
172
|
+
this.container = Object.create(null);
|
|
152
173
|
Object.defineProperty(this, 'listener', {
|
|
153
174
|
value: new Listener,
|
|
154
175
|
writable: false,
|
|
155
176
|
configurable: false
|
|
156
177
|
});
|
|
157
178
|
for (const i in obj) {
|
|
158
|
-
Object.defineProperty(this, i, {
|
|
179
|
+
Object.defineProperty(this.container, i, {
|
|
159
180
|
value: obj[i],
|
|
160
181
|
configurable: true,
|
|
161
182
|
writable: true,
|
|
@@ -170,8 +191,7 @@ class ObjectModel extends Object {
|
|
|
170
191
|
* @return {*}
|
|
171
192
|
*/
|
|
172
193
|
get(key) {
|
|
173
|
-
|
|
174
|
-
return ts[key];
|
|
194
|
+
return this.container[key];
|
|
175
195
|
}
|
|
176
196
|
/**
|
|
177
197
|
* Sets an object property value
|
|
@@ -180,21 +200,19 @@ class ObjectModel extends Object {
|
|
|
180
200
|
* @return {ObjectModel} a pointer to this
|
|
181
201
|
*/
|
|
182
202
|
set(key, v) {
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
this.listener.emitRemoved(key, ts[key]);
|
|
187
|
-
ts[key] = v;
|
|
203
|
+
if (Reflect.has(this.container, key)) {
|
|
204
|
+
this.listener.emitRemoved(key, this.container[key]);
|
|
205
|
+
this.container[key] = v;
|
|
188
206
|
}
|
|
189
207
|
else {
|
|
190
|
-
Object.defineProperty(
|
|
208
|
+
Object.defineProperty(this.container, key, {
|
|
191
209
|
value: v,
|
|
192
210
|
configurable: true,
|
|
193
211
|
writable: true,
|
|
194
212
|
enumerable: true
|
|
195
213
|
});
|
|
196
214
|
}
|
|
197
|
-
this.listener.emitAdded(key,
|
|
215
|
+
this.listener.emitAdded(key, this.container[key]);
|
|
198
216
|
return this;
|
|
199
217
|
}
|
|
200
218
|
/**
|
|
@@ -202,12 +220,28 @@ class ObjectModel extends Object {
|
|
|
202
220
|
* @param key {string} property name
|
|
203
221
|
*/
|
|
204
222
|
delete(key) {
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
this.
|
|
208
|
-
delete ts[key];
|
|
223
|
+
if (this.container[key]) {
|
|
224
|
+
this.listener.emitRemoved(key, this.container[key]);
|
|
225
|
+
delete this.container[key];
|
|
209
226
|
}
|
|
210
227
|
}
|
|
228
|
+
proxy() {
|
|
229
|
+
// eslint-disable-next-line @typescript-eslint/no-this-alias
|
|
230
|
+
const ts = this;
|
|
231
|
+
return new Proxy(this.container, {
|
|
232
|
+
get(target, p) {
|
|
233
|
+
return ts.get(p);
|
|
234
|
+
},
|
|
235
|
+
set(target, p, value) {
|
|
236
|
+
ts.set(p, value);
|
|
237
|
+
return true;
|
|
238
|
+
},
|
|
239
|
+
deleteProperty(target, p) {
|
|
240
|
+
ts.delete(p);
|
|
241
|
+
return true;
|
|
242
|
+
}
|
|
243
|
+
});
|
|
244
|
+
}
|
|
211
245
|
enableReactivity() {
|
|
212
246
|
this.listener.enableReactivity();
|
|
213
247
|
}
|
|
@@ -373,6 +407,15 @@ class ArrayModel extends Array {
|
|
|
373
407
|
super.push(data[i]);
|
|
374
408
|
}
|
|
375
409
|
}
|
|
410
|
+
// proxy
|
|
411
|
+
proxy() {
|
|
412
|
+
return new Proxy(this, {
|
|
413
|
+
set(target, p, value) {
|
|
414
|
+
target.splice(parseInt(p), 1, value);
|
|
415
|
+
return true;
|
|
416
|
+
}
|
|
417
|
+
});
|
|
418
|
+
}
|
|
376
419
|
/* Array members */
|
|
377
420
|
/**
|
|
378
421
|
* Gets the last item of array
|
|
@@ -563,6 +606,266 @@ class ArrayModel extends Array {
|
|
|
563
606
|
|
|
564
607
|
window.ArrayModel = ArrayModel;
|
|
565
608
|
|
|
609
|
+
// ./lib/functional/merge.js
|
|
610
|
+
function merge(main, ...targets) {
|
|
611
|
+
function refactorClass(obj) {
|
|
612
|
+
if (Array.isArray(obj.class)) {
|
|
613
|
+
const out = {
|
|
614
|
+
$: []
|
|
615
|
+
};
|
|
616
|
+
obj.class.forEach(item => {
|
|
617
|
+
if (item instanceof IValue) {
|
|
618
|
+
out.$.push(item);
|
|
619
|
+
}
|
|
620
|
+
else if (typeof item === 'string') {
|
|
621
|
+
out[item] = true;
|
|
622
|
+
}
|
|
623
|
+
else if (typeof item === 'object') {
|
|
624
|
+
Object.assign(out, item);
|
|
625
|
+
}
|
|
626
|
+
});
|
|
627
|
+
obj.class = out;
|
|
628
|
+
}
|
|
629
|
+
}
|
|
630
|
+
refactorClass(main);
|
|
631
|
+
targets.forEach(target => {
|
|
632
|
+
Reflect.ownKeys(target).forEach((prop) => {
|
|
633
|
+
if (!Reflect.has(main, prop)) {
|
|
634
|
+
main[prop] = target[prop];
|
|
635
|
+
}
|
|
636
|
+
else if (typeof main[prop] === 'object' && typeof target[prop] === 'object') {
|
|
637
|
+
if (prop === 'class') {
|
|
638
|
+
refactorClass(target);
|
|
639
|
+
}
|
|
640
|
+
if (prop === '$' && Array.isArray(main[prop]) && Array.isArray(target[prop])) {
|
|
641
|
+
main.$.push(...target.$);
|
|
642
|
+
}
|
|
643
|
+
else {
|
|
644
|
+
merge(main[prop], target[prop]);
|
|
645
|
+
}
|
|
646
|
+
}
|
|
647
|
+
});
|
|
648
|
+
});
|
|
649
|
+
}
|
|
650
|
+
|
|
651
|
+
window.merge = merge;
|
|
652
|
+
|
|
653
|
+
// ./lib/functional/stack.js
|
|
654
|
+
function app(renderer) {
|
|
655
|
+
return (node, opts) => {
|
|
656
|
+
return new App(node, opts).runFunctional(renderer, opts);
|
|
657
|
+
};
|
|
658
|
+
}
|
|
659
|
+
function component(renderer) {
|
|
660
|
+
return (opts, callback) => {
|
|
661
|
+
const component = new Component(opts);
|
|
662
|
+
if (!(current instanceof Fragment))
|
|
663
|
+
throw userError('missing parent node', 'out-of-context');
|
|
664
|
+
let ret;
|
|
665
|
+
if (callback)
|
|
666
|
+
opts.slot = callback;
|
|
667
|
+
current.create(component, node => {
|
|
668
|
+
ret = node.runFunctional(renderer, opts);
|
|
669
|
+
});
|
|
670
|
+
return ret;
|
|
671
|
+
};
|
|
672
|
+
}
|
|
673
|
+
function fragment(renderer) {
|
|
674
|
+
return (opts, callback) => {
|
|
675
|
+
const frag = new Fragment(opts);
|
|
676
|
+
if (!(current instanceof Fragment))
|
|
677
|
+
throw userError('missing parent node', 'out-of-context');
|
|
678
|
+
if (callback)
|
|
679
|
+
opts.slot = callback;
|
|
680
|
+
current.create(frag);
|
|
681
|
+
return frag.runFunctional(renderer, opts);
|
|
682
|
+
};
|
|
683
|
+
}
|
|
684
|
+
function extension(renderer) {
|
|
685
|
+
return (opts, callback) => {
|
|
686
|
+
const ext = new Extension(opts);
|
|
687
|
+
if (!(current instanceof Fragment))
|
|
688
|
+
throw userError('missing parent node', 'out-of-context');
|
|
689
|
+
if (callback)
|
|
690
|
+
opts.slot = callback;
|
|
691
|
+
current.create(ext);
|
|
692
|
+
return ext.runFunctional(renderer, opts);
|
|
693
|
+
};
|
|
694
|
+
}
|
|
695
|
+
function tag(name, opts, callback) {
|
|
696
|
+
if (!(current instanceof Fragment))
|
|
697
|
+
throw userError('missing parent node', 'out-of-context');
|
|
698
|
+
return {
|
|
699
|
+
node: current.tag(name, opts, (node) => {
|
|
700
|
+
callback && node.runFunctional(callback);
|
|
701
|
+
})
|
|
702
|
+
};
|
|
703
|
+
}
|
|
704
|
+
function create(node, callback) {
|
|
705
|
+
if (!(current instanceof Fragment))
|
|
706
|
+
throw userError('missing current node', 'out-of-context');
|
|
707
|
+
current.create(node, (node, ...args) => {
|
|
708
|
+
callback && node.runFunctional(callback, ...args);
|
|
709
|
+
});
|
|
710
|
+
return node;
|
|
711
|
+
}
|
|
712
|
+
const vx = {
|
|
713
|
+
if(condition, callback) {
|
|
714
|
+
if (current instanceof Fragment) {
|
|
715
|
+
current.if(condition, node => node.runFunctional(callback));
|
|
716
|
+
}
|
|
717
|
+
else {
|
|
718
|
+
throw userError("wrong use of `v.if` function", "logic-error");
|
|
719
|
+
}
|
|
720
|
+
},
|
|
721
|
+
else(callback) {
|
|
722
|
+
if (current instanceof Fragment) {
|
|
723
|
+
current.else(node => node.runFunctional(callback));
|
|
724
|
+
}
|
|
725
|
+
else {
|
|
726
|
+
throw userError("wrong use of `v.else` function", "logic-error");
|
|
727
|
+
}
|
|
728
|
+
},
|
|
729
|
+
elif(condition, callback) {
|
|
730
|
+
if (current instanceof Fragment) {
|
|
731
|
+
current.elif(condition, node => node.runFunctional(callback));
|
|
732
|
+
}
|
|
733
|
+
else {
|
|
734
|
+
throw userError("wrong use of `v.elif` function", "logic-error");
|
|
735
|
+
}
|
|
736
|
+
},
|
|
737
|
+
for(model, callback) {
|
|
738
|
+
if (model instanceof ArrayModel) {
|
|
739
|
+
// for arrays T & K are the same type
|
|
740
|
+
create(new ArrayView({ model }), callback);
|
|
741
|
+
}
|
|
742
|
+
else if (model instanceof MapModel) {
|
|
743
|
+
create(new MapView({ model }), callback);
|
|
744
|
+
}
|
|
745
|
+
else if (model instanceof SetModel) {
|
|
746
|
+
// for sets T & K are the same type
|
|
747
|
+
create(new SetView({ model }), callback);
|
|
748
|
+
}
|
|
749
|
+
else if (model instanceof ObjectModel) {
|
|
750
|
+
// for objects K is always string
|
|
751
|
+
create(new ObjectView({ model }), callback);
|
|
752
|
+
}
|
|
753
|
+
else {
|
|
754
|
+
throw userError("wrong use of `v.for` function", 'wrong-model');
|
|
755
|
+
}
|
|
756
|
+
},
|
|
757
|
+
watch(model, callback) {
|
|
758
|
+
const opts = { model };
|
|
759
|
+
create(new Watch(opts), callback);
|
|
760
|
+
},
|
|
761
|
+
nextTick(callback) {
|
|
762
|
+
const node = current;
|
|
763
|
+
window.setTimeout(() => {
|
|
764
|
+
node.runFunctional(callback);
|
|
765
|
+
}, 0);
|
|
766
|
+
}
|
|
767
|
+
};
|
|
768
|
+
|
|
769
|
+
window.app = app;
|
|
770
|
+
window.component = component;
|
|
771
|
+
window.fragment = fragment;
|
|
772
|
+
window.extension = extension;
|
|
773
|
+
window.tag = tag;
|
|
774
|
+
window.create = create;
|
|
775
|
+
window.vx = vx;
|
|
776
|
+
|
|
777
|
+
// ./lib/functional/models.js
|
|
778
|
+
function arrayModel(arr = []) {
|
|
779
|
+
if (!current)
|
|
780
|
+
throw userError('missing parent node', 'out-of-context');
|
|
781
|
+
return current.register(new ArrayModel(arr)).proxy();
|
|
782
|
+
}
|
|
783
|
+
function mapModel(map = []) {
|
|
784
|
+
if (!current)
|
|
785
|
+
throw userError('missing parent node', 'out-of-context');
|
|
786
|
+
return current.register(new MapModel(map));
|
|
787
|
+
}
|
|
788
|
+
function setModel(arr = []) {
|
|
789
|
+
if (!current)
|
|
790
|
+
throw userError('missing parent node', 'out-of-context');
|
|
791
|
+
return current.register(new SetModel(arr));
|
|
792
|
+
}
|
|
793
|
+
function objectModel(obj = {}) {
|
|
794
|
+
if (!current)
|
|
795
|
+
throw userError('missing parent node', 'out-of-context');
|
|
796
|
+
return current.register(new ObjectModel(obj));
|
|
797
|
+
}
|
|
798
|
+
|
|
799
|
+
window.arrayModel = arrayModel;
|
|
800
|
+
window.mapModel = mapModel;
|
|
801
|
+
window.setModel = setModel;
|
|
802
|
+
window.objectModel = objectModel;
|
|
803
|
+
|
|
804
|
+
// ./lib/functional/options.js
|
|
805
|
+
|
|
806
|
+
|
|
807
|
+
|
|
808
|
+
// ./lib/functional/reactivity.js
|
|
809
|
+
function ref(value) {
|
|
810
|
+
const ref = current.ref(value);
|
|
811
|
+
return [ref, (value) => ref.$ = value];
|
|
812
|
+
}
|
|
813
|
+
function mirror(value) {
|
|
814
|
+
return current.mirror(value);
|
|
815
|
+
}
|
|
816
|
+
function forward(value) {
|
|
817
|
+
return current.forward(value);
|
|
818
|
+
}
|
|
819
|
+
function point(value) {
|
|
820
|
+
return current.point(value);
|
|
821
|
+
}
|
|
822
|
+
function expr(func, ...values) {
|
|
823
|
+
return current.expr(func, ...values);
|
|
824
|
+
}
|
|
825
|
+
function watch(func, ...values) {
|
|
826
|
+
current.watch(func, ...values);
|
|
827
|
+
}
|
|
828
|
+
function valueOf(value) {
|
|
829
|
+
return value.$;
|
|
830
|
+
}
|
|
831
|
+
function setValue(ref, value) {
|
|
832
|
+
if (ref instanceof Pointer && value instanceof IValue) {
|
|
833
|
+
ref.point(value);
|
|
834
|
+
}
|
|
835
|
+
else {
|
|
836
|
+
ref.$ = value instanceof IValue ? value.$ : value;
|
|
837
|
+
}
|
|
838
|
+
}
|
|
839
|
+
|
|
840
|
+
window.ref = ref;
|
|
841
|
+
window.mirror = mirror;
|
|
842
|
+
window.forward = forward;
|
|
843
|
+
window.point = point;
|
|
844
|
+
window.expr = expr;
|
|
845
|
+
window.watch = watch;
|
|
846
|
+
window.valueOf = valueOf;
|
|
847
|
+
window.setValue = setValue;
|
|
848
|
+
|
|
849
|
+
// ./lib/functional/components.js
|
|
850
|
+
function text(text) {
|
|
851
|
+
if (!(current instanceof Fragment))
|
|
852
|
+
throw userError('missing parent node', 'out-of-context');
|
|
853
|
+
;
|
|
854
|
+
current.text(text);
|
|
855
|
+
}
|
|
856
|
+
function debug(text) {
|
|
857
|
+
if (!(current instanceof Fragment))
|
|
858
|
+
throw userError('missing parent node', 'out-of-context');
|
|
859
|
+
current.debug(text);
|
|
860
|
+
}
|
|
861
|
+
function predefine(slot, predefined) {
|
|
862
|
+
return slot || predefined;
|
|
863
|
+
}
|
|
864
|
+
|
|
865
|
+
window.text = text;
|
|
866
|
+
window.debug = debug;
|
|
867
|
+
window.predefine = predefine;
|
|
868
|
+
|
|
566
869
|
// ./lib/core/signal.js
|
|
567
870
|
/**
|
|
568
871
|
* Signal is an event generator
|
|
@@ -862,7 +1165,7 @@ class Destroyable {
|
|
|
862
1165
|
* Make object fields non configurable
|
|
863
1166
|
* @protected
|
|
864
1167
|
*/
|
|
865
|
-
|
|
1168
|
+
seal() {
|
|
866
1169
|
const $ = this;
|
|
867
1170
|
Object.keys($).forEach(i => {
|
|
868
1171
|
// eslint-disable-next-line no-prototype-builtins
|
|
@@ -894,7 +1197,7 @@ class Destroyable {
|
|
|
894
1197
|
/**
|
|
895
1198
|
* Garbage collector method
|
|
896
1199
|
*/
|
|
897
|
-
|
|
1200
|
+
destroy() {
|
|
898
1201
|
// nothing here
|
|
899
1202
|
}
|
|
900
1203
|
}
|
|
@@ -902,12 +1205,26 @@ class Destroyable {
|
|
|
902
1205
|
window.Destroyable = Destroyable;
|
|
903
1206
|
|
|
904
1207
|
// ./lib/core/ivalue.js
|
|
1208
|
+
class Switchable extends Destroyable {
|
|
1209
|
+
/**
|
|
1210
|
+
* Enable update handlers triggering
|
|
1211
|
+
*/
|
|
1212
|
+
enable() {
|
|
1213
|
+
throw notOverwritten();
|
|
1214
|
+
}
|
|
1215
|
+
/**
|
|
1216
|
+
* disable update handlers triggering
|
|
1217
|
+
*/
|
|
1218
|
+
disable() {
|
|
1219
|
+
throw notOverwritten();
|
|
1220
|
+
}
|
|
1221
|
+
}
|
|
905
1222
|
/**
|
|
906
1223
|
* Interface which describes a value
|
|
907
1224
|
* @class IValue
|
|
908
1225
|
* @extends Destroyable
|
|
909
1226
|
*/
|
|
910
|
-
class IValue extends
|
|
1227
|
+
class IValue extends Switchable {
|
|
911
1228
|
/**
|
|
912
1229
|
* @param isEnabled {boolean} initial is enabled state
|
|
913
1230
|
*/
|
|
@@ -943,26 +1260,27 @@ class IValue extends Destroyable {
|
|
|
943
1260
|
off(handler) {
|
|
944
1261
|
throw notOverwritten();
|
|
945
1262
|
}
|
|
946
|
-
/**
|
|
947
|
-
* Enable update handlers triggering
|
|
948
|
-
*/
|
|
949
|
-
enable() {
|
|
950
|
-
throw notOverwritten();
|
|
951
|
-
}
|
|
952
|
-
/**
|
|
953
|
-
* disable update handlers triggering
|
|
954
|
-
*/
|
|
955
|
-
disable() {
|
|
956
|
-
throw notOverwritten();
|
|
957
|
-
}
|
|
958
1263
|
}
|
|
959
1264
|
|
|
1265
|
+
window.Switchable = Switchable;
|
|
960
1266
|
window.IValue = IValue;
|
|
961
1267
|
|
|
962
1268
|
// ./lib/index.js
|
|
963
1269
|
|
|
964
1270
|
|
|
965
1271
|
|
|
1272
|
+
// ./lib/spec/svg.js
|
|
1273
|
+
|
|
1274
|
+
|
|
1275
|
+
|
|
1276
|
+
// ./lib/spec/react.js
|
|
1277
|
+
|
|
1278
|
+
|
|
1279
|
+
|
|
1280
|
+
// ./lib/spec/html.js
|
|
1281
|
+
|
|
1282
|
+
|
|
1283
|
+
|
|
966
1284
|
// ./lib/value/expression.js
|
|
967
1285
|
/**
|
|
968
1286
|
* Bind some values to one expression
|
|
@@ -970,13 +1288,18 @@ window.IValue = IValue;
|
|
|
970
1288
|
* @extends IValue
|
|
971
1289
|
*/
|
|
972
1290
|
class Expression extends IValue {
|
|
973
|
-
|
|
1291
|
+
/**
|
|
1292
|
+
* Creates a function bounded to N values
|
|
1293
|
+
* @param func {Function} the function to bound
|
|
1294
|
+
* @param values
|
|
1295
|
+
* @param link {Boolean} links immediately if true
|
|
1296
|
+
*/
|
|
1297
|
+
constructor(func, link, ...values) {
|
|
974
1298
|
super(false);
|
|
975
1299
|
/**
|
|
976
1300
|
* Expression will link different handler for each value of list
|
|
977
1301
|
*/
|
|
978
1302
|
this.linkedFunc = [];
|
|
979
|
-
const values = [v1, v2, v3, v4, v5, v6, v7, v8, v9].filter(v => v instanceof IValue);
|
|
980
1303
|
const handler = (i) => {
|
|
981
1304
|
if (i != null) {
|
|
982
1305
|
this.valuesCache[i] = this.values[i].$;
|
|
@@ -985,14 +1308,12 @@ class Expression extends IValue {
|
|
|
985
1308
|
};
|
|
986
1309
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
987
1310
|
// @ts-ignore
|
|
988
|
-
this.valuesCache = values.map(
|
|
1311
|
+
this.valuesCache = values.map(item => item.$);
|
|
989
1312
|
this.sync = new Reference(func.apply(this, this.valuesCache));
|
|
990
1313
|
let i = 0;
|
|
991
1314
|
values.forEach(() => {
|
|
992
1315
|
this.linkedFunc.push(handler.bind(this, Number(i++)));
|
|
993
1316
|
});
|
|
994
|
-
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
995
|
-
// @ts-ignore
|
|
996
1317
|
this.values = values;
|
|
997
1318
|
this.func = handler;
|
|
998
1319
|
if (link) {
|
|
@@ -1001,7 +1322,7 @@ class Expression extends IValue {
|
|
|
1001
1322
|
else {
|
|
1002
1323
|
handler();
|
|
1003
1324
|
}
|
|
1004
|
-
this
|
|
1325
|
+
this.seal();
|
|
1005
1326
|
}
|
|
1006
1327
|
get $() {
|
|
1007
1328
|
return this.sync.$;
|
|
@@ -1037,12 +1358,12 @@ class Expression extends IValue {
|
|
|
1037
1358
|
}
|
|
1038
1359
|
return this;
|
|
1039
1360
|
}
|
|
1040
|
-
|
|
1361
|
+
destroy() {
|
|
1041
1362
|
this.disable();
|
|
1042
1363
|
this.values.splice(0);
|
|
1043
1364
|
this.valuesCache.splice(0);
|
|
1044
1365
|
this.linkedFunc.splice(0);
|
|
1045
|
-
super
|
|
1366
|
+
super.destroy();
|
|
1046
1367
|
}
|
|
1047
1368
|
}
|
|
1048
1369
|
|
|
@@ -1062,7 +1383,7 @@ class Reference extends IValue {
|
|
|
1062
1383
|
super(true);
|
|
1063
1384
|
this.value = value;
|
|
1064
1385
|
this.onchange = new Set;
|
|
1065
|
-
this
|
|
1386
|
+
this.seal();
|
|
1066
1387
|
}
|
|
1067
1388
|
get $() {
|
|
1068
1389
|
return this.value;
|
|
@@ -1084,22 +1405,18 @@ class Reference extends IValue {
|
|
|
1084
1405
|
});
|
|
1085
1406
|
this.isEnabled = true;
|
|
1086
1407
|
}
|
|
1087
|
-
return this;
|
|
1088
1408
|
}
|
|
1089
1409
|
disable() {
|
|
1090
1410
|
this.isEnabled = false;
|
|
1091
|
-
return this;
|
|
1092
1411
|
}
|
|
1093
1412
|
on(handler) {
|
|
1094
1413
|
this.onchange.add(handler);
|
|
1095
|
-
return this;
|
|
1096
1414
|
}
|
|
1097
1415
|
off(handler) {
|
|
1098
1416
|
this.onchange.delete(handler);
|
|
1099
|
-
return this;
|
|
1100
1417
|
}
|
|
1101
|
-
|
|
1102
|
-
super
|
|
1418
|
+
destroy() {
|
|
1419
|
+
super.destroy();
|
|
1103
1420
|
this.onchange.clear();
|
|
1104
1421
|
}
|
|
1105
1422
|
}
|
|
@@ -1127,7 +1444,7 @@ class Mirror extends Reference {
|
|
|
1127
1444
|
this.pointedValue = value;
|
|
1128
1445
|
this.forwardOnly = forwardOnly;
|
|
1129
1446
|
value.on(this.handler);
|
|
1130
|
-
this
|
|
1447
|
+
this.seal();
|
|
1131
1448
|
}
|
|
1132
1449
|
get $() {
|
|
1133
1450
|
// this is a ts bug
|
|
@@ -1136,13 +1453,13 @@ class Mirror extends Reference {
|
|
|
1136
1453
|
return super.$;
|
|
1137
1454
|
}
|
|
1138
1455
|
set $(v) {
|
|
1456
|
+
if (!this.forwardOnly) {
|
|
1457
|
+
this.pointedValue.$ = v;
|
|
1458
|
+
}
|
|
1139
1459
|
// this is a ts bug
|
|
1140
1460
|
// eslint-disable-next-line
|
|
1141
1461
|
// @ts-ignore
|
|
1142
1462
|
super.$ = v;
|
|
1143
|
-
if (!this.forwardOnly) {
|
|
1144
|
-
this.pointedValue.$ = v;
|
|
1145
|
-
}
|
|
1146
1463
|
}
|
|
1147
1464
|
enable() {
|
|
1148
1465
|
if (!this.isEnabled) {
|
|
@@ -1150,18 +1467,16 @@ class Mirror extends Reference {
|
|
|
1150
1467
|
this.pointedValue.on(this.handler);
|
|
1151
1468
|
this.$ = this.pointedValue.$;
|
|
1152
1469
|
}
|
|
1153
|
-
return this;
|
|
1154
1470
|
}
|
|
1155
1471
|
disable() {
|
|
1156
1472
|
if (this.isEnabled) {
|
|
1157
1473
|
this.pointedValue.off(this.handler);
|
|
1158
1474
|
this.isEnabled = false;
|
|
1159
1475
|
}
|
|
1160
|
-
return this;
|
|
1161
1476
|
}
|
|
1162
|
-
|
|
1477
|
+
destroy() {
|
|
1163
1478
|
this.disable();
|
|
1164
|
-
super
|
|
1479
|
+
super.destroy();
|
|
1165
1480
|
}
|
|
1166
1481
|
}
|
|
1167
1482
|
|
|
@@ -1205,39 +1520,39 @@ window.Pointer = Pointer;
|
|
|
1205
1520
|
class Binding extends Destroyable {
|
|
1206
1521
|
/**
|
|
1207
1522
|
* Constructs a common binding logic
|
|
1208
|
-
* @param node {INode} the vasille node
|
|
1209
|
-
* @param name {String} the name of property/attribute/class
|
|
1210
1523
|
* @param value {IValue} the value to bind
|
|
1211
1524
|
*/
|
|
1212
|
-
constructor(
|
|
1525
|
+
constructor(value) {
|
|
1213
1526
|
super();
|
|
1214
|
-
this.updateFunc = this.bound(name).bind(null, node);
|
|
1215
1527
|
this.binding = value;
|
|
1216
|
-
this.
|
|
1217
|
-
this.updateFunc(this.binding.$);
|
|
1218
|
-
this.$seal();
|
|
1528
|
+
this.seal();
|
|
1219
1529
|
}
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
* @throws Always throws and must be overloaded in child class
|
|
1225
|
-
*/
|
|
1226
|
-
bound(name) {
|
|
1227
|
-
throw notOverwritten();
|
|
1530
|
+
init(bounded) {
|
|
1531
|
+
this.func = bounded;
|
|
1532
|
+
this.binding.on(this.func);
|
|
1533
|
+
this.func(this.binding.$);
|
|
1228
1534
|
}
|
|
1229
1535
|
/**
|
|
1230
1536
|
* Just clear bindings
|
|
1231
1537
|
*/
|
|
1232
|
-
|
|
1233
|
-
this.binding.off(this.
|
|
1234
|
-
super
|
|
1538
|
+
destroy() {
|
|
1539
|
+
this.binding.off(this.func);
|
|
1540
|
+
super.destroy();
|
|
1235
1541
|
}
|
|
1236
1542
|
}
|
|
1237
1543
|
|
|
1238
1544
|
window.Binding = Binding;
|
|
1239
1545
|
|
|
1240
1546
|
// ./lib/core/core.js
|
|
1547
|
+
|
|
1548
|
+
const currentStack = [];
|
|
1549
|
+
function stack(node) {
|
|
1550
|
+
currentStack.push(current);
|
|
1551
|
+
current = node;
|
|
1552
|
+
}
|
|
1553
|
+
function unstack() {
|
|
1554
|
+
current = currentStack.pop();
|
|
1555
|
+
}
|
|
1241
1556
|
/**
|
|
1242
1557
|
* Private stuff of a reactive object
|
|
1243
1558
|
* @class ReactivePrivate
|
|
@@ -1270,16 +1585,18 @@ class ReactivePrivate extends Destroyable {
|
|
|
1270
1585
|
* @type {boolean}
|
|
1271
1586
|
*/
|
|
1272
1587
|
this.frozen = false;
|
|
1273
|
-
this
|
|
1588
|
+
this.seal();
|
|
1274
1589
|
}
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
this.watch.forEach(value => value.$destroy());
|
|
1590
|
+
destroy() {
|
|
1591
|
+
this.watch.forEach(value => value.destroy());
|
|
1278
1592
|
this.watch.clear();
|
|
1279
|
-
this.bindings.forEach(binding => binding
|
|
1593
|
+
this.bindings.forEach(binding => binding.destroy());
|
|
1280
1594
|
this.bindings.clear();
|
|
1281
|
-
(
|
|
1282
|
-
|
|
1595
|
+
this.models.forEach(model => model.disableReactivity());
|
|
1596
|
+
this.models.clear();
|
|
1597
|
+
this.freezeExpr && this.freezeExpr.destroy();
|
|
1598
|
+
this.onDestroy && this.onDestroy();
|
|
1599
|
+
super.destroy();
|
|
1283
1600
|
}
|
|
1284
1601
|
}
|
|
1285
1602
|
/**
|
|
@@ -1288,15 +1605,23 @@ class ReactivePrivate extends Destroyable {
|
|
|
1288
1605
|
* @extends Destroyable
|
|
1289
1606
|
*/
|
|
1290
1607
|
class Reactive extends Destroyable {
|
|
1291
|
-
constructor($) {
|
|
1608
|
+
constructor(input, $) {
|
|
1292
1609
|
super();
|
|
1610
|
+
this.input = input;
|
|
1293
1611
|
this.$ = $ || new ReactivePrivate;
|
|
1612
|
+
this.seal();
|
|
1613
|
+
}
|
|
1614
|
+
/**
|
|
1615
|
+
* Get parent node
|
|
1616
|
+
*/
|
|
1617
|
+
get parent() {
|
|
1618
|
+
return this.$.parent;
|
|
1294
1619
|
}
|
|
1295
1620
|
/**
|
|
1296
1621
|
* Create a reference
|
|
1297
1622
|
* @param value {*} value to reference
|
|
1298
1623
|
*/
|
|
1299
|
-
|
|
1624
|
+
ref(value) {
|
|
1300
1625
|
const $ = this.$;
|
|
1301
1626
|
const ref = new Reference(value);
|
|
1302
1627
|
$.watch.add(ref);
|
|
@@ -1306,7 +1631,7 @@ class Reactive extends Destroyable {
|
|
|
1306
1631
|
* Create a mirror
|
|
1307
1632
|
* @param value {IValue} value to mirror
|
|
1308
1633
|
*/
|
|
1309
|
-
|
|
1634
|
+
mirror(value) {
|
|
1310
1635
|
const mirror = new Mirror(value, false);
|
|
1311
1636
|
this.$.watch.add(mirror);
|
|
1312
1637
|
return mirror;
|
|
@@ -1315,7 +1640,7 @@ class Reactive extends Destroyable {
|
|
|
1315
1640
|
* Create a forward-only mirror
|
|
1316
1641
|
* @param value {IValue} value to mirror
|
|
1317
1642
|
*/
|
|
1318
|
-
|
|
1643
|
+
forward(value) {
|
|
1319
1644
|
const mirror = new Mirror(value, true);
|
|
1320
1645
|
this.$.watch.add(mirror);
|
|
1321
1646
|
return mirror;
|
|
@@ -1325,14 +1650,9 @@ class Reactive extends Destroyable {
|
|
|
1325
1650
|
* @param value {*} default value to point
|
|
1326
1651
|
* @param forwardOnly {boolean} forward only sync
|
|
1327
1652
|
*/
|
|
1328
|
-
|
|
1653
|
+
point(value, forwardOnly = false) {
|
|
1329
1654
|
const $ = this.$;
|
|
1330
|
-
const
|
|
1331
|
-
const pointer = new Pointer(ref, forwardOnly);
|
|
1332
|
-
// when value is an ivalue will be equal to ref
|
|
1333
|
-
if (value !== ref) {
|
|
1334
|
-
$.watch.add(ref);
|
|
1335
|
-
}
|
|
1655
|
+
const pointer = new Pointer(value, forwardOnly);
|
|
1336
1656
|
$.watch.add(pointer);
|
|
1337
1657
|
return pointer;
|
|
1338
1658
|
}
|
|
@@ -1340,16 +1660,27 @@ class Reactive extends Destroyable {
|
|
|
1340
1660
|
* Register a model
|
|
1341
1661
|
* @param model
|
|
1342
1662
|
*/
|
|
1343
|
-
|
|
1663
|
+
register(model) {
|
|
1344
1664
|
this.$.models.add(model);
|
|
1345
1665
|
return model;
|
|
1346
1666
|
}
|
|
1347
|
-
|
|
1667
|
+
/**
|
|
1668
|
+
* Creates a watcher
|
|
1669
|
+
* @param func {function} function to run on any argument change
|
|
1670
|
+
* @param values
|
|
1671
|
+
*/
|
|
1672
|
+
watch(func, ...values) {
|
|
1348
1673
|
const $ = this.$;
|
|
1349
|
-
$.watch.add(new Expression(func, !this.$.frozen,
|
|
1674
|
+
$.watch.add(new Expression(func, !this.$.frozen, ...values));
|
|
1350
1675
|
}
|
|
1351
|
-
|
|
1352
|
-
|
|
1676
|
+
/**
|
|
1677
|
+
* Creates a computed value
|
|
1678
|
+
* @param func {function} function to run on any argument change
|
|
1679
|
+
* @param values
|
|
1680
|
+
* @return {IValue} the created ivalue
|
|
1681
|
+
*/
|
|
1682
|
+
expr(func, ...values) {
|
|
1683
|
+
const res = new Expression(func, !this.$.frozen, ...values);
|
|
1353
1684
|
const $ = this.$;
|
|
1354
1685
|
$.watch.add(res);
|
|
1355
1686
|
return res;
|
|
@@ -1357,7 +1688,7 @@ class Reactive extends Destroyable {
|
|
|
1357
1688
|
/**
|
|
1358
1689
|
* Enable reactivity of fields
|
|
1359
1690
|
*/
|
|
1360
|
-
|
|
1691
|
+
enable() {
|
|
1361
1692
|
const $ = this.$;
|
|
1362
1693
|
if (!$.enabled) {
|
|
1363
1694
|
$.watch.forEach(watcher => {
|
|
@@ -1372,7 +1703,7 @@ class Reactive extends Destroyable {
|
|
|
1372
1703
|
/**
|
|
1373
1704
|
* Disable reactivity of fields
|
|
1374
1705
|
*/
|
|
1375
|
-
|
|
1706
|
+
disable() {
|
|
1376
1707
|
const $ = this.$;
|
|
1377
1708
|
if ($.enabled) {
|
|
1378
1709
|
$.watch.forEach(watcher => {
|
|
@@ -1390,7 +1721,7 @@ class Reactive extends Destroyable {
|
|
|
1390
1721
|
* @param onOff {function} on show feedback
|
|
1391
1722
|
* @param onOn {function} on hide feedback
|
|
1392
1723
|
*/
|
|
1393
|
-
|
|
1724
|
+
bindAlive(cond, onOff, onOn) {
|
|
1394
1725
|
const $ = this.$;
|
|
1395
1726
|
if ($.freezeExpr) {
|
|
1396
1727
|
throw wrongBinding("this component already have a freeze state");
|
|
@@ -1402,18 +1733,46 @@ class Reactive extends Destroyable {
|
|
|
1402
1733
|
$.frozen = !cond;
|
|
1403
1734
|
if (cond) {
|
|
1404
1735
|
onOn === null || onOn === void 0 ? void 0 : onOn();
|
|
1405
|
-
this
|
|
1736
|
+
this.enable();
|
|
1406
1737
|
}
|
|
1407
1738
|
else {
|
|
1408
1739
|
onOff === null || onOff === void 0 ? void 0 : onOff();
|
|
1409
|
-
this
|
|
1740
|
+
this.disable();
|
|
1410
1741
|
}
|
|
1411
1742
|
}, true, cond);
|
|
1412
1743
|
return this;
|
|
1413
1744
|
}
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
this
|
|
1745
|
+
init() {
|
|
1746
|
+
this.applyOptions(this.input);
|
|
1747
|
+
this.compose(this.input);
|
|
1748
|
+
}
|
|
1749
|
+
applyOptions(input) {
|
|
1750
|
+
// empty
|
|
1751
|
+
}
|
|
1752
|
+
applyOptionsNow() {
|
|
1753
|
+
this.applyOptions(this.input);
|
|
1754
|
+
}
|
|
1755
|
+
compose(input) {
|
|
1756
|
+
// empty
|
|
1757
|
+
}
|
|
1758
|
+
composeNow() {
|
|
1759
|
+
this.compose(this.input);
|
|
1760
|
+
}
|
|
1761
|
+
runFunctional(f, ...args) {
|
|
1762
|
+
stack(this);
|
|
1763
|
+
// yet another ts bug
|
|
1764
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
1765
|
+
// @ts-ignore
|
|
1766
|
+
const result = f(...args);
|
|
1767
|
+
unstack();
|
|
1768
|
+
return result;
|
|
1769
|
+
}
|
|
1770
|
+
runOnDestroy(func) {
|
|
1771
|
+
this.$.onDestroy = func;
|
|
1772
|
+
}
|
|
1773
|
+
destroy() {
|
|
1774
|
+
super.destroy();
|
|
1775
|
+
this.$.destroy();
|
|
1417
1776
|
this.$ = null;
|
|
1418
1777
|
}
|
|
1419
1778
|
}
|
|
@@ -1430,7 +1789,7 @@ window.Reactive = Reactive;
|
|
|
1430
1789
|
class FragmentPrivate extends ReactivePrivate {
|
|
1431
1790
|
constructor() {
|
|
1432
1791
|
super();
|
|
1433
|
-
this
|
|
1792
|
+
this.seal();
|
|
1434
1793
|
}
|
|
1435
1794
|
/**
|
|
1436
1795
|
* Pre-initializes the base of a fragment
|
|
@@ -1444,10 +1803,10 @@ class FragmentPrivate extends ReactivePrivate {
|
|
|
1444
1803
|
/**
|
|
1445
1804
|
* Unlinks all bindings
|
|
1446
1805
|
*/
|
|
1447
|
-
|
|
1806
|
+
destroy() {
|
|
1448
1807
|
this.next = null;
|
|
1449
1808
|
this.prev = null;
|
|
1450
|
-
super
|
|
1809
|
+
super.destroy();
|
|
1451
1810
|
}
|
|
1452
1811
|
}
|
|
1453
1812
|
/**
|
|
@@ -1457,16 +1816,17 @@ class FragmentPrivate extends ReactivePrivate {
|
|
|
1457
1816
|
class Fragment extends Reactive {
|
|
1458
1817
|
/**
|
|
1459
1818
|
* Constructs a Vasille Node
|
|
1819
|
+
* @param input
|
|
1460
1820
|
* @param $ {FragmentPrivate}
|
|
1461
1821
|
*/
|
|
1462
|
-
constructor($) {
|
|
1463
|
-
super();
|
|
1822
|
+
constructor(input, $) {
|
|
1823
|
+
super(input, $ || new FragmentPrivate);
|
|
1464
1824
|
/**
|
|
1465
1825
|
* The children list
|
|
1466
1826
|
* @type Array
|
|
1467
1827
|
*/
|
|
1468
|
-
this
|
|
1469
|
-
this
|
|
1828
|
+
this.children = new Set;
|
|
1829
|
+
this.lastChild = null;
|
|
1470
1830
|
}
|
|
1471
1831
|
/**
|
|
1472
1832
|
* Gets the app of node
|
|
@@ -1480,43 +1840,20 @@ class Fragment extends Reactive {
|
|
|
1480
1840
|
* @param parent {Fragment} parent of node
|
|
1481
1841
|
* @param data {*} additional data
|
|
1482
1842
|
*/
|
|
1483
|
-
|
|
1843
|
+
preinit(app, parent, data) {
|
|
1484
1844
|
const $ = this.$;
|
|
1485
1845
|
$.preinit(app, parent);
|
|
1486
1846
|
}
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
$init() {
|
|
1491
|
-
this.$createSignals();
|
|
1492
|
-
this.$createWatchers();
|
|
1493
|
-
this.$created();
|
|
1494
|
-
this.$compose();
|
|
1495
|
-
this.$mounted();
|
|
1496
|
-
return this;
|
|
1497
|
-
}
|
|
1498
|
-
/** To be overloaded: created event handler */
|
|
1499
|
-
$created() {
|
|
1500
|
-
// empty
|
|
1847
|
+
init() {
|
|
1848
|
+
super.init();
|
|
1849
|
+
this.ready();
|
|
1501
1850
|
}
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1851
|
+
compose(input) {
|
|
1852
|
+
super.compose(input);
|
|
1853
|
+
input.slot && input.slot(this);
|
|
1505
1854
|
}
|
|
1506
1855
|
/** To be overloaded: ready event handler */
|
|
1507
|
-
|
|
1508
|
-
// empty
|
|
1509
|
-
}
|
|
1510
|
-
/** To be overloaded: signals creation milestone */
|
|
1511
|
-
$createSignals() {
|
|
1512
|
-
// empty
|
|
1513
|
-
}
|
|
1514
|
-
/** To be overloaded: watchers creation milestone */
|
|
1515
|
-
$createWatchers() {
|
|
1516
|
-
// empty
|
|
1517
|
-
}
|
|
1518
|
-
/** To be overloaded: DOM creation milestone */
|
|
1519
|
-
$compose() {
|
|
1856
|
+
ready() {
|
|
1520
1857
|
// empty
|
|
1521
1858
|
}
|
|
1522
1859
|
/**
|
|
@@ -1524,27 +1861,23 @@ class Fragment extends Reactive {
|
|
|
1524
1861
|
* @param node {Fragment} A node to push
|
|
1525
1862
|
* @protected
|
|
1526
1863
|
*/
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
lastChild = this.$children[this.$children.length - 1];
|
|
1864
|
+
pushNode(node) {
|
|
1865
|
+
if (this.lastChild) {
|
|
1866
|
+
this.lastChild.$.next = node;
|
|
1531
1867
|
}
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
node.$.prev = lastChild;
|
|
1536
|
-
node.$.parent = this;
|
|
1537
|
-
this.$children.push(node);
|
|
1868
|
+
node.$.prev = this.lastChild;
|
|
1869
|
+
this.lastChild = node;
|
|
1870
|
+
this.children.add(node);
|
|
1538
1871
|
}
|
|
1539
1872
|
/**
|
|
1540
1873
|
* Find first node in element if so exists
|
|
1541
1874
|
* @return {?Element}
|
|
1542
1875
|
* @protected
|
|
1543
1876
|
*/
|
|
1544
|
-
|
|
1877
|
+
findFirstChild() {
|
|
1545
1878
|
let first;
|
|
1546
|
-
this
|
|
1547
|
-
first = first || child
|
|
1879
|
+
this.children.forEach(child => {
|
|
1880
|
+
first = first || child.findFirstChild();
|
|
1548
1881
|
});
|
|
1549
1882
|
return first;
|
|
1550
1883
|
}
|
|
@@ -1552,30 +1885,30 @@ class Fragment extends Reactive {
|
|
|
1552
1885
|
* Append a node to end of element
|
|
1553
1886
|
* @param node {Node} node to insert
|
|
1554
1887
|
*/
|
|
1555
|
-
|
|
1888
|
+
appendNode(node) {
|
|
1556
1889
|
const $ = this.$;
|
|
1557
1890
|
if ($.next) {
|
|
1558
|
-
$.next
|
|
1891
|
+
$.next.insertAdjacent(node);
|
|
1559
1892
|
}
|
|
1560
1893
|
else {
|
|
1561
|
-
$.parent
|
|
1894
|
+
$.parent.appendNode(node);
|
|
1562
1895
|
}
|
|
1563
1896
|
}
|
|
1564
1897
|
/**
|
|
1565
1898
|
* Insert a node as a sibling of this
|
|
1566
1899
|
* @param node {Node} node to insert
|
|
1567
1900
|
*/
|
|
1568
|
-
|
|
1569
|
-
const child = this
|
|
1901
|
+
insertAdjacent(node) {
|
|
1902
|
+
const child = this.findFirstChild();
|
|
1570
1903
|
const $ = this.$;
|
|
1571
1904
|
if (child) {
|
|
1572
|
-
|
|
1905
|
+
child.parentElement.insertBefore(node, child);
|
|
1573
1906
|
}
|
|
1574
1907
|
else if ($.next) {
|
|
1575
|
-
$.next
|
|
1908
|
+
$.next.insertAdjacent(node);
|
|
1576
1909
|
}
|
|
1577
1910
|
else {
|
|
1578
|
-
$.parent
|
|
1911
|
+
$.parent.appendNode(node);
|
|
1579
1912
|
}
|
|
1580
1913
|
}
|
|
1581
1914
|
/**
|
|
@@ -1583,60 +1916,48 @@ class Fragment extends Reactive {
|
|
|
1583
1916
|
* @param text {String | IValue} A text fragment string
|
|
1584
1917
|
* @param cb {function (TextNode)} Callback if previous is slot name
|
|
1585
1918
|
*/
|
|
1586
|
-
|
|
1919
|
+
text(text, cb) {
|
|
1587
1920
|
const $ = this.$;
|
|
1588
1921
|
const node = new TextNode();
|
|
1589
|
-
|
|
1590
|
-
node
|
|
1591
|
-
|
|
1592
|
-
if (cb) {
|
|
1593
|
-
$.app.$run.callCallback(() => {
|
|
1594
|
-
cb(node);
|
|
1595
|
-
});
|
|
1596
|
-
}
|
|
1597
|
-
return this;
|
|
1922
|
+
node.preinit($.app, this, text);
|
|
1923
|
+
this.pushNode(node);
|
|
1924
|
+
cb && cb(node);
|
|
1598
1925
|
}
|
|
1599
|
-
|
|
1600
|
-
if (this.$.app
|
|
1926
|
+
debug(text) {
|
|
1927
|
+
if (this.$.app.debugUi) {
|
|
1601
1928
|
const node = new DebugNode();
|
|
1602
|
-
node
|
|
1603
|
-
this
|
|
1929
|
+
node.preinit(this.$.app, this, text);
|
|
1930
|
+
this.pushNode(node);
|
|
1604
1931
|
}
|
|
1605
|
-
return this;
|
|
1606
1932
|
}
|
|
1607
|
-
|
|
1933
|
+
/**
|
|
1934
|
+
* Defines a tag element
|
|
1935
|
+
* @param tagName {String} the tag name
|
|
1936
|
+
* @param input
|
|
1937
|
+
* @param cb {function(Tag, *)} callback
|
|
1938
|
+
*/
|
|
1939
|
+
tag(tagName, input, cb) {
|
|
1608
1940
|
const $ = this.$;
|
|
1609
|
-
const node = new Tag();
|
|
1610
|
-
|
|
1611
|
-
node
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
}
|
|
1617
|
-
node.$ready();
|
|
1618
|
-
});
|
|
1619
|
-
return this;
|
|
1941
|
+
const node = new Tag(input);
|
|
1942
|
+
input.slot = cb || input.slot;
|
|
1943
|
+
node.preinit($.app, this, tagName);
|
|
1944
|
+
node.init();
|
|
1945
|
+
this.pushNode(node);
|
|
1946
|
+
node.ready();
|
|
1947
|
+
return node.node;
|
|
1620
1948
|
}
|
|
1621
1949
|
/**
|
|
1622
1950
|
* Defines a custom element
|
|
1623
1951
|
* @param node {Fragment} vasille element to insert
|
|
1624
1952
|
* @param callback {function($ : *)}
|
|
1625
|
-
* @param callback1 {function($ : *)}
|
|
1626
1953
|
*/
|
|
1627
|
-
|
|
1954
|
+
create(node, callback) {
|
|
1628
1955
|
const $ = this.$;
|
|
1629
1956
|
node.$.parent = this;
|
|
1630
|
-
node
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
if (callback1) {
|
|
1635
|
-
callback1(node);
|
|
1636
|
-
}
|
|
1637
|
-
this.$$pushNode(node);
|
|
1638
|
-
node.$init().$ready();
|
|
1639
|
-
return this;
|
|
1957
|
+
node.preinit($.app, this);
|
|
1958
|
+
node.input.slot = callback || node.input.slot;
|
|
1959
|
+
this.pushNode(node);
|
|
1960
|
+
node.init();
|
|
1640
1961
|
}
|
|
1641
1962
|
/**
|
|
1642
1963
|
* Defines an if node
|
|
@@ -1644,32 +1965,29 @@ class Fragment extends Reactive {
|
|
|
1644
1965
|
* @param cb {function(Fragment)} callback to run on true
|
|
1645
1966
|
* @return {this}
|
|
1646
1967
|
*/
|
|
1647
|
-
|
|
1648
|
-
|
|
1968
|
+
if(cond, cb) {
|
|
1969
|
+
const node = new SwitchedNode();
|
|
1970
|
+
node.preinit(this.$.app, this);
|
|
1971
|
+
node.init();
|
|
1972
|
+
this.pushNode(node);
|
|
1973
|
+
node.addCase(this.case(cond, cb));
|
|
1974
|
+
node.ready();
|
|
1649
1975
|
}
|
|
1650
|
-
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
return this.$switch({ cond: ifCond, cb: ifCb }, { cond: trueIValue, cb: elseCb });
|
|
1976
|
+
else(cb) {
|
|
1977
|
+
if (this.lastChild instanceof SwitchedNode) {
|
|
1978
|
+
this.lastChild.addCase(this.default(cb));
|
|
1979
|
+
}
|
|
1980
|
+
else {
|
|
1981
|
+
throw userError('wrong `else` function use', 'logic-error');
|
|
1982
|
+
}
|
|
1658
1983
|
}
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
const node = new SwitchedNode();
|
|
1667
|
-
node.$preinit($.app, this);
|
|
1668
|
-
node.$init();
|
|
1669
|
-
this.$$pushNode(node);
|
|
1670
|
-
node.setCases(cases);
|
|
1671
|
-
node.$ready();
|
|
1672
|
-
return this;
|
|
1984
|
+
elif(cond, cb) {
|
|
1985
|
+
if (this.lastChild instanceof SwitchedNode) {
|
|
1986
|
+
this.lastChild.addCase(this.case(cond, cb));
|
|
1987
|
+
}
|
|
1988
|
+
else {
|
|
1989
|
+
throw userError('wrong `elif` function use', 'logic-error');
|
|
1990
|
+
}
|
|
1673
1991
|
}
|
|
1674
1992
|
/**
|
|
1675
1993
|
* Create a case for switch
|
|
@@ -1677,22 +1995,48 @@ class Fragment extends Reactive {
|
|
|
1677
1995
|
* @param cb {function(Fragment) : void}
|
|
1678
1996
|
* @return {{cond : IValue, cb : (function(Fragment) : void)}}
|
|
1679
1997
|
*/
|
|
1680
|
-
|
|
1998
|
+
case(cond, cb) {
|
|
1681
1999
|
return { cond, cb };
|
|
1682
2000
|
}
|
|
1683
2001
|
/**
|
|
1684
2002
|
* @param cb {(function(Fragment) : void)}
|
|
1685
2003
|
* @return {{cond : IValue, cb : (function(Fragment) : void)}}
|
|
1686
2004
|
*/
|
|
1687
|
-
|
|
2005
|
+
default(cb) {
|
|
1688
2006
|
return { cond: trueIValue, cb };
|
|
1689
2007
|
}
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
|
|
2008
|
+
insertBefore(node) {
|
|
2009
|
+
const $ = this.$;
|
|
2010
|
+
node.$.prev = $.prev;
|
|
2011
|
+
node.$.next = this;
|
|
2012
|
+
if ($.prev) {
|
|
2013
|
+
$.prev.$.next = node;
|
|
2014
|
+
}
|
|
2015
|
+
$.prev = node;
|
|
2016
|
+
}
|
|
2017
|
+
insertAfter(node) {
|
|
2018
|
+
const $ = this.$;
|
|
2019
|
+
node.$.prev = this;
|
|
2020
|
+
node.$.next = $.next;
|
|
2021
|
+
$.next = node;
|
|
2022
|
+
}
|
|
2023
|
+
remove() {
|
|
2024
|
+
const $ = this.$;
|
|
2025
|
+
if ($.next) {
|
|
2026
|
+
$.next.$.prev = $.prev;
|
|
2027
|
+
}
|
|
2028
|
+
if ($.prev) {
|
|
2029
|
+
$.prev.$.next = $.next;
|
|
2030
|
+
}
|
|
2031
|
+
}
|
|
2032
|
+
destroy() {
|
|
2033
|
+
this.children.forEach(child => child.destroy());
|
|
2034
|
+
this.children.clear();
|
|
2035
|
+
this.lastChild = null;
|
|
2036
|
+
if (this.$.parent.lastChild === this) {
|
|
2037
|
+
this.$.parent.lastChild = this.$.prev;
|
|
1693
2038
|
}
|
|
1694
|
-
|
|
1695
|
-
super.$destroy();
|
|
2039
|
+
super.destroy();
|
|
1696
2040
|
}
|
|
1697
2041
|
}
|
|
1698
2042
|
const trueIValue = new Reference(true);
|
|
@@ -1704,26 +2048,28 @@ const trueIValue = new Reference(true);
|
|
|
1704
2048
|
class TextNodePrivate extends FragmentPrivate {
|
|
1705
2049
|
constructor() {
|
|
1706
2050
|
super();
|
|
1707
|
-
this
|
|
2051
|
+
this.seal();
|
|
1708
2052
|
}
|
|
1709
2053
|
/**
|
|
1710
2054
|
* Pre-initializes a text node
|
|
1711
2055
|
* @param app {AppNode} the app node
|
|
2056
|
+
* @param parent
|
|
1712
2057
|
* @param text {IValue}
|
|
1713
2058
|
*/
|
|
1714
2059
|
preinitText(app, parent, text) {
|
|
1715
2060
|
super.preinit(app, parent);
|
|
1716
|
-
this.node = document.createTextNode(text.$);
|
|
1717
|
-
|
|
1718
|
-
this.
|
|
1719
|
-
|
|
1720
|
-
|
|
2061
|
+
this.node = document.createTextNode(text instanceof IValue ? text.$ : text);
|
|
2062
|
+
if (text instanceof IValue) {
|
|
2063
|
+
this.bindings.add(new Expression((v) => {
|
|
2064
|
+
this.node.replaceData(0, -1, v);
|
|
2065
|
+
}, true, text));
|
|
2066
|
+
}
|
|
1721
2067
|
}
|
|
1722
2068
|
/**
|
|
1723
2069
|
* Clear node data
|
|
1724
2070
|
*/
|
|
1725
|
-
|
|
1726
|
-
super
|
|
2071
|
+
destroy() {
|
|
2072
|
+
super.destroy();
|
|
1727
2073
|
}
|
|
1728
2074
|
}
|
|
1729
2075
|
/**
|
|
@@ -1732,25 +2078,25 @@ class TextNodePrivate extends FragmentPrivate {
|
|
|
1732
2078
|
* @extends Fragment
|
|
1733
2079
|
*/
|
|
1734
2080
|
class TextNode extends Fragment {
|
|
1735
|
-
constructor() {
|
|
1736
|
-
super();
|
|
1737
|
-
this
|
|
1738
|
-
this.$seal();
|
|
2081
|
+
constructor($ = new TextNodePrivate()) {
|
|
2082
|
+
super({}, $);
|
|
2083
|
+
this.seal();
|
|
1739
2084
|
}
|
|
1740
|
-
|
|
2085
|
+
preinit(app, parent, text) {
|
|
1741
2086
|
const $ = this.$;
|
|
1742
2087
|
if (!text) {
|
|
1743
2088
|
throw internalError('wrong TextNode::$preninit call');
|
|
1744
2089
|
}
|
|
1745
2090
|
$.preinitText(app, parent, text);
|
|
2091
|
+
$.parent.appendNode($.node);
|
|
1746
2092
|
}
|
|
1747
|
-
|
|
2093
|
+
findFirstChild() {
|
|
1748
2094
|
return this.$.node;
|
|
1749
2095
|
}
|
|
1750
|
-
|
|
2096
|
+
destroy() {
|
|
1751
2097
|
this.$.node.remove();
|
|
1752
|
-
this
|
|
1753
|
-
super
|
|
2098
|
+
this.$.destroy();
|
|
2099
|
+
super.destroy();
|
|
1754
2100
|
}
|
|
1755
2101
|
}
|
|
1756
2102
|
/**
|
|
@@ -1766,10 +2112,10 @@ class INodePrivate extends FragmentPrivate {
|
|
|
1766
2112
|
* @type {boolean}
|
|
1767
2113
|
*/
|
|
1768
2114
|
this.unmounted = false;
|
|
1769
|
-
this
|
|
2115
|
+
this.seal();
|
|
1770
2116
|
}
|
|
1771
|
-
|
|
1772
|
-
super
|
|
2117
|
+
destroy() {
|
|
2118
|
+
super.destroy();
|
|
1773
2119
|
}
|
|
1774
2120
|
}
|
|
1775
2121
|
/**
|
|
@@ -1780,11 +2126,12 @@ class INodePrivate extends FragmentPrivate {
|
|
|
1780
2126
|
class INode extends Fragment {
|
|
1781
2127
|
/**
|
|
1782
2128
|
* Constructs a base node
|
|
2129
|
+
* @param input
|
|
1783
2130
|
* @param $ {?INodePrivate}
|
|
1784
2131
|
*/
|
|
1785
|
-
constructor($) {
|
|
1786
|
-
super($ || new INodePrivate);
|
|
1787
|
-
this
|
|
2132
|
+
constructor(input, $) {
|
|
2133
|
+
super(input, $ || new INodePrivate);
|
|
2134
|
+
this.seal();
|
|
1788
2135
|
}
|
|
1789
2136
|
/**
|
|
1790
2137
|
* Get the bound node
|
|
@@ -1792,78 +2139,55 @@ class INode extends Fragment {
|
|
|
1792
2139
|
get node() {
|
|
1793
2140
|
return this.$.node;
|
|
1794
2141
|
}
|
|
1795
|
-
/**
|
|
1796
|
-
* Initialize node
|
|
1797
|
-
*/
|
|
1798
|
-
$init() {
|
|
1799
|
-
this.$createSignals();
|
|
1800
|
-
this.$createWatchers();
|
|
1801
|
-
this.$createAttrs();
|
|
1802
|
-
this.$createStyle();
|
|
1803
|
-
this.$created();
|
|
1804
|
-
this.$compose();
|
|
1805
|
-
this.$mounted();
|
|
1806
|
-
return this;
|
|
1807
|
-
}
|
|
1808
|
-
/** To be overloaded: attributes creation milestone */
|
|
1809
|
-
$createAttrs() {
|
|
1810
|
-
// empty
|
|
1811
|
-
}
|
|
1812
|
-
/** To be overloaded: $style attributes creation milestone */
|
|
1813
|
-
$createStyle() {
|
|
1814
|
-
// empty
|
|
1815
|
-
}
|
|
1816
2142
|
/**
|
|
1817
2143
|
* Bind attribute value
|
|
1818
2144
|
* @param name {String} name of attribute
|
|
1819
2145
|
* @param value {IValue} value
|
|
1820
2146
|
*/
|
|
1821
|
-
|
|
2147
|
+
attr(name, value) {
|
|
1822
2148
|
const $ = this.$;
|
|
1823
2149
|
const attr = new AttributeBinding(this, name, value);
|
|
1824
2150
|
$.bindings.add(attr);
|
|
1825
|
-
return this;
|
|
1826
|
-
}
|
|
1827
|
-
$bindAttr(name, calculator, v1, v2, v3, v4, v5, v6, v7, v8, v9) {
|
|
1828
|
-
const $ = this.$;
|
|
1829
|
-
const expr = this.$bind(calculator, v1, v2, v3, v4, v5, v6, v7, v8, v9);
|
|
1830
|
-
$.bindings.add(new AttributeBinding(this, name, expr));
|
|
1831
|
-
return this;
|
|
1832
2151
|
}
|
|
1833
2152
|
/**
|
|
1834
2153
|
* Set attribute value
|
|
1835
2154
|
* @param name {string} name of attribute
|
|
1836
2155
|
* @param value {string} value
|
|
1837
2156
|
*/
|
|
1838
|
-
|
|
1839
|
-
|
|
2157
|
+
setAttr(name, value) {
|
|
2158
|
+
if (typeof value === 'boolean') {
|
|
2159
|
+
if (value) {
|
|
2160
|
+
this.$.node.setAttribute(name, "");
|
|
2161
|
+
}
|
|
2162
|
+
}
|
|
2163
|
+
else {
|
|
2164
|
+
this.$.node.setAttribute(name, `${value}`);
|
|
2165
|
+
}
|
|
1840
2166
|
return this;
|
|
1841
2167
|
}
|
|
1842
2168
|
/**
|
|
1843
2169
|
* Adds a CSS class
|
|
1844
2170
|
* @param cl {string} Class name
|
|
1845
2171
|
*/
|
|
1846
|
-
|
|
1847
|
-
this.$.
|
|
2172
|
+
addClass(cl) {
|
|
2173
|
+
this.$.node.classList.add(cl);
|
|
1848
2174
|
return this;
|
|
1849
2175
|
}
|
|
1850
2176
|
/**
|
|
1851
2177
|
* Adds some CSS classes
|
|
1852
2178
|
* @param cls {...string} classes names
|
|
1853
2179
|
*/
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
this.$.app.$run.addClass(this.$.node, cl);
|
|
1857
|
-
});
|
|
2180
|
+
removeClasse(cl) {
|
|
2181
|
+
this.$.node.classList.remove(cl);
|
|
1858
2182
|
return this;
|
|
1859
2183
|
}
|
|
1860
2184
|
/**
|
|
1861
2185
|
* Bind a CSS class
|
|
1862
2186
|
* @param className {IValue}
|
|
1863
2187
|
*/
|
|
1864
|
-
|
|
2188
|
+
bindClass(className) {
|
|
1865
2189
|
const $ = this.$;
|
|
1866
|
-
$.bindings.add(new
|
|
2190
|
+
$.bindings.add(new DynamicalClassBinding(this, className));
|
|
1867
2191
|
return this;
|
|
1868
2192
|
}
|
|
1869
2193
|
/**
|
|
@@ -1871,8 +2195,8 @@ class INode extends Fragment {
|
|
|
1871
2195
|
* @param cond {IValue} condition
|
|
1872
2196
|
* @param className {string} class name
|
|
1873
2197
|
*/
|
|
1874
|
-
|
|
1875
|
-
this.$.bindings.add(new
|
|
2198
|
+
floatingClass(cond, className) {
|
|
2199
|
+
this.$.bindings.add(new StaticClassBinding(this, className, cond));
|
|
1876
2200
|
return this;
|
|
1877
2201
|
}
|
|
1878
2202
|
/**
|
|
@@ -1880,7 +2204,7 @@ class INode extends Fragment {
|
|
|
1880
2204
|
* @param name {String} name of style attribute
|
|
1881
2205
|
* @param value {IValue} value
|
|
1882
2206
|
*/
|
|
1883
|
-
|
|
2207
|
+
style(name, value) {
|
|
1884
2208
|
const $ = this.$;
|
|
1885
2209
|
if ($.node instanceof HTMLElement) {
|
|
1886
2210
|
$.bindings.add(new StyleBinding(this, name, value));
|
|
@@ -1890,28 +2214,17 @@ class INode extends Fragment {
|
|
|
1890
2214
|
}
|
|
1891
2215
|
return this;
|
|
1892
2216
|
}
|
|
1893
|
-
$bindStyle(name, calculator, v1, v2, v3, v4, v5, v6, v7, v8, v9) {
|
|
1894
|
-
const $ = this.$;
|
|
1895
|
-
const expr = this.$bind(calculator, v1, v2, v3, v4, v5, v6, v7, v8, v9);
|
|
1896
|
-
if ($.node instanceof HTMLElement) {
|
|
1897
|
-
$.bindings.add(new StyleBinding(this, name, expr));
|
|
1898
|
-
}
|
|
1899
|
-
else {
|
|
1900
|
-
throw userError('style can be applied to HTML elements only', 'non-html-element');
|
|
1901
|
-
}
|
|
1902
|
-
return this;
|
|
1903
|
-
}
|
|
1904
2217
|
/**
|
|
1905
2218
|
* Sets a style property value
|
|
1906
2219
|
* @param prop {string} Property name
|
|
1907
2220
|
* @param value {string} Property value
|
|
1908
2221
|
*/
|
|
1909
|
-
|
|
2222
|
+
setStyle(prop, value) {
|
|
1910
2223
|
if (this.$.node instanceof HTMLElement) {
|
|
1911
|
-
this.$.
|
|
2224
|
+
this.$.node.style.setProperty(prop, value);
|
|
1912
2225
|
}
|
|
1913
2226
|
else {
|
|
1914
|
-
throw userError("Style can be
|
|
2227
|
+
throw userError("Style can be set for HTML elements only", "non-html-element");
|
|
1915
2228
|
}
|
|
1916
2229
|
return this;
|
|
1917
2230
|
}
|
|
@@ -1921,403 +2234,24 @@ class INode extends Fragment {
|
|
|
1921
2234
|
* @param handler {function (Event)} Event handler
|
|
1922
2235
|
* @param options {Object | boolean} addEventListener options
|
|
1923
2236
|
*/
|
|
1924
|
-
|
|
2237
|
+
listen(name, handler, options) {
|
|
1925
2238
|
this.$.node.addEventListener(name, handler, options);
|
|
1926
2239
|
return this;
|
|
1927
2240
|
}
|
|
1928
|
-
|
|
1929
|
-
|
|
1930
|
-
* @param options {Object | boolean}
|
|
1931
|
-
*/
|
|
1932
|
-
$oncontextmenu(handler, options) {
|
|
1933
|
-
return this.$listen("contextmenu", handler, options);
|
|
1934
|
-
}
|
|
1935
|
-
/**
|
|
1936
|
-
* @param handler {function (MouseEvent)}
|
|
1937
|
-
* @param options {Object | boolean}
|
|
1938
|
-
*/
|
|
1939
|
-
$onmousedown(handler, options) {
|
|
1940
|
-
return this.$listen("mousedown", handler, options);
|
|
1941
|
-
}
|
|
1942
|
-
/**
|
|
1943
|
-
* @param handler {function (MouseEvent)}
|
|
1944
|
-
* @param options {Object | boolean}
|
|
1945
|
-
*/
|
|
1946
|
-
$onmouseenter(handler, options) {
|
|
1947
|
-
return this.$listen("mouseenter", handler, options);
|
|
2241
|
+
insertAdjacent(node) {
|
|
2242
|
+
this.$.node.parentNode.insertBefore(node, this.$.node);
|
|
1948
2243
|
}
|
|
1949
2244
|
/**
|
|
1950
|
-
*
|
|
1951
|
-
* @param
|
|
2245
|
+
* A v-show & ngShow alternative
|
|
2246
|
+
* @param cond {IValue} show condition
|
|
1952
2247
|
*/
|
|
1953
|
-
|
|
1954
|
-
return this.$listen("mouseleave", handler, options);
|
|
1955
|
-
}
|
|
1956
|
-
/**
|
|
1957
|
-
* @param handler {function (MouseEvent)}
|
|
1958
|
-
* @param options {Object | boolean}
|
|
1959
|
-
*/
|
|
1960
|
-
$onmousemove(handler, options) {
|
|
1961
|
-
return this.$listen("mousemove", handler, options);
|
|
1962
|
-
}
|
|
1963
|
-
/**
|
|
1964
|
-
* @param handler {function (MouseEvent)}
|
|
1965
|
-
* @param options {Object | boolean}
|
|
1966
|
-
*/
|
|
1967
|
-
$onmouseout(handler, options) {
|
|
1968
|
-
return this.$listen("mouseout", handler, options);
|
|
1969
|
-
}
|
|
1970
|
-
/**
|
|
1971
|
-
* @param handler {function (MouseEvent)}
|
|
1972
|
-
* @param options {Object | boolean}
|
|
1973
|
-
*/
|
|
1974
|
-
$onmouseover(handler, options) {
|
|
1975
|
-
return this.$listen("mouseover", handler, options);
|
|
1976
|
-
}
|
|
1977
|
-
/**
|
|
1978
|
-
* @param handler {function (MouseEvent)}
|
|
1979
|
-
* @param options {Object | boolean}
|
|
1980
|
-
*/
|
|
1981
|
-
$onmouseup(handler, options) {
|
|
1982
|
-
return this.$listen("mouseup", handler, options);
|
|
1983
|
-
}
|
|
1984
|
-
/**
|
|
1985
|
-
* @param handler {function (MouseEvent)}
|
|
1986
|
-
* @param options {Object | boolean}
|
|
1987
|
-
*/
|
|
1988
|
-
$onclick(handler, options) {
|
|
1989
|
-
return this.$listen("click", handler, options);
|
|
1990
|
-
}
|
|
1991
|
-
/**
|
|
1992
|
-
* @param handler {function (MouseEvent)}
|
|
1993
|
-
* @param options {Object | boolean}
|
|
1994
|
-
*/
|
|
1995
|
-
$ondblclick(handler, options) {
|
|
1996
|
-
return this.$listen("dblclick", handler, options);
|
|
1997
|
-
}
|
|
1998
|
-
/**
|
|
1999
|
-
* @param handler {function (FocusEvent)}
|
|
2000
|
-
* @param options {Object | boolean}
|
|
2001
|
-
*/
|
|
2002
|
-
$onblur(handler, options) {
|
|
2003
|
-
return this.$listen("blur", handler, options);
|
|
2004
|
-
}
|
|
2005
|
-
/**
|
|
2006
|
-
* @param handler {function (FocusEvent)}
|
|
2007
|
-
* @param options {Object | boolean}
|
|
2008
|
-
*/
|
|
2009
|
-
$onfocus(handler, options) {
|
|
2010
|
-
return this.$listen("focus", handler, options);
|
|
2011
|
-
}
|
|
2012
|
-
/**
|
|
2013
|
-
* @param handler {function (FocusEvent)}
|
|
2014
|
-
* @param options {Object | boolean}
|
|
2015
|
-
*/
|
|
2016
|
-
$onfocusin(handler, options) {
|
|
2017
|
-
return this.$listen("focusin", handler, options);
|
|
2018
|
-
}
|
|
2019
|
-
/**
|
|
2020
|
-
* @param handler {function (FocusEvent)}
|
|
2021
|
-
* @param options {Object | boolean}
|
|
2022
|
-
*/
|
|
2023
|
-
$onfocusout(handler, options) {
|
|
2024
|
-
return this.$listen("focusout", handler, options);
|
|
2025
|
-
}
|
|
2026
|
-
/**
|
|
2027
|
-
* @param handler {function (KeyboardEvent)}
|
|
2028
|
-
* @param options {Object | boolean}
|
|
2029
|
-
*/
|
|
2030
|
-
$onkeydown(handler, options) {
|
|
2031
|
-
return this.$listen("keydown", handler, options);
|
|
2032
|
-
}
|
|
2033
|
-
/**
|
|
2034
|
-
* @param handler {function (KeyboardEvent)}
|
|
2035
|
-
* @param options {Object | boolean}
|
|
2036
|
-
*/
|
|
2037
|
-
$onkeyup(handler, options) {
|
|
2038
|
-
return this.$listen("keyup", handler, options);
|
|
2039
|
-
}
|
|
2040
|
-
/**
|
|
2041
|
-
* @param handler {function (KeyboardEvent)}
|
|
2042
|
-
* @param options {Object | boolean}
|
|
2043
|
-
*/
|
|
2044
|
-
$onkeypress(handler, options) {
|
|
2045
|
-
return this.$listen("keypress", handler, options);
|
|
2046
|
-
}
|
|
2047
|
-
/**
|
|
2048
|
-
* @param handler {function (TouchEvent)}
|
|
2049
|
-
* @param options {Object | boolean}
|
|
2050
|
-
*/
|
|
2051
|
-
$ontouchstart(handler, options) {
|
|
2052
|
-
return this.$listen("touchstart", handler, options);
|
|
2053
|
-
}
|
|
2054
|
-
/**
|
|
2055
|
-
* @param handler {function (TouchEvent)}
|
|
2056
|
-
* @param options {Object | boolean}
|
|
2057
|
-
*/
|
|
2058
|
-
$ontouchmove(handler, options) {
|
|
2059
|
-
return this.$listen("touchmove", handler, options);
|
|
2060
|
-
}
|
|
2061
|
-
/**
|
|
2062
|
-
* @param handler {function (TouchEvent)}
|
|
2063
|
-
* @param options {Object | boolean}
|
|
2064
|
-
*/
|
|
2065
|
-
$ontouchend(handler, options) {
|
|
2066
|
-
return this.$listen("touchend", handler, options);
|
|
2067
|
-
}
|
|
2068
|
-
/**
|
|
2069
|
-
* @param handler {function (TouchEvent)}
|
|
2070
|
-
* @param options {Object | boolean}
|
|
2071
|
-
*/
|
|
2072
|
-
$ontouchcancel(handler, options) {
|
|
2073
|
-
return this.$listen("touchcancel", handler, options);
|
|
2074
|
-
}
|
|
2075
|
-
/**
|
|
2076
|
-
* @param handler {function (WheelEvent)}
|
|
2077
|
-
* @param options {Object | boolean}
|
|
2078
|
-
*/
|
|
2079
|
-
$onwheel(handler, options) {
|
|
2080
|
-
return this.$listen("wheel", handler, options);
|
|
2081
|
-
}
|
|
2082
|
-
/**
|
|
2083
|
-
* @param handler {function (ProgressEvent)}
|
|
2084
|
-
* @param options {Object | boolean}
|
|
2085
|
-
*/
|
|
2086
|
-
$onabort(handler, options) {
|
|
2087
|
-
return this.$listen("abort", handler, options);
|
|
2088
|
-
}
|
|
2089
|
-
/**
|
|
2090
|
-
* @param handler {function (ProgressEvent)}
|
|
2091
|
-
* @param options {Object | boolean}
|
|
2092
|
-
*/
|
|
2093
|
-
$onerror(handler, options) {
|
|
2094
|
-
return this.$listen("error", handler, options);
|
|
2095
|
-
}
|
|
2096
|
-
/**
|
|
2097
|
-
* @param handler {function (ProgressEvent)}
|
|
2098
|
-
* @param options {Object | boolean}
|
|
2099
|
-
*/
|
|
2100
|
-
$onload(handler, options) {
|
|
2101
|
-
return this.$listen("load", handler, options);
|
|
2102
|
-
}
|
|
2103
|
-
/**
|
|
2104
|
-
* @param handler {function (ProgressEvent)}
|
|
2105
|
-
* @param options {Object | boolean}
|
|
2106
|
-
*/
|
|
2107
|
-
$onloadend(handler, options) {
|
|
2108
|
-
return this.$listen("loadend", handler, options);
|
|
2109
|
-
}
|
|
2110
|
-
/**
|
|
2111
|
-
* @param handler {function (ProgressEvent)}
|
|
2112
|
-
* @param options {Object | boolean}
|
|
2113
|
-
*/
|
|
2114
|
-
$onloadstart(handler, options) {
|
|
2115
|
-
return this.$listen("loadstart", handler, options);
|
|
2116
|
-
}
|
|
2117
|
-
/**
|
|
2118
|
-
* @param handler {function (ProgressEvent)}
|
|
2119
|
-
* @param options {Object | boolean}
|
|
2120
|
-
*/
|
|
2121
|
-
$onprogress(handler, options) {
|
|
2122
|
-
return this.$listen("progress", handler, options);
|
|
2123
|
-
}
|
|
2124
|
-
/**
|
|
2125
|
-
* @param handler {function (ProgressEvent)}
|
|
2126
|
-
* @param options {Object | boolean}
|
|
2127
|
-
*/
|
|
2128
|
-
$ontimeout(handler, options) {
|
|
2129
|
-
return this.$listen("timeout", handler, options);
|
|
2130
|
-
}
|
|
2131
|
-
/**
|
|
2132
|
-
* @param handler {function (DragEvent)}
|
|
2133
|
-
* @param options {Object | boolean}
|
|
2134
|
-
*/
|
|
2135
|
-
$ondrag(handler, options) {
|
|
2136
|
-
return this.$listen("drag", handler, options);
|
|
2137
|
-
}
|
|
2138
|
-
/**
|
|
2139
|
-
* @param handler {function (DragEvent)}
|
|
2140
|
-
* @param options {Object | boolean}
|
|
2141
|
-
*/
|
|
2142
|
-
$ondragend(handler, options) {
|
|
2143
|
-
return this.$listen("dragend", handler, options);
|
|
2144
|
-
}
|
|
2145
|
-
/**
|
|
2146
|
-
* @param handler {function (DragEvent)}
|
|
2147
|
-
* @param options {Object | boolean}
|
|
2148
|
-
*/
|
|
2149
|
-
$ondragenter(handler, options) {
|
|
2150
|
-
return this.$listen("dragenter", handler, options);
|
|
2151
|
-
}
|
|
2152
|
-
/**
|
|
2153
|
-
* @param handler {function (DragEvent)}
|
|
2154
|
-
* @param options {Object | boolean}
|
|
2155
|
-
*/
|
|
2156
|
-
$ondragexit(handler, options) {
|
|
2157
|
-
return this.$listen("dragexit", handler, options);
|
|
2158
|
-
}
|
|
2159
|
-
/**
|
|
2160
|
-
* @param handler {function (DragEvent)}
|
|
2161
|
-
* @param options {Object | boolean}
|
|
2162
|
-
*/
|
|
2163
|
-
$ondragleave(handler, options) {
|
|
2164
|
-
return this.$listen("dragleave", handler, options);
|
|
2165
|
-
}
|
|
2166
|
-
/**
|
|
2167
|
-
* @param handler {function (DragEvent)}
|
|
2168
|
-
* @param options {Object | boolean}
|
|
2169
|
-
*/
|
|
2170
|
-
$ondragover(handler, options) {
|
|
2171
|
-
return this.$listen("dragover", handler, options);
|
|
2172
|
-
}
|
|
2173
|
-
/**
|
|
2174
|
-
* @param handler {function (DragEvent)}
|
|
2175
|
-
* @param options {Object | boolean}
|
|
2176
|
-
*/
|
|
2177
|
-
$ondragstart(handler, options) {
|
|
2178
|
-
return this.$listen("dragstart", handler, options);
|
|
2179
|
-
}
|
|
2180
|
-
/**
|
|
2181
|
-
* @param handler {function (DragEvent)}
|
|
2182
|
-
* @param options {Object | boolean}
|
|
2183
|
-
*/
|
|
2184
|
-
$ondrop(handler, options) {
|
|
2185
|
-
return this.$listen("drop", handler, options);
|
|
2186
|
-
}
|
|
2187
|
-
/**
|
|
2188
|
-
* @param handler {function (PointerEvent)}
|
|
2189
|
-
* @param options {Object | boolean}
|
|
2190
|
-
*/
|
|
2191
|
-
$onpointerover(handler, options) {
|
|
2192
|
-
return this.$listen("pointerover", handler, options);
|
|
2193
|
-
}
|
|
2194
|
-
/**
|
|
2195
|
-
* @param handler {function (PointerEvent)}
|
|
2196
|
-
* @param options {Object | boolean}
|
|
2197
|
-
*/
|
|
2198
|
-
$onpointerenter(handler, options) {
|
|
2199
|
-
return this.$listen("pointerenter", handler, options);
|
|
2200
|
-
}
|
|
2201
|
-
/**
|
|
2202
|
-
* @param handler {function (PointerEvent)}
|
|
2203
|
-
* @param options {Object | boolean}
|
|
2204
|
-
*/
|
|
2205
|
-
$onpointerdown(handler, options) {
|
|
2206
|
-
return this.$listen("pointerdown", handler, options);
|
|
2207
|
-
}
|
|
2208
|
-
/**
|
|
2209
|
-
* @param handler {function (PointerEvent)}
|
|
2210
|
-
* @param options {Object | boolean}
|
|
2211
|
-
*/
|
|
2212
|
-
$onpointermove(handler, options) {
|
|
2213
|
-
return this.$listen("pointermove", handler, options);
|
|
2214
|
-
}
|
|
2215
|
-
/**
|
|
2216
|
-
* @param handler {function (PointerEvent)}
|
|
2217
|
-
* @param options {Object | boolean}
|
|
2218
|
-
*/
|
|
2219
|
-
$onpointerup(handler, options) {
|
|
2220
|
-
return this.$listen("pointerup", handler, options);
|
|
2221
|
-
}
|
|
2222
|
-
/**
|
|
2223
|
-
* @param handler {function (PointerEvent)}
|
|
2224
|
-
* @param options {Object | boolean}
|
|
2225
|
-
*/
|
|
2226
|
-
$onpointercancel(handler, options) {
|
|
2227
|
-
return this.$listen("pointercancel", handler, options);
|
|
2228
|
-
}
|
|
2229
|
-
/**
|
|
2230
|
-
* @param handler {function (PointerEvent)}
|
|
2231
|
-
* @param options {Object | boolean}
|
|
2232
|
-
*/
|
|
2233
|
-
$onpointerout(handler, options) {
|
|
2234
|
-
return this.$listen("pointerout", handler, options);
|
|
2235
|
-
}
|
|
2236
|
-
/**
|
|
2237
|
-
* @param handler {function (PointerEvent)}
|
|
2238
|
-
* @param options {Object | boolean}
|
|
2239
|
-
*/
|
|
2240
|
-
$onpointerleave(handler, options) {
|
|
2241
|
-
return this.$listen("pointerleave", handler, options);
|
|
2242
|
-
}
|
|
2243
|
-
/**
|
|
2244
|
-
* @param handler {function (PointerEvent)}
|
|
2245
|
-
* @param options {Object | boolean}
|
|
2246
|
-
*/
|
|
2247
|
-
$ongotpointercapture(handler, options) {
|
|
2248
|
-
return this.$listen("gotpointercapture", handler, options);
|
|
2249
|
-
}
|
|
2250
|
-
/**
|
|
2251
|
-
* @param handler {function (PointerEvent)}
|
|
2252
|
-
* @param options {Object | boolean}
|
|
2253
|
-
*/
|
|
2254
|
-
$onlostpointercapture(handler, options) {
|
|
2255
|
-
return this.$listen("lostpointercapture", handler, options);
|
|
2256
|
-
}
|
|
2257
|
-
/**
|
|
2258
|
-
* @param handler {function (AnimationEvent)}
|
|
2259
|
-
* @param options {Object | boolean}
|
|
2260
|
-
*/
|
|
2261
|
-
$onanimationstart(handler, options) {
|
|
2262
|
-
return this.$listen("animationstart", handler, options);
|
|
2263
|
-
}
|
|
2264
|
-
/**
|
|
2265
|
-
* @param handler {function (AnimationEvent)}
|
|
2266
|
-
* @param options {Object | boolean}
|
|
2267
|
-
*/
|
|
2268
|
-
$onanimationend(handler, options) {
|
|
2269
|
-
return this.$listen("animationend", handler, options);
|
|
2270
|
-
}
|
|
2271
|
-
/**
|
|
2272
|
-
* @param handler {function (AnimationEvent)}
|
|
2273
|
-
* @param options {Object | boolean}
|
|
2274
|
-
*/
|
|
2275
|
-
$onanimationiteraton(handler, options) {
|
|
2276
|
-
return this.$listen("animationiteration", handler, options);
|
|
2277
|
-
}
|
|
2278
|
-
/**
|
|
2279
|
-
* @param handler {function (ClipboardEvent)}
|
|
2280
|
-
* @param options {Object | boolean}
|
|
2281
|
-
*/
|
|
2282
|
-
$onclipboardchange(handler, options) {
|
|
2283
|
-
return this.$listen("clipboardchange", handler, options);
|
|
2284
|
-
}
|
|
2285
|
-
/**
|
|
2286
|
-
* @param handler {function (ClipboardEvent)}
|
|
2287
|
-
* @param options {Object | boolean}
|
|
2288
|
-
*/
|
|
2289
|
-
$oncut(handler, options) {
|
|
2290
|
-
return this.$listen("cut", handler, options);
|
|
2291
|
-
}
|
|
2292
|
-
/**
|
|
2293
|
-
* @param handler {function (ClipboardEvent)}
|
|
2294
|
-
* @param options {Object | boolean}
|
|
2295
|
-
*/
|
|
2296
|
-
$oncopy(handler, options) {
|
|
2297
|
-
return this.$listen("copy", handler, options);
|
|
2298
|
-
}
|
|
2299
|
-
/**
|
|
2300
|
-
* @param handler {function (ClipboardEvent)}
|
|
2301
|
-
* @param options {Object | boolean}
|
|
2302
|
-
*/
|
|
2303
|
-
$onpaste(handler, options) {
|
|
2304
|
-
return this.$listen("paste", handler, options);
|
|
2305
|
-
}
|
|
2306
|
-
$$insertAdjacent(node) {
|
|
2307
|
-
const $ = this.$;
|
|
2308
|
-
$.app.$run.insertBefore($.node, node);
|
|
2309
|
-
}
|
|
2310
|
-
/**
|
|
2311
|
-
* A v-show & ngShow alternative
|
|
2312
|
-
* @param cond {IValue} show condition
|
|
2313
|
-
*/
|
|
2314
|
-
$bindShow(cond) {
|
|
2248
|
+
bindShow(cond) {
|
|
2315
2249
|
const $ = this.$;
|
|
2316
2250
|
const node = $.node;
|
|
2317
2251
|
if (node instanceof HTMLElement) {
|
|
2318
2252
|
let lastDisplay = node.style.display;
|
|
2319
2253
|
const htmlNode = node;
|
|
2320
|
-
return this
|
|
2254
|
+
return this.bindAlive(cond, () => {
|
|
2321
2255
|
lastDisplay = htmlNode.style.display;
|
|
2322
2256
|
htmlNode.style.display = 'none';
|
|
2323
2257
|
}, () => {
|
|
@@ -2332,19 +2266,105 @@ class INode extends Fragment {
|
|
|
2332
2266
|
* bind HTML
|
|
2333
2267
|
* @param value {IValue}
|
|
2334
2268
|
*/
|
|
2335
|
-
|
|
2269
|
+
bindDomApi(name, value) {
|
|
2336
2270
|
const $ = this.$;
|
|
2337
2271
|
const node = $.node;
|
|
2338
2272
|
if (node instanceof HTMLElement) {
|
|
2339
|
-
node
|
|
2340
|
-
this
|
|
2341
|
-
node
|
|
2273
|
+
node[name] = value.$;
|
|
2274
|
+
this.watch((v) => {
|
|
2275
|
+
node[name] = v;
|
|
2342
2276
|
}, value);
|
|
2343
2277
|
}
|
|
2344
2278
|
else {
|
|
2345
2279
|
throw userError("HTML can be bound for HTML nodes only", "dom-error");
|
|
2346
2280
|
}
|
|
2347
2281
|
}
|
|
2282
|
+
applyOptions(options) {
|
|
2283
|
+
options["v:attr"] && Object.keys(options["v:attr"]).forEach(name => {
|
|
2284
|
+
const value = options["v:attr"][name];
|
|
2285
|
+
if (value instanceof IValue) {
|
|
2286
|
+
this.attr(name, value);
|
|
2287
|
+
}
|
|
2288
|
+
else {
|
|
2289
|
+
this.setAttr(name, value);
|
|
2290
|
+
}
|
|
2291
|
+
});
|
|
2292
|
+
if (options.class) {
|
|
2293
|
+
const handleClass = (name, value) => {
|
|
2294
|
+
if (value instanceof IValue) {
|
|
2295
|
+
this.floatingClass(value, name);
|
|
2296
|
+
}
|
|
2297
|
+
else if (value && name !== '$') {
|
|
2298
|
+
this.addClass(name);
|
|
2299
|
+
}
|
|
2300
|
+
else {
|
|
2301
|
+
this.removeClasse(name);
|
|
2302
|
+
}
|
|
2303
|
+
};
|
|
2304
|
+
if (Array.isArray(options.class)) {
|
|
2305
|
+
options.class.forEach(item => {
|
|
2306
|
+
if (item instanceof IValue) {
|
|
2307
|
+
this.bindClass(item);
|
|
2308
|
+
}
|
|
2309
|
+
else if (typeof item == "string") {
|
|
2310
|
+
this.addClass(item);
|
|
2311
|
+
}
|
|
2312
|
+
else {
|
|
2313
|
+
Reflect.ownKeys(item).forEach((name) => {
|
|
2314
|
+
handleClass(name, item[name]);
|
|
2315
|
+
});
|
|
2316
|
+
}
|
|
2317
|
+
});
|
|
2318
|
+
}
|
|
2319
|
+
else {
|
|
2320
|
+
options.class.$.forEach(item => {
|
|
2321
|
+
this.bindClass(item);
|
|
2322
|
+
});
|
|
2323
|
+
Reflect.ownKeys(options.class).forEach((name) => {
|
|
2324
|
+
handleClass(name, options.class[name]);
|
|
2325
|
+
});
|
|
2326
|
+
}
|
|
2327
|
+
}
|
|
2328
|
+
options.style && Object.keys(options.style).forEach(name => {
|
|
2329
|
+
const value = options.style[name];
|
|
2330
|
+
if (value instanceof IValue) {
|
|
2331
|
+
this.style(name, value);
|
|
2332
|
+
}
|
|
2333
|
+
else if (typeof value === "string") {
|
|
2334
|
+
this.setStyle(name, value);
|
|
2335
|
+
}
|
|
2336
|
+
else {
|
|
2337
|
+
if (value[0] instanceof IValue) {
|
|
2338
|
+
this.style(name, this.expr((v) => v + value[1], value[0]));
|
|
2339
|
+
}
|
|
2340
|
+
else {
|
|
2341
|
+
this.setStyle(name, value[0] + value[1]);
|
|
2342
|
+
}
|
|
2343
|
+
}
|
|
2344
|
+
});
|
|
2345
|
+
options["v:events"] && Object.keys(options["v:events"]).forEach(name => {
|
|
2346
|
+
this.listen(name, options["v:events"][name]);
|
|
2347
|
+
});
|
|
2348
|
+
if (options["v:bind"]) {
|
|
2349
|
+
const inode = this.node;
|
|
2350
|
+
Reflect.ownKeys(options["v:bind"]).forEach((k) => {
|
|
2351
|
+
const value = options["v:bind"][k];
|
|
2352
|
+
if (k === 'value' && (inode instanceof HTMLInputElement || inode instanceof HTMLTextAreaElement)) {
|
|
2353
|
+
inode.oninput = () => value.$ = inode.value;
|
|
2354
|
+
}
|
|
2355
|
+
else if (k === 'checked' && inode instanceof HTMLInputElement) {
|
|
2356
|
+
inode.oninput = () => value.$ = inode.checked;
|
|
2357
|
+
}
|
|
2358
|
+
else if (k === 'volume' && inode instanceof HTMLMediaElement) {
|
|
2359
|
+
inode.onvolumechange = () => value.$ = inode.volume;
|
|
2360
|
+
}
|
|
2361
|
+
this.bindDomApi(k, value);
|
|
2362
|
+
});
|
|
2363
|
+
}
|
|
2364
|
+
options["v:set"] && Object.keys(options["v:set"]).forEach(key => {
|
|
2365
|
+
this.node[key] = options["v:set"][key];
|
|
2366
|
+
});
|
|
2367
|
+
}
|
|
2348
2368
|
}
|
|
2349
2369
|
/**
|
|
2350
2370
|
* Represents an Vasille.js HTML element node
|
|
@@ -2352,11 +2372,11 @@ class INode extends Fragment {
|
|
|
2352
2372
|
* @extends INode
|
|
2353
2373
|
*/
|
|
2354
2374
|
class Tag extends INode {
|
|
2355
|
-
constructor() {
|
|
2356
|
-
super();
|
|
2357
|
-
this
|
|
2375
|
+
constructor(input) {
|
|
2376
|
+
super(input);
|
|
2377
|
+
this.seal();
|
|
2358
2378
|
}
|
|
2359
|
-
|
|
2379
|
+
preinit(app, parent, tagName) {
|
|
2360
2380
|
if (!tagName || typeof tagName !== "string") {
|
|
2361
2381
|
throw internalError('wrong Tag::$preinit call');
|
|
2362
2382
|
}
|
|
@@ -2364,55 +2384,52 @@ class Tag extends INode {
|
|
|
2364
2384
|
const $ = this.$;
|
|
2365
2385
|
$.preinit(app, parent);
|
|
2366
2386
|
$.node = node;
|
|
2367
|
-
$.parent
|
|
2387
|
+
$.parent.appendNode(node);
|
|
2368
2388
|
}
|
|
2369
|
-
|
|
2389
|
+
compose(input) {
|
|
2390
|
+
input.slot && input.slot(this);
|
|
2391
|
+
}
|
|
2392
|
+
findFirstChild() {
|
|
2370
2393
|
return this.$.unmounted ? null : this.$.node;
|
|
2371
2394
|
}
|
|
2372
|
-
|
|
2395
|
+
insertAdjacent(node) {
|
|
2373
2396
|
if (this.$.unmounted) {
|
|
2374
2397
|
if (this.$.next) {
|
|
2375
|
-
this.$.next
|
|
2398
|
+
this.$.next.insertAdjacent(node);
|
|
2376
2399
|
}
|
|
2377
2400
|
else {
|
|
2378
|
-
this.$.parent
|
|
2401
|
+
this.$.parent.appendNode(node);
|
|
2379
2402
|
}
|
|
2380
2403
|
}
|
|
2381
2404
|
else {
|
|
2382
|
-
super
|
|
2405
|
+
super.insertAdjacent(node);
|
|
2383
2406
|
}
|
|
2384
2407
|
}
|
|
2385
|
-
|
|
2386
|
-
|
|
2387
|
-
$.app.$run.appendChild($.node, node);
|
|
2408
|
+
appendNode(node) {
|
|
2409
|
+
this.$.node.appendChild(node);
|
|
2388
2410
|
}
|
|
2389
2411
|
/**
|
|
2390
2412
|
* Mount/Unmount a node
|
|
2391
2413
|
* @param cond {IValue} show condition
|
|
2392
2414
|
*/
|
|
2393
|
-
|
|
2415
|
+
bindMount(cond) {
|
|
2394
2416
|
const $ = this.$;
|
|
2395
|
-
|
|
2417
|
+
this.bindAlive(cond, () => {
|
|
2396
2418
|
$.node.remove();
|
|
2397
2419
|
$.unmounted = true;
|
|
2398
2420
|
}, () => {
|
|
2399
|
-
if (
|
|
2400
|
-
|
|
2401
|
-
|
|
2402
|
-
$.next.$$insertAdjacent($.node);
|
|
2403
|
-
}
|
|
2404
|
-
else {
|
|
2405
|
-
$.parent.$$appendNode($.node);
|
|
2421
|
+
if ($.unmounted) {
|
|
2422
|
+
this.insertAdjacent($.node);
|
|
2423
|
+
$.unmounted = false;
|
|
2406
2424
|
}
|
|
2407
|
-
$.unmounted = false;
|
|
2408
2425
|
});
|
|
2409
2426
|
}
|
|
2410
2427
|
/**
|
|
2411
2428
|
* Runs GC
|
|
2412
2429
|
*/
|
|
2413
|
-
|
|
2430
|
+
destroy() {
|
|
2414
2431
|
this.node.remove();
|
|
2415
|
-
super
|
|
2432
|
+
super.destroy();
|
|
2416
2433
|
}
|
|
2417
2434
|
}
|
|
2418
2435
|
/**
|
|
@@ -2421,22 +2438,22 @@ class Tag extends INode {
|
|
|
2421
2438
|
* @extends INode
|
|
2422
2439
|
*/
|
|
2423
2440
|
class Extension extends INode {
|
|
2424
|
-
|
|
2425
|
-
|
|
2426
|
-
|
|
2427
|
-
|
|
2428
|
-
|
|
2441
|
+
preinit(app, parent) {
|
|
2442
|
+
const $ = this.$;
|
|
2443
|
+
let it = parent;
|
|
2444
|
+
while (it && !(it instanceof INode)) {
|
|
2445
|
+
it = it.parent;
|
|
2429
2446
|
}
|
|
2430
|
-
|
|
2447
|
+
if (it && it instanceof INode) {
|
|
2448
|
+
$.node = it.node;
|
|
2449
|
+
}
|
|
2450
|
+
$.preinit(app, parent);
|
|
2451
|
+
if (!it) {
|
|
2431
2452
|
throw userError("A extension node can be encapsulated only in a tag/extension/component", "virtual-dom");
|
|
2432
2453
|
}
|
|
2433
2454
|
}
|
|
2434
|
-
|
|
2435
|
-
super(
|
|
2436
|
-
this.$seal();
|
|
2437
|
-
}
|
|
2438
|
-
$destroy() {
|
|
2439
|
-
super.$destroy();
|
|
2455
|
+
destroy() {
|
|
2456
|
+
super.destroy();
|
|
2440
2457
|
}
|
|
2441
2458
|
}
|
|
2442
2459
|
/**
|
|
@@ -2445,16 +2462,17 @@ class Extension extends INode {
|
|
|
2445
2462
|
* @extends Extension
|
|
2446
2463
|
*/
|
|
2447
2464
|
class Component extends Extension {
|
|
2448
|
-
|
|
2449
|
-
super();
|
|
2450
|
-
this
|
|
2451
|
-
|
|
2452
|
-
|
|
2453
|
-
|
|
2454
|
-
|
|
2465
|
+
init() {
|
|
2466
|
+
super.composeNow();
|
|
2467
|
+
this.ready();
|
|
2468
|
+
super.applyOptionsNow();
|
|
2469
|
+
}
|
|
2470
|
+
ready() {
|
|
2471
|
+
super.ready();
|
|
2472
|
+
if (this.children.size !== 1) {
|
|
2455
2473
|
throw userError("Component must have a child only", "dom-error");
|
|
2456
2474
|
}
|
|
2457
|
-
const child = this
|
|
2475
|
+
const child = this.lastChild;
|
|
2458
2476
|
if (child instanceof Tag || child instanceof Component) {
|
|
2459
2477
|
const $ = this.$;
|
|
2460
2478
|
$.node = child.node;
|
|
@@ -2463,7 +2481,7 @@ class Component extends Extension {
|
|
|
2463
2481
|
throw userError("Component child must be Tag or Component", "dom-error");
|
|
2464
2482
|
}
|
|
2465
2483
|
}
|
|
2466
|
-
|
|
2484
|
+
preinit(app, parent) {
|
|
2467
2485
|
this.$.preinit(app, parent);
|
|
2468
2486
|
}
|
|
2469
2487
|
}
|
|
@@ -2472,21 +2490,26 @@ class Component extends Extension {
|
|
|
2472
2490
|
* @class SwitchedNodePrivate
|
|
2473
2491
|
* @extends INodePrivate
|
|
2474
2492
|
*/
|
|
2475
|
-
class SwitchedNodePrivate extends
|
|
2493
|
+
class SwitchedNodePrivate extends FragmentPrivate {
|
|
2476
2494
|
constructor() {
|
|
2477
2495
|
super();
|
|
2478
|
-
|
|
2496
|
+
/**
|
|
2497
|
+
* Array of possible cases
|
|
2498
|
+
* @type {Array<{cond : IValue<boolean>, cb : function(Fragment)}>}
|
|
2499
|
+
*/
|
|
2500
|
+
this.cases = [];
|
|
2501
|
+
this.seal();
|
|
2479
2502
|
}
|
|
2480
2503
|
/**
|
|
2481
2504
|
* Runs GC
|
|
2482
2505
|
*/
|
|
2483
|
-
|
|
2506
|
+
destroy() {
|
|
2484
2507
|
this.cases.forEach(c => {
|
|
2485
2508
|
delete c.cond;
|
|
2486
2509
|
delete c.cb;
|
|
2487
2510
|
});
|
|
2488
2511
|
this.cases.splice(0);
|
|
2489
|
-
super
|
|
2512
|
+
super.destroy();
|
|
2490
2513
|
}
|
|
2491
2514
|
}
|
|
2492
2515
|
/**
|
|
@@ -2497,7 +2520,7 @@ class SwitchedNode extends Fragment {
|
|
|
2497
2520
|
* Constructs a switch node and define a sync function
|
|
2498
2521
|
*/
|
|
2499
2522
|
constructor() {
|
|
2500
|
-
super(new SwitchedNodePrivate);
|
|
2523
|
+
super({}, new SwitchedNodePrivate);
|
|
2501
2524
|
this.$.sync = () => {
|
|
2502
2525
|
const $ = this.$;
|
|
2503
2526
|
let i = 0;
|
|
@@ -2509,10 +2532,10 @@ class SwitchedNode extends Fragment {
|
|
|
2509
2532
|
if (i === $.index) {
|
|
2510
2533
|
return;
|
|
2511
2534
|
}
|
|
2512
|
-
if (
|
|
2513
|
-
|
|
2514
|
-
this
|
|
2515
|
-
|
|
2535
|
+
if (this.lastChild) {
|
|
2536
|
+
this.lastChild.destroy();
|
|
2537
|
+
this.children.clear();
|
|
2538
|
+
this.lastChild = null;
|
|
2516
2539
|
}
|
|
2517
2540
|
if (i !== $.cases.length) {
|
|
2518
2541
|
$.index = i;
|
|
@@ -2522,43 +2545,38 @@ class SwitchedNode extends Fragment {
|
|
|
2522
2545
|
$.index = -1;
|
|
2523
2546
|
}
|
|
2524
2547
|
};
|
|
2525
|
-
this
|
|
2548
|
+
this.seal();
|
|
2526
2549
|
}
|
|
2527
|
-
|
|
2528
|
-
|
|
2529
|
-
|
|
2530
|
-
|
|
2531
|
-
setCases(cases) {
|
|
2532
|
-
const $ = this.$;
|
|
2533
|
-
$.cases = [...cases];
|
|
2550
|
+
addCase(case_) {
|
|
2551
|
+
this.$.cases.push(case_);
|
|
2552
|
+
case_.cond.on(this.$.sync);
|
|
2553
|
+
this.$.sync();
|
|
2534
2554
|
}
|
|
2535
2555
|
/**
|
|
2536
2556
|
* Creates a child node
|
|
2537
2557
|
* @param cb {function(Fragment)} Call-back
|
|
2538
2558
|
*/
|
|
2539
2559
|
createChild(cb) {
|
|
2540
|
-
const node = new Fragment();
|
|
2541
|
-
node
|
|
2542
|
-
node
|
|
2543
|
-
node
|
|
2544
|
-
this
|
|
2545
|
-
this.$children.push(node);
|
|
2560
|
+
const node = new Fragment({});
|
|
2561
|
+
node.preinit(this.$.app, this);
|
|
2562
|
+
node.init();
|
|
2563
|
+
this.lastChild = node;
|
|
2564
|
+
this.children.add(node);
|
|
2546
2565
|
cb(node);
|
|
2547
2566
|
}
|
|
2548
|
-
|
|
2567
|
+
ready() {
|
|
2549
2568
|
const $ = this.$;
|
|
2550
|
-
super.$ready();
|
|
2551
2569
|
$.cases.forEach(c => {
|
|
2552
2570
|
c.cond.on($.sync);
|
|
2553
2571
|
});
|
|
2554
2572
|
$.sync();
|
|
2555
2573
|
}
|
|
2556
|
-
|
|
2574
|
+
destroy() {
|
|
2557
2575
|
const $ = this.$;
|
|
2558
2576
|
$.cases.forEach(c => {
|
|
2559
2577
|
c.cond.off($.sync);
|
|
2560
2578
|
});
|
|
2561
|
-
super
|
|
2579
|
+
super.destroy();
|
|
2562
2580
|
}
|
|
2563
2581
|
}
|
|
2564
2582
|
/**
|
|
@@ -2567,7 +2585,7 @@ class SwitchedNode extends Fragment {
|
|
|
2567
2585
|
class DebugPrivate extends FragmentPrivate {
|
|
2568
2586
|
constructor() {
|
|
2569
2587
|
super();
|
|
2570
|
-
this
|
|
2588
|
+
this.seal();
|
|
2571
2589
|
}
|
|
2572
2590
|
/**
|
|
2573
2591
|
* Pre-initializes a text node
|
|
@@ -2581,14 +2599,14 @@ class DebugPrivate extends FragmentPrivate {
|
|
|
2581
2599
|
this.bindings.add(new Expression((v) => {
|
|
2582
2600
|
this.node.replaceData(0, -1, v);
|
|
2583
2601
|
}, true, text));
|
|
2584
|
-
this.parent
|
|
2602
|
+
this.parent.appendNode(this.node);
|
|
2585
2603
|
}
|
|
2586
2604
|
/**
|
|
2587
2605
|
* Clear node data
|
|
2588
2606
|
*/
|
|
2589
|
-
|
|
2607
|
+
destroy() {
|
|
2590
2608
|
this.node.remove();
|
|
2591
|
-
super
|
|
2609
|
+
super.destroy();
|
|
2592
2610
|
}
|
|
2593
2611
|
}
|
|
2594
2612
|
/**
|
|
@@ -2598,15 +2616,15 @@ class DebugPrivate extends FragmentPrivate {
|
|
|
2598
2616
|
*/
|
|
2599
2617
|
class DebugNode extends Fragment {
|
|
2600
2618
|
constructor() {
|
|
2601
|
-
super();
|
|
2619
|
+
super({});
|
|
2602
2620
|
/**
|
|
2603
2621
|
* private data
|
|
2604
2622
|
* @type {DebugNode}
|
|
2605
2623
|
*/
|
|
2606
2624
|
this.$ = new DebugPrivate();
|
|
2607
|
-
this
|
|
2625
|
+
this.seal();
|
|
2608
2626
|
}
|
|
2609
|
-
|
|
2627
|
+
preinit(app, parent, text) {
|
|
2610
2628
|
const $ = this.$;
|
|
2611
2629
|
if (!text) {
|
|
2612
2630
|
throw internalError('wrong DebugNode::$preninit call');
|
|
@@ -2616,9 +2634,9 @@ class DebugNode extends Fragment {
|
|
|
2616
2634
|
/**
|
|
2617
2635
|
* Runs garbage collector
|
|
2618
2636
|
*/
|
|
2619
|
-
|
|
2620
|
-
this
|
|
2621
|
-
super
|
|
2637
|
+
destroy() {
|
|
2638
|
+
this.$.destroy();
|
|
2639
|
+
super.destroy();
|
|
2622
2640
|
}
|
|
2623
2641
|
}
|
|
2624
2642
|
|
|
@@ -2632,6 +2650,7 @@ window.Tag = Tag;
|
|
|
2632
2650
|
window.Extension = Extension;
|
|
2633
2651
|
window.Component = Component;
|
|
2634
2652
|
window.SwitchedNodePrivate = SwitchedNodePrivate;
|
|
2653
|
+
window.SwitchedNode = SwitchedNode;
|
|
2635
2654
|
window.DebugPrivate = DebugPrivate;
|
|
2636
2655
|
window.DebugNode = DebugNode;
|
|
2637
2656
|
|
|
@@ -2643,12 +2662,12 @@ window.DebugNode = DebugNode;
|
|
|
2643
2662
|
*/
|
|
2644
2663
|
class AppNode extends INode {
|
|
2645
2664
|
/**
|
|
2646
|
-
* @param
|
|
2665
|
+
* @param input
|
|
2647
2666
|
*/
|
|
2648
|
-
constructor(
|
|
2649
|
-
super();
|
|
2650
|
-
this
|
|
2651
|
-
this
|
|
2667
|
+
constructor(input) {
|
|
2668
|
+
super(input);
|
|
2669
|
+
this.debugUi = input.debugUi || false;
|
|
2670
|
+
this.seal();
|
|
2652
2671
|
}
|
|
2653
2672
|
}
|
|
2654
2673
|
/**
|
|
@@ -2660,22 +2679,33 @@ class App extends AppNode {
|
|
|
2660
2679
|
/**
|
|
2661
2680
|
* Constructs an app node
|
|
2662
2681
|
* @param node {Element} The root of application
|
|
2663
|
-
* @param
|
|
2682
|
+
* @param input
|
|
2664
2683
|
*/
|
|
2665
|
-
constructor(node,
|
|
2666
|
-
super(
|
|
2684
|
+
constructor(node, input) {
|
|
2685
|
+
super(input);
|
|
2667
2686
|
this.$.node = node;
|
|
2668
|
-
this
|
|
2669
|
-
this
|
|
2687
|
+
this.preinit(this, this);
|
|
2688
|
+
this.init();
|
|
2689
|
+
this.seal();
|
|
2670
2690
|
}
|
|
2671
|
-
|
|
2672
|
-
|
|
2673
|
-
|
|
2691
|
+
appendNode(node) {
|
|
2692
|
+
this.$.node.appendChild(node);
|
|
2693
|
+
}
|
|
2694
|
+
}
|
|
2695
|
+
class Portal extends AppNode {
|
|
2696
|
+
constructor(input) {
|
|
2697
|
+
super(input);
|
|
2698
|
+
this.$.node = input.node;
|
|
2699
|
+
this.seal();
|
|
2700
|
+
}
|
|
2701
|
+
appendNode(node) {
|
|
2702
|
+
this.$.node.appendChild(node);
|
|
2674
2703
|
}
|
|
2675
2704
|
}
|
|
2676
2705
|
|
|
2677
2706
|
window.AppNode = AppNode;
|
|
2678
2707
|
window.App = App;
|
|
2708
|
+
window.Portal = Portal;
|
|
2679
2709
|
|
|
2680
2710
|
// ./lib/node/interceptor.js
|
|
2681
2711
|
/**
|
|
@@ -2725,8 +2755,8 @@ class Interceptor extends Destroyable {
|
|
|
2725
2755
|
signal.unsubscribe(handler);
|
|
2726
2756
|
});
|
|
2727
2757
|
}
|
|
2728
|
-
|
|
2729
|
-
super
|
|
2758
|
+
destroy() {
|
|
2759
|
+
super.destroy();
|
|
2730
2760
|
this.signals.forEach(signal => {
|
|
2731
2761
|
this.handlers.forEach(handler => {
|
|
2732
2762
|
signal.unsubscribe(handler);
|
|
@@ -2753,7 +2783,7 @@ class InterceptorNode extends Fragment {
|
|
|
2753
2783
|
*/
|
|
2754
2784
|
this.slot = new Slot;
|
|
2755
2785
|
}
|
|
2756
|
-
|
|
2786
|
+
compose() {
|
|
2757
2787
|
this.slot.release(this, this.interceptor);
|
|
2758
2788
|
}
|
|
2759
2789
|
}
|
|
@@ -2775,22 +2805,21 @@ class AttributeBinding extends Binding {
|
|
|
2775
2805
|
* @param value {IValue} value to bind
|
|
2776
2806
|
*/
|
|
2777
2807
|
constructor(node, name, value) {
|
|
2778
|
-
super(
|
|
2779
|
-
|
|
2780
|
-
/**
|
|
2781
|
-
* Generates a function which updates the attribute value
|
|
2782
|
-
* @param name {String} The name of attribute
|
|
2783
|
-
* @returns {Function} a function which will update attribute value
|
|
2784
|
-
*/
|
|
2785
|
-
bound(name) {
|
|
2786
|
-
return function (node, value) {
|
|
2808
|
+
super(value);
|
|
2809
|
+
this.init((value) => {
|
|
2787
2810
|
if (value) {
|
|
2788
|
-
|
|
2811
|
+
if (typeof value === 'boolean') {
|
|
2812
|
+
node.node.setAttribute(name, "");
|
|
2813
|
+
}
|
|
2814
|
+
else {
|
|
2815
|
+
node.node.setAttribute(name, `${value}`);
|
|
2816
|
+
}
|
|
2789
2817
|
}
|
|
2790
2818
|
else {
|
|
2791
|
-
node.
|
|
2819
|
+
node.node.removeAttribute(name);
|
|
2792
2820
|
}
|
|
2793
|
-
};
|
|
2821
|
+
});
|
|
2822
|
+
this.seal();
|
|
2794
2823
|
}
|
|
2795
2824
|
}
|
|
2796
2825
|
|
|
@@ -2810,77 +2839,64 @@ class StyleBinding extends Binding {
|
|
|
2810
2839
|
* @param value {IValue} the value to bind
|
|
2811
2840
|
*/
|
|
2812
2841
|
constructor(node, name, value) {
|
|
2813
|
-
super(
|
|
2814
|
-
|
|
2815
|
-
/**
|
|
2816
|
-
* Generates a function to update style property value
|
|
2817
|
-
* @param name {string}
|
|
2818
|
-
* @returns {Function} a function to update style property
|
|
2819
|
-
*/
|
|
2820
|
-
bound(name) {
|
|
2821
|
-
return function (node, value) {
|
|
2842
|
+
super(value);
|
|
2843
|
+
this.init((value) => {
|
|
2822
2844
|
if (node.node instanceof HTMLElement) {
|
|
2823
|
-
node.
|
|
2845
|
+
node.node.style.setProperty(name, value);
|
|
2824
2846
|
}
|
|
2825
|
-
};
|
|
2847
|
+
});
|
|
2848
|
+
this.seal();
|
|
2826
2849
|
}
|
|
2827
2850
|
}
|
|
2828
2851
|
|
|
2829
2852
|
window.StyleBinding = StyleBinding;
|
|
2830
2853
|
|
|
2831
2854
|
// ./lib/binding/class.js
|
|
2832
|
-
|
|
2833
|
-
|
|
2834
|
-
|
|
2835
|
-
|
|
2836
|
-
|
|
2837
|
-
|
|
2838
|
-
|
|
2839
|
-
* Constructs an HTML class binding description
|
|
2840
|
-
* @param node {INode} the vasille node
|
|
2841
|
-
* @param name {String} the name of class
|
|
2842
|
-
* @param value {IValue} the value to bind
|
|
2843
|
-
*/
|
|
2855
|
+
function addClass(node, cl) {
|
|
2856
|
+
node.node.classList.add(cl);
|
|
2857
|
+
}
|
|
2858
|
+
function removeClass(node, cl) {
|
|
2859
|
+
node.node.classList.remove(cl);
|
|
2860
|
+
}
|
|
2861
|
+
class StaticClassBinding extends Binding {
|
|
2844
2862
|
constructor(node, name, value) {
|
|
2845
|
-
super(
|
|
2846
|
-
this
|
|
2847
|
-
|
|
2848
|
-
|
|
2849
|
-
|
|
2850
|
-
|
|
2851
|
-
* @returns {Function} a function which will update attribute value
|
|
2852
|
-
*/
|
|
2853
|
-
bound(name) {
|
|
2854
|
-
let current = null;
|
|
2855
|
-
function addClass(node, cl) {
|
|
2856
|
-
node.app.$run.addClass(node.node, cl);
|
|
2857
|
-
}
|
|
2858
|
-
function removeClass(node, cl) {
|
|
2859
|
-
node.app.$run.removeClass(node.node, cl);
|
|
2860
|
-
}
|
|
2861
|
-
return (node, value) => {
|
|
2862
|
-
if (value !== current) {
|
|
2863
|
-
if (typeof current === "string" && current !== "") {
|
|
2864
|
-
removeClass(node, current);
|
|
2863
|
+
super(value);
|
|
2864
|
+
this.current = false;
|
|
2865
|
+
this.init((value) => {
|
|
2866
|
+
if (value !== this.current) {
|
|
2867
|
+
if (value) {
|
|
2868
|
+
addClass(node, name);
|
|
2865
2869
|
}
|
|
2866
|
-
|
|
2867
|
-
|
|
2868
|
-
addClass(node, name);
|
|
2869
|
-
}
|
|
2870
|
-
else {
|
|
2871
|
-
removeClass(node, name);
|
|
2872
|
-
}
|
|
2870
|
+
else {
|
|
2871
|
+
removeClass(node, name);
|
|
2873
2872
|
}
|
|
2874
|
-
|
|
2873
|
+
this.current = value;
|
|
2874
|
+
}
|
|
2875
|
+
});
|
|
2876
|
+
this.seal();
|
|
2877
|
+
}
|
|
2878
|
+
}
|
|
2879
|
+
class DynamicalClassBinding extends Binding {
|
|
2880
|
+
constructor(node, value) {
|
|
2881
|
+
super(value);
|
|
2882
|
+
this.current = "";
|
|
2883
|
+
this.init((value) => {
|
|
2884
|
+
if (this.current != value) {
|
|
2885
|
+
if (this.current.length) {
|
|
2886
|
+
removeClass(node, this.current);
|
|
2887
|
+
}
|
|
2888
|
+
if (value.length) {
|
|
2875
2889
|
addClass(node, value);
|
|
2876
2890
|
}
|
|
2877
|
-
current = value;
|
|
2891
|
+
this.current = value;
|
|
2878
2892
|
}
|
|
2879
|
-
};
|
|
2893
|
+
});
|
|
2894
|
+
this.seal();
|
|
2880
2895
|
}
|
|
2881
2896
|
}
|
|
2882
2897
|
|
|
2883
|
-
window.
|
|
2898
|
+
window.StaticClassBinding = StaticClassBinding;
|
|
2899
|
+
window.DynamicalClassBinding = DynamicalClassBinding;
|
|
2884
2900
|
|
|
2885
2901
|
// ./lib/views/repeat-node.js
|
|
2886
2902
|
/**
|
|
@@ -2896,11 +2912,11 @@ class RepeatNodePrivate extends INodePrivate {
|
|
|
2896
2912
|
* @type {Map}
|
|
2897
2913
|
*/
|
|
2898
2914
|
this.nodes = new Map();
|
|
2899
|
-
this
|
|
2915
|
+
this.seal();
|
|
2900
2916
|
}
|
|
2901
|
-
|
|
2917
|
+
destroy() {
|
|
2902
2918
|
this.nodes.clear();
|
|
2903
|
-
super
|
|
2919
|
+
super.destroy();
|
|
2904
2920
|
}
|
|
2905
2921
|
}
|
|
2906
2922
|
/**
|
|
@@ -2909,80 +2925,42 @@ class RepeatNodePrivate extends INodePrivate {
|
|
|
2909
2925
|
* @extends Fragment
|
|
2910
2926
|
*/
|
|
2911
2927
|
class RepeatNode extends Fragment {
|
|
2912
|
-
constructor($) {
|
|
2913
|
-
super($
|
|
2928
|
+
constructor(input, $) {
|
|
2929
|
+
super(input, $);
|
|
2914
2930
|
/**
|
|
2915
2931
|
* If false will use timeout executor, otherwise the app executor
|
|
2916
2932
|
*/
|
|
2917
2933
|
this.freezeUi = true;
|
|
2918
|
-
this.slot = new Slot;
|
|
2919
2934
|
}
|
|
2920
|
-
createChild(id, item, before) {
|
|
2921
|
-
|
|
2922
|
-
const node = new Fragment();
|
|
2923
|
-
// eslint-disable-next-line
|
|
2924
|
-
// @ts-ignore
|
|
2925
|
-
const $ = node.$;
|
|
2935
|
+
createChild(opts, id, item, before) {
|
|
2936
|
+
const node = new Fragment({});
|
|
2926
2937
|
this.destroyChild(id, item);
|
|
2927
2938
|
if (before) {
|
|
2928
|
-
|
|
2929
|
-
|
|
2930
|
-
// @ts-ignore
|
|
2931
|
-
$.prev = before.$.prev;
|
|
2932
|
-
// eslint-disable-next-line
|
|
2933
|
-
// @ts-ignore
|
|
2934
|
-
before.$.prev = node;
|
|
2935
|
-
if ($.prev) {
|
|
2936
|
-
// eslint-disable-next-line
|
|
2937
|
-
// @ts-ignore
|
|
2938
|
-
$.prev.$.next = node;
|
|
2939
|
-
}
|
|
2940
|
-
this.$children.splice(this.$children.indexOf(before), 0, node);
|
|
2939
|
+
this.children.add(node);
|
|
2940
|
+
before.insertBefore(node);
|
|
2941
2941
|
}
|
|
2942
2942
|
else {
|
|
2943
|
-
const lastChild = this
|
|
2943
|
+
const lastChild = this.lastChild;
|
|
2944
2944
|
if (lastChild) {
|
|
2945
|
-
|
|
2946
|
-
// @ts-ignore
|
|
2947
|
-
lastChild.$.next = node;
|
|
2945
|
+
lastChild.insertAfter(node);
|
|
2948
2946
|
}
|
|
2949
|
-
|
|
2950
|
-
this.$children.push(node);
|
|
2951
|
-
}
|
|
2952
|
-
node.$preinit(this.$.app, this);
|
|
2953
|
-
node.$init();
|
|
2954
|
-
const callback = () => {
|
|
2955
|
-
this.slot.release(node, item, id);
|
|
2956
|
-
node.$ready();
|
|
2957
|
-
};
|
|
2958
|
-
if (this.freezeUi) {
|
|
2959
|
-
this.$.app.$run.callCallback(callback);
|
|
2960
|
-
}
|
|
2961
|
-
else {
|
|
2962
|
-
timeoutExecutor.callCallback(callback);
|
|
2947
|
+
this.children.add(node);
|
|
2963
2948
|
}
|
|
2949
|
+
this.lastChild = node;
|
|
2950
|
+
node.preinit(this.$.app, this);
|
|
2951
|
+
node.init();
|
|
2952
|
+
opts.slot && opts.slot(node, item, id);
|
|
2953
|
+
node.ready();
|
|
2964
2954
|
this.$.nodes.set(id, node);
|
|
2965
2955
|
}
|
|
2966
2956
|
destroyChild(id, item) {
|
|
2967
2957
|
const $ = this.$;
|
|
2968
2958
|
const child = $.nodes.get(id);
|
|
2969
2959
|
if (child) {
|
|
2970
|
-
|
|
2971
|
-
|
|
2972
|
-
const $ = child.$;
|
|
2973
|
-
if ($.prev) {
|
|
2974
|
-
// eslint-disable-next-line
|
|
2975
|
-
// @ts-ignore
|
|
2976
|
-
$.prev.$.next = $.next;
|
|
2977
|
-
}
|
|
2978
|
-
if ($.next) {
|
|
2979
|
-
// eslint-disable-next-line
|
|
2980
|
-
// @ts-ignore
|
|
2981
|
-
$.next.$.prev = $.prev;
|
|
2982
|
-
}
|
|
2983
|
-
child.$destroy();
|
|
2960
|
+
child.remove();
|
|
2961
|
+
child.destroy();
|
|
2984
2962
|
this.$.nodes.delete(id);
|
|
2985
|
-
this
|
|
2963
|
+
this.children.delete(child);
|
|
2986
2964
|
}
|
|
2987
2965
|
}
|
|
2988
2966
|
}
|
|
@@ -3003,7 +2981,7 @@ class RepeaterPrivate extends RepeatNodePrivate {
|
|
|
3003
2981
|
* Current count of child nodes
|
|
3004
2982
|
*/
|
|
3005
2983
|
this.currentCount = 0;
|
|
3006
|
-
this
|
|
2984
|
+
this.seal();
|
|
3007
2985
|
}
|
|
3008
2986
|
}
|
|
3009
2987
|
/**
|
|
@@ -3018,7 +2996,7 @@ class Repeater extends RepeatNode {
|
|
|
3018
2996
|
* The count of children
|
|
3019
2997
|
*/
|
|
3020
2998
|
this.count = new Reference(0);
|
|
3021
|
-
this
|
|
2999
|
+
this.seal();
|
|
3022
3000
|
}
|
|
3023
3001
|
/**
|
|
3024
3002
|
* Changes the children count
|
|
@@ -3037,18 +3015,18 @@ class Repeater extends RepeatNode {
|
|
|
3037
3015
|
}
|
|
3038
3016
|
$.currentCount = number;
|
|
3039
3017
|
}
|
|
3040
|
-
|
|
3018
|
+
created() {
|
|
3041
3019
|
const $ = this.$;
|
|
3042
|
-
super
|
|
3020
|
+
super.created();
|
|
3043
3021
|
$.updateHandler = this.changeCount.bind(this);
|
|
3044
3022
|
this.count.on($.updateHandler);
|
|
3045
3023
|
}
|
|
3046
|
-
|
|
3024
|
+
ready() {
|
|
3047
3025
|
this.changeCount(this.count.$);
|
|
3048
3026
|
}
|
|
3049
|
-
|
|
3027
|
+
destroy() {
|
|
3050
3028
|
const $ = this.$;
|
|
3051
|
-
super
|
|
3029
|
+
super.destroy();
|
|
3052
3030
|
this.count.off($.updateHandler);
|
|
3053
3031
|
}
|
|
3054
3032
|
}
|
|
@@ -3065,7 +3043,7 @@ window.Repeater = Repeater;
|
|
|
3065
3043
|
class BaseViewPrivate extends RepeatNodePrivate {
|
|
3066
3044
|
constructor() {
|
|
3067
3045
|
super();
|
|
3068
|
-
this
|
|
3046
|
+
this.seal();
|
|
3069
3047
|
}
|
|
3070
3048
|
}
|
|
3071
3049
|
/**
|
|
@@ -3075,34 +3053,23 @@ class BaseViewPrivate extends RepeatNodePrivate {
|
|
|
3075
3053
|
* @implements IModel
|
|
3076
3054
|
*/
|
|
3077
3055
|
class BaseView extends RepeatNode {
|
|
3078
|
-
constructor($
|
|
3079
|
-
super($
|
|
3056
|
+
constructor(input, $) {
|
|
3057
|
+
super(input, $ || new BaseViewPrivate);
|
|
3058
|
+
}
|
|
3059
|
+
compose(input) {
|
|
3080
3060
|
const $ = this.$;
|
|
3081
3061
|
$.addHandler = (id, item) => {
|
|
3082
|
-
this.createChild(id, item);
|
|
3062
|
+
this.createChild(input, id, item);
|
|
3083
3063
|
};
|
|
3084
3064
|
$.removeHandler = (id, item) => {
|
|
3085
3065
|
this.destroyChild(id, item);
|
|
3086
3066
|
};
|
|
3087
|
-
|
|
3088
|
-
|
|
3089
|
-
|
|
3090
|
-
|
|
3091
|
-
|
|
3092
|
-
|
|
3093
|
-
const $ = this.$;
|
|
3094
|
-
this.model.listener.onAdd($.addHandler);
|
|
3095
|
-
this.model.listener.onRemove($.removeHandler);
|
|
3096
|
-
super.$ready();
|
|
3097
|
-
}
|
|
3098
|
-
/**
|
|
3099
|
-
* Handles destroy event
|
|
3100
|
-
*/
|
|
3101
|
-
$destroy() {
|
|
3102
|
-
const $ = this.$;
|
|
3103
|
-
this.model.listener.offAdd($.addHandler);
|
|
3104
|
-
this.model.listener.offRemove($.removeHandler);
|
|
3105
|
-
super.$destroy();
|
|
3067
|
+
input.model.listener.onAdd($.addHandler);
|
|
3068
|
+
input.model.listener.onRemove($.removeHandler);
|
|
3069
|
+
this.runOnDestroy(() => {
|
|
3070
|
+
input.model.listener.offAdd($.addHandler);
|
|
3071
|
+
input.model.listener.offRemove($.removeHandler);
|
|
3072
|
+
});
|
|
3106
3073
|
}
|
|
3107
3074
|
}
|
|
3108
3075
|
|
|
@@ -3116,18 +3083,14 @@ window.BaseView = BaseView;
|
|
|
3116
3083
|
* @extends BaseView
|
|
3117
3084
|
*/
|
|
3118
3085
|
class ArrayView extends BaseView {
|
|
3119
|
-
|
|
3120
|
-
super();
|
|
3121
|
-
this.model = model;
|
|
3122
|
-
}
|
|
3123
|
-
createChild(id, item, before) {
|
|
3124
|
-
super.createChild(item, item, before || this.$.nodes.get(id));
|
|
3086
|
+
createChild(input, id, item, before) {
|
|
3087
|
+
super.createChild(input, item, item, before || this.$.nodes.get(id));
|
|
3125
3088
|
}
|
|
3126
|
-
|
|
3127
|
-
|
|
3128
|
-
|
|
3089
|
+
compose(input) {
|
|
3090
|
+
super.compose(input);
|
|
3091
|
+
input.model.forEach(item => {
|
|
3092
|
+
this.createChild(input, item, item);
|
|
3129
3093
|
});
|
|
3130
|
-
super.$ready();
|
|
3131
3094
|
}
|
|
3132
3095
|
}
|
|
3133
3096
|
|
|
@@ -3140,23 +3103,16 @@ window.ArrayView = ArrayView;
|
|
|
3140
3103
|
* @extends Fragment
|
|
3141
3104
|
*/
|
|
3142
3105
|
class Watch extends Fragment {
|
|
3143
|
-
|
|
3144
|
-
|
|
3145
|
-
|
|
3146
|
-
|
|
3147
|
-
this.$seal();
|
|
3148
|
-
}
|
|
3149
|
-
$createWatchers() {
|
|
3150
|
-
this.$watch((value) => {
|
|
3151
|
-
this.$children.forEach(child => {
|
|
3152
|
-
child.$destroy();
|
|
3106
|
+
compose(input) {
|
|
3107
|
+
this.watch((value) => {
|
|
3108
|
+
this.children.forEach(child => {
|
|
3109
|
+
child.destroy();
|
|
3153
3110
|
});
|
|
3154
|
-
this
|
|
3155
|
-
this.
|
|
3156
|
-
|
|
3157
|
-
|
|
3158
|
-
|
|
3159
|
-
this.slot.release(this, this.model.$);
|
|
3111
|
+
this.children.clear();
|
|
3112
|
+
this.lastChild = null;
|
|
3113
|
+
input.slot && input.slot(this, value);
|
|
3114
|
+
}, input.model);
|
|
3115
|
+
input.slot(this, input.model.$);
|
|
3160
3116
|
}
|
|
3161
3117
|
}
|
|
3162
3118
|
|
|
@@ -3169,16 +3125,13 @@ window.Watch = Watch;
|
|
|
3169
3125
|
* @extends BaseView
|
|
3170
3126
|
*/
|
|
3171
3127
|
class ObjectView extends BaseView {
|
|
3172
|
-
|
|
3173
|
-
super();
|
|
3174
|
-
|
|
3175
|
-
}
|
|
3176
|
-
$ready() {
|
|
3177
|
-
const obj = this.model;
|
|
3128
|
+
compose(input) {
|
|
3129
|
+
super.compose(input);
|
|
3130
|
+
const obj = input.model.proxy();
|
|
3178
3131
|
for (const key in obj) {
|
|
3179
|
-
this.createChild(key, obj[key]);
|
|
3132
|
+
this.createChild(input, key, obj[key]);
|
|
3180
3133
|
}
|
|
3181
|
-
super
|
|
3134
|
+
super.ready();
|
|
3182
3135
|
}
|
|
3183
3136
|
}
|
|
3184
3137
|
|
|
@@ -3191,16 +3144,11 @@ window.ObjectView = ObjectView;
|
|
|
3191
3144
|
* @extends BaseView
|
|
3192
3145
|
*/
|
|
3193
3146
|
class MapView extends BaseView {
|
|
3194
|
-
|
|
3195
|
-
super();
|
|
3196
|
-
|
|
3197
|
-
|
|
3198
|
-
$ready() {
|
|
3199
|
-
const map = this.model;
|
|
3200
|
-
map.forEach((value, key) => {
|
|
3201
|
-
this.createChild(key, value);
|
|
3147
|
+
compose(input) {
|
|
3148
|
+
super.compose(input);
|
|
3149
|
+
input.model.forEach((value, key) => {
|
|
3150
|
+
this.createChild(input, key, value);
|
|
3202
3151
|
});
|
|
3203
|
-
super.$ready();
|
|
3204
3152
|
}
|
|
3205
3153
|
}
|
|
3206
3154
|
|
|
@@ -3213,19 +3161,12 @@ window.MapView = MapView;
|
|
|
3213
3161
|
* @extends BaseView
|
|
3214
3162
|
*/
|
|
3215
3163
|
class SetView extends BaseView {
|
|
3216
|
-
|
|
3217
|
-
super();
|
|
3218
|
-
|
|
3219
|
-
}
|
|
3220
|
-
$ready() {
|
|
3221
|
-
const $ = this.$;
|
|
3222
|
-
const set = this.model;
|
|
3164
|
+
compose(input) {
|
|
3165
|
+
super.compose(input);
|
|
3166
|
+
const set = input.model;
|
|
3223
3167
|
set.forEach(item => {
|
|
3224
|
-
|
|
3225
|
-
this.createChild(item, item);
|
|
3226
|
-
});
|
|
3168
|
+
this.createChild(input, item, item);
|
|
3227
3169
|
});
|
|
3228
|
-
super.$ready();
|
|
3229
3170
|
}
|
|
3230
3171
|
}
|
|
3231
3172
|
|