@twobirds/microcomponents 0.0.34 → 0.0.39

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.
Files changed (120) hide show
  1. package/README.md +40 -27
  2. package/assets/documentation/{MicroComponents.md → MC.md} +17 -17
  3. package/assets/documentation/comparision.md +0 -0
  4. package/assets/documentation/elements.md +276 -0
  5. package/assets/documentation/magic.md +10 -68
  6. package/assets/my-tag.css +6 -2
  7. package/dist/MC.d.ts +3 -4
  8. package/dist/MC.d.ts.map +1 -1
  9. package/dist/MC.min.js +89 -66
  10. package/dist/MC.ts +213 -178
  11. package/dist/autoloader.ts +1 -1
  12. package/dist/{customElements.d.ts → elements.d.ts} +1 -1
  13. package/dist/elements.d.ts.map +1 -0
  14. package/dist/elements.min.js +1 -0
  15. package/dist/{customElements.ts → elements.ts} +23 -14
  16. package/dist/helpers.d.ts +6 -4
  17. package/dist/helpers.d.ts.map +1 -1
  18. package/dist/helpers.ts +95 -128
  19. package/dist/microcomponents.d.ts +3 -3
  20. package/dist/microcomponents.d.ts.map +1 -1
  21. package/dist/microcomponents.min.js +1 -1
  22. package/dist/microcomponents.ts +3 -3
  23. package/dist/{customObservables.d.ts → observables.d.ts} +3 -3
  24. package/dist/observables.d.ts.map +1 -0
  25. package/dist/observables.min.js +1 -0
  26. package/dist/observables.ts +353 -0
  27. package/dist/{customSelectors.d.ts → selectors.d.ts} +1 -1
  28. package/dist/selectors.d.ts.map +1 -0
  29. package/dist/selectors.min.js +1 -0
  30. package/dist/test.ts +135 -156
  31. package/klemmstein.png +0 -0
  32. package/package.json +52 -52
  33. package/public/MC.js +90 -67
  34. package/public/MC.js.map +1 -1
  35. package/public/MC.min.js +89 -66
  36. package/public/assets/search.js +1 -1
  37. package/public/autoloader.js +1 -1
  38. package/public/autoloader.js.map +1 -1
  39. package/public/classes/{DC.html → MC.DC.html} +60 -59
  40. package/public/classes/{MC.html → MC.MC.html} +41 -35
  41. package/public/classes/{McBase.html → MC.McBase.html} +28 -20
  42. package/public/classes/{McEvent.html → MC.McEvent.html} +48 -42
  43. package/public/documentation/{MicroComponents.md → MC.md} +17 -17
  44. package/public/documentation/comparision.md +0 -0
  45. package/public/documentation/elements.md +276 -0
  46. package/public/documentation/magic.md +10 -68
  47. package/public/{customElements.js → elements.js} +9 -10
  48. package/public/elements.js.map +1 -0
  49. package/public/elements.min.js +1 -0
  50. package/public/functions/{addListener.html → MC.addListener.html} +18 -12
  51. package/public/functions/{removeListener.html → MC.removeListener.html} +18 -12
  52. package/public/functions/elements.defineCE.html +78 -0
  53. package/public/functions/elements.getCE.html +63 -0
  54. package/public/functions/formValues.formValues.html +68 -0
  55. package/public/functions/observables.observe.html +65 -0
  56. package/public/functions/selectors._d.html +69 -0
  57. package/public/functions/selectors._t.html +69 -0
  58. package/public/helpers.js +66 -89
  59. package/public/helpers.js.map +1 -1
  60. package/public/index.html +48 -33
  61. package/public/interfaces/{HTMLMcElement.html → MC.HTMLMcElement.html} +601 -595
  62. package/public/interfaces/selectors.DSelector.html +1013 -0
  63. package/public/interfaces/selectors.TSelector.html +712 -0
  64. package/public/microcomponents.js +3 -3
  65. package/public/microcomponents.js.map +1 -1
  66. package/public/microcomponents.min.js +1 -1
  67. package/public/modules/MC.html +78 -0
  68. package/public/modules/elements.html +62 -0
  69. package/public/modules/formValues.html +60 -0
  70. package/public/modules/observables.html +65 -0
  71. package/public/modules/selectors.html +76 -0
  72. package/public/modules.html +11 -23
  73. package/public/my-tag.css +6 -2
  74. package/public/observables.js +259 -0
  75. package/public/observables.js.map +1 -0
  76. package/public/observables.min.js +1 -0
  77. package/public/{customSelectors.js → selectors.js} +1 -1
  78. package/public/selectors.js.map +1 -0
  79. package/public/selectors.min.js +1 -0
  80. package/public/src/MC.ts +413 -0
  81. package/public/src/McEvent.ts +96 -0
  82. package/public/src/autoloader.ts +98 -0
  83. package/{src/customElements.ts → public/src/elements.ts} +23 -14
  84. package/public/src/formValues.ts +275 -0
  85. package/public/src/helpers.ts +140 -0
  86. package/public/src/microcomponents.ts +8 -0
  87. package/public/src/observables.ts +353 -0
  88. package/public/src/test.ts +190 -0
  89. package/public/test.js +93 -118
  90. package/public/test.js.map +1 -1
  91. package/public/types/observables.Observable.html +91 -0
  92. package/public/types/selectors.selection.html +58 -0
  93. package/public/types/selectors.singleSelector.html +58 -0
  94. package/src/MC.ts +213 -178
  95. package/src/autoloader.ts +1 -1
  96. package/src/elements.ts +76 -0
  97. package/src/helpers.ts +95 -128
  98. package/src/microcomponents.ts +3 -3
  99. package/src/observables.ts +353 -0
  100. package/src/selectors.ts +1634 -0
  101. package/src/test.ts +135 -156
  102. package/typedoc.json +1 -1
  103. package/webpack.config.js +9 -9
  104. package/dist/customElements.d.ts.map +0 -1
  105. package/dist/customElements.min.js +0 -1
  106. package/dist/customObservables.d.ts.map +0 -1
  107. package/dist/customObservables.min.js +0 -1
  108. package/dist/customObservables.ts +0 -348
  109. package/dist/customSelectors.d.ts.map +0 -1
  110. package/dist/customSelectors.min.js +0 -1
  111. package/public/customElements.js.map +0 -1
  112. package/public/customElements.min.js +0 -1
  113. package/public/customObservables.js +0 -256
  114. package/public/customObservables.js.map +0 -1
  115. package/public/customObservables.min.js +0 -1
  116. package/public/customSelectors.js.map +0 -1
  117. package/public/customSelectors.min.js +0 -1
  118. package/src/customObservables.ts +0 -348
  119. /package/dist/{customSelectors.ts → selectors.ts} +0 -0
  120. /package/{src/customSelectors.ts → public/src/selectors.ts} +0 -0
package/src/MC.ts CHANGED
@@ -1,34 +1,37 @@
1
- "use strict";
1
+ 'use strict';
2
2
 
3
3
  import { LooseObject } from './helpers.js';
4
4
  import { McEvent } from './McEvent.js';
5
5
 
6
- var isBrowser=new Function("try {return this===window;}catch(e){ return false;}");
6
+ var isBrowser = new Function(
7
+ 'try {return this===window;}catch(e){ return false;}'
8
+ );
7
9
 
8
10
  let nativeEventNames: Set<string> = new Set();
9
11
 
10
12
  // HTMLElement native event names
11
- if ( isBrowser() ){
12
- Object.keys( HTMLElement.prototype ).filter( key => /^on/.test(key) ).forEach( eventName => nativeEventNames.add( eventName ) );
13
+ if (isBrowser()) {
14
+ Object.keys(HTMLElement.prototype)
15
+ .filter((key) => /^on/.test(key))
16
+ .forEach((eventName) => nativeEventNames.add(eventName));
13
17
  }
14
18
 
15
- export interface HTMLMcElement extends HTMLElement{
19
+ export interface HTMLMcElement extends HTMLElement {
16
20
  _mc: LooseObject;
17
21
  }
18
22
 
19
23
  // get all microcomponents from a list of HTMLElements
20
- function getMicroComponents( elements: any[], search: string): any[] {
24
+ function getMicroComponents(elements: any[], search: string): any[] {
21
25
  let mcValues: any[] = [];
22
26
 
23
- elements.forEach( e => {
27
+ elements.forEach((e) => {
24
28
  if (e) {
25
29
  if (e instanceof HTMLElement) {
26
- const _mc = ( e as any )?._mc;
27
- if ( !search && _mc ) {
28
- mcValues = mcValues.concat(Object.values(( e as any )._mc));
29
- }
30
- else if ( search && _mc && _mc[search] ) {
31
- mcValues.push( _mc[search] );
30
+ const _mc = (e as any)?._mc;
31
+ if (!search && _mc) {
32
+ mcValues = mcValues.concat(Object.values((e as any)._mc));
33
+ } else if (search && _mc && _mc[search]) {
34
+ mcValues.push(_mc[search]);
32
35
  }
33
36
  }
34
37
  }
@@ -37,70 +40,78 @@ function getMicroComponents( elements: any[], search: string): any[] {
37
40
  }
38
41
 
39
42
  // get all ancestor DOM nodes up to the document root
40
- function traverseNodes(node: { [key:string]: any }, search: string, firstonly = true): any[] {
43
+ function traverseNodes(
44
+ node: { [key: string]: any },
45
+ search: string,
46
+ firstonly = true
47
+ ): any[] {
41
48
  let mcValues: any[] = [];
42
49
  while (node) {
43
50
  if (node._mc) {
44
51
  if (!search) {
45
52
  mcValues = mcValues.concat(Object.values(node._mc));
46
- }
47
- else if (search && node._mc[search]) {
53
+ } else if (search && node._mc[search]) {
48
54
  mcValues.push(node._mc[search]);
49
55
  }
50
- if (firstonly)
51
- return mcValues;
56
+ if (firstonly) return mcValues;
52
57
  }
53
58
  node = node.parentNode;
54
59
  }
55
60
  return mcValues;
56
61
  }
57
62
 
58
- function isDOM(element: { [key:string]: any } ) {
63
+ function isDOM(element: { [key: string]: any }) {
59
64
  return element && element instanceof HTMLElement;
60
65
  }
61
66
 
62
- function addListener( domNode: Node, eventName: string, handler: EventListenerOrEventListenerObject | null, capture: boolean = false, once: boolean = false ){
63
- let
64
- options: EventListenerOptions & { once: boolean } = { once: false }
65
- ;
66
-
67
- if ( capture ){
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) {
68
76
  options.capture = capture;
69
77
  }
70
78
 
71
- if ( once ){
79
+ if (once) {
72
80
  options.once = once;
73
81
  }
74
82
 
75
83
  //console.log( 'addEventListener', eventName, ( handler as Function ).name, options );
76
- domNode.addEventListener( eventName, handler, options );
84
+ domNode.addEventListener(eventName, handler, options);
77
85
  }
78
86
 
79
- function removeListener( domNode: Node, eventName: string, handler: EventListenerOrEventListenerObject | null ){
80
- domNode.removeEventListener( eventName, handler );
87
+ function removeListener(
88
+ domNode: Node,
89
+ eventName: string,
90
+ handler: EventListenerOrEventListenerObject | null
91
+ ) {
92
+ domNode.removeEventListener(eventName, handler);
81
93
  }
82
94
 
83
95
  // add a microcomponent to a target DOM node
84
- function add( target: HTMLElement, key: string, element = {} ): any {
85
-
96
+ function add(target: HTMLElement, key: string, element = {}): any {
86
97
  let node = target as HTMLMcElement;
87
98
 
88
99
  // create the _mc property if necessary
89
100
  if (!node._mc) {
90
101
  let debug = (DC as any)?.debug;
91
- ( DC as any ).debug = false;
92
- node._mc = new ( DC as any )( target );
93
- ( DC as any ).debug = debug;
102
+ (DC as any).debug = false;
103
+ node._mc = new (DC as any)(target);
104
+ (DC as any).debug = debug;
94
105
  delete node._mc._mc; // NOT NEEDED on the top level _mc property of a DOM HTMLElement
95
106
  }
96
107
 
97
108
  const _mc = node._mc;
98
109
 
99
110
  // add the element with the given property key to the _mc property
100
- if ( key.length && !_mc[key]) {
111
+ if (key.length && !_mc[key]) {
101
112
  _mc[key] = element;
102
113
  // add attribute if HTMLElement
103
- if ( target instanceof HTMLElement ) {
114
+ if (target instanceof HTMLElement) {
104
115
  target.setAttribute('_mc', '');
105
116
  }
106
117
  }
@@ -108,239 +119,264 @@ function add( target: HTMLElement, key: string, element = {} ): any {
108
119
  }
109
120
 
110
121
  // remove a micro component from the DOM
111
- function remove( target: HTMLMcElement, key: string) {
112
- if ( !key ) return; // silent fail
122
+ function remove(target: HTMLMcElement, key: string) {
123
+ if (!key) return; // silent fail
113
124
 
114
125
  const _mc = target?._mc || {};
115
126
 
116
127
  // delete the property from the HTMLElement _mc collection
117
- if ( _mc && _mc[key] ) {
128
+ if (_mc && _mc[key]) {
118
129
  delete _mc[key];
119
130
  }
120
131
 
121
132
  // remove the _mc attribute if the DOM collection is empty
122
- if ( !Object.keys(_mc).length && target instanceof HTMLElement && target.hasAttribute('_mc') ) {
133
+ if (
134
+ !Object.keys(_mc).length &&
135
+ target instanceof HTMLElement &&
136
+ target.hasAttribute('_mc')
137
+ ) {
123
138
  target.removeAttribute('_mc');
124
139
  }
125
140
  return;
126
141
  }
127
142
 
128
143
  // trigger an event
129
- function trigger( target: unknown, ev: McEvent | string, data: any = {}) {
144
+ function trigger(
145
+ target: HTMLElement,
146
+ ev: McEvent | string,
147
+ data: any = {},
148
+ bubble: string = 'l'
149
+ ) {
130
150
  let _mc = (target as any)?._mc;
131
- if ( !_mc ) return;
132
- [ ...Object.values( _mc ) ].forEach( (mc: any) => {
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) => {
133
161
  //console.log( 'mc [', mc.constructor.name, ']', mc.constructor.prototype?.oneInit );
134
- if ( (mc as any)?.trigger && typeof (mc as any)?.trigger === 'function' ){
135
- (mc as any)?.trigger( ev, data );
162
+ if ((mc as any)?.trigger && typeof (mc as any)?.trigger === 'function') {
163
+ (mc as any)?.trigger(event);
136
164
  }
137
165
  });
166
+
167
+ if (/[ud]/.test(mcEvent.bubble)) {
168
+ bubbleEvent(target, mcEvent);
169
+ }
170
+
138
171
  return;
139
172
  }
140
173
 
141
- // run the "init" lifecycle event on the completemcr structure
142
- function init( element: MC | DC ){
143
- if ( element.constructor === DC ) return;
144
-
145
- setTimeout(
146
- () => {
147
- element.trigger('Init');
148
- setTimeout(
149
- () => {
150
- let keys = Object.keys( ( element as any)?._mc );
151
- if ( keys.length ){
152
- //console.log( 'inner Inits on [', mc.constructor.name, ']', keys );
153
- keys?.forEach( (key: string) => {
154
- let mc = ( element as any)?._mc?.[key];
155
- //console.log( key, typeof mc?.oneInit, mc );
156
- if ( ( mc as any )['oneInit'] && typeof ( mc as any ).oneInit == 'function' ){
157
- ( mc as any ).oneInit( new McEvent('Init') );
158
- }
159
- });
160
- };
161
- }
162
- , 0
163
- );
164
- }
165
- , 0
166
- );
167
-
174
+ // run the "init" lifecycle event on the complete _mc structure
175
+ function init(element: MC | DC) {
176
+ if (element.constructor === DC) return;
177
+
178
+ setTimeout(() => {
179
+ element.trigger('Init');
180
+ /*
181
+ let keys = Object.keys( ( element as any)?._mc );
182
+ if ( keys.length ){
183
+ //console.log( 'inner Inits on [', mc.constructor.name, ']', keys );
184
+ keys?.forEach( (key: string) => {
185
+ let mc = ( element as any)?._mc?.[key];
186
+ //console.log( key, typeof mc?.oneInit, mc );
187
+ if ( ( mc as any )['oneInit'] && typeof ( mc as any ).oneInit == 'function' ){
188
+ ( mc as any ).oneInit( new McEvent('Init') );
189
+ }
190
+ });
191
+ };
192
+ */
193
+ }, 0);
168
194
  }
169
195
 
170
- function autoAttachListeners( element: MC | DC ){
171
- if ( !isBrowser() || element.constructor === DC ) return;
196
+ function autoAttachListeners(element: MC | DC) {
197
+ if (!isBrowser() || element.constructor === DC) return;
172
198
 
173
199
  const target = element.target;
174
200
 
175
- if ( target instanceof HTMLElement ){
201
+ if (target instanceof HTMLElement) {
176
202
  let that: LooseObject = element;
177
- Object
178
- .getOwnPropertyNames( that.constructor.prototype )
179
- .filter( key => /^on[A-Z]|one[A-Z]/.test(key) && typeof that.constructor.prototype[key] === 'function' )
180
- .forEach( key => {
181
- let
182
- once = /^one/.test(key),
183
- withoutOnOne = key.replace( /^on[e]{0,1}/, '' ), // preserves upper/lowercase for non-native events
203
+ Object.getOwnPropertyNames(that.constructor.prototype)
204
+ .filter(
205
+ (key) =>
206
+ /^on[A-Z]|one[A-Z]/.test(key) &&
207
+ typeof that.constructor.prototype[key] === 'function'
208
+ )
209
+ .forEach((key) => {
210
+ let once = /^one/.test(key),
211
+ withoutOnOne = key.replace(/^on[e]{0,1}/, ''), // preserves upper/lowercase for non-native events
184
212
  nativeEventName = withoutOnOne.toLowerCase(),
185
- listener = ( ev: McEvent | Event | CustomEvent ) => { that.trigger( withoutOnOne, ev ); };
186
- ;
187
-
188
- if ( once ){
213
+ listener = (ev: McEvent | Event | CustomEvent) => {
214
+ that.trigger(withoutOnOne, ev);
215
+ };
216
+ if (once) {
189
217
  // console.log( '...is only called once', that.constructor.prototype[key] );
190
- Object.defineProperty(
191
- element,
192
- 'on' + withoutOnOne,
193
- {
194
- configurable: true,
195
- enumerable: false,
196
- writable: true,
197
- value: (ev: any) => {
198
- // console.log( 'onceHandler execute:', that.constructor.prototype[key] );
199
- ( that.constructor.prototype[key] ).bind(that)(ev);
200
- }
201
- }
202
- );
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
+ });
203
227
  }
204
228
 
205
- if ( nativeEventNames.has( 'on' + nativeEventName ) ){ // native event defined in HTMLElement
229
+ if (nativeEventNames.has('on' + nativeEventName)) {
230
+ // native event defined in HTMLElement
206
231
  // console.log('added as native listener', target, nativeEventName );
207
- addListener( target, nativeEventName, listener, false, once );
232
+ addListener(target, nativeEventName, listener, false, once);
208
233
  }
209
234
  });
210
235
  }
211
236
  }
212
237
 
213
- class McBase {
238
+ function bubbleEvent(target: HTMLElement, ev: McEvent) {
239
+ // at this point, either 'u' or 'd' bubbling should be indicated
240
+ // mcEvent bubbling is asynchronous, and the order of target MC execution in case of multiple matches is not guaranteed!
241
+ if (/[ud]/.test(ev.bubble)) {
242
+ setTimeout(() => {
243
+ // bubbling must include 'l' for local, or else no handlers are executed'
244
+ if (ev.bubble.indexOf('l') === -1) {
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
+ }
214
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
+ }
267
+ }
268
+
269
+ class McBase {
215
270
  #target: WeakRef<any>; // avoid circular reference
216
271
 
217
- constructor( target?: { [key:string]: any } ) {
272
+ constructor(target?: { [key: string]: any }, debug: boolean = false) {
218
273
  let that: unknown = this,
219
- element = (that as MC | DC );
274
+ element = that as MC | DC;
220
275
 
221
- this.#target = new WeakRef( target || {} );
276
+ this.#target = new WeakRef(target || {});
222
277
 
223
- init( element ); // async lifecycle event
278
+ init(element); // async lifecycle event
224
279
 
225
- autoAttachListeners( element );
280
+ autoAttachListeners(element);
226
281
  }
227
282
 
228
283
  get target(): any {
229
284
  return this.#target.deref();
230
285
  }
231
-
232
286
  }
233
287
 
234
288
  class MC extends McBase {
235
-
236
- _mc: { [key:string]: any } = {};
289
+ _mc: { [key: string]: any } = {};
237
290
 
238
291
  constructor(target?: any) {
239
292
  super(target);
240
293
  }
241
294
 
242
- static trigger = trigger;
295
+ static trigger = trigger;
243
296
 
244
- trigger( ev: McEvent | string, data: any = {}, bubble?: string ) {
297
+ trigger(ev: McEvent | string, data: any = {}, bubble: string = 'l') {
245
298
  let that = this;
246
299
 
247
300
  //console.log( that, '.trigger(', ev, data, bubble, ')' );
248
- bubble = bubble || 'l';
249
301
 
250
302
  // run all triggers
251
- if ( that.constructor === MC || that.constructor === DC){
252
- [ ...Object.getOwnPropertyNames( that ) ].forEach( (mc) => {
253
- if ( (that as any)[mc]?.trigger && typeof (that as any)[mc]?.trigger === 'function' ){
254
- (that as any)[mc]?.trigger( ev, data, bubble );
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);
255
318
  }
256
319
  });
320
+
321
+ if (/[ud]/.test(mcEvent.bubble)) {
322
+ bubbleEvent(that.target, mcEvent);
323
+ }
324
+
257
325
  return; // must return here!
258
326
  }
259
327
 
260
328
  // only this instance
261
- if ( (that as any) instanceof MC || (that as any) instanceof DC ){
262
-
263
- const
264
- that = this,
265
- mcEvent: McEvent = typeof ev !== 'string' ? ( ev as McEvent) : new McEvent( ev, data, bubble ),
266
- handlerName = 'on' + mcEvent.type[0].toUpperCase() + mcEvent.type.slice(1);
267
- ;
268
-
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);
269
337
  // console.log('trigger', handlerName, mcEvent, data, bubble );
270
338
 
271
- if ( mcEvent.bubble.indexOf('l') > -1 ){
272
- if ( !mcEvent.immediateStopped
273
- && typeof ( that as any )[ handlerName ] === 'function'
274
- ){
339
+ if (mcEvent.bubble.indexOf('l') > -1) {
340
+ if (
341
+ !mcEvent.immediateStopped &&
342
+ typeof (that as any)[handlerName] === 'function'
343
+ ) {
275
344
  // console.log( 'execute handler:', handlerName );
276
- ( that as any )[handlerName]( mcEvent );
277
- if ( ( that as any ).hasOwnProperty( handlerName ) ){ // it is a once handler
278
- delete ( that as any )[ handlerName ]; // remove after first execution
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
279
349
  }
280
350
  }
281
351
  }
282
352
 
283
353
  // if event stopped or local only, handling is cancelled
284
- if ( mcEvent.stopped || mcEvent.bubble === 'l') {
354
+ if (mcEvent.stopped || mcEvent.bubble === 'l') {
285
355
  return that;
286
356
  }
287
357
 
288
- // at this point, either 'u' or 'd' bubbling should be indicated
289
- // mcEvent bubbling is asynchronous, and the order of target MC execution in case of multiple matches is not guaranteed!
290
- if ( isBrowser() && /[ud]/.test( mcEvent.bubble ) && (that as any) instanceof MC ){
291
- setTimeout(
292
- () => {
293
- // bubbling must include 'l' for local, or else no handlers are executed'
294
- if ( mcEvent.bubble.indexOf('l') === -1 ){
295
- mcEvent.bubble += 'l';
296
- }
297
-
298
- // bubble up towards root
299
- if ( mcEvent.bubble.indexOf('u') > -1 ){
300
- (that as any)
301
- .parent()
302
- .forEach( (mc: any) => {
303
- mc instanceof MC ? ( mc as any ).trigger(mcEvent) : null;
304
- });
305
- }
306
-
307
- // bubble down
308
- if ( mcEvent.bubble.indexOf('d') > -1 ){
309
- (that as any)
310
- .children()
311
- .forEach( (mc: any) => {
312
- mc instanceof MC ? ( mc as any ).trigger(mcEvent) : null;
313
- });
314
- }
315
-
316
- },
317
- 0
318
- );
358
+ //console.log('bubble', mcEvent);
359
+ if (/[ud]/.test(mcEvent.bubble)) {
360
+ bubbleEvent(that.target, mcEvent);
319
361
  }
320
-
321
362
  }
322
-
323
363
  }
324
-
325
- };
364
+ }
326
365
 
327
366
  class DC extends McBase {
367
+ _mc: { [key: string]: any } = {};
328
368
 
329
- _mc: { [key:string]: any } = {};
330
-
331
- constructor(target: HTMLElement ) {
369
+ constructor(target: HTMLElement, debug: boolean = false) {
332
370
  super(target);
333
371
  }
334
372
 
335
- static debug: boolean = false;
336
-
337
373
  static add: Function = add;
338
374
  static remove: Function = remove;
339
375
  static trigger: Function = trigger;
340
376
 
341
- trigger( ev: McEvent | string, data: any = {}, bubble?: string ) {
342
- MC.prototype.trigger.call( this, ev, data, bubble );
343
- };
377
+ trigger(ev: McEvent | string, data: any = {}, bubble?: string) {
378
+ MC.prototype.trigger.call(this, ev, data, bubble);
379
+ }
344
380
 
345
381
  parent(search: string = ''): any[] {
346
382
  let target: HTMLElement = (this as any).target;
@@ -372,7 +408,6 @@ class DC extends McBase {
372
408
  const myDomElements = target.querySelectorAll('*[_mc]');
373
409
  return getMicroComponents([...myDomElements], search);
374
410
  }
375
-
376
- };
411
+ }
377
412
 
378
413
  export { addListener, removeListener, McBase, MC, DC, McEvent };
package/src/autoloader.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
 
3
- import { getCE } from './customElements.js'
3
+ import { getCE } from './elements.js'
4
4
 
5
5
  // set of currently loading scripts
6
6
  const loadingScripts: Set<string> = new Set();
@@ -0,0 +1,76 @@
1
+ "use strict";
2
+
3
+ import { DC } from "./MC.js";
4
+ import { kebabToPascal } from "./helpers.js";
5
+
6
+ class CeBaseClass extends HTMLElement {
7
+ constructor() {
8
+ super();
9
+ }
10
+
11
+ connectedCallback() {
12
+ (DC as any).trigger(this, "Connected");
13
+ }
14
+
15
+ disconnectedCallback() {
16
+ (DC as any).trigger(this, "Disconnected");
17
+ }
18
+
19
+ adoptedCallback() {
20
+ (DC as any).trigger(this, "Adopted");
21
+ }
22
+
23
+ attributeChangedCallback(name: string, oldValue: any, newValue: any) {
24
+ (DC as any).trigger(this, "AttributeChanged", { name, oldValue, newValue });
25
+ }
26
+ }
27
+
28
+ function createNamedClass(
29
+ name: string,
30
+ ClassBody: { new (...args: any[]): any }
31
+ ) {
32
+ return Object.defineProperty(ClassBody, "name", { value: name });
33
+ }
34
+
35
+ export function defineCE(
36
+ tagName: string,
37
+ DefinitionClass: { new (...args: any[]): any },
38
+ observedAttributes: string[] = []
39
+ ) {
40
+ if (customElements.get(tagName)) {
41
+ console.warn(`IGNORED: Custom element "${tagName}" is already defined!`);
42
+ return;
43
+ }
44
+
45
+ if (!tagName.includes("-")) {
46
+ throw new Error(
47
+ 'createCustomElement: tagName must contain at least one hyphen ("-").'
48
+ );
49
+ }
50
+
51
+ let name = kebabToPascal(tagName);
52
+
53
+ customElements.define(
54
+ tagName,
55
+ createNamedClass(
56
+ name,
57
+ class extends CeBaseClass {
58
+ instance: any;
59
+
60
+ constructor(data?: any) {
61
+ super();
62
+ let instance = new DefinitionClass(this, data);
63
+ (DC as any).add(this, name, instance);
64
+ }
65
+
66
+ static get observedAttributes() {
67
+ return observedAttributes;
68
+ }
69
+ }
70
+ )
71
+ );
72
+ }
73
+
74
+ export function getCE(tagName: string): CustomElementConstructor | undefined {
75
+ return customElements.get(tagName);
76
+ }