@twobirds/microcomponents 0.0.33 → 0.0.37
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 +40 -27
- package/assets/documentation/{MicroComponents.md → MC.md} +17 -17
- package/assets/documentation/comparision.md +0 -0
- package/assets/documentation/elements.md +276 -0
- package/assets/documentation/magic.md +10 -68
- package/dist/MC.d.ts +2 -3
- package/dist/MC.d.ts.map +1 -1
- package/dist/MC.min.js +45 -43
- package/dist/MC.ts +173 -175
- package/dist/autoloader.ts +1 -1
- package/dist/{customElements.d.ts → elements.d.ts} +1 -1
- package/dist/elements.d.ts.map +1 -0
- package/dist/elements.min.js +1 -0
- package/dist/{customElements.ts → elements.ts} +23 -14
- package/dist/helpers.d.ts +6 -4
- package/dist/helpers.d.ts.map +1 -1
- package/dist/helpers.ts +95 -128
- package/dist/microcomponents.d.ts +3 -3
- package/dist/microcomponents.d.ts.map +1 -1
- package/dist/microcomponents.min.js +1 -1
- package/dist/microcomponents.ts +3 -3
- package/dist/{customObservables.d.ts → observables.d.ts} +3 -3
- package/dist/observables.d.ts.map +1 -0
- package/dist/observables.min.js +1 -0
- package/dist/observables.ts +354 -0
- package/dist/{customSelectors.d.ts → selectors.d.ts} +1 -1
- package/dist/selectors.d.ts.map +1 -0
- package/dist/selectors.min.js +1 -0
- package/dist/test.ts +133 -157
- package/klemmstein.png +0 -0
- package/package.json +52 -52
- package/public/MC.js +46 -44
- package/public/MC.js.map +1 -1
- package/public/MC.min.js +45 -43
- package/public/assets/search.js +1 -1
- package/public/autoloader.js +1 -1
- package/public/autoloader.js.map +1 -1
- package/public/classes/{DC.html → MC.DC.html} +60 -59
- package/public/classes/{MC.html → MC.MC.html} +41 -35
- package/public/classes/{McBase.html → MC.McBase.html} +28 -20
- package/public/classes/{McEvent.html → MC.McEvent.html} +48 -42
- package/public/documentation/{MicroComponents.md → MC.md} +17 -17
- package/public/documentation/comparision.md +0 -0
- package/public/documentation/elements.md +276 -0
- package/public/documentation/magic.md +10 -68
- package/public/{customElements.js → elements.js} +9 -10
- package/public/elements.js.map +1 -0
- package/public/elements.min.js +1 -0
- package/public/functions/{addListener.html → MC.addListener.html} +18 -12
- package/public/functions/{removeListener.html → MC.removeListener.html} +18 -12
- package/public/functions/elements.defineCE.html +78 -0
- package/public/functions/elements.getCE.html +63 -0
- package/public/functions/formValues.formValues.html +68 -0
- package/public/functions/observables.observe.html +65 -0
- package/public/functions/selectors._d.html +69 -0
- package/public/functions/selectors._t.html +69 -0
- package/public/helpers.js +66 -89
- package/public/helpers.js.map +1 -1
- package/public/index.html +48 -33
- package/public/interfaces/{HTMLMcElement.html → MC.HTMLMcElement.html} +601 -595
- package/public/interfaces/selectors.DSelector.html +1013 -0
- package/public/interfaces/selectors.TSelector.html +712 -0
- package/public/microcomponents.js +3 -3
- package/public/microcomponents.js.map +1 -1
- package/public/microcomponents.min.js +1 -1
- package/public/modules/MC.html +78 -0
- package/public/modules/elements.html +62 -0
- package/public/modules/formValues.html +60 -0
- package/public/modules/observables.html +65 -0
- package/public/modules/selectors.html +76 -0
- package/public/modules.html +11 -23
- package/public/observables.js +255 -0
- package/public/observables.js.map +1 -0
- package/public/observables.min.js +1 -0
- package/public/{customSelectors.js → selectors.js} +1 -1
- package/public/selectors.js.map +1 -0
- package/public/selectors.min.js +1 -0
- package/public/src/MC.ts +376 -0
- package/public/src/McEvent.ts +96 -0
- package/public/src/autoloader.ts +98 -0
- package/{src/customElements.ts → public/src/elements.ts} +23 -14
- package/public/src/formValues.ts +275 -0
- package/public/src/helpers.ts +140 -0
- package/public/src/microcomponents.ts +8 -0
- package/public/src/observables.ts +354 -0
- package/public/src/test.ts +187 -0
- package/public/test.js +99 -115
- package/public/test.js.map +1 -1
- package/public/types/observables.Observable.html +91 -0
- package/public/types/selectors.selection.html +58 -0
- package/public/types/selectors.singleSelector.html +58 -0
- package/src/MC.ts +173 -175
- package/src/autoloader.ts +1 -1
- package/src/elements.ts +76 -0
- package/src/helpers.ts +95 -128
- package/src/microcomponents.ts +3 -3
- package/src/observables.ts +354 -0
- package/src/selectors.ts +1634 -0
- package/src/test.ts +133 -157
- package/typedoc.json +1 -1
- package/webpack.config.js +9 -9
- package/dist/customElements.d.ts.map +0 -1
- package/dist/customElements.min.js +0 -1
- package/dist/customObservables.d.ts.map +0 -1
- package/dist/customObservables.min.js +0 -1
- package/dist/customObservables.ts +0 -348
- package/dist/customSelectors.d.ts.map +0 -1
- package/dist/customSelectors.min.js +0 -1
- package/public/customElements.js.map +0 -1
- package/public/customElements.min.js +0 -1
- package/public/customObservables.js +0 -256
- package/public/customObservables.js.map +0 -1
- package/public/customObservables.min.js +0 -1
- package/public/customSelectors.js.map +0 -1
- package/public/customSelectors.min.js +0 -1
- package/src/customObservables.ts +0 -348
- /package/dist/{customSelectors.ts → selectors.ts} +0 -0
- /package/{src/customSelectors.ts → public/src/selectors.ts} +0 -0
package/src/helpers.ts
CHANGED
|
@@ -1,173 +1,140 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
export function isObject( value: any ): boolean {
|
|
4
|
-
return value != null && typeof value === 'object';
|
|
5
|
-
}
|
|
1
|
+
'use strict';
|
|
6
2
|
|
|
7
3
|
export interface LooseObject {
|
|
8
4
|
[key: string | symbol]: any;
|
|
9
5
|
}
|
|
10
6
|
|
|
11
|
-
export function
|
|
12
|
-
return
|
|
13
|
-
.split('-') // Split by hyphens
|
|
14
|
-
.map(word => word.charAt(0).toUpperCase() + word.slice(1)) // Capitalize each part
|
|
15
|
-
.join(''); // Join without spaces
|
|
7
|
+
export function isNativeObject(value: any): boolean {
|
|
8
|
+
return value && value['constructor'] && value.constructor === Object;
|
|
16
9
|
}
|
|
17
10
|
|
|
18
|
-
export function
|
|
19
|
-
let
|
|
20
|
-
|
|
11
|
+
export function sortObject(o: LooseObject): LooseObject {
|
|
12
|
+
let result: LooseObject = {},
|
|
13
|
+
keys = [...Object.keys(o)].sort();
|
|
21
14
|
|
|
22
|
-
|
|
15
|
+
keys.forEach((key) => {
|
|
16
|
+
if (isNativeObject(o[key])) {
|
|
17
|
+
result[key] = sortObject(o[key]);
|
|
18
|
+
} else {
|
|
19
|
+
result[key] = o[key];
|
|
20
|
+
}
|
|
21
|
+
});
|
|
23
22
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
func( ...arguments );
|
|
27
|
-
},
|
|
28
|
-
milliseconds
|
|
29
|
-
);
|
|
30
|
-
};
|
|
31
|
-
};
|
|
23
|
+
return result;
|
|
24
|
+
}
|
|
32
25
|
|
|
33
|
-
export function
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
const
|
|
41
|
-
v1 = o1[key],
|
|
42
|
-
v2 = o2[key],
|
|
43
|
-
recurse = isObject(v1) && isObject(v2);
|
|
44
|
-
;
|
|
26
|
+
export function flattenObject(
|
|
27
|
+
o: LooseObject,
|
|
28
|
+
doSort: boolean = true
|
|
29
|
+
): LooseObject {
|
|
30
|
+
let result: LooseObject = {};
|
|
31
|
+
|
|
32
|
+
[...Object.getOwnPropertyNames(o)].forEach((propName) => {
|
|
45
33
|
if (
|
|
46
|
-
|
|
47
|
-
|
|
34
|
+
o[propName] &&
|
|
35
|
+
o[propName]['constructor'] &&
|
|
36
|
+
o[propName].constructor === Object
|
|
48
37
|
) {
|
|
49
|
-
|
|
38
|
+
const temp = flattenObject(o[propName], false);
|
|
39
|
+
for (const j in temp) {
|
|
40
|
+
result[propName + '.' + j] = temp[j];
|
|
41
|
+
}
|
|
42
|
+
} else {
|
|
43
|
+
result[propName] = o[propName];
|
|
50
44
|
}
|
|
51
|
-
}
|
|
52
|
-
return true;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
export function nameSpace( ns: string, obj: LooseObject, val: any = null, orig?: any ): any {
|
|
56
|
-
let leftOver: Array<any> = ns.split('.');
|
|
57
|
-
|
|
58
|
-
if ( !orig ){
|
|
59
|
-
orig = obj;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
// console.log( 'start', ns, obj, val, leftOver );
|
|
45
|
+
});
|
|
63
46
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
lns: string = leftOver.join('.') // the leftover namespace
|
|
67
|
-
;
|
|
68
|
-
|
|
69
|
-
if ( val !== null && last.length && obj[last] === undefined ){ // extend if val given and ns leftover...
|
|
70
|
-
// console.log( 'add prop', last );
|
|
71
|
-
obj[last] = {};
|
|
72
|
-
}
|
|
47
|
+
return doSort ? sortObject(result) : result;
|
|
48
|
+
}
|
|
73
49
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
50
|
+
export function deepEqual(o1: LooseObject, o2: LooseObject): boolean {
|
|
51
|
+
return (
|
|
52
|
+
JSON.stringify(flattenObject(o1)) === JSON.stringify(flattenObject(o2))
|
|
53
|
+
);
|
|
54
|
+
}
|
|
77
55
|
|
|
78
|
-
|
|
56
|
+
export function nameSpace(ns: string | string[], obj: LooseObject = {}): any {
|
|
57
|
+
let nsa = ns.constructor === String ? ns.split('.') : ns;
|
|
79
58
|
|
|
80
|
-
if (
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
return orig;
|
|
84
|
-
}
|
|
85
|
-
return obj[last];
|
|
59
|
+
if (!obj || !nsa[0] || !obj[nsa[0]]) {
|
|
60
|
+
console.warn('ns', nsa[0], 'not in', obj);
|
|
61
|
+
return;
|
|
86
62
|
}
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
return nameSpace( lns, obj[last], val, orig );
|
|
90
|
-
} else {
|
|
91
|
-
if (val){
|
|
92
|
-
return orig;
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
return lob[last];
|
|
63
|
+
if (obj[nsa[0]].constructor === Object && nsa.length > 1) {
|
|
64
|
+
return nameSpace((nsa as string[]).splice(1), obj[nsa[0]]);
|
|
96
65
|
}
|
|
97
|
-
|
|
66
|
+
return obj[nsa[0]];
|
|
98
67
|
}
|
|
99
68
|
|
|
100
|
-
export function parse(
|
|
69
|
+
export function parse(what: string | Object | any[], parseThis: Object) {
|
|
101
70
|
var args = Array.from(arguments);
|
|
102
71
|
|
|
103
|
-
if (
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
if (args.length === 1){
|
|
109
|
-
return args[1];
|
|
110
|
-
} else if (args.length > 2) {
|
|
111
|
-
while (args.length > 1){
|
|
112
|
-
args[0] = parse( args[0], args[1]);
|
|
72
|
+
if (args.length > 2) {
|
|
73
|
+
while (args.length > 1) {
|
|
74
|
+
args[0] = parse(args[0], args[1]);
|
|
113
75
|
args.splice(1, 1);
|
|
114
76
|
}
|
|
115
77
|
return args[0];
|
|
116
78
|
}
|
|
117
79
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
.
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
if ( typeof value !== 'undefined' ){
|
|
130
|
-
what = (what as string).replace( pPropname, value );
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
);
|
|
134
|
-
}
|
|
135
|
-
} else if ( isObject(what) ){
|
|
136
|
-
switch ( what.constructor ){
|
|
80
|
+
if (typeof what === 'string') {
|
|
81
|
+
what.match(/\{[^\{\}]*\}/g)?.forEach(function (pPropname) {
|
|
82
|
+
var propname = pPropname.substring(1, pPropname.length - 1),
|
|
83
|
+
value = nameSpace(propname, parseThis);
|
|
84
|
+
//console.log(propname, value);
|
|
85
|
+
if (typeof value !== 'undefined') {
|
|
86
|
+
what = (what as string).replace(pPropname, value);
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
} else if (isNativeObject(what)) {
|
|
90
|
+
switch (what.constructor) {
|
|
137
91
|
case Object:
|
|
138
|
-
Object
|
|
139
|
-
.
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
);
|
|
92
|
+
Object.keys(what).forEach(function (pKey) {
|
|
93
|
+
if (what.hasOwnProperty(pKey)) {
|
|
94
|
+
(what as LooseObject)[pKey] = parse(
|
|
95
|
+
(what as LooseObject)[pKey],
|
|
96
|
+
parseThis
|
|
97
|
+
);
|
|
98
|
+
}
|
|
99
|
+
});
|
|
147
100
|
break;
|
|
148
101
|
case Array:
|
|
149
|
-
(
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
original[ pKey ] = parse( (what as any)[ pKey ], parseThis );
|
|
153
|
-
}
|
|
154
|
-
);
|
|
102
|
+
(what as Array<any>).forEach(function (pValue, pKey, original) {
|
|
103
|
+
original[pKey] = parse((what as any)[pKey], parseThis);
|
|
104
|
+
});
|
|
155
105
|
break;
|
|
156
106
|
}
|
|
157
107
|
}
|
|
158
108
|
|
|
159
109
|
return what;
|
|
160
|
-
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
export function kebabToPascal(str: string) {
|
|
113
|
+
return str
|
|
114
|
+
.split('-') // Split by hyphens
|
|
115
|
+
.map((word) => word.charAt(0).toUpperCase() + word.slice(1)) // Capitalize each part
|
|
116
|
+
.join(''); // Join without spaces
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
export function debounce(func: Function, milliseconds: number): Function {
|
|
120
|
+
let timeout: any;
|
|
121
|
+
return () => {
|
|
122
|
+
clearTimeout(timeout);
|
|
123
|
+
|
|
124
|
+
timeout = setTimeout(function () {
|
|
125
|
+
func(...arguments);
|
|
126
|
+
}, milliseconds);
|
|
127
|
+
};
|
|
128
|
+
}
|
|
161
129
|
|
|
162
|
-
export function htmlToElements(
|
|
130
|
+
export function htmlToElements(html: string): HTMLElement[] {
|
|
163
131
|
let template = document.createElement('template');
|
|
164
132
|
|
|
165
|
-
html = html
|
|
166
|
-
.replace( /<([A-Za-z0-9\-]*)([^>\/]*)(\/>)/gi, "<$1$2></$1>"); // replace XHTML closing tags by full closing tags
|
|
133
|
+
html = html.replace(/<([A-Za-z0-9\-]*)([^>\/]*)(\/>)/gi, '<$1$2></$1>'); // replace XHTML closing tags by full closing tags
|
|
167
134
|
|
|
168
135
|
template.innerHTML = html;
|
|
169
136
|
|
|
170
137
|
template.content.normalize();
|
|
171
138
|
|
|
172
|
-
return
|
|
139
|
+
return Array.from(template.content.childNodes) as HTMLElement[];
|
|
173
140
|
}
|
package/src/microcomponents.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
export * from './helpers.js';
|
|
3
3
|
export * from './MC.js';
|
|
4
4
|
export * from './McEvent.js';
|
|
5
|
-
export * from './
|
|
6
|
-
export * from './
|
|
7
|
-
export * from './
|
|
5
|
+
export * from './elements.js';
|
|
6
|
+
export * from './observables.js';
|
|
7
|
+
export * from './selectors.js';
|
|
8
8
|
export * from './formValues.js';
|
|
@@ -0,0 +1,354 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
LooseObject,
|
|
5
|
+
parse,
|
|
6
|
+
debounce,
|
|
7
|
+
deepEqual,
|
|
8
|
+
nameSpace,
|
|
9
|
+
flattenObject,
|
|
10
|
+
} from './helpers.js';
|
|
11
|
+
|
|
12
|
+
import { DC, HTMLMcElement, McEvent } from './MC.js';
|
|
13
|
+
|
|
14
|
+
function isObservableObject(value: any): boolean {
|
|
15
|
+
return value != null && typeof value === 'object';
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
type Callback = (value: any) => void;
|
|
19
|
+
|
|
20
|
+
function getPlaceholders(target: HTMLElement): string[] {
|
|
21
|
+
let placeholders: Set<string> = new Set();
|
|
22
|
+
|
|
23
|
+
// scan attributes
|
|
24
|
+
target
|
|
25
|
+
.getAttributeNames()
|
|
26
|
+
.filter((attr) => target.getAttribute(attr)?.match(/\{[^\{\}]*\}/g)) // extract placeholder(s)
|
|
27
|
+
.forEach((attr) => {
|
|
28
|
+
let phs: Set<string> = new Set(
|
|
29
|
+
target.getAttribute(attr)?.match(/\{[^\{\}]*\}/g)
|
|
30
|
+
);
|
|
31
|
+
phs.forEach((placeholder) =>
|
|
32
|
+
placeholders.add(placeholder.replace(/[\{\}]/g, ''))
|
|
33
|
+
);
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
// scan children text nodes
|
|
37
|
+
[...target.childNodes]
|
|
38
|
+
.filter((childNode) => {
|
|
39
|
+
return (
|
|
40
|
+
// is text node and has placeholders
|
|
41
|
+
childNode.nodeType === 3 &&
|
|
42
|
+
((childNode as any).nodeValue || '').match(/\{[^\{\}]*\}/g)
|
|
43
|
+
);
|
|
44
|
+
})
|
|
45
|
+
.forEach((childNode) => {
|
|
46
|
+
((childNode as any).nodeValue || '')
|
|
47
|
+
.match(/\{[^\{\}]*\}/g)
|
|
48
|
+
.forEach((placeholder: string) => {
|
|
49
|
+
placeholders.add(placeholder.replace(/[\{\}]/g, ''));
|
|
50
|
+
});
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
// extract {}
|
|
54
|
+
let result: string[] = [...placeholders].map((placeholder) =>
|
|
55
|
+
placeholder.replace(/[\{\}]/g, '')
|
|
56
|
+
);
|
|
57
|
+
|
|
58
|
+
//console.log('getPlaceholders()', target, result);
|
|
59
|
+
|
|
60
|
+
return [...placeholders];
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
class Placeholders extends DC {
|
|
64
|
+
data: LooseObject = {};
|
|
65
|
+
placeholders: string[] = [];
|
|
66
|
+
|
|
67
|
+
constructor(target: HTMLElement) {
|
|
68
|
+
super(target);
|
|
69
|
+
let that = this;
|
|
70
|
+
getPlaceholders(target).forEach((property) => (that.data[property] = ''));
|
|
71
|
+
observe(that);
|
|
72
|
+
that.#attachCallbacks();
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
#attachCallbacks() {
|
|
76
|
+
let that = this,
|
|
77
|
+
target = that.target;
|
|
78
|
+
|
|
79
|
+
// console.log('attachCallbacks', that.target);
|
|
80
|
+
|
|
81
|
+
// scan attributes
|
|
82
|
+
target
|
|
83
|
+
.getAttributeNames()
|
|
84
|
+
.filter((attr: string) =>
|
|
85
|
+
target.getAttribute(attr)?.match(/\{[^\{\}]*\}/g)
|
|
86
|
+
) // extract placeholder(s)
|
|
87
|
+
.forEach((attr: string) => {
|
|
88
|
+
let phs: Set<string> = new Set(
|
|
89
|
+
target.getAttribute(attr)?.match(/\{[^\{\}]*\}/g)
|
|
90
|
+
);
|
|
91
|
+
// attach callback
|
|
92
|
+
that.data.observe(
|
|
93
|
+
((template: string) => (data: LooseObject) => {
|
|
94
|
+
let result: string = template;
|
|
95
|
+
phs.forEach((placeholder) => {
|
|
96
|
+
result = result.replace(
|
|
97
|
+
placeholder,
|
|
98
|
+
data[placeholder.replace(/[\{\}]/g, '')]
|
|
99
|
+
);
|
|
100
|
+
});
|
|
101
|
+
target.setAttribute(attr, result);
|
|
102
|
+
//console.log('cb setAttribute()', data, template, attr, result);
|
|
103
|
+
})(target.getAttribute(attr))
|
|
104
|
+
);
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
// scan children text nodes
|
|
108
|
+
[...target.childNodes]
|
|
109
|
+
.filter((childNode) => {
|
|
110
|
+
return (
|
|
111
|
+
// is text node and has placeholders
|
|
112
|
+
childNode.nodeType === 3 &&
|
|
113
|
+
((childNode as any).nodeValue || '').match(/\{[^\{\}]*\}/g)
|
|
114
|
+
);
|
|
115
|
+
})
|
|
116
|
+
.forEach((childNode) => {
|
|
117
|
+
let phs: Set<string> = new Set(
|
|
118
|
+
childNode.nodeValue.match(/\{[^\{\}]*\}/g)
|
|
119
|
+
);
|
|
120
|
+
|
|
121
|
+
// attach callback
|
|
122
|
+
that.data.observe(
|
|
123
|
+
((template: string) => (data: LooseObject) => {
|
|
124
|
+
let result: string = template;
|
|
125
|
+
phs.forEach((placeholder) => {
|
|
126
|
+
result = result.replace(
|
|
127
|
+
placeholder,
|
|
128
|
+
data[placeholder.replace(/[\{\}]/g, '')]
|
|
129
|
+
);
|
|
130
|
+
});
|
|
131
|
+
//console.log('cb nodeValue', phs, data, template, childNode, result);
|
|
132
|
+
childNode.nodeValue = result;
|
|
133
|
+
})(childNode.nodeValue)
|
|
134
|
+
);
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
onData(ev: McEvent) {
|
|
139
|
+
let that = this,
|
|
140
|
+
data: LooseObject = {};
|
|
141
|
+
Object.keys(ev.data).forEach((key) => {
|
|
142
|
+
if (that.data.hasOwnProperty(key)) data[key] = ev.data[key];
|
|
143
|
+
});
|
|
144
|
+
// console.log('onData()', ev, data, that.data);
|
|
145
|
+
if (JSON.stringify(data) !== JSON.stringify(that.data))
|
|
146
|
+
Object.assign(that.data, data); // will trigger callbacks
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
function getPlaceholderElements(
|
|
151
|
+
target: HTMLElement | DocumentFragment | ShadowRoot
|
|
152
|
+
): HTMLElement[] {
|
|
153
|
+
let elements: Array<HTMLElement | DocumentFragment | ShadowRoot> = [target]
|
|
154
|
+
.concat([...(target.querySelectorAll('*') as unknown as HTMLElement[])])
|
|
155
|
+
.filter((e) => !!getPlaceholders(e as HTMLElement).length);
|
|
156
|
+
return elements as HTMLElement[];
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
function makePlaceHolders(
|
|
160
|
+
element: HTMLElement | DocumentFragment | ShadowRoot
|
|
161
|
+
): void {
|
|
162
|
+
getPlaceholderElements(element).forEach((e) =>
|
|
163
|
+
DC.add(e, '_placeholders', new Placeholders(e))
|
|
164
|
+
);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
export type Observable = {
|
|
168
|
+
observe: (cb: Callback) => void;
|
|
169
|
+
notify: () => void;
|
|
170
|
+
bind: (target: HTMLElement | DocumentFragment | ShadowRoot) => void;
|
|
171
|
+
};
|
|
172
|
+
|
|
173
|
+
export const observe = (target: LooseObject, propertyName?: string) => {
|
|
174
|
+
let keys = !propertyName
|
|
175
|
+
? [...Object.getOwnPropertyNames(target)]
|
|
176
|
+
: [propertyName];
|
|
177
|
+
|
|
178
|
+
keys.forEach((key) => {
|
|
179
|
+
// console.log( 'co propname', key, typeof target[key], target[key] );
|
|
180
|
+
if (key[0] === '_' || target?.[key] === undefined) return;
|
|
181
|
+
let val: any = target[key],
|
|
182
|
+
Constructor: any;
|
|
183
|
+
|
|
184
|
+
if (!val.prototype) {
|
|
185
|
+
switch (typeof val) {
|
|
186
|
+
case 'string':
|
|
187
|
+
Constructor = String;
|
|
188
|
+
break;
|
|
189
|
+
case 'number':
|
|
190
|
+
Constructor = Number;
|
|
191
|
+
break;
|
|
192
|
+
case 'boolean':
|
|
193
|
+
Constructor = Boolean;
|
|
194
|
+
break;
|
|
195
|
+
case 'object':
|
|
196
|
+
if (val instanceof Array) {
|
|
197
|
+
Constructor = Array;
|
|
198
|
+
} else {
|
|
199
|
+
Constructor = Object;
|
|
200
|
+
}
|
|
201
|
+
break;
|
|
202
|
+
default:
|
|
203
|
+
return;
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
let Observable = class extends Constructor {
|
|
208
|
+
constructor(val: any) {
|
|
209
|
+
super(val);
|
|
210
|
+
(this.constructor as LooseObject).callbacks = [];
|
|
211
|
+
if (isObservableObject(val)) {
|
|
212
|
+
// you cannot bind native values to the dom
|
|
213
|
+
(this.constructor as LooseObject).bound = [];
|
|
214
|
+
Object.getOwnPropertyNames(val).forEach((key) => {
|
|
215
|
+
this[key] = val[key];
|
|
216
|
+
});
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
observe(f: Function) {
|
|
221
|
+
//console.log('observe');
|
|
222
|
+
(this.constructor as any).callbacks.push(f);
|
|
223
|
+
return this;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
bind(target: HTMLElement | DocumentFragment | ShadowRoot) {
|
|
227
|
+
const that = this,
|
|
228
|
+
iso = isObservableObject(that.valueOf()),
|
|
229
|
+
bound = (that.constructor as any).bound;
|
|
230
|
+
//console.log('bind', iso, target);
|
|
231
|
+
|
|
232
|
+
if (iso) {
|
|
233
|
+
makePlaceHolders(target);
|
|
234
|
+
(this.constructor as any).callbacks.push((data: LooseObject) => {
|
|
235
|
+
DC.trigger(target, 'data', flattenObject(data), 'ld');
|
|
236
|
+
});
|
|
237
|
+
that.notify();
|
|
238
|
+
} else {
|
|
239
|
+
console.warn(
|
|
240
|
+
'IGNORED - cannot bind a non-Object to the dom, IS:',
|
|
241
|
+
typeof that.valueOf(),
|
|
242
|
+
that
|
|
243
|
+
);
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
return this;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
notify() {
|
|
250
|
+
let that = this,
|
|
251
|
+
data =
|
|
252
|
+
isObservableObject(that.valueOf()) &&
|
|
253
|
+
that.valueOf() instanceof Array === false
|
|
254
|
+
? structuredClone(Object.assign({}, that))
|
|
255
|
+
: that.valueOf();
|
|
256
|
+
// console.log('notify', that.constructor, (that.constructor as any).callbacks.length, (that.constructor as any)?.bound?.length, data );
|
|
257
|
+
(that.constructor as any).callbacks.forEach((f: Function) => {
|
|
258
|
+
// console.log( 'callback', f, data);
|
|
259
|
+
f(data);
|
|
260
|
+
});
|
|
261
|
+
if (isObservableObject(that.valueOf())) {
|
|
262
|
+
// console.log('bound', this.constructor);
|
|
263
|
+
(that.constructor as any).bound.forEach((f: Function) => {
|
|
264
|
+
// console.log( 'bound', f, data);
|
|
265
|
+
f(data);
|
|
266
|
+
});
|
|
267
|
+
}
|
|
268
|
+
return this;
|
|
269
|
+
}
|
|
270
|
+
};
|
|
271
|
+
|
|
272
|
+
//(Observable.constructor as LooseObject).callbacks = [];
|
|
273
|
+
let o = new Observable(val);
|
|
274
|
+
|
|
275
|
+
Object.defineProperty(target, key, {
|
|
276
|
+
enumerable: true,
|
|
277
|
+
get() {
|
|
278
|
+
if (isObservableObject(o.valueOf())) {
|
|
279
|
+
let check = structuredClone(Object.assign({}, o));
|
|
280
|
+
setTimeout(
|
|
281
|
+
debounce(function checkChanges() {
|
|
282
|
+
let state = structuredClone(Object.assign({}, o));
|
|
283
|
+
//console.log( 'check changes', state, check );
|
|
284
|
+
if (!deepEqual(state, check)) {
|
|
285
|
+
//console.log( '-> not equal!' );
|
|
286
|
+
o.notify();
|
|
287
|
+
}
|
|
288
|
+
}, 0),
|
|
289
|
+
0
|
|
290
|
+
);
|
|
291
|
+
}
|
|
292
|
+
return o;
|
|
293
|
+
},
|
|
294
|
+
set(val: any) {
|
|
295
|
+
//console.log( 'SET:', isObservableObject( val.valueOf() ), 'set:', val, 'to', isObservableObject( o.valueOf() ), o, );
|
|
296
|
+
if (typeof val === typeof o.valueOf()) {
|
|
297
|
+
let iso =
|
|
298
|
+
isObservableObject(o.valueOf()) &&
|
|
299
|
+
o.valueOf() instanceof Array === false;
|
|
300
|
+
//let iso = o.constructor.prototype.__proto__.constructor === Object;
|
|
301
|
+
//console.log('target iso:', iso);
|
|
302
|
+
if (iso) {
|
|
303
|
+
let old = structuredClone(Object.assign({}, o));
|
|
304
|
+
val = structuredClone(Object.assign({}, val));
|
|
305
|
+
|
|
306
|
+
let hasFormHandler =
|
|
307
|
+
(o.constructor as LooseObject)?.hasFormHandler ?? false,
|
|
308
|
+
callbacks = (o.constructor as LooseObject).callbacks,
|
|
309
|
+
bound = (o.constructor as LooseObject).bound;
|
|
310
|
+
o = new Observable(structuredClone(Object.assign({}, val)));
|
|
311
|
+
|
|
312
|
+
//console.log('after set o=', o, 'check', old);
|
|
313
|
+
(o.constructor as LooseObject).callbacks = hasFormHandler;
|
|
314
|
+
(o.constructor as LooseObject).callbacks = callbacks;
|
|
315
|
+
(o.constructor as LooseObject).bound = bound;
|
|
316
|
+
|
|
317
|
+
setTimeout(
|
|
318
|
+
// check for changes
|
|
319
|
+
debounce(function checkChanges() {
|
|
320
|
+
let state = structuredClone(Object.assign({}, o));
|
|
321
|
+
//console.log( 'check changes', state, check );
|
|
322
|
+
if (!deepEqual(state, old)) {
|
|
323
|
+
//console.log( '-> not equal!' );
|
|
324
|
+
o.notify();
|
|
325
|
+
}
|
|
326
|
+
}, 0),
|
|
327
|
+
0
|
|
328
|
+
);
|
|
329
|
+
} else {
|
|
330
|
+
// simple native var
|
|
331
|
+
let old = o.valueOf(),
|
|
332
|
+
callbacks = (o.constructor as LooseObject).callbacks;
|
|
333
|
+
o = new Observable(val);
|
|
334
|
+
(o.constructor as LooseObject).callbacks = callbacks;
|
|
335
|
+
if (val !== old) {
|
|
336
|
+
o.notify();
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
} else {
|
|
340
|
+
console.warn(
|
|
341
|
+
'IGNORED - cannot change observable types, IS:',
|
|
342
|
+
typeof o.valueOf(),
|
|
343
|
+
o,
|
|
344
|
+
'- CANNOT BECOME:',
|
|
345
|
+
typeof val
|
|
346
|
+
);
|
|
347
|
+
}
|
|
348
|
+
},
|
|
349
|
+
});
|
|
350
|
+
|
|
351
|
+
// replace old property with proxy (observable)
|
|
352
|
+
target[key] = val;
|
|
353
|
+
});
|
|
354
|
+
};
|