vasille 2.0.3 → 2.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -3
- package/cdn/es2015.js +939 -1009
- package/cdn/es5.js +1048 -1029
- package/flow-typed/vasille.js +2641 -832
- package/lib/binding/attribute.js +11 -12
- package/lib/binding/binding.js +9 -19
- package/lib/binding/class.js +34 -42
- package/lib/binding/style.js +5 -11
- package/lib/core/core.js +78 -32
- package/lib/core/destroyable.js +2 -2
- package/lib/core/ivalue.js +15 -13
- package/lib/functional/components.js +17 -0
- package/lib/functional/merge.js +41 -0
- package/lib/functional/models.js +26 -0
- package/lib/functional/options.js +1 -0
- package/lib/functional/reactivity.js +33 -0
- package/lib/functional/stack.js +127 -0
- package/lib/index.js +2 -7
- package/lib/models/array-model.js +9 -0
- package/lib/models/object-model.js +28 -14
- package/lib/node/app.js +23 -14
- package/lib/node/interceptor.js +3 -3
- package/lib/node/node.js +338 -684
- package/lib/node/watch.js +9 -17
- package/lib/spec/html.js +1 -0
- package/lib/spec/react.js +1 -0
- package/lib/spec/svg.js +1 -0
- package/lib/v/index.js +23 -0
- package/lib/value/expression.js +11 -8
- package/lib/value/mirror.js +6 -8
- package/lib/value/reference.js +3 -7
- package/lib/views/array-view.js +6 -10
- package/lib/views/base-view.js +12 -23
- package/lib/views/map-view.js +4 -9
- package/lib/views/object-view.js +5 -8
- package/lib/views/repeat-node.js +20 -60
- package/lib/views/repeater.js +7 -7
- package/lib/views/set-view.js +4 -11
- package/package.json +7 -6
- package/types/binding/attribute.d.ts +2 -8
- package/types/binding/binding.d.ts +4 -13
- package/types/binding/class.d.ts +7 -19
- package/types/binding/style.d.ts +0 -6
- package/types/core/core.d.ts +40 -54
- package/types/core/destroyable.d.ts +2 -2
- package/types/core/ivalue.d.ts +13 -11
- package/types/functional/components.d.ts +4 -0
- package/types/functional/merge.d.ts +1 -0
- package/types/functional/models.d.ts +10 -0
- package/types/functional/options.d.ts +23 -0
- package/types/functional/reactivity.d.ts +11 -0
- package/types/functional/stack.d.ts +24 -0
- package/types/index.d.ts +3 -7
- package/types/models/array-model.d.ts +3 -2
- package/types/models/map-model.d.ts +2 -2
- package/types/models/model.d.ts +3 -1
- package/types/models/object-model.d.ts +4 -2
- package/types/models/set-model.d.ts +2 -2
- package/types/node/app.d.ts +21 -19
- package/types/node/node.d.ts +97 -422
- package/types/node/watch.d.ts +9 -15
- package/types/spec/html.d.ts +975 -0
- package/types/spec/react.d.ts +4 -0
- package/types/spec/svg.d.ts +314 -0
- package/types/v/index.d.ts +32 -0
- package/types/value/expression.d.ts +7 -20
- package/types/value/mirror.d.ts +3 -3
- package/types/value/reference.d.ts +5 -5
- package/types/views/array-view.d.ts +3 -4
- package/types/views/base-view.d.ts +9 -17
- package/types/views/map-view.d.ts +2 -3
- package/types/views/object-view.d.ts +2 -3
- package/types/views/repeat-node.d.ts +8 -9
- package/types/views/set-view.d.ts +2 -3
- package/types/core/executor.d.ts +0 -87
- package/types/core/signal.d.ts +0 -35
- package/types/core/slot.d.ts +0 -45
- package/types/node/interceptor.d.ts +0 -50
- package/types/views/repeater.d.ts +0 -38
package/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,40 @@ 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
|
+
compose(input) {
|
|
1753
|
+
// empty
|
|
1754
|
+
}
|
|
1755
|
+
runFunctional(f, ...args) {
|
|
1756
|
+
stack(this);
|
|
1757
|
+
// yet another ts bug
|
|
1758
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
1759
|
+
// @ts-ignore
|
|
1760
|
+
const result = f(...args);
|
|
1761
|
+
unstack();
|
|
1762
|
+
return result;
|
|
1763
|
+
}
|
|
1764
|
+
runOnDestroy(func) {
|
|
1765
|
+
this.$.onDestroy = func;
|
|
1766
|
+
}
|
|
1767
|
+
destroy() {
|
|
1768
|
+
super.destroy();
|
|
1769
|
+
this.$.destroy();
|
|
1417
1770
|
this.$ = null;
|
|
1418
1771
|
}
|
|
1419
1772
|
}
|
|
@@ -1430,7 +1783,7 @@ window.Reactive = Reactive;
|
|
|
1430
1783
|
class FragmentPrivate extends ReactivePrivate {
|
|
1431
1784
|
constructor() {
|
|
1432
1785
|
super();
|
|
1433
|
-
this
|
|
1786
|
+
this.seal();
|
|
1434
1787
|
}
|
|
1435
1788
|
/**
|
|
1436
1789
|
* Pre-initializes the base of a fragment
|
|
@@ -1444,10 +1797,10 @@ class FragmentPrivate extends ReactivePrivate {
|
|
|
1444
1797
|
/**
|
|
1445
1798
|
* Unlinks all bindings
|
|
1446
1799
|
*/
|
|
1447
|
-
|
|
1800
|
+
destroy() {
|
|
1448
1801
|
this.next = null;
|
|
1449
1802
|
this.prev = null;
|
|
1450
|
-
super
|
|
1803
|
+
super.destroy();
|
|
1451
1804
|
}
|
|
1452
1805
|
}
|
|
1453
1806
|
/**
|
|
@@ -1457,16 +1810,17 @@ class FragmentPrivate extends ReactivePrivate {
|
|
|
1457
1810
|
class Fragment extends Reactive {
|
|
1458
1811
|
/**
|
|
1459
1812
|
* Constructs a Vasille Node
|
|
1813
|
+
* @param input
|
|
1460
1814
|
* @param $ {FragmentPrivate}
|
|
1461
1815
|
*/
|
|
1462
|
-
constructor($) {
|
|
1463
|
-
super();
|
|
1816
|
+
constructor(input, $) {
|
|
1817
|
+
super(input, $ || new FragmentPrivate);
|
|
1464
1818
|
/**
|
|
1465
1819
|
* The children list
|
|
1466
1820
|
* @type Array
|
|
1467
1821
|
*/
|
|
1468
|
-
this
|
|
1469
|
-
this
|
|
1822
|
+
this.children = new Set;
|
|
1823
|
+
this.lastChild = null;
|
|
1470
1824
|
}
|
|
1471
1825
|
/**
|
|
1472
1826
|
* Gets the app of node
|
|
@@ -1480,43 +1834,16 @@ class Fragment extends Reactive {
|
|
|
1480
1834
|
* @param parent {Fragment} parent of node
|
|
1481
1835
|
* @param data {*} additional data
|
|
1482
1836
|
*/
|
|
1483
|
-
|
|
1837
|
+
preinit(app, parent, data) {
|
|
1484
1838
|
const $ = this.$;
|
|
1485
1839
|
$.preinit(app, parent);
|
|
1486
1840
|
}
|
|
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
|
|
1501
|
-
}
|
|
1502
|
-
/** To be overloaded: mounted event handler */
|
|
1503
|
-
$mounted() {
|
|
1504
|
-
// empty
|
|
1841
|
+
compose(input) {
|
|
1842
|
+
super.compose(input);
|
|
1843
|
+
input.slot && input.slot(this);
|
|
1505
1844
|
}
|
|
1506
1845
|
/** 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() {
|
|
1846
|
+
ready() {
|
|
1520
1847
|
// empty
|
|
1521
1848
|
}
|
|
1522
1849
|
/**
|
|
@@ -1524,27 +1851,23 @@ class Fragment extends Reactive {
|
|
|
1524
1851
|
* @param node {Fragment} A node to push
|
|
1525
1852
|
* @protected
|
|
1526
1853
|
*/
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
lastChild = this.$children[this.$children.length - 1];
|
|
1531
|
-
}
|
|
1532
|
-
if (lastChild) {
|
|
1533
|
-
lastChild.$.next = node;
|
|
1854
|
+
pushNode(node) {
|
|
1855
|
+
if (this.lastChild) {
|
|
1856
|
+
this.lastChild.$.next = node;
|
|
1534
1857
|
}
|
|
1535
|
-
node.$.prev = lastChild;
|
|
1536
|
-
|
|
1537
|
-
this
|
|
1858
|
+
node.$.prev = this.lastChild;
|
|
1859
|
+
this.lastChild = node;
|
|
1860
|
+
this.children.add(node);
|
|
1538
1861
|
}
|
|
1539
1862
|
/**
|
|
1540
1863
|
* Find first node in element if so exists
|
|
1541
1864
|
* @return {?Element}
|
|
1542
1865
|
* @protected
|
|
1543
1866
|
*/
|
|
1544
|
-
|
|
1867
|
+
findFirstChild() {
|
|
1545
1868
|
let first;
|
|
1546
|
-
this
|
|
1547
|
-
first = first || child
|
|
1869
|
+
this.children.forEach(child => {
|
|
1870
|
+
first = first || child.findFirstChild();
|
|
1548
1871
|
});
|
|
1549
1872
|
return first;
|
|
1550
1873
|
}
|
|
@@ -1552,30 +1875,30 @@ class Fragment extends Reactive {
|
|
|
1552
1875
|
* Append a node to end of element
|
|
1553
1876
|
* @param node {Node} node to insert
|
|
1554
1877
|
*/
|
|
1555
|
-
|
|
1878
|
+
appendNode(node) {
|
|
1556
1879
|
const $ = this.$;
|
|
1557
1880
|
if ($.next) {
|
|
1558
|
-
$.next
|
|
1881
|
+
$.next.insertAdjacent(node);
|
|
1559
1882
|
}
|
|
1560
1883
|
else {
|
|
1561
|
-
$.parent
|
|
1884
|
+
$.parent.appendNode(node);
|
|
1562
1885
|
}
|
|
1563
1886
|
}
|
|
1564
1887
|
/**
|
|
1565
1888
|
* Insert a node as a sibling of this
|
|
1566
1889
|
* @param node {Node} node to insert
|
|
1567
1890
|
*/
|
|
1568
|
-
|
|
1569
|
-
const child = this
|
|
1891
|
+
insertAdjacent(node) {
|
|
1892
|
+
const child = this.findFirstChild();
|
|
1570
1893
|
const $ = this.$;
|
|
1571
1894
|
if (child) {
|
|
1572
|
-
|
|
1895
|
+
child.parentElement.insertBefore(node, child);
|
|
1573
1896
|
}
|
|
1574
1897
|
else if ($.next) {
|
|
1575
|
-
$.next
|
|
1898
|
+
$.next.insertAdjacent(node);
|
|
1576
1899
|
}
|
|
1577
1900
|
else {
|
|
1578
|
-
$.parent
|
|
1901
|
+
$.parent.appendNode(node);
|
|
1579
1902
|
}
|
|
1580
1903
|
}
|
|
1581
1904
|
/**
|
|
@@ -1583,60 +1906,49 @@ class Fragment extends Reactive {
|
|
|
1583
1906
|
* @param text {String | IValue} A text fragment string
|
|
1584
1907
|
* @param cb {function (TextNode)} Callback if previous is slot name
|
|
1585
1908
|
*/
|
|
1586
|
-
|
|
1909
|
+
text(text, cb) {
|
|
1587
1910
|
const $ = this.$;
|
|
1588
1911
|
const node = new TextNode();
|
|
1589
|
-
|
|
1590
|
-
node
|
|
1591
|
-
|
|
1592
|
-
if (cb) {
|
|
1593
|
-
$.app.$run.callCallback(() => {
|
|
1594
|
-
cb(node);
|
|
1595
|
-
});
|
|
1596
|
-
}
|
|
1597
|
-
return this;
|
|
1912
|
+
node.preinit($.app, this, text);
|
|
1913
|
+
this.pushNode(node);
|
|
1914
|
+
cb && cb(node);
|
|
1598
1915
|
}
|
|
1599
|
-
|
|
1600
|
-
if (this.$.app
|
|
1916
|
+
debug(text) {
|
|
1917
|
+
if (this.$.app.debugUi) {
|
|
1601
1918
|
const node = new DebugNode();
|
|
1602
|
-
node
|
|
1603
|
-
this
|
|
1919
|
+
node.preinit(this.$.app, this, text);
|
|
1920
|
+
this.pushNode(node);
|
|
1604
1921
|
}
|
|
1605
|
-
return this;
|
|
1606
1922
|
}
|
|
1607
|
-
|
|
1923
|
+
/**
|
|
1924
|
+
* Defines a tag element
|
|
1925
|
+
* @param tagName {String} the tag name
|
|
1926
|
+
* @param input
|
|
1927
|
+
* @param cb {function(Tag, *)} callback
|
|
1928
|
+
*/
|
|
1929
|
+
tag(tagName, input, cb) {
|
|
1608
1930
|
const $ = this.$;
|
|
1609
|
-
const node = new Tag();
|
|
1610
|
-
|
|
1611
|
-
node
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
}
|
|
1617
|
-
node.$ready();
|
|
1618
|
-
});
|
|
1619
|
-
return this;
|
|
1931
|
+
const node = new Tag(input);
|
|
1932
|
+
input.slot = cb || input.slot;
|
|
1933
|
+
node.preinit($.app, this, tagName);
|
|
1934
|
+
node.init();
|
|
1935
|
+
this.pushNode(node);
|
|
1936
|
+
node.ready();
|
|
1937
|
+
return node.node;
|
|
1620
1938
|
}
|
|
1621
1939
|
/**
|
|
1622
1940
|
* Defines a custom element
|
|
1623
1941
|
* @param node {Fragment} vasille element to insert
|
|
1624
1942
|
* @param callback {function($ : *)}
|
|
1625
|
-
* @param callback1 {function($ : *)}
|
|
1626
1943
|
*/
|
|
1627
|
-
|
|
1944
|
+
create(node, callback) {
|
|
1628
1945
|
const $ = this.$;
|
|
1629
1946
|
node.$.parent = this;
|
|
1630
|
-
node
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
callback1(node);
|
|
1636
|
-
}
|
|
1637
|
-
this.$$pushNode(node);
|
|
1638
|
-
node.$init().$ready();
|
|
1639
|
-
return this;
|
|
1947
|
+
node.preinit($.app, this);
|
|
1948
|
+
node.input.slot = callback || node.input.slot;
|
|
1949
|
+
this.pushNode(node);
|
|
1950
|
+
node.init();
|
|
1951
|
+
node.ready();
|
|
1640
1952
|
}
|
|
1641
1953
|
/**
|
|
1642
1954
|
* Defines an if node
|
|
@@ -1644,32 +1956,29 @@ class Fragment extends Reactive {
|
|
|
1644
1956
|
* @param cb {function(Fragment)} callback to run on true
|
|
1645
1957
|
* @return {this}
|
|
1646
1958
|
*/
|
|
1647
|
-
|
|
1648
|
-
|
|
1959
|
+
if(cond, cb) {
|
|
1960
|
+
const node = new SwitchedNode();
|
|
1961
|
+
node.preinit(this.$.app, this);
|
|
1962
|
+
node.init();
|
|
1963
|
+
this.pushNode(node);
|
|
1964
|
+
node.addCase(this.case(cond, cb));
|
|
1965
|
+
node.ready();
|
|
1649
1966
|
}
|
|
1650
|
-
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
return this.$switch({ cond: ifCond, cb: ifCb }, { cond: trueIValue, cb: elseCb });
|
|
1967
|
+
else(cb) {
|
|
1968
|
+
if (this.lastChild instanceof SwitchedNode) {
|
|
1969
|
+
this.lastChild.addCase(this.default(cb));
|
|
1970
|
+
}
|
|
1971
|
+
else {
|
|
1972
|
+
throw userError('wrong `else` function use', 'logic-error');
|
|
1973
|
+
}
|
|
1658
1974
|
}
|
|
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;
|
|
1975
|
+
elif(cond, cb) {
|
|
1976
|
+
if (this.lastChild instanceof SwitchedNode) {
|
|
1977
|
+
this.lastChild.addCase(this.case(cond, cb));
|
|
1978
|
+
}
|
|
1979
|
+
else {
|
|
1980
|
+
throw userError('wrong `elif` function use', 'logic-error');
|
|
1981
|
+
}
|
|
1673
1982
|
}
|
|
1674
1983
|
/**
|
|
1675
1984
|
* Create a case for switch
|
|
@@ -1677,22 +1986,48 @@ class Fragment extends Reactive {
|
|
|
1677
1986
|
* @param cb {function(Fragment) : void}
|
|
1678
1987
|
* @return {{cond : IValue, cb : (function(Fragment) : void)}}
|
|
1679
1988
|
*/
|
|
1680
|
-
|
|
1989
|
+
case(cond, cb) {
|
|
1681
1990
|
return { cond, cb };
|
|
1682
1991
|
}
|
|
1683
1992
|
/**
|
|
1684
1993
|
* @param cb {(function(Fragment) : void)}
|
|
1685
1994
|
* @return {{cond : IValue, cb : (function(Fragment) : void)}}
|
|
1686
1995
|
*/
|
|
1687
|
-
|
|
1996
|
+
default(cb) {
|
|
1688
1997
|
return { cond: trueIValue, cb };
|
|
1689
1998
|
}
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
|
|
1999
|
+
insertBefore(node) {
|
|
2000
|
+
const $ = this.$;
|
|
2001
|
+
node.$.prev = $.prev;
|
|
2002
|
+
node.$.next = this;
|
|
2003
|
+
if ($.prev) {
|
|
2004
|
+
$.prev.$.next = node;
|
|
2005
|
+
}
|
|
2006
|
+
$.prev = node;
|
|
2007
|
+
}
|
|
2008
|
+
insertAfter(node) {
|
|
2009
|
+
const $ = this.$;
|
|
2010
|
+
node.$.prev = this;
|
|
2011
|
+
node.$.next = $.next;
|
|
2012
|
+
$.next = node;
|
|
2013
|
+
}
|
|
2014
|
+
remove() {
|
|
2015
|
+
const $ = this.$;
|
|
2016
|
+
if ($.next) {
|
|
2017
|
+
$.next.$.prev = $.prev;
|
|
2018
|
+
}
|
|
2019
|
+
if ($.prev) {
|
|
2020
|
+
$.prev.$.next = $.next;
|
|
2021
|
+
}
|
|
2022
|
+
}
|
|
2023
|
+
destroy() {
|
|
2024
|
+
this.children.forEach(child => child.destroy());
|
|
2025
|
+
this.children.clear();
|
|
2026
|
+
this.lastChild = null;
|
|
2027
|
+
if (this.$.parent.lastChild === this) {
|
|
2028
|
+
this.$.parent.lastChild = this.$.prev;
|
|
1693
2029
|
}
|
|
1694
|
-
|
|
1695
|
-
super.$destroy();
|
|
2030
|
+
super.destroy();
|
|
1696
2031
|
}
|
|
1697
2032
|
}
|
|
1698
2033
|
const trueIValue = new Reference(true);
|
|
@@ -1704,26 +2039,28 @@ const trueIValue = new Reference(true);
|
|
|
1704
2039
|
class TextNodePrivate extends FragmentPrivate {
|
|
1705
2040
|
constructor() {
|
|
1706
2041
|
super();
|
|
1707
|
-
this
|
|
2042
|
+
this.seal();
|
|
1708
2043
|
}
|
|
1709
2044
|
/**
|
|
1710
2045
|
* Pre-initializes a text node
|
|
1711
2046
|
* @param app {AppNode} the app node
|
|
2047
|
+
* @param parent
|
|
1712
2048
|
* @param text {IValue}
|
|
1713
2049
|
*/
|
|
1714
2050
|
preinitText(app, parent, text) {
|
|
1715
2051
|
super.preinit(app, parent);
|
|
1716
|
-
this.node = document.createTextNode(text.$);
|
|
1717
|
-
|
|
1718
|
-
this.
|
|
1719
|
-
|
|
1720
|
-
|
|
2052
|
+
this.node = document.createTextNode(text instanceof IValue ? text.$ : text);
|
|
2053
|
+
if (text instanceof IValue) {
|
|
2054
|
+
this.bindings.add(new Expression((v) => {
|
|
2055
|
+
this.node.replaceData(0, -1, v);
|
|
2056
|
+
}, true, text));
|
|
2057
|
+
}
|
|
1721
2058
|
}
|
|
1722
2059
|
/**
|
|
1723
2060
|
* Clear node data
|
|
1724
2061
|
*/
|
|
1725
|
-
|
|
1726
|
-
super
|
|
2062
|
+
destroy() {
|
|
2063
|
+
super.destroy();
|
|
1727
2064
|
}
|
|
1728
2065
|
}
|
|
1729
2066
|
/**
|
|
@@ -1732,25 +2069,25 @@ class TextNodePrivate extends FragmentPrivate {
|
|
|
1732
2069
|
* @extends Fragment
|
|
1733
2070
|
*/
|
|
1734
2071
|
class TextNode extends Fragment {
|
|
1735
|
-
constructor() {
|
|
1736
|
-
super();
|
|
1737
|
-
this
|
|
1738
|
-
this.$seal();
|
|
2072
|
+
constructor($ = new TextNodePrivate()) {
|
|
2073
|
+
super({}, $);
|
|
2074
|
+
this.seal();
|
|
1739
2075
|
}
|
|
1740
|
-
|
|
2076
|
+
preinit(app, parent, text) {
|
|
1741
2077
|
const $ = this.$;
|
|
1742
2078
|
if (!text) {
|
|
1743
2079
|
throw internalError('wrong TextNode::$preninit call');
|
|
1744
2080
|
}
|
|
1745
2081
|
$.preinitText(app, parent, text);
|
|
2082
|
+
$.parent.appendNode($.node);
|
|
1746
2083
|
}
|
|
1747
|
-
|
|
2084
|
+
findFirstChild() {
|
|
1748
2085
|
return this.$.node;
|
|
1749
2086
|
}
|
|
1750
|
-
|
|
2087
|
+
destroy() {
|
|
1751
2088
|
this.$.node.remove();
|
|
1752
|
-
this
|
|
1753
|
-
super
|
|
2089
|
+
this.$.destroy();
|
|
2090
|
+
super.destroy();
|
|
1754
2091
|
}
|
|
1755
2092
|
}
|
|
1756
2093
|
/**
|
|
@@ -1766,10 +2103,10 @@ class INodePrivate extends FragmentPrivate {
|
|
|
1766
2103
|
* @type {boolean}
|
|
1767
2104
|
*/
|
|
1768
2105
|
this.unmounted = false;
|
|
1769
|
-
this
|
|
2106
|
+
this.seal();
|
|
1770
2107
|
}
|
|
1771
|
-
|
|
1772
|
-
super
|
|
2108
|
+
destroy() {
|
|
2109
|
+
super.destroy();
|
|
1773
2110
|
}
|
|
1774
2111
|
}
|
|
1775
2112
|
/**
|
|
@@ -1780,11 +2117,12 @@ class INodePrivate extends FragmentPrivate {
|
|
|
1780
2117
|
class INode extends Fragment {
|
|
1781
2118
|
/**
|
|
1782
2119
|
* Constructs a base node
|
|
2120
|
+
* @param input
|
|
1783
2121
|
* @param $ {?INodePrivate}
|
|
1784
2122
|
*/
|
|
1785
|
-
constructor($) {
|
|
1786
|
-
super($ || new INodePrivate);
|
|
1787
|
-
this
|
|
2123
|
+
constructor(input, $) {
|
|
2124
|
+
super(input, $ || new INodePrivate);
|
|
2125
|
+
this.seal();
|
|
1788
2126
|
}
|
|
1789
2127
|
/**
|
|
1790
2128
|
* Get the bound node
|
|
@@ -1792,78 +2130,55 @@ class INode extends Fragment {
|
|
|
1792
2130
|
get node() {
|
|
1793
2131
|
return this.$.node;
|
|
1794
2132
|
}
|
|
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
2133
|
/**
|
|
1817
2134
|
* Bind attribute value
|
|
1818
2135
|
* @param name {String} name of attribute
|
|
1819
2136
|
* @param value {IValue} value
|
|
1820
2137
|
*/
|
|
1821
|
-
|
|
2138
|
+
attr(name, value) {
|
|
1822
2139
|
const $ = this.$;
|
|
1823
2140
|
const attr = new AttributeBinding(this, name, value);
|
|
1824
2141
|
$.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
2142
|
}
|
|
1833
2143
|
/**
|
|
1834
2144
|
* Set attribute value
|
|
1835
2145
|
* @param name {string} name of attribute
|
|
1836
2146
|
* @param value {string} value
|
|
1837
2147
|
*/
|
|
1838
|
-
|
|
1839
|
-
|
|
2148
|
+
setAttr(name, value) {
|
|
2149
|
+
if (typeof value === 'boolean') {
|
|
2150
|
+
if (value) {
|
|
2151
|
+
this.$.node.setAttribute(name, "");
|
|
2152
|
+
}
|
|
2153
|
+
}
|
|
2154
|
+
else {
|
|
2155
|
+
this.$.node.setAttribute(name, `${value}`);
|
|
2156
|
+
}
|
|
1840
2157
|
return this;
|
|
1841
2158
|
}
|
|
1842
2159
|
/**
|
|
1843
2160
|
* Adds a CSS class
|
|
1844
2161
|
* @param cl {string} Class name
|
|
1845
2162
|
*/
|
|
1846
|
-
|
|
1847
|
-
this.$.
|
|
2163
|
+
addClass(cl) {
|
|
2164
|
+
this.$.node.classList.add(cl);
|
|
1848
2165
|
return this;
|
|
1849
2166
|
}
|
|
1850
2167
|
/**
|
|
1851
2168
|
* Adds some CSS classes
|
|
1852
2169
|
* @param cls {...string} classes names
|
|
1853
2170
|
*/
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
this.$.app.$run.addClass(this.$.node, cl);
|
|
1857
|
-
});
|
|
2171
|
+
removeClasse(cl) {
|
|
2172
|
+
this.$.node.classList.remove(cl);
|
|
1858
2173
|
return this;
|
|
1859
2174
|
}
|
|
1860
2175
|
/**
|
|
1861
2176
|
* Bind a CSS class
|
|
1862
2177
|
* @param className {IValue}
|
|
1863
2178
|
*/
|
|
1864
|
-
|
|
2179
|
+
bindClass(className) {
|
|
1865
2180
|
const $ = this.$;
|
|
1866
|
-
$.bindings.add(new
|
|
2181
|
+
$.bindings.add(new DynamicalClassBinding(this, className));
|
|
1867
2182
|
return this;
|
|
1868
2183
|
}
|
|
1869
2184
|
/**
|
|
@@ -1871,8 +2186,8 @@ class INode extends Fragment {
|
|
|
1871
2186
|
* @param cond {IValue} condition
|
|
1872
2187
|
* @param className {string} class name
|
|
1873
2188
|
*/
|
|
1874
|
-
|
|
1875
|
-
this.$.bindings.add(new
|
|
2189
|
+
floatingClass(cond, className) {
|
|
2190
|
+
this.$.bindings.add(new StaticClassBinding(this, className, cond));
|
|
1876
2191
|
return this;
|
|
1877
2192
|
}
|
|
1878
2193
|
/**
|
|
@@ -1880,7 +2195,7 @@ class INode extends Fragment {
|
|
|
1880
2195
|
* @param name {String} name of style attribute
|
|
1881
2196
|
* @param value {IValue} value
|
|
1882
2197
|
*/
|
|
1883
|
-
|
|
2198
|
+
style(name, value) {
|
|
1884
2199
|
const $ = this.$;
|
|
1885
2200
|
if ($.node instanceof HTMLElement) {
|
|
1886
2201
|
$.bindings.add(new StyleBinding(this, name, value));
|
|
@@ -1890,28 +2205,17 @@ class INode extends Fragment {
|
|
|
1890
2205
|
}
|
|
1891
2206
|
return this;
|
|
1892
2207
|
}
|
|
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
2208
|
/**
|
|
1905
2209
|
* Sets a style property value
|
|
1906
2210
|
* @param prop {string} Property name
|
|
1907
2211
|
* @param value {string} Property value
|
|
1908
2212
|
*/
|
|
1909
|
-
|
|
2213
|
+
setStyle(prop, value) {
|
|
1910
2214
|
if (this.$.node instanceof HTMLElement) {
|
|
1911
|
-
this.$.
|
|
2215
|
+
this.$.node.style.setProperty(prop, value);
|
|
1912
2216
|
}
|
|
1913
2217
|
else {
|
|
1914
|
-
throw userError("Style can be
|
|
2218
|
+
throw userError("Style can be set for HTML elements only", "non-html-element");
|
|
1915
2219
|
}
|
|
1916
2220
|
return this;
|
|
1917
2221
|
}
|
|
@@ -1921,403 +2225,24 @@ class INode extends Fragment {
|
|
|
1921
2225
|
* @param handler {function (Event)} Event handler
|
|
1922
2226
|
* @param options {Object | boolean} addEventListener options
|
|
1923
2227
|
*/
|
|
1924
|
-
|
|
2228
|
+
listen(name, handler, options) {
|
|
1925
2229
|
this.$.node.addEventListener(name, handler, options);
|
|
1926
2230
|
return this;
|
|
1927
2231
|
}
|
|
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);
|
|
2232
|
+
insertAdjacent(node) {
|
|
2233
|
+
this.$.node.parentNode.insertBefore(node, this.$.node);
|
|
1948
2234
|
}
|
|
1949
2235
|
/**
|
|
1950
|
-
*
|
|
1951
|
-
* @param
|
|
2236
|
+
* A v-show & ngShow alternative
|
|
2237
|
+
* @param cond {IValue} show condition
|
|
1952
2238
|
*/
|
|
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) {
|
|
2239
|
+
bindShow(cond) {
|
|
2315
2240
|
const $ = this.$;
|
|
2316
2241
|
const node = $.node;
|
|
2317
2242
|
if (node instanceof HTMLElement) {
|
|
2318
2243
|
let lastDisplay = node.style.display;
|
|
2319
2244
|
const htmlNode = node;
|
|
2320
|
-
return this
|
|
2245
|
+
return this.bindAlive(cond, () => {
|
|
2321
2246
|
lastDisplay = htmlNode.style.display;
|
|
2322
2247
|
htmlNode.style.display = 'none';
|
|
2323
2248
|
}, () => {
|
|
@@ -2332,19 +2257,105 @@ class INode extends Fragment {
|
|
|
2332
2257
|
* bind HTML
|
|
2333
2258
|
* @param value {IValue}
|
|
2334
2259
|
*/
|
|
2335
|
-
|
|
2260
|
+
bindDomApi(name, value) {
|
|
2336
2261
|
const $ = this.$;
|
|
2337
2262
|
const node = $.node;
|
|
2338
2263
|
if (node instanceof HTMLElement) {
|
|
2339
|
-
node
|
|
2340
|
-
this
|
|
2341
|
-
node
|
|
2264
|
+
node[name] = value.$;
|
|
2265
|
+
this.watch((v) => {
|
|
2266
|
+
node[name] = v;
|
|
2342
2267
|
}, value);
|
|
2343
2268
|
}
|
|
2344
2269
|
else {
|
|
2345
2270
|
throw userError("HTML can be bound for HTML nodes only", "dom-error");
|
|
2346
2271
|
}
|
|
2347
2272
|
}
|
|
2273
|
+
applyOptions(options) {
|
|
2274
|
+
options["v:attr"] && Object.keys(options["v:attr"]).forEach(name => {
|
|
2275
|
+
const value = options["v:attr"][name];
|
|
2276
|
+
if (value instanceof IValue) {
|
|
2277
|
+
this.attr(name, value);
|
|
2278
|
+
}
|
|
2279
|
+
else {
|
|
2280
|
+
this.setAttr(name, value);
|
|
2281
|
+
}
|
|
2282
|
+
});
|
|
2283
|
+
if (options.class) {
|
|
2284
|
+
const handleClass = (name, value) => {
|
|
2285
|
+
if (value instanceof IValue) {
|
|
2286
|
+
this.floatingClass(value, name);
|
|
2287
|
+
}
|
|
2288
|
+
else if (value && name !== '$') {
|
|
2289
|
+
this.addClass(name);
|
|
2290
|
+
}
|
|
2291
|
+
else {
|
|
2292
|
+
this.removeClasse(name);
|
|
2293
|
+
}
|
|
2294
|
+
};
|
|
2295
|
+
if (Array.isArray(options.class)) {
|
|
2296
|
+
options.class.forEach(item => {
|
|
2297
|
+
if (item instanceof IValue) {
|
|
2298
|
+
this.bindClass(item);
|
|
2299
|
+
}
|
|
2300
|
+
else if (typeof item == "string") {
|
|
2301
|
+
this.addClass(item);
|
|
2302
|
+
}
|
|
2303
|
+
else {
|
|
2304
|
+
Reflect.ownKeys(item).forEach((name) => {
|
|
2305
|
+
handleClass(name, item[name]);
|
|
2306
|
+
});
|
|
2307
|
+
}
|
|
2308
|
+
});
|
|
2309
|
+
}
|
|
2310
|
+
else {
|
|
2311
|
+
options.class.$.forEach(item => {
|
|
2312
|
+
this.bindClass(item);
|
|
2313
|
+
});
|
|
2314
|
+
Reflect.ownKeys(options.class).forEach((name) => {
|
|
2315
|
+
handleClass(name, options.class[name]);
|
|
2316
|
+
});
|
|
2317
|
+
}
|
|
2318
|
+
}
|
|
2319
|
+
options.style && Object.keys(options.style).forEach(name => {
|
|
2320
|
+
const value = options.style[name];
|
|
2321
|
+
if (value instanceof IValue) {
|
|
2322
|
+
this.style(name, value);
|
|
2323
|
+
}
|
|
2324
|
+
else if (typeof value === "string") {
|
|
2325
|
+
this.setStyle(name, value);
|
|
2326
|
+
}
|
|
2327
|
+
else {
|
|
2328
|
+
if (value[0] instanceof IValue) {
|
|
2329
|
+
this.style(name, this.expr((v) => v + value[1], value[0]));
|
|
2330
|
+
}
|
|
2331
|
+
else {
|
|
2332
|
+
this.setStyle(name, value[0] + value[1]);
|
|
2333
|
+
}
|
|
2334
|
+
}
|
|
2335
|
+
});
|
|
2336
|
+
options["v:events"] && Object.keys(options["v:events"]).forEach(name => {
|
|
2337
|
+
this.listen(name, options["v:events"][name]);
|
|
2338
|
+
});
|
|
2339
|
+
if (options["v:bind"]) {
|
|
2340
|
+
const inode = this.node;
|
|
2341
|
+
Reflect.ownKeys(options["v:bind"]).forEach((k) => {
|
|
2342
|
+
const value = options["v:bind"][k];
|
|
2343
|
+
if (k === 'value' && (inode instanceof HTMLInputElement || inode instanceof HTMLTextAreaElement)) {
|
|
2344
|
+
inode.oninput = () => value.$ = inode.value;
|
|
2345
|
+
}
|
|
2346
|
+
else if (k === 'checked' && inode instanceof HTMLInputElement) {
|
|
2347
|
+
inode.oninput = () => value.$ = inode.checked;
|
|
2348
|
+
}
|
|
2349
|
+
else if (k === 'volume' && inode instanceof HTMLMediaElement) {
|
|
2350
|
+
inode.onvolumechange = () => value.$ = inode.volume;
|
|
2351
|
+
}
|
|
2352
|
+
this.bindDomApi(k, value);
|
|
2353
|
+
});
|
|
2354
|
+
}
|
|
2355
|
+
options["v:set"] && Object.keys(options["v:set"]).forEach(key => {
|
|
2356
|
+
this.node[key] = options["v:set"][key];
|
|
2357
|
+
});
|
|
2358
|
+
}
|
|
2348
2359
|
}
|
|
2349
2360
|
/**
|
|
2350
2361
|
* Represents an Vasille.js HTML element node
|
|
@@ -2352,11 +2363,11 @@ class INode extends Fragment {
|
|
|
2352
2363
|
* @extends INode
|
|
2353
2364
|
*/
|
|
2354
2365
|
class Tag extends INode {
|
|
2355
|
-
constructor() {
|
|
2356
|
-
super();
|
|
2357
|
-
this
|
|
2366
|
+
constructor(input) {
|
|
2367
|
+
super(input);
|
|
2368
|
+
this.seal();
|
|
2358
2369
|
}
|
|
2359
|
-
|
|
2370
|
+
preinit(app, parent, tagName) {
|
|
2360
2371
|
if (!tagName || typeof tagName !== "string") {
|
|
2361
2372
|
throw internalError('wrong Tag::$preinit call');
|
|
2362
2373
|
}
|
|
@@ -2364,55 +2375,52 @@ class Tag extends INode {
|
|
|
2364
2375
|
const $ = this.$;
|
|
2365
2376
|
$.preinit(app, parent);
|
|
2366
2377
|
$.node = node;
|
|
2367
|
-
$.parent
|
|
2378
|
+
$.parent.appendNode(node);
|
|
2379
|
+
}
|
|
2380
|
+
compose(input) {
|
|
2381
|
+
input.slot && input.slot(this);
|
|
2368
2382
|
}
|
|
2369
|
-
|
|
2383
|
+
findFirstChild() {
|
|
2370
2384
|
return this.$.unmounted ? null : this.$.node;
|
|
2371
2385
|
}
|
|
2372
|
-
|
|
2386
|
+
insertAdjacent(node) {
|
|
2373
2387
|
if (this.$.unmounted) {
|
|
2374
2388
|
if (this.$.next) {
|
|
2375
|
-
this.$.next
|
|
2389
|
+
this.$.next.insertAdjacent(node);
|
|
2376
2390
|
}
|
|
2377
2391
|
else {
|
|
2378
|
-
this.$.parent
|
|
2392
|
+
this.$.parent.appendNode(node);
|
|
2379
2393
|
}
|
|
2380
2394
|
}
|
|
2381
2395
|
else {
|
|
2382
|
-
super
|
|
2396
|
+
super.insertAdjacent(node);
|
|
2383
2397
|
}
|
|
2384
2398
|
}
|
|
2385
|
-
|
|
2386
|
-
|
|
2387
|
-
$.app.$run.appendChild($.node, node);
|
|
2399
|
+
appendNode(node) {
|
|
2400
|
+
this.$.node.appendChild(node);
|
|
2388
2401
|
}
|
|
2389
2402
|
/**
|
|
2390
2403
|
* Mount/Unmount a node
|
|
2391
2404
|
* @param cond {IValue} show condition
|
|
2392
2405
|
*/
|
|
2393
|
-
|
|
2406
|
+
bindMount(cond) {
|
|
2394
2407
|
const $ = this.$;
|
|
2395
|
-
|
|
2408
|
+
this.bindAlive(cond, () => {
|
|
2396
2409
|
$.node.remove();
|
|
2397
2410
|
$.unmounted = true;
|
|
2398
2411
|
}, () => {
|
|
2399
|
-
if (
|
|
2400
|
-
|
|
2401
|
-
|
|
2402
|
-
$.next.$$insertAdjacent($.node);
|
|
2412
|
+
if ($.unmounted) {
|
|
2413
|
+
this.insertAdjacent($.node);
|
|
2414
|
+
$.unmounted = false;
|
|
2403
2415
|
}
|
|
2404
|
-
else {
|
|
2405
|
-
$.parent.$$appendNode($.node);
|
|
2406
|
-
}
|
|
2407
|
-
$.unmounted = false;
|
|
2408
2416
|
});
|
|
2409
2417
|
}
|
|
2410
2418
|
/**
|
|
2411
2419
|
* Runs GC
|
|
2412
2420
|
*/
|
|
2413
|
-
|
|
2421
|
+
destroy() {
|
|
2414
2422
|
this.node.remove();
|
|
2415
|
-
super
|
|
2423
|
+
super.destroy();
|
|
2416
2424
|
}
|
|
2417
2425
|
}
|
|
2418
2426
|
/**
|
|
@@ -2421,22 +2429,22 @@ class Tag extends INode {
|
|
|
2421
2429
|
* @extends INode
|
|
2422
2430
|
*/
|
|
2423
2431
|
class Extension extends INode {
|
|
2424
|
-
|
|
2425
|
-
|
|
2426
|
-
|
|
2427
|
-
|
|
2428
|
-
|
|
2432
|
+
preinit(app, parent) {
|
|
2433
|
+
const $ = this.$;
|
|
2434
|
+
let it = parent;
|
|
2435
|
+
while (it && !(it instanceof INode)) {
|
|
2436
|
+
it = it.parent;
|
|
2429
2437
|
}
|
|
2430
|
-
|
|
2431
|
-
|
|
2438
|
+
if (it && it instanceof INode) {
|
|
2439
|
+
$.node = it.node;
|
|
2440
|
+
}
|
|
2441
|
+
$.preinit(app, parent);
|
|
2442
|
+
if (!it) {
|
|
2443
|
+
throw userError("A extension node can be encapsulated only in a tag/extension/component", "virtual-dom");
|
|
2432
2444
|
}
|
|
2433
2445
|
}
|
|
2434
|
-
|
|
2435
|
-
super(
|
|
2436
|
-
this.$seal();
|
|
2437
|
-
}
|
|
2438
|
-
$destroy() {
|
|
2439
|
-
super.$destroy();
|
|
2446
|
+
destroy() {
|
|
2447
|
+
super.destroy();
|
|
2440
2448
|
}
|
|
2441
2449
|
}
|
|
2442
2450
|
/**
|
|
@@ -2445,45 +2453,49 @@ class Extension extends INode {
|
|
|
2445
2453
|
* @extends Extension
|
|
2446
2454
|
*/
|
|
2447
2455
|
class Component extends Extension {
|
|
2448
|
-
|
|
2449
|
-
super();
|
|
2450
|
-
this
|
|
2451
|
-
|
|
2452
|
-
$mounted() {
|
|
2453
|
-
super.$mounted();
|
|
2454
|
-
if (this.$children.length !== 1) {
|
|
2455
|
-
throw userError("UserNode must have a child only", "dom-error");
|
|
2456
|
+
ready() {
|
|
2457
|
+
super.ready();
|
|
2458
|
+
if (this.children.size !== 1) {
|
|
2459
|
+
throw userError("Component must have a child only", "dom-error");
|
|
2456
2460
|
}
|
|
2457
|
-
const child = this
|
|
2461
|
+
const child = this.lastChild;
|
|
2458
2462
|
if (child instanceof Tag || child instanceof Component) {
|
|
2459
2463
|
const $ = this.$;
|
|
2460
2464
|
$.node = child.node;
|
|
2461
2465
|
}
|
|
2462
2466
|
else {
|
|
2463
|
-
throw userError("
|
|
2467
|
+
throw userError("Component child must be Tag or Component", "dom-error");
|
|
2464
2468
|
}
|
|
2465
2469
|
}
|
|
2470
|
+
preinit(app, parent) {
|
|
2471
|
+
this.$.preinit(app, parent);
|
|
2472
|
+
}
|
|
2466
2473
|
}
|
|
2467
2474
|
/**
|
|
2468
2475
|
* Private part of switch node
|
|
2469
2476
|
* @class SwitchedNodePrivate
|
|
2470
2477
|
* @extends INodePrivate
|
|
2471
2478
|
*/
|
|
2472
|
-
class SwitchedNodePrivate extends
|
|
2479
|
+
class SwitchedNodePrivate extends FragmentPrivate {
|
|
2473
2480
|
constructor() {
|
|
2474
2481
|
super();
|
|
2475
|
-
|
|
2482
|
+
/**
|
|
2483
|
+
* Array of possible cases
|
|
2484
|
+
* @type {Array<{cond : IValue<boolean>, cb : function(Fragment)}>}
|
|
2485
|
+
*/
|
|
2486
|
+
this.cases = [];
|
|
2487
|
+
this.seal();
|
|
2476
2488
|
}
|
|
2477
2489
|
/**
|
|
2478
2490
|
* Runs GC
|
|
2479
2491
|
*/
|
|
2480
|
-
|
|
2492
|
+
destroy() {
|
|
2481
2493
|
this.cases.forEach(c => {
|
|
2482
2494
|
delete c.cond;
|
|
2483
2495
|
delete c.cb;
|
|
2484
2496
|
});
|
|
2485
2497
|
this.cases.splice(0);
|
|
2486
|
-
super
|
|
2498
|
+
super.destroy();
|
|
2487
2499
|
}
|
|
2488
2500
|
}
|
|
2489
2501
|
/**
|
|
@@ -2494,7 +2506,7 @@ class SwitchedNode extends Fragment {
|
|
|
2494
2506
|
* Constructs a switch node and define a sync function
|
|
2495
2507
|
*/
|
|
2496
2508
|
constructor() {
|
|
2497
|
-
super(new SwitchedNodePrivate);
|
|
2509
|
+
super({}, new SwitchedNodePrivate);
|
|
2498
2510
|
this.$.sync = () => {
|
|
2499
2511
|
const $ = this.$;
|
|
2500
2512
|
let i = 0;
|
|
@@ -2506,10 +2518,10 @@ class SwitchedNode extends Fragment {
|
|
|
2506
2518
|
if (i === $.index) {
|
|
2507
2519
|
return;
|
|
2508
2520
|
}
|
|
2509
|
-
if (
|
|
2510
|
-
|
|
2511
|
-
this
|
|
2512
|
-
|
|
2521
|
+
if (this.lastChild) {
|
|
2522
|
+
this.lastChild.destroy();
|
|
2523
|
+
this.children.clear();
|
|
2524
|
+
this.lastChild = null;
|
|
2513
2525
|
}
|
|
2514
2526
|
if (i !== $.cases.length) {
|
|
2515
2527
|
$.index = i;
|
|
@@ -2519,43 +2531,38 @@ class SwitchedNode extends Fragment {
|
|
|
2519
2531
|
$.index = -1;
|
|
2520
2532
|
}
|
|
2521
2533
|
};
|
|
2522
|
-
this
|
|
2534
|
+
this.seal();
|
|
2523
2535
|
}
|
|
2524
|
-
|
|
2525
|
-
|
|
2526
|
-
|
|
2527
|
-
|
|
2528
|
-
setCases(cases) {
|
|
2529
|
-
const $ = this.$;
|
|
2530
|
-
$.cases = [...cases];
|
|
2536
|
+
addCase(case_) {
|
|
2537
|
+
this.$.cases.push(case_);
|
|
2538
|
+
case_.cond.on(this.$.sync);
|
|
2539
|
+
this.$.sync();
|
|
2531
2540
|
}
|
|
2532
2541
|
/**
|
|
2533
2542
|
* Creates a child node
|
|
2534
2543
|
* @param cb {function(Fragment)} Call-back
|
|
2535
2544
|
*/
|
|
2536
2545
|
createChild(cb) {
|
|
2537
|
-
const node = new Fragment();
|
|
2538
|
-
node
|
|
2539
|
-
node
|
|
2540
|
-
node
|
|
2541
|
-
this
|
|
2542
|
-
this.$children.push(node);
|
|
2546
|
+
const node = new Fragment({});
|
|
2547
|
+
node.preinit(this.$.app, this);
|
|
2548
|
+
node.init();
|
|
2549
|
+
this.lastChild = node;
|
|
2550
|
+
this.children.add(node);
|
|
2543
2551
|
cb(node);
|
|
2544
2552
|
}
|
|
2545
|
-
|
|
2553
|
+
ready() {
|
|
2546
2554
|
const $ = this.$;
|
|
2547
|
-
super.$ready();
|
|
2548
2555
|
$.cases.forEach(c => {
|
|
2549
2556
|
c.cond.on($.sync);
|
|
2550
2557
|
});
|
|
2551
2558
|
$.sync();
|
|
2552
2559
|
}
|
|
2553
|
-
|
|
2560
|
+
destroy() {
|
|
2554
2561
|
const $ = this.$;
|
|
2555
2562
|
$.cases.forEach(c => {
|
|
2556
2563
|
c.cond.off($.sync);
|
|
2557
2564
|
});
|
|
2558
|
-
super
|
|
2565
|
+
super.destroy();
|
|
2559
2566
|
}
|
|
2560
2567
|
}
|
|
2561
2568
|
/**
|
|
@@ -2564,7 +2571,7 @@ class SwitchedNode extends Fragment {
|
|
|
2564
2571
|
class DebugPrivate extends FragmentPrivate {
|
|
2565
2572
|
constructor() {
|
|
2566
2573
|
super();
|
|
2567
|
-
this
|
|
2574
|
+
this.seal();
|
|
2568
2575
|
}
|
|
2569
2576
|
/**
|
|
2570
2577
|
* Pre-initializes a text node
|
|
@@ -2578,14 +2585,14 @@ class DebugPrivate extends FragmentPrivate {
|
|
|
2578
2585
|
this.bindings.add(new Expression((v) => {
|
|
2579
2586
|
this.node.replaceData(0, -1, v);
|
|
2580
2587
|
}, true, text));
|
|
2581
|
-
this.parent
|
|
2588
|
+
this.parent.appendNode(this.node);
|
|
2582
2589
|
}
|
|
2583
2590
|
/**
|
|
2584
2591
|
* Clear node data
|
|
2585
2592
|
*/
|
|
2586
|
-
|
|
2593
|
+
destroy() {
|
|
2587
2594
|
this.node.remove();
|
|
2588
|
-
super
|
|
2595
|
+
super.destroy();
|
|
2589
2596
|
}
|
|
2590
2597
|
}
|
|
2591
2598
|
/**
|
|
@@ -2595,15 +2602,15 @@ class DebugPrivate extends FragmentPrivate {
|
|
|
2595
2602
|
*/
|
|
2596
2603
|
class DebugNode extends Fragment {
|
|
2597
2604
|
constructor() {
|
|
2598
|
-
super();
|
|
2605
|
+
super({});
|
|
2599
2606
|
/**
|
|
2600
2607
|
* private data
|
|
2601
2608
|
* @type {DebugNode}
|
|
2602
2609
|
*/
|
|
2603
2610
|
this.$ = new DebugPrivate();
|
|
2604
|
-
this
|
|
2611
|
+
this.seal();
|
|
2605
2612
|
}
|
|
2606
|
-
|
|
2613
|
+
preinit(app, parent, text) {
|
|
2607
2614
|
const $ = this.$;
|
|
2608
2615
|
if (!text) {
|
|
2609
2616
|
throw internalError('wrong DebugNode::$preninit call');
|
|
@@ -2613,9 +2620,9 @@ class DebugNode extends Fragment {
|
|
|
2613
2620
|
/**
|
|
2614
2621
|
* Runs garbage collector
|
|
2615
2622
|
*/
|
|
2616
|
-
|
|
2617
|
-
this
|
|
2618
|
-
super
|
|
2623
|
+
destroy() {
|
|
2624
|
+
this.$.destroy();
|
|
2625
|
+
super.destroy();
|
|
2619
2626
|
}
|
|
2620
2627
|
}
|
|
2621
2628
|
|
|
@@ -2629,6 +2636,7 @@ window.Tag = Tag;
|
|
|
2629
2636
|
window.Extension = Extension;
|
|
2630
2637
|
window.Component = Component;
|
|
2631
2638
|
window.SwitchedNodePrivate = SwitchedNodePrivate;
|
|
2639
|
+
window.SwitchedNode = SwitchedNode;
|
|
2632
2640
|
window.DebugPrivate = DebugPrivate;
|
|
2633
2641
|
window.DebugNode = DebugNode;
|
|
2634
2642
|
|
|
@@ -2640,12 +2648,12 @@ window.DebugNode = DebugNode;
|
|
|
2640
2648
|
*/
|
|
2641
2649
|
class AppNode extends INode {
|
|
2642
2650
|
/**
|
|
2643
|
-
* @param
|
|
2651
|
+
* @param input
|
|
2644
2652
|
*/
|
|
2645
|
-
constructor(
|
|
2646
|
-
super();
|
|
2647
|
-
this
|
|
2648
|
-
this
|
|
2653
|
+
constructor(input) {
|
|
2654
|
+
super(input);
|
|
2655
|
+
this.debugUi = input.debugUi || false;
|
|
2656
|
+
this.seal();
|
|
2649
2657
|
}
|
|
2650
2658
|
}
|
|
2651
2659
|
/**
|
|
@@ -2657,22 +2665,33 @@ class App extends AppNode {
|
|
|
2657
2665
|
/**
|
|
2658
2666
|
* Constructs an app node
|
|
2659
2667
|
* @param node {Element} The root of application
|
|
2660
|
-
* @param
|
|
2668
|
+
* @param input
|
|
2661
2669
|
*/
|
|
2662
|
-
constructor(node,
|
|
2663
|
-
super(
|
|
2670
|
+
constructor(node, input) {
|
|
2671
|
+
super(input);
|
|
2664
2672
|
this.$.node = node;
|
|
2665
|
-
this
|
|
2666
|
-
this
|
|
2673
|
+
this.preinit(this, this);
|
|
2674
|
+
this.init();
|
|
2675
|
+
this.seal();
|
|
2667
2676
|
}
|
|
2668
|
-
|
|
2669
|
-
|
|
2670
|
-
|
|
2677
|
+
appendNode(node) {
|
|
2678
|
+
this.$.node.appendChild(node);
|
|
2679
|
+
}
|
|
2680
|
+
}
|
|
2681
|
+
class Portal extends AppNode {
|
|
2682
|
+
constructor(input) {
|
|
2683
|
+
super(input);
|
|
2684
|
+
this.$.node = input.node;
|
|
2685
|
+
this.seal();
|
|
2686
|
+
}
|
|
2687
|
+
appendNode(node) {
|
|
2688
|
+
this.$.node.appendChild(node);
|
|
2671
2689
|
}
|
|
2672
2690
|
}
|
|
2673
2691
|
|
|
2674
2692
|
window.AppNode = AppNode;
|
|
2675
2693
|
window.App = App;
|
|
2694
|
+
window.Portal = Portal;
|
|
2676
2695
|
|
|
2677
2696
|
// ./lib/node/interceptor.js
|
|
2678
2697
|
/**
|
|
@@ -2722,8 +2741,8 @@ class Interceptor extends Destroyable {
|
|
|
2722
2741
|
signal.unsubscribe(handler);
|
|
2723
2742
|
});
|
|
2724
2743
|
}
|
|
2725
|
-
|
|
2726
|
-
super
|
|
2744
|
+
destroy() {
|
|
2745
|
+
super.destroy();
|
|
2727
2746
|
this.signals.forEach(signal => {
|
|
2728
2747
|
this.handlers.forEach(handler => {
|
|
2729
2748
|
signal.unsubscribe(handler);
|
|
@@ -2750,7 +2769,7 @@ class InterceptorNode extends Fragment {
|
|
|
2750
2769
|
*/
|
|
2751
2770
|
this.slot = new Slot;
|
|
2752
2771
|
}
|
|
2753
|
-
|
|
2772
|
+
compose() {
|
|
2754
2773
|
this.slot.release(this, this.interceptor);
|
|
2755
2774
|
}
|
|
2756
2775
|
}
|
|
@@ -2772,22 +2791,21 @@ class AttributeBinding extends Binding {
|
|
|
2772
2791
|
* @param value {IValue} value to bind
|
|
2773
2792
|
*/
|
|
2774
2793
|
constructor(node, name, value) {
|
|
2775
|
-
super(
|
|
2776
|
-
|
|
2777
|
-
/**
|
|
2778
|
-
* Generates a function which updates the attribute value
|
|
2779
|
-
* @param name {String} The name of attribute
|
|
2780
|
-
* @returns {Function} a function which will update attribute value
|
|
2781
|
-
*/
|
|
2782
|
-
bound(name) {
|
|
2783
|
-
return function (node, value) {
|
|
2794
|
+
super(value);
|
|
2795
|
+
this.init((value) => {
|
|
2784
2796
|
if (value) {
|
|
2785
|
-
|
|
2797
|
+
if (typeof value === 'boolean') {
|
|
2798
|
+
node.node.setAttribute(name, "");
|
|
2799
|
+
}
|
|
2800
|
+
else {
|
|
2801
|
+
node.node.setAttribute(name, `${value}`);
|
|
2802
|
+
}
|
|
2786
2803
|
}
|
|
2787
2804
|
else {
|
|
2788
|
-
node.
|
|
2805
|
+
node.node.removeAttribute(name);
|
|
2789
2806
|
}
|
|
2790
|
-
};
|
|
2807
|
+
});
|
|
2808
|
+
this.seal();
|
|
2791
2809
|
}
|
|
2792
2810
|
}
|
|
2793
2811
|
|
|
@@ -2807,77 +2825,64 @@ class StyleBinding extends Binding {
|
|
|
2807
2825
|
* @param value {IValue} the value to bind
|
|
2808
2826
|
*/
|
|
2809
2827
|
constructor(node, name, value) {
|
|
2810
|
-
super(
|
|
2811
|
-
|
|
2812
|
-
/**
|
|
2813
|
-
* Generates a function to update style property value
|
|
2814
|
-
* @param name {string}
|
|
2815
|
-
* @returns {Function} a function to update style property
|
|
2816
|
-
*/
|
|
2817
|
-
bound(name) {
|
|
2818
|
-
return function (node, value) {
|
|
2828
|
+
super(value);
|
|
2829
|
+
this.init((value) => {
|
|
2819
2830
|
if (node.node instanceof HTMLElement) {
|
|
2820
|
-
node.
|
|
2831
|
+
node.node.style.setProperty(name, value);
|
|
2821
2832
|
}
|
|
2822
|
-
};
|
|
2833
|
+
});
|
|
2834
|
+
this.seal();
|
|
2823
2835
|
}
|
|
2824
2836
|
}
|
|
2825
2837
|
|
|
2826
2838
|
window.StyleBinding = StyleBinding;
|
|
2827
2839
|
|
|
2828
2840
|
// ./lib/binding/class.js
|
|
2829
|
-
|
|
2830
|
-
|
|
2831
|
-
|
|
2832
|
-
|
|
2833
|
-
|
|
2834
|
-
|
|
2835
|
-
|
|
2836
|
-
* Constructs an HTML class binding description
|
|
2837
|
-
* @param node {INode} the vasille node
|
|
2838
|
-
* @param name {String} the name of class
|
|
2839
|
-
* @param value {IValue} the value to bind
|
|
2840
|
-
*/
|
|
2841
|
+
function addClass(node, cl) {
|
|
2842
|
+
node.node.classList.add(cl);
|
|
2843
|
+
}
|
|
2844
|
+
function removeClass(node, cl) {
|
|
2845
|
+
node.node.classList.remove(cl);
|
|
2846
|
+
}
|
|
2847
|
+
class StaticClassBinding extends Binding {
|
|
2841
2848
|
constructor(node, name, value) {
|
|
2842
|
-
super(
|
|
2843
|
-
this
|
|
2844
|
-
|
|
2845
|
-
|
|
2846
|
-
|
|
2847
|
-
|
|
2848
|
-
* @returns {Function} a function which will update attribute value
|
|
2849
|
-
*/
|
|
2850
|
-
bound(name) {
|
|
2851
|
-
let current = null;
|
|
2852
|
-
function addClass(node, cl) {
|
|
2853
|
-
node.app.$run.addClass(node.node, cl);
|
|
2854
|
-
}
|
|
2855
|
-
function removeClass(node, cl) {
|
|
2856
|
-
node.app.$run.removeClass(node.node, cl);
|
|
2857
|
-
}
|
|
2858
|
-
return (node, value) => {
|
|
2859
|
-
if (value !== current) {
|
|
2860
|
-
if (typeof current === "string" && current !== "") {
|
|
2861
|
-
removeClass(node, current);
|
|
2849
|
+
super(value);
|
|
2850
|
+
this.current = false;
|
|
2851
|
+
this.init((value) => {
|
|
2852
|
+
if (value !== this.current) {
|
|
2853
|
+
if (value) {
|
|
2854
|
+
addClass(node, name);
|
|
2862
2855
|
}
|
|
2863
|
-
|
|
2864
|
-
|
|
2865
|
-
addClass(node, name);
|
|
2866
|
-
}
|
|
2867
|
-
else {
|
|
2868
|
-
removeClass(node, name);
|
|
2869
|
-
}
|
|
2856
|
+
else {
|
|
2857
|
+
removeClass(node, name);
|
|
2870
2858
|
}
|
|
2871
|
-
|
|
2859
|
+
this.current = value;
|
|
2860
|
+
}
|
|
2861
|
+
});
|
|
2862
|
+
this.seal();
|
|
2863
|
+
}
|
|
2864
|
+
}
|
|
2865
|
+
class DynamicalClassBinding extends Binding {
|
|
2866
|
+
constructor(node, value) {
|
|
2867
|
+
super(value);
|
|
2868
|
+
this.current = "";
|
|
2869
|
+
this.init((value) => {
|
|
2870
|
+
if (this.current != value) {
|
|
2871
|
+
if (this.current.length) {
|
|
2872
|
+
removeClass(node, this.current);
|
|
2873
|
+
}
|
|
2874
|
+
if (value.length) {
|
|
2872
2875
|
addClass(node, value);
|
|
2873
2876
|
}
|
|
2874
|
-
current = value;
|
|
2877
|
+
this.current = value;
|
|
2875
2878
|
}
|
|
2876
|
-
};
|
|
2879
|
+
});
|
|
2880
|
+
this.seal();
|
|
2877
2881
|
}
|
|
2878
2882
|
}
|
|
2879
2883
|
|
|
2880
|
-
window.
|
|
2884
|
+
window.StaticClassBinding = StaticClassBinding;
|
|
2885
|
+
window.DynamicalClassBinding = DynamicalClassBinding;
|
|
2881
2886
|
|
|
2882
2887
|
// ./lib/views/repeat-node.js
|
|
2883
2888
|
/**
|
|
@@ -2893,11 +2898,11 @@ class RepeatNodePrivate extends INodePrivate {
|
|
|
2893
2898
|
* @type {Map}
|
|
2894
2899
|
*/
|
|
2895
2900
|
this.nodes = new Map();
|
|
2896
|
-
this
|
|
2901
|
+
this.seal();
|
|
2897
2902
|
}
|
|
2898
|
-
|
|
2903
|
+
destroy() {
|
|
2899
2904
|
this.nodes.clear();
|
|
2900
|
-
super
|
|
2905
|
+
super.destroy();
|
|
2901
2906
|
}
|
|
2902
2907
|
}
|
|
2903
2908
|
/**
|
|
@@ -2906,80 +2911,42 @@ class RepeatNodePrivate extends INodePrivate {
|
|
|
2906
2911
|
* @extends Fragment
|
|
2907
2912
|
*/
|
|
2908
2913
|
class RepeatNode extends Fragment {
|
|
2909
|
-
constructor($) {
|
|
2910
|
-
super($
|
|
2914
|
+
constructor(input, $) {
|
|
2915
|
+
super(input, $);
|
|
2911
2916
|
/**
|
|
2912
2917
|
* If false will use timeout executor, otherwise the app executor
|
|
2913
2918
|
*/
|
|
2914
2919
|
this.freezeUi = true;
|
|
2915
|
-
this.slot = new Slot;
|
|
2916
2920
|
}
|
|
2917
|
-
createChild(id, item, before) {
|
|
2918
|
-
|
|
2919
|
-
const node = new Fragment();
|
|
2920
|
-
// eslint-disable-next-line
|
|
2921
|
-
// @ts-ignore
|
|
2922
|
-
const $ = node.$;
|
|
2921
|
+
createChild(opts, id, item, before) {
|
|
2922
|
+
const node = new Fragment({});
|
|
2923
2923
|
this.destroyChild(id, item);
|
|
2924
2924
|
if (before) {
|
|
2925
|
-
|
|
2926
|
-
|
|
2927
|
-
// @ts-ignore
|
|
2928
|
-
$.prev = before.$.prev;
|
|
2929
|
-
// eslint-disable-next-line
|
|
2930
|
-
// @ts-ignore
|
|
2931
|
-
before.$.prev = node;
|
|
2932
|
-
if ($.prev) {
|
|
2933
|
-
// eslint-disable-next-line
|
|
2934
|
-
// @ts-ignore
|
|
2935
|
-
$.prev.$.next = node;
|
|
2936
|
-
}
|
|
2937
|
-
this.$children.splice(this.$children.indexOf(before), 0, node);
|
|
2925
|
+
this.children.add(node);
|
|
2926
|
+
before.insertBefore(node);
|
|
2938
2927
|
}
|
|
2939
2928
|
else {
|
|
2940
|
-
const lastChild = this
|
|
2929
|
+
const lastChild = this.lastChild;
|
|
2941
2930
|
if (lastChild) {
|
|
2942
|
-
|
|
2943
|
-
// @ts-ignore
|
|
2944
|
-
lastChild.$.next = node;
|
|
2931
|
+
lastChild.insertAfter(node);
|
|
2945
2932
|
}
|
|
2946
|
-
|
|
2947
|
-
this.$children.push(node);
|
|
2948
|
-
}
|
|
2949
|
-
node.$preinit(this.$.app, this);
|
|
2950
|
-
node.$init();
|
|
2951
|
-
const callback = () => {
|
|
2952
|
-
this.slot.release(node, item, id);
|
|
2953
|
-
node.$ready();
|
|
2954
|
-
};
|
|
2955
|
-
if (this.freezeUi) {
|
|
2956
|
-
this.$.app.$run.callCallback(callback);
|
|
2957
|
-
}
|
|
2958
|
-
else {
|
|
2959
|
-
timeoutExecutor.callCallback(callback);
|
|
2933
|
+
this.children.add(node);
|
|
2960
2934
|
}
|
|
2935
|
+
this.lastChild = node;
|
|
2936
|
+
node.preinit(this.$.app, this);
|
|
2937
|
+
node.init();
|
|
2938
|
+
opts.slot && opts.slot(node, item, id);
|
|
2939
|
+
node.ready();
|
|
2961
2940
|
this.$.nodes.set(id, node);
|
|
2962
2941
|
}
|
|
2963
2942
|
destroyChild(id, item) {
|
|
2964
2943
|
const $ = this.$;
|
|
2965
2944
|
const child = $.nodes.get(id);
|
|
2966
2945
|
if (child) {
|
|
2967
|
-
|
|
2968
|
-
|
|
2969
|
-
const $ = child.$;
|
|
2970
|
-
if ($.prev) {
|
|
2971
|
-
// eslint-disable-next-line
|
|
2972
|
-
// @ts-ignore
|
|
2973
|
-
$.prev.$.next = $.next;
|
|
2974
|
-
}
|
|
2975
|
-
if ($.next) {
|
|
2976
|
-
// eslint-disable-next-line
|
|
2977
|
-
// @ts-ignore
|
|
2978
|
-
$.next.$.prev = $.prev;
|
|
2979
|
-
}
|
|
2980
|
-
child.$destroy();
|
|
2946
|
+
child.remove();
|
|
2947
|
+
child.destroy();
|
|
2981
2948
|
this.$.nodes.delete(id);
|
|
2982
|
-
this
|
|
2949
|
+
this.children.delete(child);
|
|
2983
2950
|
}
|
|
2984
2951
|
}
|
|
2985
2952
|
}
|
|
@@ -3000,7 +2967,7 @@ class RepeaterPrivate extends RepeatNodePrivate {
|
|
|
3000
2967
|
* Current count of child nodes
|
|
3001
2968
|
*/
|
|
3002
2969
|
this.currentCount = 0;
|
|
3003
|
-
this
|
|
2970
|
+
this.seal();
|
|
3004
2971
|
}
|
|
3005
2972
|
}
|
|
3006
2973
|
/**
|
|
@@ -3015,7 +2982,7 @@ class Repeater extends RepeatNode {
|
|
|
3015
2982
|
* The count of children
|
|
3016
2983
|
*/
|
|
3017
2984
|
this.count = new Reference(0);
|
|
3018
|
-
this
|
|
2985
|
+
this.seal();
|
|
3019
2986
|
}
|
|
3020
2987
|
/**
|
|
3021
2988
|
* Changes the children count
|
|
@@ -3034,18 +3001,18 @@ class Repeater extends RepeatNode {
|
|
|
3034
3001
|
}
|
|
3035
3002
|
$.currentCount = number;
|
|
3036
3003
|
}
|
|
3037
|
-
|
|
3004
|
+
created() {
|
|
3038
3005
|
const $ = this.$;
|
|
3039
|
-
super
|
|
3006
|
+
super.created();
|
|
3040
3007
|
$.updateHandler = this.changeCount.bind(this);
|
|
3041
3008
|
this.count.on($.updateHandler);
|
|
3042
3009
|
}
|
|
3043
|
-
|
|
3010
|
+
ready() {
|
|
3044
3011
|
this.changeCount(this.count.$);
|
|
3045
3012
|
}
|
|
3046
|
-
|
|
3013
|
+
destroy() {
|
|
3047
3014
|
const $ = this.$;
|
|
3048
|
-
super
|
|
3015
|
+
super.destroy();
|
|
3049
3016
|
this.count.off($.updateHandler);
|
|
3050
3017
|
}
|
|
3051
3018
|
}
|
|
@@ -3062,7 +3029,7 @@ window.Repeater = Repeater;
|
|
|
3062
3029
|
class BaseViewPrivate extends RepeatNodePrivate {
|
|
3063
3030
|
constructor() {
|
|
3064
3031
|
super();
|
|
3065
|
-
this
|
|
3032
|
+
this.seal();
|
|
3066
3033
|
}
|
|
3067
3034
|
}
|
|
3068
3035
|
/**
|
|
@@ -3072,34 +3039,23 @@ class BaseViewPrivate extends RepeatNodePrivate {
|
|
|
3072
3039
|
* @implements IModel
|
|
3073
3040
|
*/
|
|
3074
3041
|
class BaseView extends RepeatNode {
|
|
3075
|
-
constructor($
|
|
3076
|
-
super($
|
|
3042
|
+
constructor(input, $) {
|
|
3043
|
+
super(input, $ || new BaseViewPrivate);
|
|
3044
|
+
}
|
|
3045
|
+
compose(input) {
|
|
3077
3046
|
const $ = this.$;
|
|
3078
3047
|
$.addHandler = (id, item) => {
|
|
3079
|
-
this.createChild(id, item);
|
|
3048
|
+
this.createChild(input, id, item);
|
|
3080
3049
|
};
|
|
3081
3050
|
$.removeHandler = (id, item) => {
|
|
3082
3051
|
this.destroyChild(id, item);
|
|
3083
3052
|
};
|
|
3084
|
-
|
|
3085
|
-
|
|
3086
|
-
|
|
3087
|
-
|
|
3088
|
-
|
|
3089
|
-
|
|
3090
|
-
const $ = this.$;
|
|
3091
|
-
this.model.listener.onAdd($.addHandler);
|
|
3092
|
-
this.model.listener.onRemove($.removeHandler);
|
|
3093
|
-
super.$ready();
|
|
3094
|
-
}
|
|
3095
|
-
/**
|
|
3096
|
-
* Handles destroy event
|
|
3097
|
-
*/
|
|
3098
|
-
$destroy() {
|
|
3099
|
-
const $ = this.$;
|
|
3100
|
-
this.model.listener.offAdd($.addHandler);
|
|
3101
|
-
this.model.listener.offRemove($.removeHandler);
|
|
3102
|
-
super.$destroy();
|
|
3053
|
+
input.model.listener.onAdd($.addHandler);
|
|
3054
|
+
input.model.listener.onRemove($.removeHandler);
|
|
3055
|
+
this.runOnDestroy(() => {
|
|
3056
|
+
input.model.listener.offAdd($.addHandler);
|
|
3057
|
+
input.model.listener.offRemove($.removeHandler);
|
|
3058
|
+
});
|
|
3103
3059
|
}
|
|
3104
3060
|
}
|
|
3105
3061
|
|
|
@@ -3113,18 +3069,14 @@ window.BaseView = BaseView;
|
|
|
3113
3069
|
* @extends BaseView
|
|
3114
3070
|
*/
|
|
3115
3071
|
class ArrayView extends BaseView {
|
|
3116
|
-
|
|
3117
|
-
super();
|
|
3118
|
-
this.model = model;
|
|
3119
|
-
}
|
|
3120
|
-
createChild(id, item, before) {
|
|
3121
|
-
super.createChild(item, item, before || this.$.nodes.get(id));
|
|
3072
|
+
createChild(input, id, item, before) {
|
|
3073
|
+
super.createChild(input, item, item, before || this.$.nodes.get(id));
|
|
3122
3074
|
}
|
|
3123
|
-
|
|
3124
|
-
|
|
3125
|
-
|
|
3075
|
+
compose(input) {
|
|
3076
|
+
super.compose(input);
|
|
3077
|
+
input.model.forEach(item => {
|
|
3078
|
+
this.createChild(input, item, item);
|
|
3126
3079
|
});
|
|
3127
|
-
super.$ready();
|
|
3128
3080
|
}
|
|
3129
3081
|
}
|
|
3130
3082
|
|
|
@@ -3137,23 +3089,16 @@ window.ArrayView = ArrayView;
|
|
|
3137
3089
|
* @extends Fragment
|
|
3138
3090
|
*/
|
|
3139
3091
|
class Watch extends Fragment {
|
|
3140
|
-
|
|
3141
|
-
|
|
3142
|
-
|
|
3143
|
-
|
|
3144
|
-
this.$seal();
|
|
3145
|
-
}
|
|
3146
|
-
$createWatchers() {
|
|
3147
|
-
this.$watch((value) => {
|
|
3148
|
-
this.$children.forEach(child => {
|
|
3149
|
-
child.$destroy();
|
|
3092
|
+
compose(input) {
|
|
3093
|
+
this.watch((value) => {
|
|
3094
|
+
this.children.forEach(child => {
|
|
3095
|
+
child.destroy();
|
|
3150
3096
|
});
|
|
3151
|
-
this
|
|
3152
|
-
this.
|
|
3153
|
-
|
|
3154
|
-
|
|
3155
|
-
|
|
3156
|
-
this.slot.release(this, this.model.$);
|
|
3097
|
+
this.children.clear();
|
|
3098
|
+
this.lastChild = null;
|
|
3099
|
+
input.slot && input.slot(this, value);
|
|
3100
|
+
}, input.model);
|
|
3101
|
+
input.slot(this, input.model.$);
|
|
3157
3102
|
}
|
|
3158
3103
|
}
|
|
3159
3104
|
|
|
@@ -3166,16 +3111,13 @@ window.Watch = Watch;
|
|
|
3166
3111
|
* @extends BaseView
|
|
3167
3112
|
*/
|
|
3168
3113
|
class ObjectView extends BaseView {
|
|
3169
|
-
|
|
3170
|
-
super();
|
|
3171
|
-
|
|
3172
|
-
}
|
|
3173
|
-
$ready() {
|
|
3174
|
-
const obj = this.model;
|
|
3114
|
+
compose(input) {
|
|
3115
|
+
super.compose(input);
|
|
3116
|
+
const obj = input.model.proxy();
|
|
3175
3117
|
for (const key in obj) {
|
|
3176
|
-
this.createChild(key, obj[key]);
|
|
3118
|
+
this.createChild(input, key, obj[key]);
|
|
3177
3119
|
}
|
|
3178
|
-
super
|
|
3120
|
+
super.ready();
|
|
3179
3121
|
}
|
|
3180
3122
|
}
|
|
3181
3123
|
|
|
@@ -3188,16 +3130,11 @@ window.ObjectView = ObjectView;
|
|
|
3188
3130
|
* @extends BaseView
|
|
3189
3131
|
*/
|
|
3190
3132
|
class MapView extends BaseView {
|
|
3191
|
-
|
|
3192
|
-
super();
|
|
3193
|
-
|
|
3194
|
-
|
|
3195
|
-
$ready() {
|
|
3196
|
-
const map = this.model;
|
|
3197
|
-
map.forEach((value, key) => {
|
|
3198
|
-
this.createChild(key, value);
|
|
3133
|
+
compose(input) {
|
|
3134
|
+
super.compose(input);
|
|
3135
|
+
input.model.forEach((value, key) => {
|
|
3136
|
+
this.createChild(input, key, value);
|
|
3199
3137
|
});
|
|
3200
|
-
super.$ready();
|
|
3201
3138
|
}
|
|
3202
3139
|
}
|
|
3203
3140
|
|
|
@@ -3210,19 +3147,12 @@ window.MapView = MapView;
|
|
|
3210
3147
|
* @extends BaseView
|
|
3211
3148
|
*/
|
|
3212
3149
|
class SetView extends BaseView {
|
|
3213
|
-
|
|
3214
|
-
super();
|
|
3215
|
-
|
|
3216
|
-
}
|
|
3217
|
-
$ready() {
|
|
3218
|
-
const $ = this.$;
|
|
3219
|
-
const set = this.model;
|
|
3150
|
+
compose(input) {
|
|
3151
|
+
super.compose(input);
|
|
3152
|
+
const set = input.model;
|
|
3220
3153
|
set.forEach(item => {
|
|
3221
|
-
|
|
3222
|
-
this.createChild(item, item);
|
|
3223
|
-
});
|
|
3154
|
+
this.createChild(input, item, item);
|
|
3224
3155
|
});
|
|
3225
|
-
super.$ready();
|
|
3226
3156
|
}
|
|
3227
3157
|
}
|
|
3228
3158
|
|