@twobirds/microcomponents 0.1.16 → 0.1.18
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/dist/MC.d.ts.map +1 -1
- package/dist/MC.js +2 -5
- package/dist/MC.min.js +2 -5
- package/dist/MC.ts +336 -346
- package/dist/elements.d.ts.map +1 -1
- package/dist/elements.ts +90 -90
- package/dist/formValues.d.ts.map +1 -1
- package/dist/formValues.js +0 -1
- package/dist/formValues.min.js +1 -1
- package/dist/formValues.ts +165 -171
- package/dist/helpers.d.ts.map +1 -1
- package/dist/helpers.ts +100 -100
- package/dist/microcomponents.min.js +1 -1
- package/dist/observables.d.ts.map +1 -1
- package/dist/observables.js +3 -9
- package/dist/observables.min.js +1 -1
- package/dist/observables.ts +287 -325
- package/package.json +1 -1
package/dist/MC.ts
CHANGED
|
@@ -5,308 +5,298 @@ import { LooseObject } from './helpers.js';
|
|
|
5
5
|
const isBrowser = new Function('try {return this===window;}catch(e){ return false;}');
|
|
6
6
|
|
|
7
7
|
export interface HTMLMcElement extends HTMLElement {
|
|
8
|
-
|
|
8
|
+
_mc: LooseObject;
|
|
9
9
|
}
|
|
10
10
|
|
|
11
11
|
function isDOM(element: { [key: string]: any }) {
|
|
12
|
-
|
|
12
|
+
return element && element instanceof HTMLElement;
|
|
13
13
|
}
|
|
14
14
|
|
|
15
15
|
// add a microcomponent to a target DOM node
|
|
16
16
|
function add(target: HTMLElement, key: string, element: any = {}): HTMLMcElement {
|
|
17
|
-
|
|
17
|
+
let node = target as HTMLMcElement;
|
|
18
18
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
19
|
+
// create the _mc property if necessary
|
|
20
|
+
if (!node._mc) {
|
|
21
|
+
node._mc = new (DC as any)(target);
|
|
22
|
+
}
|
|
23
23
|
|
|
24
|
-
|
|
24
|
+
const _mc = node._mc;
|
|
25
25
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
26
|
+
// add the element with the given property key to the _mc property
|
|
27
|
+
if (key.length && !_mc[key]) {
|
|
28
|
+
_mc[key] = element;
|
|
29
|
+
// add attribute if HTMLElement
|
|
30
|
+
if (target instanceof HTMLElement && !target.getAttribute('data-mc')) {
|
|
31
|
+
target.setAttribute('data-mc', '');
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
34
|
|
|
35
|
-
|
|
35
|
+
return node;
|
|
36
36
|
}
|
|
37
37
|
|
|
38
38
|
// remove a micro component from the DOM
|
|
39
39
|
function remove(target: HTMLElement, key: string) {
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
) {
|
|
55
|
-
target.removeAttribute('data-mc');
|
|
56
|
-
}
|
|
57
|
-
return;
|
|
40
|
+
if (!key) return; // silent fail
|
|
41
|
+
|
|
42
|
+
const _mc = (target as unknown as HTMLMcElement)?._mc || {};
|
|
43
|
+
|
|
44
|
+
// delete the property from the HTMLElement _mc collection
|
|
45
|
+
if (_mc && _mc[key]) {
|
|
46
|
+
delete _mc[key];
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// remove the _mc attribute if the DOM collection is empty
|
|
50
|
+
if (!Object.keys(_mc).length && target instanceof HTMLElement && target.hasAttribute('data-mc')) {
|
|
51
|
+
target.removeAttribute('data-mc');
|
|
52
|
+
}
|
|
53
|
+
return;
|
|
58
54
|
}
|
|
59
55
|
|
|
60
56
|
// run the "init" lifecycle event on the complete _mc structure
|
|
61
57
|
function init(element: DC) {
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
58
|
+
setTimeout(() => {
|
|
59
|
+
if (element.constructor === DC) return;
|
|
60
|
+
element.trigger('Init');
|
|
61
|
+
}, 0);
|
|
66
62
|
}
|
|
67
63
|
|
|
68
64
|
// 'eventName' => '_mcEventName'
|
|
69
65
|
function getMcEventName(eventName: string): string {
|
|
70
|
-
|
|
66
|
+
return '_mc' + eventName[0].toUpperCase() + eventName.substring(1);
|
|
71
67
|
}
|
|
72
68
|
|
|
73
69
|
/*
|
|
74
70
|
CustomEvent Section...
|
|
75
71
|
*/
|
|
76
72
|
function off(domNode: Node, eventName: string, handler: EventListenerOrEventListenerObject) {
|
|
77
|
-
|
|
73
|
+
domNode.removeEventListener(getMcEventName(eventName), handler);
|
|
78
74
|
}
|
|
79
75
|
|
|
80
76
|
function on(
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
77
|
+
domNode: Node,
|
|
78
|
+
eventName: string,
|
|
79
|
+
handler: EventListenerOrEventListenerObject,
|
|
80
|
+
once: boolean = false
|
|
85
81
|
): EventListenerOrEventListenerObject {
|
|
86
|
-
|
|
87
|
-
|
|
82
|
+
domNode.addEventListener(getMcEventName(eventName), handler, { capture: false, once });
|
|
83
|
+
return handler;
|
|
88
84
|
}
|
|
89
85
|
|
|
90
86
|
function one(
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
87
|
+
domNode: Node,
|
|
88
|
+
eventName: string,
|
|
89
|
+
handler: EventListenerOrEventListenerObject
|
|
94
90
|
): EventListenerOrEventListenerObject {
|
|
95
|
-
|
|
96
|
-
|
|
91
|
+
on(domNode, eventName, handler, true);
|
|
92
|
+
return handler;
|
|
97
93
|
}
|
|
98
94
|
|
|
99
95
|
class BubbleController {
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
96
|
+
stopped = false;
|
|
97
|
+
constructor() {}
|
|
98
|
+
stop() {
|
|
99
|
+
this.stopped = true;
|
|
100
|
+
}
|
|
105
101
|
}
|
|
106
102
|
|
|
107
103
|
// create and dispatch custom event
|
|
108
104
|
function trigger(
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
105
|
+
domNode: HTMLElement,
|
|
106
|
+
event: string,
|
|
107
|
+
data: any = {},
|
|
108
|
+
bubble: string = 'l', // direction of bubbling
|
|
109
|
+
controller?: BubbleController
|
|
114
110
|
) {
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
111
|
+
const eventName = /^_mc/.test(event) ? event : getMcEventName(event),
|
|
112
|
+
bubbleController = controller ? controller : new BubbleController(),
|
|
113
|
+
ev = new CustomEvent(eventName, {
|
|
114
|
+
detail: { data, control: bubbleController },
|
|
115
|
+
bubbles: false,
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
if (bubbleController.stopped) return;
|
|
119
|
+
|
|
120
|
+
if (/l/.test(bubble)) {
|
|
121
|
+
domNode.dispatchEvent(ev);
|
|
122
|
+
ev.stopImmediatePropagation();
|
|
123
|
+
|
|
124
|
+
if (bubbleController.stopped) return;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// bubble if up or down is indicated
|
|
128
|
+
if (/[ud]/.test(bubble)) {
|
|
129
|
+
//console.log( 'bubble', bubble, domNode );
|
|
130
|
+
|
|
131
|
+
// add missing 'l', or else no handlers are executed
|
|
132
|
+
if (bubble.indexOf('l') === -1) {
|
|
133
|
+
bubble += 'l';
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
setTimeout(() => {
|
|
137
|
+
// bubble up towards document.body
|
|
138
|
+
if (bubble.indexOf('u') > -1) {
|
|
139
|
+
let parentMc: HTMLMcElement | null | undefined =
|
|
140
|
+
domNode.parentElement?.closest('[data-mc]');
|
|
141
|
+
if (parentMc) {
|
|
142
|
+
parentMc?._mc.trigger(eventName, data, bubble, bubbleController);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// bubble down towards DOM children
|
|
147
|
+
if (bubble.indexOf('d') > -1) {
|
|
148
|
+
let childNodes: DC[] | null = (domNode as HTMLMcElement)._mc.children();
|
|
149
|
+
if (childNodes) {
|
|
150
|
+
childNodes.forEach((_mc: DC) => _mc.trigger(eventName, data, bubble)); // event multiplex - dont carry bubble controller
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}, 0);
|
|
154
|
+
}
|
|
159
155
|
}
|
|
160
156
|
|
|
161
157
|
function autoAttachListeners(element: MC | DC) {
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
}
|
|
158
|
+
if (!isBrowser() || element.constructor === DC) return;
|
|
159
|
+
|
|
160
|
+
const target = element.target;
|
|
161
|
+
|
|
162
|
+
if (target instanceof HTMLElement) {
|
|
163
|
+
let that: LooseObject = element;
|
|
164
|
+
Object.getOwnPropertyNames(that.constructor.prototype)
|
|
165
|
+
.filter(
|
|
166
|
+
(key) =>
|
|
167
|
+
/^(on[A-Z]|one[A-Z])/.test(key) && typeof that.constructor.prototype[key] === 'function'
|
|
168
|
+
)
|
|
169
|
+
.forEach((key) => {
|
|
170
|
+
let once = /^one/.test(key),
|
|
171
|
+
withoutOnOne = key.replace(/^on[e]{0,1}/, ''), // preserves upper/lowercase for non-native events
|
|
172
|
+
nativeEventName = withoutOnOne.toLowerCase(); // lowercase for native event names
|
|
173
|
+
|
|
174
|
+
if ('on' + nativeEventName in target) {
|
|
175
|
+
// it is a native HTML event
|
|
176
|
+
let listener = (ev: Event) => {
|
|
177
|
+
that[key](ev);
|
|
178
|
+
};
|
|
179
|
+
// console.log( 'AAL: attach native event listener', nativeEventName, 'to', target );
|
|
180
|
+
target.addEventListener(nativeEventName, listener);
|
|
181
|
+
} else {
|
|
182
|
+
// it is a customEvent
|
|
183
|
+
// console.log( 'AAL: attach custom event listener', '_mc' + withoutOnOne , 'to key', key, 'in', element );
|
|
184
|
+
let listener = (ev: CustomEvent) => {
|
|
185
|
+
that[key](ev);
|
|
186
|
+
};
|
|
187
|
+
on(target, withoutOnOne, listener as EventListenerOrEventListenerObject, once);
|
|
188
|
+
}
|
|
189
|
+
});
|
|
190
|
+
}
|
|
196
191
|
}
|
|
197
192
|
|
|
198
193
|
function getMcChildNodes(domNode: HTMLElement): DC[] | null {
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
194
|
+
const id = Math.random().toString().replace('.', '');
|
|
195
|
+
const selector = '[data-mc]:not([temp_id="' + id + '"] [data-mc] [data-mc])';
|
|
196
|
+
domNode.setAttribute('temp_id', id);
|
|
197
|
+
const mcArray: unknown[] = ([...domNode.querySelectorAll(selector)] as HTMLMcElement[])
|
|
198
|
+
.filter((e) => !!e._mc)
|
|
199
|
+
.map((e) => e._mc);
|
|
200
|
+
domNode.removeAttribute('temp_id');
|
|
201
|
+
return mcArray.length ? (mcArray as DC[]) : null;
|
|
207
202
|
}
|
|
208
203
|
|
|
209
204
|
class McBase {
|
|
210
|
-
|
|
205
|
+
private _target: WeakRef<any>; // avoid circular reference
|
|
211
206
|
|
|
212
|
-
|
|
213
|
-
|
|
207
|
+
constructor(target?: { [key: string]: any }) {
|
|
208
|
+
let element = this as unknown as MC | DC;
|
|
214
209
|
|
|
215
|
-
|
|
210
|
+
this._target = new WeakRef(target || {});
|
|
216
211
|
|
|
217
|
-
|
|
212
|
+
autoAttachListeners(element);
|
|
218
213
|
|
|
219
|
-
|
|
220
|
-
|
|
214
|
+
init(element as DC); // async lifecycle event
|
|
215
|
+
}
|
|
221
216
|
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
217
|
+
get target(): any {
|
|
218
|
+
return this._target.deref();
|
|
219
|
+
}
|
|
225
220
|
}
|
|
226
221
|
|
|
227
222
|
class MC extends McBase {
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
223
|
+
constructor(target?: any) {
|
|
224
|
+
super(target);
|
|
225
|
+
}
|
|
231
226
|
}
|
|
232
227
|
|
|
233
228
|
class DC extends McBase {
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
const mcArray: unknown[] = ([...target.querySelectorAll('[data-mc]')] as HTMLMcElement[])
|
|
306
|
-
.filter((e) => !!e._mc)
|
|
307
|
-
.map((e) => e._mc);
|
|
308
|
-
return mcArray.length ? (mcArray as DC[]) : null;
|
|
309
|
-
}
|
|
229
|
+
constructor(target: HTMLElement) {
|
|
230
|
+
super(target);
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
static add(target: HTMLElement, key: string, element: any = {}): HTMLMcElement {
|
|
234
|
+
return add(target, key, element);
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
static remove(target: HTMLElement, key: string) {
|
|
238
|
+
remove(target, key);
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
/* event handling */
|
|
242
|
+
off(eventName: string, handler: EventListenerOrEventListenerObject) {
|
|
243
|
+
off(this.target, eventName, handler);
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
on(
|
|
247
|
+
eventName: string,
|
|
248
|
+
handler: EventListenerOrEventListenerObject
|
|
249
|
+
): EventListenerOrEventListenerObject {
|
|
250
|
+
return on(this.target, eventName, handler);
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
one(
|
|
254
|
+
eventName: string,
|
|
255
|
+
handler: EventListenerOrEventListenerObject
|
|
256
|
+
): EventListenerOrEventListenerObject {
|
|
257
|
+
return one(this.target, eventName, handler);
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
trigger(eventName: string, data: any = {}, bubble: string = 'l', controller?: BubbleController) {
|
|
261
|
+
trigger(this.target, eventName, data, bubble, controller);
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
/* DOM traversal */
|
|
265
|
+
ancestors(): DC[] | null {
|
|
266
|
+
let currentNode: HTMLElement | null = (this as DC)?.target as HTMLMcElement,
|
|
267
|
+
result: DC[] = [];
|
|
268
|
+
|
|
269
|
+
if (!isDOM(currentNode)) return [];
|
|
270
|
+
|
|
271
|
+
while ((currentNode = currentNode.closest('[data-mc]'))) {
|
|
272
|
+
if ((currentNode as HTMLMcElement)?._mc) {
|
|
273
|
+
result.push((currentNode as HTMLMcElement)?._mc as DC);
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
return result.length ? result : null;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
closest(): DC | null {
|
|
281
|
+
let target: HTMLElement = (this as DC).target;
|
|
282
|
+
if (!isDOM(target)) return null;
|
|
283
|
+
return ((target.closest('[data-mc]') as HTMLMcElement)?._mc as DC) || null;
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
children(): DC[] | null {
|
|
287
|
+
let target: any = (this as any)?.target;
|
|
288
|
+
if (!isDOM(target)) return null;
|
|
289
|
+
return getMcChildNodes(target);
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
descendants(): DC[] | null {
|
|
293
|
+
const target: any = (this as DC)?.target;
|
|
294
|
+
if (!isDOM(target)) return [];
|
|
295
|
+
const mcArray: unknown[] = ([...target.querySelectorAll('[data-mc]')] as HTMLMcElement[])
|
|
296
|
+
.filter((e) => !!e._mc)
|
|
297
|
+
.map((e) => e._mc);
|
|
298
|
+
return mcArray.length ? (mcArray as DC[]) : null;
|
|
299
|
+
}
|
|
310
300
|
}
|
|
311
301
|
|
|
312
302
|
/*
|
|
@@ -316,141 +306,141 @@ Autoload Section...
|
|
|
316
306
|
const loadingDCs = new Set<string>();
|
|
317
307
|
|
|
318
308
|
function attachDC(element: string): Function {
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
309
|
+
//@ts-ignore
|
|
310
|
+
return () => {
|
|
311
|
+
const elements: HTMLElement[] = Array.from(
|
|
312
|
+
document.querySelectorAll(`[data-mc*="${element}"]`)
|
|
313
|
+
).filter((element) => element instanceof HTMLElement);
|
|
314
|
+
|
|
315
|
+
if (elements.length === 0) return;
|
|
316
|
+
|
|
317
|
+
//console.log( 'loadedPromise elements', elements );
|
|
318
|
+
|
|
319
|
+
const Klass = customElements.get(element);
|
|
320
|
+
|
|
321
|
+
elements.forEach((node: HTMLElement) => {
|
|
322
|
+
try {
|
|
323
|
+
//console.log( 'add', klass!.name, 'to', node );
|
|
324
|
+
DC.add(node, Klass!.name, new Klass!(node));
|
|
325
|
+
} catch (error) {
|
|
326
|
+
if ((Klass as LooseObject)['create']) {
|
|
327
|
+
let element: HTMLMcElement = (Klass as LooseObject).create(node);
|
|
328
|
+
element.setAttribute('data-mc', node.getAttribute('data-mc')!);
|
|
329
|
+
node.replaceWith(element);
|
|
330
|
+
node = element;
|
|
331
|
+
} else {
|
|
332
|
+
throw `Class ${(Klass as LooseObject).name} doesn't have a callable constructor AND class doesn't have a static .create() method.`;
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
//@ts-ignore
|
|
337
|
+
const new_mc = node
|
|
338
|
+
.getAttribute('data-mc')
|
|
339
|
+
.split(' ')
|
|
340
|
+
.filter((name) => name !== element && name !== '')
|
|
341
|
+
.join(' ')
|
|
342
|
+
.trim();
|
|
343
|
+
|
|
344
|
+
//@ts-ignore
|
|
345
|
+
node.setAttribute(
|
|
346
|
+
'data-mc',
|
|
347
|
+
//@ts-ignore
|
|
348
|
+
new_mc
|
|
349
|
+
);
|
|
350
|
+
});
|
|
351
|
+
};
|
|
362
352
|
}
|
|
363
353
|
|
|
364
354
|
function makeLoadScript(element: string) {
|
|
365
|
-
|
|
355
|
+
if (loadingDCs.has(element)) return; // already loading
|
|
366
356
|
|
|
367
|
-
|
|
357
|
+
loadingDCs.add(element);
|
|
368
358
|
|
|
369
|
-
|
|
370
|
-
|
|
359
|
+
//console.log( 'makeLoadScript:', element);
|
|
360
|
+
const fileName: string = './' + element.split('-').join('/') + '.js';
|
|
371
361
|
|
|
372
|
-
|
|
362
|
+
const se: HTMLScriptElement = document.createElement('script');
|
|
373
363
|
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
364
|
+
se.setAttribute('src', fileName);
|
|
365
|
+
se.setAttribute('blocking', 'render');
|
|
366
|
+
se.async = true;
|
|
367
|
+
se.setAttribute('type', 'module');
|
|
368
|
+
se.setAttribute('data-name', element);
|
|
369
|
+
se.setAttribute('loading', '');
|
|
380
370
|
|
|
381
|
-
|
|
371
|
+
const loadedPromise = customElements.whenDefined(element);
|
|
382
372
|
|
|
383
|
-
|
|
384
|
-
|
|
373
|
+
//@ts-ignore
|
|
374
|
+
loadedPromise.then(attachDC(element));
|
|
385
375
|
|
|
386
|
-
|
|
387
|
-
|
|
376
|
+
se.addEventListener('load', (ev: Event) => {
|
|
377
|
+
loadingDCs.delete(element);
|
|
388
378
|
|
|
389
|
-
|
|
390
|
-
|
|
379
|
+
document.head.querySelector(`script[data-name="${element}"]`)?.remove();
|
|
380
|
+
});
|
|
391
381
|
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
382
|
+
se.addEventListener('error', (ev: Event) => {
|
|
383
|
+
console.error('could not load DC code from', fileName);
|
|
384
|
+
});
|
|
395
385
|
|
|
396
|
-
|
|
386
|
+
document.head.append(se);
|
|
397
387
|
}
|
|
398
388
|
|
|
399
389
|
function loadUndefinedMCs() {
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
390
|
+
// load unresolved custom elements
|
|
391
|
+
[...document.querySelectorAll(':not(:defined)')]
|
|
392
|
+
.filter(
|
|
393
|
+
(element) =>
|
|
394
|
+
!!element &&
|
|
395
|
+
!customElements.get(element.tagName.toLowerCase()) && // not in CustomElementsRegistry
|
|
396
|
+
!loadingDCs.has(element.tagName.toLowerCase()) // not in loading list
|
|
397
|
+
)
|
|
398
|
+
.forEach((el) => {
|
|
399
|
+
//console.log( 'detected CE', el.tagName.toLowerCase() );
|
|
400
|
+
makeLoadScript(el.tagName.toLowerCase()); // will automatically be instanciated
|
|
401
|
+
});
|
|
402
|
+
|
|
403
|
+
// if defined in _mc attribute: instanciate DCs, load if necessary
|
|
404
|
+
[...document.querySelectorAll('[data-mc]:not([data-mc=""]')]
|
|
405
|
+
.filter((element) => !!element)
|
|
406
|
+
.forEach((el) => {
|
|
407
|
+
const _mc = el
|
|
408
|
+
.getAttribute('data-mc')
|
|
409
|
+
?.split(' ')
|
|
410
|
+
.filter((name) => name !== '');
|
|
411
|
+
_mc?.forEach((element) => {
|
|
412
|
+
//console.log( 'detected DC', dc );
|
|
413
|
+
const isDefined = customElements.get(element);
|
|
414
|
+
if (!loadingDCs.has(element) && !isDefined) {
|
|
415
|
+
makeLoadScript(element);
|
|
416
|
+
} else if (isDefined) {
|
|
417
|
+
attachDC(element)();
|
|
418
|
+
}
|
|
419
|
+
});
|
|
420
|
+
});
|
|
431
421
|
}
|
|
432
422
|
|
|
433
423
|
let autoloadEnabled: boolean = false;
|
|
434
424
|
let observer: MutationObserver | null = null;
|
|
435
425
|
|
|
436
426
|
function autoload(enable: boolean = true): boolean {
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
427
|
+
if (!enable) {
|
|
428
|
+
observer?.disconnect();
|
|
429
|
+
observer = null;
|
|
430
|
+
return autoloadEnabled;
|
|
431
|
+
}
|
|
442
432
|
|
|
443
|
-
|
|
444
|
-
|
|
433
|
+
autoloadEnabled = enable;
|
|
434
|
+
observer = new MutationObserver(loadUndefinedMCs);
|
|
445
435
|
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
436
|
+
setTimeout(() => {
|
|
437
|
+
observer!.observe(document.body, { childList: true, subtree: true });
|
|
438
|
+
loadUndefinedMCs();
|
|
439
|
+
}, 5);
|
|
450
440
|
|
|
451
|
-
|
|
441
|
+
(window as LooseObject).autoload = (window as LooseObject).autoload || autoload;
|
|
452
442
|
|
|
453
|
-
|
|
443
|
+
return autoloadEnabled;
|
|
454
444
|
}
|
|
455
445
|
|
|
456
446
|
(autoload as LooseObject).state = loadingDCs;
|