@twobirds/microcomponents 0.0.48 → 0.0.51

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 (130) hide show
  1. package/assets/Grandparent.css +13 -0
  2. package/assets/documentation/MC.md +380 -166
  3. package/assets/test.html +5 -1
  4. package/dist/MC.d.ts +1 -0
  5. package/dist/MC.d.ts.map +1 -1
  6. package/dist/MC.min.js +44 -0
  7. package/dist/MC.ts +65 -0
  8. package/dist/elements.min.js +1 -1
  9. package/dist/elements.ts +10 -10
  10. package/dist/formValues.d.ts +3 -2
  11. package/dist/formValues.d.ts.map +1 -1
  12. package/dist/formValues.ts +205 -203
  13. package/dist/formvValues.min.js +1 -1
  14. package/dist/helpers.d.ts +1 -0
  15. package/dist/helpers.d.ts.map +1 -1
  16. package/dist/helpers.ts +9 -0
  17. package/dist/microcomponents.min.js +1 -1
  18. package/dist/observables.d.ts +1 -1
  19. package/dist/observables.d.ts.map +1 -1
  20. package/dist/observables.min.js +1 -1
  21. package/dist/observables.ts +64 -31
  22. package/dist/selectors.min.js +1 -1
  23. package/dist/test.ts +8 -5
  24. package/package.json +1 -1
  25. package/public/assets/search.js +1 -1
  26. package/public/classes/MC.DC.html +13 -13
  27. package/public/classes/MC.MC.html +7 -7
  28. package/public/classes/MC.McBase.html +4 -4
  29. package/public/classes/MC.McEvent.html +13 -13
  30. package/public/classes/formValues.FormValues.html +86 -0
  31. package/public/functions/MC.addListener.html +2 -1
  32. package/public/functions/{formValues.formValues.html → MC.autoload.html} +18 -17
  33. package/public/functions/MC.removeListener.html +2 -1
  34. package/public/functions/elements.defineCE.html +1 -1
  35. package/public/functions/elements.getCE.html +1 -1
  36. package/public/functions/observables.observe.html +3 -3
  37. package/public/functions/selectors._d.html +1 -1
  38. package/public/functions/selectors._t.html +1 -1
  39. package/public/interfaces/MC.HTMLMcElement.html +2 -2
  40. package/public/interfaces/selectors.DSelector.html +55 -55
  41. package/public/interfaces/selectors.TSelector.html +37 -37
  42. package/public/modules/MC.html +3 -1
  43. package/public/modules/elements.html +1 -1
  44. package/public/modules/formValues.html +4 -4
  45. package/public/modules/observables.html +1 -1
  46. package/public/modules/selectors.html +1 -1
  47. package/public/types/observables.Observable.html +1 -1
  48. package/public/types/selectors.selection.html +1 -1
  49. package/public/types/selectors.singleSelector.html +1 -1
  50. package/src/MC.ts +65 -0
  51. package/src/elements.ts +10 -10
  52. package/src/formValues.ts +205 -203
  53. package/src/helpers.ts +9 -0
  54. package/src/observables.ts +64 -31
  55. package/src/test/Child.ts +21 -0
  56. package/src/test/Grandchild.ts +21 -0
  57. package/src/test/Grandparent.css +11 -0
  58. package/src/test/Grandparent.ts +21 -0
  59. package/src/test/Greatgrandchild.ts +42 -0
  60. package/src/test/Parent.ts +21 -0
  61. package/src/test/Testform.css +47 -0
  62. package/src/test/Testform.html +56 -0
  63. package/src/test/Testform.json +27 -0
  64. package/src/test/Testform.ts +159 -0
  65. package/src/test.ts +8 -5
  66. package/webpack.config.js +135 -61
  67. package/public/3d.html +0 -42
  68. package/public/MC.js +0 -271
  69. package/public/MC.js.map +0 -1
  70. package/public/MC.min.js +0 -407
  71. package/public/McEvent.js +0 -71
  72. package/public/McEvent.js.map +0 -1
  73. package/public/MicroComponents.svg +0 -15
  74. package/public/autoloader.js +0 -53
  75. package/public/autoloader.js.map +0 -1
  76. package/public/documentation/MC.md +0 -256
  77. package/public/documentation/ajaxian-1.png +0 -0
  78. package/public/documentation/ajaxian-2.png +0 -0
  79. package/public/documentation/ajaxian-3.png +0 -0
  80. package/public/documentation/comparision.md +0 -0
  81. package/public/documentation/elements.md +0 -276
  82. package/public/documentation/functional_requirements.md +0 -8
  83. package/public/documentation/history.md +0 -436
  84. package/public/documentation/how_tos.md +0 -0
  85. package/public/documentation/introduction.md +0 -0
  86. package/public/documentation/magic.md +0 -29
  87. package/public/documentation/proposal_draft.md +0 -37
  88. package/public/documentation/rnd0023-1.jpg +0 -0
  89. package/public/documentation/rnd0023-2.jpg +0 -0
  90. package/public/documentation/rnd0023-3.jpg +0 -0
  91. package/public/documentation/tB_react.md +0 -207
  92. package/public/documentation/usage.md +0 -142
  93. package/public/documentation/why.md +0 -25
  94. package/public/elements.js +0 -48
  95. package/public/elements.js.map +0 -1
  96. package/public/elements.min.js +0 -1
  97. package/public/fiddle/MicroComponents.svg +0 -15
  98. package/public/fiddle/fiddle.css +0 -0
  99. package/public/fiddle/fiddle.js +0 -0
  100. package/public/fiddle/index.html +0 -0
  101. package/public/formValues.js +0 -196
  102. package/public/formValues.js.map +0 -1
  103. package/public/formvValues.min.js +0 -1
  104. package/public/helpers.js +0 -105
  105. package/public/helpers.js.map +0 -1
  106. package/public/microcomponents.es3.js +0 -303
  107. package/public/microcomponents.es3.js.map +0 -1
  108. package/public/microcomponents.js +0 -9
  109. package/public/microcomponents.js.map +0 -1
  110. package/public/microcomponents.min.js +0 -1
  111. package/public/my-tag.css +0 -19
  112. package/public/observables.js +0 -239
  113. package/public/observables.js.map +0 -1
  114. package/public/observables.min.js +0 -1
  115. package/public/selectors.js +0 -971
  116. package/public/selectors.js.map +0 -1
  117. package/public/selectors.min.js +0 -1
  118. package/public/src/MC.ts +0 -413
  119. package/public/src/McEvent.ts +0 -96
  120. package/public/src/autoloader.ts +0 -98
  121. package/public/src/elements.ts +0 -76
  122. package/public/src/formValues.ts +0 -275
  123. package/public/src/helpers.ts +0 -140
  124. package/public/src/microcomponents.ts +0 -8
  125. package/public/src/observables.ts +0 -372
  126. package/public/src/selectors.ts +0 -1634
  127. package/public/src/test.ts +0 -174
  128. package/public/test.html +0 -23
  129. package/public/test.js +0 -79
  130. package/public/test.js.map +0 -1
package/src/MC.ts CHANGED
@@ -411,3 +411,68 @@ class DC extends McBase {
411
411
  }
412
412
 
413
413
  export { addListener, removeListener, McBase, MC, DC, McEvent };
414
+
415
+ let observer: MutationObserver | null = null;
416
+ const unresolved = new Map();
417
+
418
+ function loadit() {
419
+ document
420
+ .querySelectorAll(':not(:defined),[_mc]:not([_mc=""])')
421
+ .forEach((el) => {
422
+ const load: string[] = el.tagName.includes('-')
423
+ ? [el.tagName.toLowerCase()]
424
+ : el.getAttribute('_mc')!.trim().split(' ');
425
+
426
+ load.forEach((elementName) => {
427
+ let fileName: any = elementName.toLowerCase().split('-'), // intentional any
428
+ lastElement = fileName[fileName.length - 1],
429
+ renameLastElement =
430
+ lastElement[0].toUpperCase() + lastElement.slice(1);
431
+ fileName[fileName.length - 1] = renameLastElement;
432
+ fileName = fileName.join('/') + '.js';
433
+
434
+ // autoload web components
435
+ // TBD: _mc components
436
+ if (
437
+ el.tagName.includes('-') &&
438
+ !unresolved.has(el.tagName.toLowerCase())
439
+ ) {
440
+ const se: HTMLScriptElement = document.createElement('script');
441
+
442
+ unresolved.set(elementName, fileName);
443
+
444
+ se.setAttribute('src', fileName);
445
+ se.setAttribute('blocking', 'render');
446
+ se.setAttribute('type', 'module');
447
+ se.onload = () => {
448
+ // console.info('loaded', s);
449
+ unresolved.delete(elementName);
450
+ //console.log(unresolved);
451
+ };
452
+
453
+ document.head.append(se);
454
+ }
455
+ });
456
+ //console.log(unresolved);
457
+ });
458
+ }
459
+
460
+ let autoloadEnabled: boolean = false;
461
+
462
+ export function autoload(enable: boolean = true): boolean {
463
+ if (!enable) {
464
+ observer?.disconnect();
465
+ observer = null;
466
+ return autoloadEnabled;
467
+ }
468
+
469
+ autoloadEnabled = enable;
470
+ observer = new MutationObserver(loadit);
471
+
472
+ setTimeout(() => {
473
+ observer!.observe(document.body, { childList: true, subtree: true });
474
+ loadit();
475
+ }, 5);
476
+
477
+ return autoloadEnabled;
478
+ }
package/src/elements.ts CHANGED
@@ -1,7 +1,7 @@
1
- "use strict";
1
+ 'use strict';
2
2
 
3
- import { DC } from "./MC.js";
4
- import { kebabToPascal } from "./helpers.js";
3
+ import { DC } from './MC.js';
4
+ import { kebabToPascal } from './helpers.js';
5
5
 
6
6
  class CeBaseClass extends HTMLElement {
7
7
  constructor() {
@@ -9,19 +9,19 @@ class CeBaseClass extends HTMLElement {
9
9
  }
10
10
 
11
11
  connectedCallback() {
12
- (DC as any).trigger(this, "Connected");
12
+ (DC as any).trigger(this, 'Connected');
13
13
  }
14
14
 
15
15
  disconnectedCallback() {
16
- (DC as any).trigger(this, "Disconnected");
16
+ (DC as any).trigger(this, 'Disconnected');
17
17
  }
18
18
 
19
19
  adoptedCallback() {
20
- (DC as any).trigger(this, "Adopted");
20
+ (DC as any).trigger(this, 'Adopted');
21
21
  }
22
22
 
23
23
  attributeChangedCallback(name: string, oldValue: any, newValue: any) {
24
- (DC as any).trigger(this, "AttributeChanged", { name, oldValue, newValue });
24
+ (DC as any).trigger(this, 'AttributeChanged', { name, oldValue, newValue });
25
25
  }
26
26
  }
27
27
 
@@ -29,7 +29,7 @@ function createNamedClass(
29
29
  name: string,
30
30
  ClassBody: { new (...args: any[]): any }
31
31
  ) {
32
- return Object.defineProperty(ClassBody, "name", { value: name });
32
+ return Object.defineProperty(ClassBody, 'name', { value: name });
33
33
  }
34
34
 
35
35
  export function defineCE(
@@ -42,7 +42,7 @@ export function defineCE(
42
42
  return;
43
43
  }
44
44
 
45
- if (!tagName.includes("-")) {
45
+ if (!tagName.includes('-')) {
46
46
  throw new Error(
47
47
  'createCustomElement: tagName must contain at least one hyphen ("-").'
48
48
  );
@@ -60,7 +60,7 @@ export function defineCE(
60
60
  constructor(data?: any) {
61
61
  super();
62
62
  let instance = new DefinitionClass(this, data);
63
- (DC as any).add(this, name, instance);
63
+ DC.add(this, name, instance);
64
64
  }
65
65
 
66
66
  static get observedAttributes() {
package/src/formValues.ts CHANGED
@@ -1,275 +1,277 @@
1
- "use strict";
1
+ 'use strict';
2
2
 
3
- import { LooseObject } from './helpers.js'
4
- import { MC, addListener } from './MC.js'
3
+ import { LooseObject, copyGettersSetters } from './helpers.js';
4
+ import { DC, addListener } from './MC.js';
5
+ import { observe } from './observables.js';
5
6
 
6
7
  type inputTypes = HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement;
7
8
 
8
- const getInputName = ( e: HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement ): string => {
9
+ const getInputName = (
10
+ e: HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement
11
+ ): string => {
12
+ return e.tagName.toLowerCase();
13
+ };
9
14
 
10
- let ret = e instanceof HTMLInputElement
11
- ? 'input'
12
- : e instanceof HTMLSelectElement
13
- ? 'select'
14
- : e instanceof HTMLTextAreaElement
15
- ? 'textarea'
16
- : ''
17
- ;
18
-
19
- return ret;
20
- }
21
-
22
- abstract class InputBase{
23
- constructor( e: any ){
24
- }
15
+ abstract class InputBase {
16
+ constructor(e: inputTypes) {}
25
17
 
26
18
  abstract get val(): any;
27
19
 
28
- abstract set val( value: any );
29
-
20
+ abstract set val(value: any);
30
21
  }
31
22
 
32
- const getInputHandlers = ( e: HTMLElement | ShadowRoot ): LooseObject => {
33
-
34
- let
35
- //inputList = ( Array.from( e.querySelectorAll('*') ) as HTMLElement[] ).filter( i => isInputElement(i) ),
36
- inputList = [ ...( e || document).querySelectorAll('input,select,textarea') ],
37
- handlers: LooseObject = {};
38
-
39
- inputList.forEach( (i) => {
40
- const
41
- name: string = ( i as inputTypes ).getAttribute('name') || 'undefined';
42
-
43
- if ( name ){
44
- let h: InputBase;
45
- switch ( getInputName( i as inputTypes ) ){
46
- case 'input':
47
- //console.log( i, 'is HTMLInputElement');
48
- h = new InputHandler( i as HTMLInputElement, e ); // e = element to search radios in = radioBase
49
- Object.defineProperty( handlers, name, {
50
- enumerable: true,
51
- configurable: true,
52
- get: (): any => { return h.val },
53
- set: ( value: any ) => { h.val = value }
54
- });
55
- break;
56
- case 'select':
57
- //console.log( i, 'is HTMLSelectElement');
58
- h = new SelectHandler( i as HTMLSelectElement );
59
- Object.defineProperty( handlers, name, {
60
- enumerable: true,
61
- configurable: true,
62
- get: (): any => { return h.val },
63
- set: ( value: any ) => { h.val = value }
64
- });
65
- break;
66
- case 'textarea':
67
- //console.log( i, 'is HTMLTextAreaElement');
68
- h = new TextAreaHandler( i as HTMLTextAreaElement );
69
- Object.defineProperty( handlers, name, {
70
- enumerable: true,
71
- configurable: true,
72
- get: (): any => { return h.val },
73
- set: ( value: any ) => { h.val = value }
74
- });
75
- break;
76
- default:
77
- console.warn('handler missing:', name, 'for', i);
78
- break;
79
- }
80
- }
81
- });
82
-
83
- return handlers;
84
- }
85
-
86
- class InputHandler extends InputBase {
87
-
23
+ class RadioHandler extends InputBase {
88
24
  #e: HTMLInputElement;
89
- #type: string;
90
- #radioBase: any;
25
+ #form: HTMLFormElement;
91
26
 
92
- constructor( e: HTMLInputElement, radioBase?: HTMLElement | ShadowRoot ){
93
- super( e );
27
+ constructor(e: HTMLInputElement, form: HTMLFormElement) {
28
+ super(e);
94
29
  this.#e = e;
95
- this.#type = e.type;
96
- this.#radioBase = radioBase;
30
+ this.#form = form;
97
31
  }
98
32
 
99
- get val(): any{
100
- let that = this,
101
- type = that.#type,
102
- ret: any;
103
-
104
- switch (type){
105
- case 'radio':
106
- const check = [ ...(this.#radioBase || document).querySelectorAll( `input[type="radio"][name="${ this.#e.getAttribute('name') }"]` ) ]
107
- .filter( e => e.checked );
108
- if ( !check.length ) return '';
109
- ret = check?.[0];
110
- return ret.value;
111
- case 'checkbox':
112
- return that.#e.checked;
113
- default:
114
- return that.#e.value;
115
- break;
116
- }
33
+ get val(): string {
34
+ let ret = new FormData(this.#form).get(this.#e.name);
117
35
 
118
- return '';
36
+ //console.log('radio[', this.#e.name, '] = "' + ret + '"');
37
+ return ret as string;
119
38
  }
120
39
 
121
- set val( value: any ){
122
- let that = this,
123
- type = that.#type,
124
- ret: any;
125
-
126
- switch (type){
127
- case 'radio':
128
- const
129
- radios = [ ...(this.#radioBase || document).querySelectorAll( `input[type="radio"][name="${ this.#e.getAttribute('name') }"]` ) ];
130
-
131
- // console.log('set radios', selection, this.#radioBase, radios.array );
132
-
133
- if ( !radios.length ) return;
40
+ set val(value: string) {
41
+ let arr = [
42
+ ...this.#form.querySelectorAll(
43
+ `input[type="radio][name="${this.#e.name}"]`
44
+ ),
45
+ ] as HTMLInputElement[];
46
+
47
+ (
48
+ arr
49
+ .filter((e) => e.getAttribute('value') === value)
50
+ .shift() as HTMLInputElement
51
+ ).checked = true;
52
+ }
53
+ }
134
54
 
135
- if ( value === '' ){ // uncheck all
136
- radios.forEach( r => { if (r.checked) r.checked = false } );
137
- //console.log('unset all radios', radios.array );
138
- return;
139
- }
55
+ class CheckboxHandler extends InputBase {
56
+ #e: HTMLInputElement;
140
57
 
141
- const setRadioElement = radios.filter( r => r.getAttribute('value') === value );
58
+ constructor(e: HTMLInputElement) {
59
+ super(e);
60
+ this.#e = e;
61
+ }
142
62
 
143
- if ( !setRadioElement.length ) return;
63
+ get val(): boolean {
64
+ return this.#e.checked;
65
+ }
144
66
 
145
- // console.log('set this radio', setRadioElement.array );
67
+ set val(value: boolean) {
68
+ this.#e.checked = value;
69
+ }
70
+ }
146
71
 
147
- (setRadioElement?.[0] as HTMLInputElement).checked = true;
72
+ class InputHandler extends InputBase {
73
+ #e: HTMLInputElement;
148
74
 
149
- // console.log('done', setRadioElement.array );
150
- return;
151
- break;
152
- case 'checkbox':
153
- that.#e.checked = value;
154
- break;
155
- default:
156
- that.#e.value = value;
157
- break;
158
- }
75
+ constructor(e: HTMLInputElement) {
76
+ super(e);
77
+ this.#e = e;
78
+ }
159
79
 
160
- return;
80
+ get val(): string {
81
+ return this.#e.value;
161
82
  }
162
83
 
84
+ set val(value: string) {
85
+ this.#e.value = value;
86
+ }
163
87
  }
164
88
 
165
89
  class SelectHandler extends InputBase {
166
-
167
90
  #e: HTMLSelectElement;
168
91
  #multi: boolean = false;
169
92
 
170
- constructor( e: HTMLSelectElement ){
171
- super( e );
93
+ constructor(e: HTMLSelectElement) {
94
+ super(e);
172
95
  this.#e = e;
173
- this.#multi = e.type === 'select-multiple';
96
+ this.#multi = e.multiple;
174
97
  }
175
98
 
176
- get val(): string[] | string{
177
- const
178
- that = this,
99
+ get val(): string[] | string {
100
+ const that = this,
179
101
  ret: string[] = [];
180
102
 
181
103
  // get all options
182
- const options = [ ...that.#e.querySelectorAll('option') ]
183
- .filter( o => o.selected )
184
- .forEach( o => { if ( o.selected ) ret.push( o.value ) } );
104
+ const options = [...that.#e.querySelectorAll('option')]
105
+ .filter((o) => o.selected)
106
+ .forEach((o) => {
107
+ if (o.selected) ret.push(o.value);
108
+ });
185
109
 
186
- if ( this.#multi ) return ret;
110
+ if (this.#multi) return ret;
187
111
  return ret.length ? ret[0] : '';
188
112
  }
189
113
 
190
- set val( value: string[] | string ){
191
- const
192
- that = this;
193
-
194
- value = typeof value === 'string' ? [ value ] : value;
114
+ set val(value: string[] | string) {
115
+ const that = this;
195
116
 
196
- //console.log('set values', value );
117
+ value = typeof value === 'string' ? [value] : value;
197
118
 
198
119
  // set all options
199
- const options = [ ...that.#e.querySelectorAll('option') ]
200
- .forEach( o => {
201
- if ( value.indexOf( o.value ) > -1 ) {
202
- o.setAttribute( 'selected', 'selected' )
203
- o.selected = true;
204
- } else {
205
- o.removeAttribute( 'selected' )
206
- o.selected = false;
207
- }
208
- });
120
+ const options = [...that.#e.querySelectorAll('option')].forEach((o) => {
121
+ if (value.indexOf(o.value) > -1) {
122
+ o.setAttribute('selected', 'selected');
123
+ o.selected = true;
124
+ } else {
125
+ o.removeAttribute('selected');
126
+ o.selected = false;
127
+ }
128
+ });
209
129
 
210
130
  return;
211
131
  }
212
-
213
132
  }
214
133
 
215
134
  class TextAreaHandler extends InputBase {
216
- #e: HTMLTextAreaElement
217
- constructor( e: HTMLTextAreaElement ){
135
+ #e: HTMLTextAreaElement;
136
+ constructor(e: HTMLTextAreaElement) {
218
137
  super(e);
219
138
  this.#e = e;
220
139
  }
221
140
 
222
- get val(): string{
223
- return this.#e.value;
141
+ get val(): string {
142
+ return this.#e.value || '';
224
143
  }
225
144
 
226
- set val( value: string ){
145
+ set val(value: string) {
227
146
  this.#e.value = value;
228
147
  return;
229
148
  }
230
-
231
149
  }
232
150
 
233
- export const formValues = ( target: HTMLElement | ShadowRoot, values: Object = {}, mc?: typeof MC, observable?: string ): LooseObject => {
234
-
235
- //console.log( 'values(', target, ',', values, ',', observable, ')' );
151
+ const getInputHandlers = (e: HTMLElement | ShadowRoot): LooseObject => {
152
+ let inputList = [
153
+ ...(e || document).querySelectorAll('input,select,textarea'),
154
+ ],
155
+ handlers: LooseObject = {};
156
+
157
+ inputList.forEach((i) => {
158
+ const name: string = (i as inputTypes).getAttribute('name') || 'undefined';
159
+ // console.log(name);
160
+ if (name) {
161
+ let h: InputBase,
162
+ type = (i as HTMLInputElement).type,
163
+ handler: any;
164
+ switch (getInputName(i as inputTypes)) {
165
+ case 'input':
166
+ switch (type) {
167
+ case 'radio':
168
+ handler = new RadioHandler(
169
+ i as HTMLInputElement,
170
+ (e.constructor === HTMLFormElement
171
+ ? e
172
+ : e.querySelector('form')) as HTMLFormElement
173
+ );
174
+ DC.add(i, name, handler);
175
+ break;
176
+ case 'checkbox':
177
+ handler = new CheckboxHandler(i as HTMLInputElement);
178
+ DC.add(i, name, handler);
179
+ break;
180
+ default:
181
+ handler = new InputHandler(i as HTMLInputElement);
182
+ DC.add(i, name, handler);
183
+ }
184
+
185
+ Object.defineProperty(handlers, name, {
186
+ enumerable: true,
187
+ configurable: true,
188
+ get: (): any => {
189
+ return handler.val;
190
+ },
191
+ set: (value: any) => {
192
+ if (handler.val !== value) {
193
+ handler.val = value;
194
+ }
195
+ },
196
+ });
197
+
198
+ break;
199
+ case 'select':
200
+ handler = new SelectHandler(i as HTMLSelectElement);
201
+ DC.add(i, name, handler);
202
+ Object.defineProperty(handlers, name, {
203
+ enumerable: true,
204
+ configurable: true,
205
+ get: (): any => {
206
+ return handler.val;
207
+ },
208
+ set: (value: any) => {
209
+ if (handler.val !== value) {
210
+ handler.val = value;
211
+ }
212
+ },
213
+ });
214
+ break;
215
+ case 'textarea':
216
+ handler = new TextAreaHandler(i as HTMLTextAreaElement);
217
+ DC.add(i, name, handler);
218
+ Object.defineProperty(handlers, name, {
219
+ enumerable: true,
220
+ configurable: true,
221
+ get: (): any => {
222
+ return handler.val;
223
+ },
224
+ set: (value: any) => {
225
+ if (handler.val !== value) {
226
+ handler.val = value;
227
+ }
228
+ },
229
+ });
230
+ break;
231
+ default:
232
+ console.warn(
233
+ 'handler missing:',
234
+ name,
235
+ 'for',
236
+ i.tagName.toLowerCase(),
237
+ i
238
+ );
239
+ break;
240
+ }
241
+ }
242
+ });
236
243
 
237
- //console.log( 'values()', values );
238
- let handlers = getInputHandlers( target );
244
+ return handlers;
245
+ };
239
246
 
240
- function updateForm( values: Object ){
241
- Object
242
- .keys( values )
243
- .forEach( (key) => {
244
- if ( handlers.hasOwnProperty(key) && values.hasOwnProperty(key) ) {
245
- //console.log( 'set value', key, values[key] );
246
- handlers[key] = (values as LooseObject)[key];
247
- }
248
- });
249
- }
247
+ export class FormValues {
248
+ constructor(
249
+ targetObject: LooseObject,
250
+ propertyName: string,
251
+ dom: HTMLElement | ShadowRoot
252
+ ) {
253
+ let that = this,
254
+ handlers = getInputHandlers(dom);
250
255
 
251
- if ( Object.keys(values).length > 0 ){
252
- updateForm( values );
253
- }
256
+ targetObject[propertyName] = Object.assign({}, handlers);
254
257
 
255
- //console.log( 'set observable on form change', observable );
256
- if ( observable !== undefined ){
257
- let obs = ( mc as LooseObject )[observable];
258
- if ( !obs.constructor?.hasFormHandler ){
259
- obs.constructor.hasFormHandler = true;
260
- obs.observe( updateForm );
261
- }
258
+ observe(targetObject, propertyName);
262
259
 
263
- ( mc as any)[observable].observe( () => { } );
260
+ copyGettersSetters(handlers, targetObject[propertyName]);
264
261
 
265
- [ ...target.querySelectorAll('input, textarea, select') ].forEach( ( e ) => {
266
- addListener( (e as HTMLElement), 'keyup', () => { ( mc as any)[observable] = structuredClone( Object.assign( handlers ) ) } );
267
- addListener( (e as HTMLElement), 'change', () => { ( mc as any)[observable] = structuredClone( Object.assign( handlers ) ) } );
268
- if ( (e as HTMLElement) instanceof HTMLSelectElement ){
269
- addListener( (e as HTMLElement), 'select', () => { ( mc as any)[observable] = structuredClone( Object.assign( handlers ) ) } );
270
- };
262
+ [...dom.querySelectorAll('input, textarea, select')].forEach((input) => {
263
+ addListener(input as inputTypes, 'keyup', (ev: Event) => {
264
+ //console.log('keyup', ev);
265
+ targetObject[propertyName].notify();
266
+ });
267
+ addListener(input as HTMLElement, 'change', (ev: Event) => {
268
+ //console.log('change', ev);
269
+ targetObject[propertyName].notify();
270
+ });
271
+ addListener(input as inputTypes, 'select', (ev: Event) => {
272
+ //console.log('select', ev);
273
+ targetObject[propertyName].notify();
274
+ });
271
275
  });
272
276
  }
273
-
274
- return observable ? ( mc as any)[observable] : Object.assign( {}, handlers );
275
277
  }
package/src/helpers.ts CHANGED
@@ -138,3 +138,12 @@ export function htmlToElements(html: string): HTMLElement[] {
138
138
 
139
139
  return Array.from(template.content.childNodes) as HTMLElement[];
140
140
  }
141
+
142
+ export function copyGettersSetters(source: LooseObject, target: LooseObject) {
143
+ const descriptors = Object.getOwnPropertyDescriptors(source);
144
+ for (const [key, descriptor] of Object.entries(descriptors)) {
145
+ if ('get' in descriptor || 'set' in descriptor) {
146
+ Object.defineProperty(target, key, descriptor);
147
+ }
148
+ }
149
+ }