@twobirds/microcomponents 0.0.82 → 0.0.84
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/assets/documentation/MC.md +0 -1
- package/assets/test/test.html +1 -1
- package/dist/MC.d.ts +11 -10
- package/dist/MC.d.ts.map +1 -1
- package/dist/MC.js +137 -200
- package/dist/MC.min.js +157 -296
- package/dist/MC.ts +202 -337
- package/dist/elements.d.ts +1 -1
- package/dist/elements.d.ts.map +1 -1
- package/dist/elements.js +26 -6
- package/dist/elements.min.js +1 -1
- package/dist/elements.ts +50 -7
- package/dist/formValues.js +2 -2
- package/dist/formValues.min.js +1 -1
- package/dist/formValues.ts +3 -3
- package/dist/microcomponents.d.ts +0 -1
- package/dist/microcomponents.d.ts.map +1 -1
- package/dist/microcomponents.js +0 -1
- package/dist/microcomponents.min.js +1 -1
- package/dist/microcomponents.ts +1 -1
- package/dist/observables.d.ts.map +1 -1
- package/dist/observables.js +52 -57
- package/dist/observables.min.js +1 -1
- package/dist/observables.ts +68 -73
- package/package.json +6 -5
- package/public/MC.d.ts +11 -10
- package/public/MC.d.ts.map +1 -1
- package/public/MC.js +137 -200
- package/public/MC.js.map +1 -1
- package/public/MC.min.js +157 -296
- package/public/MC.ts +202 -337
- package/public/documentation/MC.md +0 -1
- package/public/elements.d.ts +1 -1
- package/public/elements.d.ts.map +1 -1
- package/public/elements.js +26 -6
- package/public/elements.js.map +1 -1
- package/public/elements.min.js +1 -1
- package/public/elements.ts +50 -7
- package/public/formValues.js +2 -2
- package/public/formValues.js.map +1 -1
- package/public/formValues.min.js +1 -1
- package/public/formValues.ts +3 -3
- package/public/microcomponents.d.ts +0 -1
- package/public/microcomponents.d.ts.map +1 -1
- package/public/microcomponents.js +0 -1
- package/public/microcomponents.js.map +1 -1
- package/public/microcomponents.min.js +1 -1
- package/public/microcomponents.ts +1 -1
- package/public/observables.d.ts.map +1 -1
- package/public/observables.js +52 -57
- package/public/observables.js.map +1 -1
- package/public/observables.min.js +1 -1
- package/public/observables.ts +68 -73
- package/public/{test/selectors.ts → selectors._ts} +2 -367
- package/public/src/MC.d.ts +37 -0
- package/public/src/MC.d.ts.map +1 -0
- package/public/src/MC.js +316 -0
- package/public/src/MC.js.map +1 -0
- package/public/src/MC.ts +202 -337
- package/public/src/elements.d.ts +5 -0
- package/public/src/elements.d.ts.map +1 -0
- package/public/src/elements.js +68 -0
- package/public/src/elements.js.map +1 -0
- package/public/src/elements.ts +50 -7
- package/public/src/formValues.d.ts +3 -0
- package/public/src/formValues.d.ts.map +1 -0
- package/public/src/formValues.js +162 -0
- package/public/src/formValues.js.map +1 -0
- package/public/src/formValues.ts +3 -3
- package/public/src/helpers.d.ts +14 -0
- package/public/src/helpers.d.ts.map +1 -0
- package/public/src/helpers.js +113 -0
- package/public/src/microcomponents.d.ts +6 -0
- package/public/src/microcomponents.d.ts.map +1 -0
- package/public/src/microcomponents.js +7 -0
- package/public/src/microcomponents.js.map +1 -0
- package/public/src/microcomponents.ts +1 -1
- package/public/src/observables.d.ts +11 -0
- package/public/src/observables.d.ts.map +1 -0
- package/public/src/observables.js +244 -0
- package/public/src/observables.js.map +1 -0
- package/public/src/observables.ts +68 -73
- package/public/{selectors.ts → src/selectors._ts} +2 -367
- package/public/src/test/grandparent.css +11 -0
- package/public/src/test/test/child.d.ts +2 -0
- package/public/src/test/test/child.d.ts.map +1 -0
- package/public/src/test/test/child.js +15 -0
- package/public/src/test/test/child.js.map +1 -0
- package/public/src/test/test/child.ts +21 -0
- package/public/src/test/test/grandchild.d.ts +2 -0
- package/public/src/test/test/grandchild.d.ts.map +1 -0
- package/public/src/test/test/grandchild.js +15 -0
- package/public/src/test/test/grandchild.js.map +1 -0
- package/public/src/test/test/grandchild.ts +21 -0
- package/public/src/test/test/grandparent.d.ts +2 -0
- package/public/src/test/test/grandparent.d.ts.map +1 -0
- package/public/src/test/test/grandparent.js +1 -0
- package/public/src/test/test/grandparent.js.map +1 -0
- package/public/src/test/test/grandparent.ts +29 -0
- package/public/src/test/test/greatgrandchild.d.ts +2 -0
- package/public/src/test/test/greatgrandchild.d.ts.map +1 -0
- package/public/src/test/test/greatgrandchild.js +29 -0
- package/public/src/test/test/greatgrandchild.js.map +1 -0
- package/public/src/test/test/greatgrandchild.ts +42 -0
- package/public/src/test/test/parent.d.ts +2 -0
- package/public/src/test/test/parent.d.ts.map +1 -0
- package/public/src/test/test/parent.js +15 -0
- package/public/src/test/test/parent.js.map +1 -0
- package/public/src/test/test/parent.ts +21 -0
- package/public/src/test/test/testform.d.ts +2 -0
- package/public/src/test/test/testform.d.ts.map +1 -0
- package/public/src/test/test/testform.js +1 -0
- package/public/src/test/test/testform.js.map +1 -0
- package/public/src/test/test/testform.ts +153 -0
- package/public/src/test/test/testfunction.d.ts +3 -0
- package/public/src/test/test/testfunction.d.ts.map +1 -0
- package/public/src/test/test/testfunction.js +7 -0
- package/public/src/test/test/testfunction.js.map +1 -0
- package/public/src/test/test/testfunction.ts +12 -0
- package/public/src/test/test/testmc.d.ts +3 -0
- package/public/src/test/test/testmc.d.ts.map +1 -0
- package/public/src/test/test/testmc.js +10 -0
- package/public/src/test/test/testmc.js.map +1 -0
- package/public/src/test/test/testmc.ts +16 -0
- package/public/src/test/test/testsimpleclass.d.ts +3 -0
- package/public/src/test/test/testsimpleclass.d.ts.map +1 -0
- package/public/src/test/test/testsimpleclass.js +9 -0
- package/public/src/test/test/testsimpleclass.js.map +1 -0
- package/public/src/test/test/testsimpleclass.ts +15 -0
- package/public/src/test/test.d.ts +2 -0
- package/public/src/test/test.d.ts.map +1 -0
- package/public/src/test/test.js +80 -0
- package/public/src/test/test.js.map +1 -0
- package/public/src/test/test.ts +188 -0
- package/public/src/test/testform.css +47 -0
- package/public/src/test/testform.html +56 -0
- package/public/src/test/testform.json +27 -0
- package/public/test/MC.d.ts +11 -10
- package/public/test/MC.d.ts.map +1 -1
- package/public/test/MC.js +137 -200
- package/public/test/MC.min.js +377 -0
- package/public/test/MC.ts +202 -337
- package/public/test/elements.d.ts +1 -1
- package/public/test/elements.d.ts.map +1 -1
- package/public/test/elements.js +26 -6
- package/public/test/elements.min.js +1 -0
- package/public/test/elements.ts +50 -7
- package/public/test/formValues.js +2 -2
- package/public/test/formValues.min.js +1 -0
- package/public/test/formValues.ts +3 -3
- package/public/test/grandparent.css +1 -3
- package/public/test/microcomponents.d.ts +0 -1
- package/public/test/microcomponents.d.ts.map +1 -1
- package/public/test/microcomponents.js +0 -1
- package/public/test/microcomponents.min.js +1 -1
- package/public/test/microcomponents.ts +1 -1
- package/public/test/observables.d.ts.map +1 -1
- package/public/test/observables.js +52 -57
- package/public/test/observables.min.js +1 -0
- package/public/test/observables.ts +68 -73
- package/public/test/test/child.ts +21 -0
- package/public/test/test/grandchild.ts +21 -0
- package/public/test/test/grandparent.d.ts.map +1 -1
- package/public/test/test/grandparent.js +1 -1
- package/public/test/test/grandparent.js.map +1 -1
- package/public/test/test/grandparent.ts +29 -0
- package/public/test/test/greatgrandchild.ts +42 -0
- package/public/test/test/parent.ts +21 -0
- package/public/test/test/testform.js +1 -1
- package/public/test/test/testform.js.map +1 -1
- package/public/test/test/testform.ts +153 -0
- package/public/test/test/testfunction.d.ts +3 -0
- package/public/test/test/testfunction.d.ts.map +1 -0
- package/public/test/test/testfunction.js +7 -0
- package/public/test/test/testfunction.js.map +1 -0
- package/public/test/test/testfunction.ts +12 -0
- package/public/test/test/testmc.d.ts +2 -5
- package/public/test/test/testmc.d.ts.map +1 -1
- package/public/test/test/testmc.js +4 -4
- package/public/test/test/testmc.js.map +1 -1
- package/public/test/test/testmc.ts +16 -0
- package/public/test/test/testsimpleclass.d.ts +3 -0
- package/public/test/test/testsimpleclass.d.ts.map +1 -0
- package/public/test/test/testsimpleclass.js +9 -0
- package/public/test/test/testsimpleclass.js.map +1 -0
- package/public/test/test/testsimpleclass.ts +15 -0
- package/public/test/test.html +1 -1
- package/public/test/test.js +5 -6
- package/public/test/test.js.map +1 -1
- package/public/test/test.ts +188 -0
- package/public/test/testform.css +47 -0
- package/public/test/testform.html +56 -0
- package/public/test/testform.json +3 -3
- package/public/typedoc/assets/navigation.js +1 -1
- package/public/typedoc/assets/search.js +1 -1
- package/public/typedoc/classes/MC.DC.html +6 -4
- package/public/typedoc/classes/MC.MC.html +3 -4
- package/public/typedoc/classes/MC.McBase.html +2 -2
- package/public/typedoc/functions/MC.autoload.html +1 -1
- package/public/typedoc/functions/MC.off.html +1 -0
- package/public/typedoc/functions/MC.on.html +1 -0
- package/public/typedoc/functions/MC.one.html +1 -0
- package/public/typedoc/functions/elements.defineCE.html +1 -1
- package/public/typedoc/functions/elements.getCE.html +1 -1
- package/public/typedoc/functions/formValues.formValues.html +1 -1
- package/public/typedoc/functions/observables.observe.html +1 -1
- package/public/typedoc/interfaces/MC.HTMLMcElement.html +2 -2
- package/public/typedoc/modules/MC.html +7 -6
- package/public/typedoc/modules/elements.html +1 -1
- package/public/typedoc/modules/formValues.html +1 -1
- package/public/typedoc/modules/observables.html +1 -1
- package/public/typedoc/types/observables.Observable.html +1 -1
- package/src/MC.ts +202 -337
- package/src/elements.ts +50 -7
- package/src/formValues.ts +3 -3
- package/src/microcomponents.ts +1 -1
- package/src/observables.ts +68 -73
- package/{dist/selectors.ts → src/selectors._ts} +2 -367
- package/src/test/test/grandparent.ts +12 -4
- package/src/test/test/testform.ts +13 -11
- package/src/test/test/testfunction.ts +12 -0
- package/src/test/test/testmc.ts +13 -9
- package/src/test/test/testsimpleclass.ts +15 -0
- package/src/test/test.ts +8 -20
- package/tasks.md +36 -0
- package/tsconfig.json +2 -2
- package/typedoc.json +1 -1
- package/webpack.config.js +2 -2
- package/dist/McEvent.d.ts +0 -15
- package/dist/McEvent.d.ts.map +0 -1
- package/dist/McEvent.js +0 -71
- package/dist/selectors.d.ts +0 -108
- package/dist/selectors.d.ts.map +0 -1
- package/dist/selectors.js +0 -971
- package/dist/selectors.min.js +0 -1
- package/public/McEvent.d.ts +0 -15
- package/public/McEvent.d.ts.map +0 -1
- package/public/McEvent.js +0 -71
- package/public/McEvent.js.map +0 -1
- package/public/selectors.d.ts +0 -108
- package/public/selectors.d.ts.map +0 -1
- package/public/selectors.js +0 -971
- package/public/selectors.js.map +0 -1
- package/public/selectors.min.js +0 -1
- package/public/src/selectors.ts +0 -1634
- package/public/test/MC.js.map +0 -1
- package/public/test/McEvent.d.ts +0 -15
- package/public/test/McEvent.d.ts.map +0 -1
- package/public/test/McEvent.js +0 -71
- package/public/test/McEvent.js.map +0 -1
- package/public/test/McEvent.ts +0 -96
- package/public/test/elements.js.map +0 -1
- package/public/test/formValues.js.map +0 -1
- package/public/test/microcomponents.js.map +0 -1
- package/public/test/observables.js.map +0 -1
- package/public/test/selectors.d.ts +0 -108
- package/public/test/selectors.d.ts.map +0 -1
- package/public/test/selectors.js +0 -971
- package/public/test/selectors.js.map +0 -1
- package/public/typedoc/classes/MC.McEvent.html +0 -9
- package/public/typedoc/functions/MC.addListener.html +0 -1
- package/public/typedoc/functions/MC.removeListener.html +0 -1
- package/src/McEvent.ts +0 -96
- package/src/selectors.ts +0 -1634
- /package/{dist/McEvent.ts → public/McEvent._ts} +0 -0
- /package/public/{McEvent.ts → src/McEvent._ts} +0 -0
- /package/public/{test → src}/helpers.js.map +0 -0
- /package/{public/src/McEvent.ts → src/McEvent._ts} +0 -0
package/public/src/MC.ts
CHANGED
|
@@ -1,19 +1,20 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
import { LooseObject } from './helpers.js';
|
|
4
|
-
import { McEvent } from './McEvent.js';
|
|
5
4
|
|
|
6
5
|
var isBrowser = new Function(
|
|
7
6
|
'try {return this===window;}catch(e){ return false;}'
|
|
8
7
|
);
|
|
9
8
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
if (isBrowser()) {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
9
|
+
// get HTMLElement native event names
|
|
10
|
+
function getNativeEventNames( domNode: HTMLElement ): string[] {
|
|
11
|
+
let nativeEventNames: Array<string> = [];
|
|
12
|
+
if (isBrowser()) {
|
|
13
|
+
Object.keys(HTMLElement.prototype)
|
|
14
|
+
.filter((key) => /^on/.test(key))
|
|
15
|
+
.forEach((eventName) => nativeEventNames.push(eventName));
|
|
16
|
+
}
|
|
17
|
+
return nativeEventNames;
|
|
17
18
|
}
|
|
18
19
|
|
|
19
20
|
export interface HTMLMcElement extends HTMLElement {
|
|
@@ -64,34 +65,6 @@ function isDOM(element: { [key: string]: any }) {
|
|
|
64
65
|
return element && element instanceof HTMLElement;
|
|
65
66
|
}
|
|
66
67
|
|
|
67
|
-
function addListener(
|
|
68
|
-
domNode: Node,
|
|
69
|
-
eventName: string,
|
|
70
|
-
handler: EventListenerOrEventListenerObject | null,
|
|
71
|
-
capture: boolean = false,
|
|
72
|
-
once: boolean = false
|
|
73
|
-
) {
|
|
74
|
-
let options: EventListenerOptions & { once: boolean } = { once: false };
|
|
75
|
-
if (capture) {
|
|
76
|
-
options.capture = capture;
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
if (once) {
|
|
80
|
-
options.once = once;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
//console.log( 'addEventListener', eventName, ( handler as Function ).name, options );
|
|
84
|
-
domNode.addEventListener(eventName, handler, options);
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
function removeListener(
|
|
88
|
-
domNode: Node,
|
|
89
|
-
eventName: string,
|
|
90
|
-
handler: EventListenerOrEventListenerObject | null
|
|
91
|
-
) {
|
|
92
|
-
domNode.removeEventListener(eventName, handler);
|
|
93
|
-
}
|
|
94
|
-
|
|
95
68
|
// add a microcomponent to a target DOM node
|
|
96
69
|
function add(target: HTMLElement, key: string, element = {}): any {
|
|
97
70
|
let node = target as HTMLMcElement;
|
|
@@ -111,8 +84,8 @@ function add(target: HTMLElement, key: string, element = {}): any {
|
|
|
111
84
|
if (key.length && !_mc[key]) {
|
|
112
85
|
_mc[key] = element;
|
|
113
86
|
// add attribute if HTMLElement
|
|
114
|
-
if (target instanceof HTMLElement && ! target.getAttribute('
|
|
115
|
-
target.setAttribute('
|
|
87
|
+
if (target instanceof HTMLElement && ! target.getAttribute('data-mc') ) {
|
|
88
|
+
target.setAttribute('data-mc', '');
|
|
116
89
|
}
|
|
117
90
|
}
|
|
118
91
|
return element;
|
|
@@ -133,41 +106,10 @@ function remove(target: HTMLMcElement, key: string) {
|
|
|
133
106
|
if (
|
|
134
107
|
!Object.keys(_mc).length &&
|
|
135
108
|
target instanceof HTMLElement &&
|
|
136
|
-
target.hasAttribute('
|
|
109
|
+
target.hasAttribute('data-mc')
|
|
137
110
|
) {
|
|
138
|
-
target.removeAttribute('
|
|
139
|
-
}
|
|
140
|
-
return;
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
// trigger an event
|
|
144
|
-
function trigger(
|
|
145
|
-
target: HTMLElement,
|
|
146
|
-
ev: McEvent | string,
|
|
147
|
-
data: any = {},
|
|
148
|
-
bubble: string = 'l'
|
|
149
|
-
) {
|
|
150
|
-
let _mc = (target as any)?._mc;
|
|
151
|
-
if (!_mc) return;
|
|
152
|
-
|
|
153
|
-
let event =
|
|
154
|
-
ev instanceof McEvent
|
|
155
|
-
? new McEvent(ev.type, ev.data, 'l')
|
|
156
|
-
: new McEvent(ev, data, 'l'),
|
|
157
|
-
mcEvent: McEvent =
|
|
158
|
-
typeof ev !== 'string' ? (ev as McEvent) : new McEvent(ev, data, bubble);
|
|
159
|
-
|
|
160
|
-
[...Object.values(_mc)].forEach((mc: any) => {
|
|
161
|
-
//console.log( 'mc [', mc.constructor.name, ']', mc.constructor.prototype?.oneInit );
|
|
162
|
-
if ((mc as any)?.trigger && typeof (mc as any)?.trigger === 'function') {
|
|
163
|
-
(mc as any)?.trigger(event);
|
|
164
|
-
}
|
|
165
|
-
});
|
|
166
|
-
|
|
167
|
-
if (/[ud]/.test(mcEvent.bubble)) {
|
|
168
|
-
bubbleEvent(target, mcEvent);
|
|
111
|
+
target.removeAttribute('data-mc');
|
|
169
112
|
}
|
|
170
|
-
|
|
171
113
|
return;
|
|
172
114
|
}
|
|
173
115
|
|
|
@@ -193,6 +135,77 @@ function init(element: MC | DC) {
|
|
|
193
135
|
}, 0);
|
|
194
136
|
}
|
|
195
137
|
|
|
138
|
+
function getMcEventName( eventName: string ): string {
|
|
139
|
+
return '_mc' + eventName[0].toUpperCase() + eventName.substring(1);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/*
|
|
143
|
+
CustomEvent Section...
|
|
144
|
+
*/
|
|
145
|
+
function off( domNode: Node, eventName: string, handler: EventListenerOrEventListenerObject ){
|
|
146
|
+
domNode.removeEventListener( getMcEventName(eventName), handler );
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
function on( domNode: Node, eventName: string, handler: EventListenerOrEventListenerObject, once: boolean = false ) {
|
|
150
|
+
domNode.addEventListener( getMcEventName(eventName), handler, { capture: false, once });
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
function one( domNode: Node, eventName: string, handler: EventListenerOrEventListenerObject ) {
|
|
154
|
+
on(domNode, eventName, handler, true );
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// create and dispatch custom event
|
|
158
|
+
function trigger(
|
|
159
|
+
domNode: HTMLElement,
|
|
160
|
+
event: CustomEvent | string,
|
|
161
|
+
data: any = {},
|
|
162
|
+
bubble: string = 'l'
|
|
163
|
+
){
|
|
164
|
+
const ev = typeof event === 'string'
|
|
165
|
+
? new CustomEvent( getMcEventName( event ), { detail: {data, bubble} } )
|
|
166
|
+
: event;
|
|
167
|
+
|
|
168
|
+
// execute locally if 'l' or nothing is given as bubble
|
|
169
|
+
if( bubble.length && bubble.indexOf('l') > -1 ){
|
|
170
|
+
domNode.dispatchEvent( ev );
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// bubble if up or down is indicated
|
|
174
|
+
if( /[u|d]/.test( bubble ) ){
|
|
175
|
+
bubbleEvent( domNode, ev );
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
function bubbleEvent( domNode: HTMLElement, ev: CustomEvent) {
|
|
180
|
+
// at this point, either 'u' or 'd' bubbling should be indicated
|
|
181
|
+
// event bubbling is asynchronous!
|
|
182
|
+
setTimeout(() => {
|
|
183
|
+
|
|
184
|
+
// add missing 'l', or else no handlers are executed
|
|
185
|
+
if (ev.detail.bubble.indexOf('l') === -1) {
|
|
186
|
+
ev.detail.bubble += 'l';
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
// bubble up towards root
|
|
190
|
+
if (ev.detail.bubble.indexOf('u') > -1 ) {
|
|
191
|
+
domNode.closest('[data-mc]')?.dispatchEvent( ev );
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
// bubble down
|
|
195
|
+
if (ev.detail.bubble.indexOf('d') > -1) {
|
|
196
|
+
let targets = new Set<HTMLMcElement>(
|
|
197
|
+
(domNode as HTMLMcElement)._mc
|
|
198
|
+
.children()
|
|
199
|
+
.map((c: unknown) => (c as any)?.target)
|
|
200
|
+
);
|
|
201
|
+
targets.forEach((target: HTMLMcElement) => {
|
|
202
|
+
if (target) DC.trigger(target, ev);
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
}, 0);
|
|
207
|
+
}
|
|
208
|
+
|
|
196
209
|
function autoAttachListeners(element: MC | DC) {
|
|
197
210
|
if (!isBrowser() || element.constructor === DC) return;
|
|
198
211
|
|
|
@@ -209,71 +222,41 @@ function autoAttachListeners(element: MC | DC) {
|
|
|
209
222
|
.forEach((key) => {
|
|
210
223
|
let once = /^one/.test(key),
|
|
211
224
|
withoutOnOne = key.replace(/^on[e]{0,1}/, ''), // preserves upper/lowercase for non-native events
|
|
212
|
-
nativeEventName = withoutOnOne.toLowerCase()
|
|
213
|
-
listener = (ev: McEvent | Event | CustomEvent) => {
|
|
214
|
-
that.trigger(withoutOnOne, ev);
|
|
215
|
-
};
|
|
216
|
-
if (once) {
|
|
217
|
-
// console.log( '...is only called once', that.constructor.prototype[key] );
|
|
218
|
-
Object.defineProperty(element, 'on' + withoutOnOne, {
|
|
219
|
-
configurable: true,
|
|
220
|
-
enumerable: false,
|
|
221
|
-
writable: true,
|
|
222
|
-
value: (ev: any) => {
|
|
223
|
-
// console.log( 'onceHandler execute:', that.constructor.prototype[key] );
|
|
224
|
-
that.constructor.prototype[key].bind(that)(ev);
|
|
225
|
-
},
|
|
226
|
-
});
|
|
227
|
-
}
|
|
225
|
+
nativeEventName = withoutOnOne.toLowerCase(); // lowercase for native event names
|
|
228
226
|
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
227
|
+
let listener = (ev: Event | CustomEvent) => {
|
|
228
|
+
that[key]( ev );
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
if ( !!( target as any )['on' + nativeEventName] ) {
|
|
232
|
+
// it is a native HTML event
|
|
233
|
+
//console.log( 'AAL: attach native event listener', nativeEventName, 'to', target );
|
|
234
|
+
target.addEventListener( nativeEventName, listener);
|
|
235
|
+
} else {
|
|
236
|
+
// it is a customEvent
|
|
237
|
+
//console.log( 'AAL: attach custom event listener', '_mc' + withoutOnOne , 'to key', key, 'in', element );
|
|
238
|
+
on( target, withoutOnOne, listener, once );
|
|
233
239
|
}
|
|
234
240
|
});
|
|
235
241
|
}
|
|
236
242
|
}
|
|
237
243
|
|
|
238
|
-
function
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
ev.bubble += 'l';
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
// bubble up towards root
|
|
249
|
-
if (ev.bubble.indexOf('u') > -1) {
|
|
250
|
-
let parent = traverseNodes(target, '', true)?.[0].target;
|
|
251
|
-
if (parent) DC.trigger(parent, ev);
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
// bubble down
|
|
255
|
-
if (ev.bubble.indexOf('d') > -1) {
|
|
256
|
-
let targets = new Set<HTMLMcElement>(
|
|
257
|
-
(target as HTMLMcElement)._mc
|
|
258
|
-
.children()
|
|
259
|
-
.map((c: unknown) => (c as any)?.target)
|
|
260
|
-
);
|
|
261
|
-
targets.forEach((target: HTMLMcElement) => {
|
|
262
|
-
if (target) DC.trigger(target, ev);
|
|
263
|
-
});
|
|
264
|
-
}
|
|
265
|
-
}, 0);
|
|
266
|
-
}
|
|
244
|
+
function getMcChildNodes(domNode: HTMLElement): NodeListOf<Element> {
|
|
245
|
+
const id = Math.random().toString().replace('.', '');
|
|
246
|
+
const selector = '[data-mc]:not([temp_id="' + id + '"] [data-mc] [data-mc])';
|
|
247
|
+
domNode.setAttribute('temp_id', id);
|
|
248
|
+
const myDomElements = domNode.querySelectorAll(selector);
|
|
249
|
+
domNode.removeAttribute('temp_id');
|
|
250
|
+
return myDomElements;
|
|
267
251
|
}
|
|
268
252
|
|
|
269
253
|
class McBase {
|
|
270
|
-
|
|
254
|
+
private _target: WeakRef<any>; // avoid circular reference
|
|
271
255
|
|
|
272
256
|
constructor(target?: { [key: string]: any }, debug: boolean = false) {
|
|
273
|
-
let
|
|
274
|
-
element = that as MC | DC;
|
|
257
|
+
let element = this as unknown as MC | DC;
|
|
275
258
|
|
|
276
|
-
this
|
|
259
|
+
this._target = new WeakRef(target || {});
|
|
277
260
|
|
|
278
261
|
init(element); // async lifecycle event
|
|
279
262
|
|
|
@@ -281,91 +264,24 @@ class McBase {
|
|
|
281
264
|
}
|
|
282
265
|
|
|
283
266
|
get target(): any {
|
|
284
|
-
return this
|
|
267
|
+
return this._target.deref();
|
|
285
268
|
}
|
|
269
|
+
|
|
286
270
|
}
|
|
287
271
|
|
|
288
272
|
class MC extends McBase {
|
|
289
|
-
_mc?: LooseObject = {};
|
|
290
|
-
|
|
291
273
|
constructor(target?: any) {
|
|
292
274
|
super(target);
|
|
293
275
|
}
|
|
294
276
|
|
|
295
277
|
static trigger = trigger;
|
|
296
|
-
|
|
297
|
-
trigger(ev:
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
//console.log( that, '.trigger(', ev, data, bubble, ')' );
|
|
301
|
-
|
|
302
|
-
// run all triggers
|
|
303
|
-
if (that.constructor === MC || that.constructor === DC) {
|
|
304
|
-
let event =
|
|
305
|
-
ev instanceof McEvent
|
|
306
|
-
? new McEvent(ev.type, ev.data, 'l')
|
|
307
|
-
: new McEvent(ev, data, 'l'),
|
|
308
|
-
mcEvent: McEvent =
|
|
309
|
-
typeof ev !== 'string'
|
|
310
|
-
? (ev as McEvent)
|
|
311
|
-
: new McEvent(ev, data, bubble);
|
|
312
|
-
[...Object.getOwnPropertyNames(that)].forEach((mc) => {
|
|
313
|
-
if (
|
|
314
|
-
(that as any)[mc]?.trigger &&
|
|
315
|
-
typeof (that as any)[mc]?.trigger === 'function'
|
|
316
|
-
) {
|
|
317
|
-
(that as any)[mc]?.trigger(event);
|
|
318
|
-
}
|
|
319
|
-
});
|
|
320
|
-
|
|
321
|
-
if (/[ud]/.test(mcEvent.bubble)) {
|
|
322
|
-
bubbleEvent(that.target, mcEvent);
|
|
323
|
-
}
|
|
324
|
-
|
|
325
|
-
return; // must return here!
|
|
326
|
-
}
|
|
327
|
-
|
|
328
|
-
// only this instance
|
|
329
|
-
if ((that as any) instanceof MC || (that as any) instanceof DC) {
|
|
330
|
-
const that = this,
|
|
331
|
-
mcEvent: McEvent =
|
|
332
|
-
typeof ev !== 'string'
|
|
333
|
-
? (ev as McEvent)
|
|
334
|
-
: new McEvent(ev, data, bubble),
|
|
335
|
-
handlerName =
|
|
336
|
-
'on' + mcEvent.type[0].toUpperCase() + mcEvent.type.slice(1);
|
|
337
|
-
// console.log('trigger', handlerName, mcEvent, data, bubble );
|
|
338
|
-
|
|
339
|
-
if (mcEvent.bubble.indexOf('l') > -1) {
|
|
340
|
-
if (
|
|
341
|
-
!mcEvent.immediateStopped &&
|
|
342
|
-
typeof (that as any)[handlerName] === 'function'
|
|
343
|
-
) {
|
|
344
|
-
// console.log( 'execute handler:', handlerName );
|
|
345
|
-
(that as any)[handlerName](mcEvent);
|
|
346
|
-
if ((that as any).hasOwnProperty(handlerName)) {
|
|
347
|
-
// it is a once handler
|
|
348
|
-
delete (that as any)[handlerName]; // remove after first execution
|
|
349
|
-
}
|
|
350
|
-
}
|
|
351
|
-
}
|
|
352
|
-
|
|
353
|
-
// if event stopped or local only, handling is cancelled
|
|
354
|
-
if (mcEvent.stopped || mcEvent.bubble === 'l') {
|
|
355
|
-
return that;
|
|
356
|
-
}
|
|
357
|
-
|
|
358
|
-
//console.log('bubble', mcEvent);
|
|
359
|
-
if (/[ud]/.test(mcEvent.bubble)) {
|
|
360
|
-
bubbleEvent(that.target, mcEvent);
|
|
361
|
-
}
|
|
362
|
-
}
|
|
278
|
+
|
|
279
|
+
trigger(ev: string, data: any = {}, bubble: string = 'l') {
|
|
280
|
+
// TBD
|
|
363
281
|
}
|
|
364
282
|
}
|
|
365
283
|
|
|
366
284
|
class DC extends McBase {
|
|
367
|
-
_mc?: LooseObject = {};
|
|
368
|
-
|
|
369
285
|
constructor(target: HTMLElement, debug: boolean = false) {
|
|
370
286
|
super(target);
|
|
371
287
|
}
|
|
@@ -374,8 +290,23 @@ class DC extends McBase {
|
|
|
374
290
|
static remove: Function = remove;
|
|
375
291
|
static trigger: Function = trigger;
|
|
376
292
|
|
|
377
|
-
|
|
378
|
-
|
|
293
|
+
off( eventName: string, handler: EventListenerOrEventListenerObject ) {
|
|
294
|
+
off( this.target, eventName, handler );
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
on( eventName: string, handler: EventListenerOrEventListenerObject ) {
|
|
298
|
+
on( this.target, eventName, handler );
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
one( eventName: string, handler: EventListenerOrEventListenerObject ) {
|
|
302
|
+
one( this.target, eventName, handler );
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
trigger(ev: CustomEvent | string, data: any = {}, bubble: string = 'l') {
|
|
306
|
+
if ( typeof ev === 'string' ){
|
|
307
|
+
|
|
308
|
+
}
|
|
309
|
+
//trigger( this.target, ev, data, bubble);
|
|
379
310
|
}
|
|
380
311
|
|
|
381
312
|
parent(search: string = ''): any[] {
|
|
@@ -393,62 +324,66 @@ class DC extends McBase {
|
|
|
393
324
|
children(search: string = ''): any[] {
|
|
394
325
|
let target: any = (this as any)?.target;
|
|
395
326
|
if (!isDOM(target)) return [];
|
|
396
|
-
const
|
|
397
|
-
const selector = '[_mc]:not([temp_id="' + id + '"] [_mc] [_mc])';
|
|
398
|
-
target.setAttribute('temp_id', id);
|
|
399
|
-
const myDomElements = target.querySelectorAll(selector);
|
|
327
|
+
const myDomElements = getMcChildNodes(target);
|
|
400
328
|
const mcValues = getMicroComponents([...myDomElements], search);
|
|
401
|
-
target.removeAttribute('temp_id');
|
|
402
329
|
return mcValues;
|
|
403
330
|
}
|
|
404
331
|
|
|
405
332
|
descendants(search: string = ''): any[] {
|
|
406
333
|
let target: any = (this as any)?.target;
|
|
407
334
|
if (!isDOM(target)) return [];
|
|
408
|
-
const myDomElements = target.querySelectorAll('*[
|
|
335
|
+
const myDomElements = target.querySelectorAll('*[data-mc]');
|
|
409
336
|
return getMicroComponents([...myDomElements], search);
|
|
410
337
|
}
|
|
411
338
|
}
|
|
412
339
|
|
|
413
|
-
|
|
414
|
-
unresolvedCEs (code below this comment):
|
|
340
|
+
const loadingDCs = new Set<string>();
|
|
415
341
|
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
if they are loaded, the entry is deleted and the browser instanciates it automatically
|
|
420
|
-
if they cannot be loaded, the browser will throw an error
|
|
342
|
+
// this only applies to DCs defined in the data-mc attribute,
|
|
343
|
+
// since they need to be attached manually
|
|
344
|
+
function attachDC(element: string): Function {
|
|
421
345
|
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
346
|
+
//@ts-ignore
|
|
347
|
+
return () => {
|
|
348
|
+
const elements: HTMLElement[] = Array
|
|
349
|
+
.from(document.querySelectorAll(`[data-mc*="${element}"]`))
|
|
350
|
+
.filter( element => element instanceof HTMLElement );
|
|
426
351
|
|
|
427
|
-
|
|
428
|
-
The only difference is that the micro component is loaded only when needed, and not on page load.
|
|
429
|
-
*/
|
|
352
|
+
if ( elements.length === 0 ) return;
|
|
430
353
|
|
|
431
|
-
|
|
354
|
+
//console.log( 'loadedPromise elements', elements );
|
|
432
355
|
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
356
|
+
const klass = customElements.get( element );
|
|
357
|
+
|
|
358
|
+
elements.forEach((node: HTMLElement) => {
|
|
359
|
+
//console.log( 'add', klass!.name, 'to', node );
|
|
360
|
+
DC.add(node, klass!.name, new klass!(node));
|
|
361
|
+
|
|
362
|
+
//@ts-ignore
|
|
363
|
+
const new_mc = node
|
|
364
|
+
.getAttribute( 'data-mc' )
|
|
365
|
+
.split(' ')
|
|
366
|
+
.filter( (name) => name !== element && name !== '' )
|
|
367
|
+
.join(' ')
|
|
368
|
+
.trim();
|
|
439
369
|
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
370
|
+
//@ts-ignore
|
|
371
|
+
node.setAttribute(
|
|
372
|
+
'data-mc',
|
|
373
|
+
//@ts-ignore
|
|
374
|
+
new_mc
|
|
375
|
+
)
|
|
376
|
+
});
|
|
377
|
+
};
|
|
378
|
+
};
|
|
444
379
|
|
|
445
|
-
|
|
446
|
-
The only difference is that the micro component is loaded only when needed, and not on page load.
|
|
447
|
-
*/
|
|
448
|
-
const MCs = new Map();
|
|
380
|
+
function makeLoadScript( element: string ) {
|
|
449
381
|
|
|
450
|
-
|
|
382
|
+
if ( loadingDCs.has( element ) ) return; // already loading
|
|
451
383
|
|
|
384
|
+
loadingDCs.add( element );
|
|
385
|
+
|
|
386
|
+
//console.log( 'makeLoadScript:', element);
|
|
452
387
|
const fileName: string = './' + element.split('-').join('/')+'.js';
|
|
453
388
|
|
|
454
389
|
const se: HTMLScriptElement = document.createElement('script');
|
|
@@ -457,123 +392,53 @@ function makeLoadScript( element: string ): HTMLScriptElement {
|
|
|
457
392
|
se.setAttribute('blocking', 'render');
|
|
458
393
|
se.async = true;
|
|
459
394
|
se.setAttribute('type', 'module');
|
|
460
|
-
se.setAttribute( 'name', element);
|
|
395
|
+
se.setAttribute( 'data-name', element);
|
|
461
396
|
se.setAttribute( 'loading', '');
|
|
462
397
|
|
|
463
|
-
|
|
464
|
-
// console.info('loaded MC', elementName);
|
|
465
|
-
se.removeAttribute( 'loading' );
|
|
466
|
-
se.setAttribute( 'loaded', '');
|
|
467
|
-
});
|
|
398
|
+
const loadedPromise = customElements.whenDefined( element );
|
|
468
399
|
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
});
|
|
472
|
-
|
|
473
|
-
return se;
|
|
474
|
-
}
|
|
400
|
+
//@ts-ignore
|
|
401
|
+
loadedPromise.then( attachDC( element ) );
|
|
475
402
|
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
// it is essential to do this in a timeout and via another script tag,
|
|
479
|
-
// to force it to be a top level module allowing for the use of "import"
|
|
480
|
-
setTimeout( function(){
|
|
481
|
-
// create callback script tag
|
|
482
|
-
const importFileName = script.getAttribute('src');
|
|
483
|
-
const elementName = script.getAttribute('name');
|
|
484
|
-
|
|
485
|
-
const se: HTMLScriptElement = document.createElement('script');
|
|
486
|
-
|
|
487
|
-
se.async = true;
|
|
488
|
-
se.setAttribute( 'type', 'module');
|
|
489
|
-
|
|
490
|
-
// --- autoload script
|
|
491
|
-
const code = /*javascript*/`
|
|
492
|
-
|
|
493
|
-
import _ from "${importFileName}";
|
|
494
|
-
import { DC } from "./microcomponents.js";
|
|
495
|
-
|
|
496
|
-
const elements = Array.from(document.querySelectorAll('[_mc*="${elementName}"]')).filter( element => element instanceof HTMLElement );
|
|
497
|
-
|
|
498
|
-
elements.forEach((element) => {
|
|
499
|
-
// add class to MCs repository
|
|
500
|
-
autoload.state.MCs.set( '${elementName}', _ );
|
|
501
|
-
// add instance to HTMLElement
|
|
502
|
-
DC.add(element, _.name, new _(element));
|
|
503
|
-
// remove instance name from elements "_mc" attribute
|
|
504
|
-
element.setAttribute('_mc', element.getAttribute('_mc').replace('${elementName}', '').replace( /\w\w/g, ' ').trim());
|
|
505
|
-
});
|
|
403
|
+
se.addEventListener( 'load', (ev: Event) => {
|
|
404
|
+
loadingDCs.delete( element );
|
|
506
405
|
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
},0);
|
|
406
|
+
document.head.querySelector(`script[data-name="${element}"]`)?.remove();
|
|
407
|
+
});
|
|
510
408
|
|
|
511
|
-
|
|
512
|
-
|
|
409
|
+
se.addEventListener( 'error', (ev: Event) => {
|
|
410
|
+
console.error('could not load DC code from', fileName);
|
|
411
|
+
});
|
|
513
412
|
|
|
514
|
-
|
|
515
|
-
document.body.append(se);
|
|
516
|
-
}, 0);
|
|
413
|
+
document.head.append(se);
|
|
517
414
|
}
|
|
518
415
|
|
|
519
|
-
function
|
|
416
|
+
function loadUndefinedMCs() {
|
|
520
417
|
|
|
521
|
-
// load unresolved custom
|
|
522
|
-
[ ...document.querySelectorAll(':not(:defined)') ]
|
|
418
|
+
// load unresolved custom elements
|
|
419
|
+
[ ...document.querySelectorAll(':not(:defined)') ]
|
|
523
420
|
.filter( (element) => !!element
|
|
524
421
|
&& !customElements.get(element.tagName.toLowerCase()) // not in CustomElementsRegistry
|
|
525
|
-
&& !
|
|
422
|
+
&& !loadingDCs.has(element.tagName.toLowerCase()) // not in loading list
|
|
526
423
|
)
|
|
527
424
|
.forEach((el) => {
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
const se: HTMLScriptElement = makeLoadScript( elementName );
|
|
532
|
-
|
|
533
|
-
addListener( se, 'load', () => {
|
|
534
|
-
CEs.set( elementName, customElements.get(el.tagName.toLowerCase()) );
|
|
535
|
-
});
|
|
536
|
-
|
|
537
|
-
CEs.set( elementName, 'loading');
|
|
538
|
-
document.head.append(se);
|
|
539
|
-
|
|
540
|
-
// instanciation of the micro component will be handled by the browser automatically
|
|
541
|
-
// module code must define the micro component class and add it to the customElementRegistry
|
|
425
|
+
//console.log( 'detected CE', el.tagName.toLowerCase() );
|
|
426
|
+
makeLoadScript( el.tagName.toLowerCase() ); // will automatically be instanciated
|
|
542
427
|
});
|
|
543
428
|
|
|
544
|
-
|
|
429
|
+
// if defined in _mc attribute: instanciate DCs, load if necessary
|
|
430
|
+
[ ...document.querySelectorAll('[data-mc]:not([data-mc=""]') ]
|
|
545
431
|
.filter( (element) => !!element )
|
|
546
432
|
.forEach((el) => {
|
|
547
|
-
const
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
MCs.set( elementName, 'loading');
|
|
557
|
-
|
|
558
|
-
document.head.append(se);
|
|
559
|
-
});
|
|
560
|
-
|
|
561
|
-
// loading MC components already have callbacks attached
|
|
562
|
-
const elementsAlreadyLoaded = elements.filter( m => MCs.has( m ) && !MCs.get( m )!.length);
|
|
563
|
-
|
|
564
|
-
// MCs that are already loaded will trigger the onLoadCallback manually
|
|
565
|
-
elementsAlreadyLoaded?.forEach( elementName => {
|
|
566
|
-
setTimeout( ()=>{
|
|
567
|
-
//console.log('attaching', elementName, (autoload as any).state.MCs.get(elementName));
|
|
568
|
-
DC.add(el, elementName, new ( (autoload as any).state.MCs.get(elementName) as any)(el)); // add instance to DOM
|
|
569
|
-
|
|
570
|
-
const newAttribute = (el as any).getAttribute('_mc')
|
|
571
|
-
.replace('${elementName}', '')
|
|
572
|
-
.replace( /\w\w/g, ' ')
|
|
573
|
-
.trim() || '_mc';
|
|
574
|
-
|
|
575
|
-
(el as any).setAttribute('_mc', ); // set new "_mc" attribute
|
|
576
|
-
}, 5);
|
|
433
|
+
const _mc = el.getAttribute('data-mc')?.split(' ').filter( name => name !== '' );
|
|
434
|
+
_mc?.forEach( element => {
|
|
435
|
+
//console.log( 'detected DC', dc );
|
|
436
|
+
const isDefined = customElements.get(element);
|
|
437
|
+
if ( !loadingDCs.has(element) && !isDefined ) {
|
|
438
|
+
makeLoadScript( element );
|
|
439
|
+
} else if ( isDefined ) {
|
|
440
|
+
attachDC(element)();
|
|
441
|
+
}
|
|
577
442
|
});
|
|
578
443
|
});
|
|
579
444
|
}
|
|
@@ -590,11 +455,11 @@ function autoload(enable: boolean = true): boolean {
|
|
|
590
455
|
}
|
|
591
456
|
|
|
592
457
|
autoloadEnabled = enable;
|
|
593
|
-
observer = new MutationObserver(
|
|
458
|
+
observer = new MutationObserver(loadUndefinedMCs);
|
|
594
459
|
|
|
595
460
|
setTimeout(() => {
|
|
596
461
|
observer!.observe(document.body, { childList: true, subtree: true });
|
|
597
|
-
|
|
462
|
+
loadUndefinedMCs();
|
|
598
463
|
}, 5);
|
|
599
464
|
|
|
600
465
|
(window as any).autoload = (window as any).autoload || autoload;
|
|
@@ -602,7 +467,7 @@ function autoload(enable: boolean = true): boolean {
|
|
|
602
467
|
return autoloadEnabled;
|
|
603
468
|
}
|
|
604
469
|
|
|
605
|
-
(autoload as LooseObject).state =
|
|
470
|
+
(autoload as LooseObject).state = loadingDCs;
|
|
606
471
|
|
|
607
|
-
export {
|
|
472
|
+
export { McBase, MC, DC, autoload, on, one, off, trigger };
|
|
608
473
|
|