@twobirds/microcomponents 0.0.46 → 0.0.50

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 (100) 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 +206 -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 +72 -33
  22. package/dist/selectors.min.js +1 -1
  23. package/dist/test.ts +14 -14
  24. package/package.json +1 -1
  25. package/public/Grandparent.css +13 -0
  26. package/public/Grandparent.js +338 -0
  27. package/public/MC.js +43 -0
  28. package/public/MC.js.map +1 -1
  29. package/public/MC.min.js +44 -0
  30. package/public/TestForm.css +47 -0
  31. package/public/TestForm.html +56 -0
  32. package/public/TestForm.js +56 -0
  33. package/public/TestForm.json +27 -0
  34. package/public/Testform.js +149 -0
  35. package/public/classes/MC.DC.html +13 -13
  36. package/public/classes/MC.MC.html +7 -7
  37. package/public/classes/MC.McBase.html +4 -4
  38. package/public/classes/MC.McEvent.html +13 -13
  39. package/public/documentation/MC.md +380 -166
  40. package/public/documentation/observe.md +317 -0
  41. package/public/elements.js +9 -9
  42. package/public/elements.js.map +1 -1
  43. package/public/elements.min.js +1 -1
  44. package/public/formValues.js +142 -133
  45. package/public/formValues.js.map +1 -1
  46. package/public/formvValues.min.js +1 -1
  47. package/public/functions/MC.addListener.html +1 -1
  48. package/public/functions/MC.removeListener.html +1 -1
  49. package/public/functions/elements.defineCE.html +1 -1
  50. package/public/functions/elements.getCE.html +1 -1
  51. package/public/functions/formValues.formValues.html +1 -1
  52. package/public/functions/observables.observe.html +1 -1
  53. package/public/functions/selectors._d.html +1 -1
  54. package/public/functions/selectors._t.html +1 -1
  55. package/public/helpers.js +8 -0
  56. package/public/helpers.js.map +1 -1
  57. package/public/interfaces/MC.HTMLMcElement.html +2 -2
  58. package/public/interfaces/selectors.DSelector.html +55 -55
  59. package/public/interfaces/selectors.TSelector.html +37 -37
  60. package/public/microcomponents.min.js +1 -1
  61. package/public/modules/MC.html +1 -1
  62. package/public/modules/elements.html +1 -1
  63. package/public/modules/formValues.html +1 -1
  64. package/public/modules/observables.html +1 -1
  65. package/public/modules/selectors.html +1 -1
  66. package/public/observables.js +39 -21
  67. package/public/observables.js.map +1 -1
  68. package/public/observables.min.js +1 -1
  69. package/public/selectors.min.js +1 -1
  70. package/public/src/MC.ts +65 -0
  71. package/public/src/elements.ts +10 -10
  72. package/public/src/formValues.ts +206 -203
  73. package/public/src/helpers.ts +9 -0
  74. package/public/src/observables.ts +72 -33
  75. package/public/src/test.ts +14 -14
  76. package/public/test/Grandparent.js +1 -0
  77. package/public/test/Testform.js +1 -0
  78. package/public/test.html +5 -1
  79. package/public/test.js +9 -11
  80. package/public/test.js.map +1 -1
  81. package/public/types/observables.Observable.html +1 -1
  82. package/public/types/selectors.selection.html +1 -1
  83. package/public/types/selectors.singleSelector.html +1 -1
  84. package/src/MC.ts +65 -0
  85. package/src/elements.ts +10 -10
  86. package/src/formValues.ts +206 -203
  87. package/src/helpers.ts +9 -0
  88. package/src/observables.ts +72 -33
  89. package/src/test/Child.ts +21 -0
  90. package/src/test/Grandchild.ts +21 -0
  91. package/src/test/Grandparent.css +11 -0
  92. package/src/test/Grandparent.ts +21 -0
  93. package/src/test/Greatgrandchild.ts +42 -0
  94. package/src/test/Parent.ts +21 -0
  95. package/src/test/Testform.css +47 -0
  96. package/src/test/Testform.html +56 -0
  97. package/src/test/Testform.json +27 -0
  98. package/src/test/Testform.ts +159 -0
  99. package/src/test.ts +14 -14
  100. package/webpack.config.js +135 -61
@@ -1,256 +1,470 @@
1
- # Micro Components <span style="float:right; height:1em;"><img height="24px" src="./MicroComponents.svg" /></span>
1
+ # Microcomponent Framework Documentation <span style="float:right; height:1em;"><img height="24px" src="./MicroComponents.svg" /></span>
2
+
3
+ This document details a lightweight JavaScript framework for creating and managing "microcomponents" (MCs) associated with DOM elements or other microcomponents. It allows you to define reusable components and attach them to build complex functionalities.
4
+
5
+ The framework exports 2 main classes:
6
+
7
+ - **MC**: Micro Component. The base component class, suitable for logic that doesn't directly interact with the DOM or for use on the server.
8
+ - **DC**: DOM Component. Extends `MC` and adds DOM-specific methods (like traversal). Use this for components that need to interact with the browser's DOM.
9
+
10
+ ## Table of Contents
11
+
12
+ - [Usage Guidance](#usage-guidance)
13
+ - [Core Concepts](#core-concepts)
14
+ - [Microcomponents (MCs)](#microcomponents-mcs)
15
+ - [`_mc` Property](#_mc-property)
16
+ - [DOM Association & `target`](#dom-association--target)
17
+ - [Event System](#event-system)
18
+ - [Observables (Mention)](#observables-mention)
19
+ - [DOM Traversal](#dom-traversal)
20
+ - [Autoloading Concept](#autoloading-concept)
21
+ - [Important Rule](#important-rule)
22
+ - [Framework Classes](#framework-classes)
23
+ - [Not Exported: `McBase` (Superclass)](#not-exported-mcbase-superclass)
24
+ - [Exported: `MC` Class](#exported-mc-class)
25
+ - [Exported: `DC` Class](#exported-dc-class)
26
+ - [Examples](#examples)
27
+ - [Typical Workflow](#typical-workflow)
28
+ - [Attach Micro Components (`DC.add`)](#attach-micro-components-dcadd)
29
+ - [Remove Micro Components (`DC.remove`)](#remove-micro-components-dcremove)
30
+ - [Retrieve Micro Components](#retrieve-micro-components)
31
+ - [Triggering Events](#triggering-events)
32
+ - [Retrieving Inner Micro Components](#retrieving-inner-micro-components)
33
+ - [Navigating Parent/Ancestor MCs](#navigating-parentancestor-mcs)
34
+ - [Retrieving Child/Descendant MCs](#retrieving-childdescendant-mcs)
35
+ - [Auto-attaching DOM Listeners](#auto-attaching-dom-listeners)
36
+ - [Lifecycle Events](#lifecycle-events)
37
+ - [Init](#init)
38
+ - [Destroy (TBD)](#destroy-tbd)
39
+ - [Helper Functions (Internal)](#helper-functions-internal)
40
+ - [`isBrowser()`](#isbrowser)
41
+ - [`nativeEventNames`](#nativeeventnames)
42
+ - [`getMicroComponents(...)`](#getmicrocomponents)
43
+ - [`traverseNodes(...)`](#traversenodes)
44
+ - [`isDOM(...)`](#isdom)
45
+ - [`addListener(...)`](#addlistener)
46
+ - [`removeListener(...)`](#removelistener)
47
+ - [`add(...)`](#add)
48
+ - [`remove(...)`](#remove)
49
+ - [`trigger(...)`](#trigger)
50
+ - [`init(...)`](#init-helper)
51
+ - [`autoAttachListeners(...)`](#autoattachlisteners)
52
+ - [`bubbleEvent(...)`](#bubbleevent)
53
+ - [Autoloading Implementation](#autoloading-implementation)
54
+ - [`autoload(enable?)`](#autoload)
55
+ - [`loadit()`](#loadit)
56
+ - [Interfaces and Types](#interfaces-and-types)
57
+ - [`LooseObject`](#looseobject)
58
+ - [`McEvent`](#mcevent)
59
+ - [`HTMLMcElement`](#htmlmcelement)
2
60
 
3
- This system allows you to to define **Micro Components** and attach them to DOM elements or other Micro Components.
61
+ ## Usage Guidance
4
62
 
5
- The module exports 2 classes:
6
- - **MC**: Micro Component ( not DOM related, works on the server also )
7
- - **DC**: Dom Component ( extends MC and adds DOM related methods, client only )
63
+ - **If your component needs to access or manipulate the DOM** (e.g., find other components in the DOM, attach listeners directly, read element properties), **your class MUST extend `DC`**. This is client-side only.
64
+ - **Otherwise** (e.g., for pure logic, state management, or server-side usage), **your class should extend `MC`**.
65
+
66
+ Think **DRY** (Don't Repeat Yourself) and **SOLID** principles when designing your components.
8
67
 
9
- # Usage
68
+ ## Core Concepts
10
69
 
11
- - **If your functionality needs to access the DOM**, e.g. to find other DC instances, **your class extends DC**.
12
- - **Otherwise** - and always on the server - **your class extends MC**.
70
+ Fundamental ideas behind the framework.
13
71
 
14
- In any case, your class instances will contain a property **"_mc"** where you can (but don't have to) put in other MCs.
72
+ ### Microcomponents (MCs)
15
73
 
16
- Also your class instances will have a readonly **"target"** property that is back reference to the instance they are contained in.
74
+ Plain JavaScript objects or class instances (extending `MC` or `DC`) that encapsulate behavior and state. They can be attached to DOM elements (via `DC`) or nested within other MCs.
17
75
 
18
- - if your class extends **DC: "target"** will refer the **DOM HTMLElement your instance resides in**.
19
- - if your class extends **MC: "target"** will refer the **parent MC your instance resides in**.
76
+ ### `_mc` Property
20
77
 
21
- As an application programmer you should understand **MC** and **DC** methods and the structure they provide:
22
- - **MC** encapsule functionality in a reusable way. Think DRY, and SOLID because we talk about objects.
23
- - **MC** can use observables to provide data driven workflow between multiple MCs.
24
- - **DC** use observables and formValues to provide 1-way and 2-way binding to the DOM.
25
- - **DC** have selectors to find other DCs in the DOM.
78
+ A special property attached to `HTMLElement` instances (when using `DC.add`) or parent `MC`/`DC` instances. It acts as an object container (`{ key: mcInstance, ... }`) holding one or more named microcomponent instances.
26
79
 
27
- # Rules
80
+ - On HTMLElements, the presence of attached components is also marked by a `_mc` attribute for CSS selection and discovery. This attribute is added by `DC.add` and removed by `DC.remove` when the `_mc` object becomes empty.
28
81
 
29
- - **Your own application code MUST NOT overwrite the properties and methods in the classes below.**
30
- - If you do it anyway, you do it on your own risk.
82
+ ### DOM Association & `target`
31
83
 
32
- # Not Exported
84
+ Each microcomponent instance has a read-only `target` property providing a back-reference:
33
85
 
34
- ## **McBase** Superclass
86
+ - If the instance extends **`DC`** and was added via `DC.add`, `target` refers to the **DOM HTMLElement** it's attached to.
87
+ - If the instance extends **`MC`** (or `DC`) and is nested within another component's `_mc` property, `target` refers to the **parent MC/DC instance**.
35
88
 
36
- **Instance Properties**
37
- - `.target`: readonly, a getter returning the DOM element or parent MC instance your instance resides in
89
+ This reference is managed using `WeakRef` internally by `McBase` to prevent circular references and potential memory leaks.
38
90
 
39
- **Constructor:**
40
- - calls `init()`: triggers the 'init' lifecycle event, also recursively into the inner '._mc' structure.
41
- - calls `autoAttachListeners()`: methods in your class code that start with "on[A-Z]" or "one[A-Z]" and describe native DOM events (e.g. "onClick") will be added to the DOM Element as listeners.
91
+ ### Event System
42
92
 
43
- - **Instance Methods:**
44
- - `.trigger( eventName, data )`: runs callback methods.
93
+ A custom event system using the `McEvent` class allows components to communicate.
45
94
 
46
- # Exported:
95
+ - **Triggering:** Events are dispatched using the `trigger` method:
96
+ - `DC.trigger(targetElement, ...)`: Dispatches to all MCs on a specific DOM element. Handles bubbling (`u`/`d`).
97
+ - `this.trigger(...)`: Dispatches within the current MC instance and its potential nested MCs. Can also initiate bubbling if the instance is a `DC`.
98
+ - **Handling:**
99
+ - Components listen for events by defining methods named `onEventName` or `oneEventName` (for once-off handling).
100
+ - These are automatically detected by `autoAttachListeners`.
101
+ - Native DOM events matching this pattern on `DC` instances are also automatically bound to the target element.
102
+ - **Bubbling:** Events triggered via `DC.trigger` or `dcInstance.trigger` can bubble:
103
+ - `'l'`: Local only (default). Handlers on the target element's/instance's MCs are executed.
104
+ - `'u'`: Upwards. Event propagates to MCs on parent elements (DOM tree).
105
+ - `'d'`: Downwards. Event propagates to MCs on descendant elements (DOM tree).
106
+ - Combinations are possible (e.g., `'lu'`, `'ldu'`). Bubbling (`u`/`d`) occurs asynchronously via `setTimeout`.
47
107
 
48
- ## **MC** Class, extends McBase
108
+ ### Observables (Mention)
49
109
 
50
- **Instance Properties**
51
- - `.target`: (inherited from McBase)
52
- - `._mc`: a hash object that contains inner micro components
110
+ - MCs can utilize observables (implementation not detailed here) for data-driven workflows.
111
+ - `DC` components can leverage observables and potentially form values for 1-way or 2-way data binding with the DOM.
112
+
113
+ ### DOM Traversal
53
114
 
54
- - **Instance Methods:**
55
- - `.trigger( eventName, data )`: (inherited from McBase)
115
+ The `DC` class provides methods (`parent`, `ancestors`, `children`, `descendants`) to find related `DC` instances attached to elements elsewhere in the DOM hierarchy, skipping over elements without attached microcomponents.
56
116
 
57
- ## **DC** Class, extends McBase
117
+ ### Autoloading Concept
58
118
 
59
- - **Static Methods:**
60
- - `DC.add( DomElement, key, mc)`: Add a DC to an HTMLElement.
61
- - `DC.remove( DomElement, key )`: Remove a DC from an HTMLElement.
62
- - `DC.trigger( eventName, DomElement, data, bubble )`: trigger an event, handles directional traversal in the DOM.
119
+ An optional feature (`autoload()`) that automatically detects specific HTML tags (e.g., `<my-component>`) or elements with an `_mc="MyComponent"` attribute and attempts to dynamically load the corresponding JavaScript module (e.g., `/my/Component.js`).
63
120
 
64
- **Instance Properties**
65
- - `.target`: (inherited from McBase)
66
- - `._mc`: a hash object that contains inner micro components
121
+ ### Important Rule
67
122
 
68
- - **Instance Methods:**
69
- - `.parent(search?)`: Get parent DCs.
70
- - `.ancestors(search?)`: Get ancestor DCs.
71
- - `.children(search?)`: Get child DCs.
72
- - `.descendants(search?)`: Get descendant DCs.
73
- - `.trigger( eventName, data, bubble )`: trigger an event on "this", handles directional bubbling in the DOM.
123
+ **Your own application code MUST NOT overwrite the core properties and methods provided by the `McBase`, `MC`, and `DC` classes (like `_mc`, `target`, `trigger`, `parent`, etc.). Doing so may break framework functionality.**
74
124
 
75
- # Examples
125
+ ## Framework Classes
76
126
 
77
- ## Typical Workflow
127
+ ### Not Exported: `McBase` (Superclass)
78
128
 
79
- 1. **Attach DCs** to HTMLElements using `DC.add()`.
80
- 2. **Access** other DCs by their property key or navigating through DOM (e.g., `ancestors()`, `children()`, etc.) **and use their inner functionality**.
129
+ The internal base class for `MC` and `DC`. You don't extend this directly.
81
130
 
82
- ### Attach Micro Components to a DOM element
131
+ - **Instance Properties**:
132
+ - `.target`: Read-only getter returning the containing DOM element (for DCs added via `DC.add`) or parent MC/DC instance (for nested MCs). Uses `WeakRef`.
133
+ - **Constructor Behavior**:
134
+ - Initializes the `.target` reference.
135
+ - Calls `init(this)`: Triggers the 'Init' lifecycle event asynchronously.
136
+ - Calls `autoAttachListeners(this)`: Sets up automatic event listeners based on method names (`onEventName`, `oneEventName`).
137
+ - **Instance Methods**:
138
+ - `.trigger(eventName, data)`: Base trigger logic used by `MC` and `DC`.
83
139
 
84
- To attach a micro component to an HTML element, use the `DC.add()` static function.
140
+ ### Exported: `MC` Class
141
+
142
+ Base class for non-DOM or server-side components. Extends `McBase`.
143
+
144
+ - **Instance Properties**:
145
+ - `.target`: (Inherited from `McBase`) Refers to the parent MC/DC instance it's nested within.
146
+ - `._mc`: An object `{}` to hold nested microcomponent instances.
147
+ - **Instance Methods**:
148
+ - `.trigger(eventName, data)`: (Inherited) Triggers events locally within the instance and its nested `_mc` structure. Does not handle DOM bubbling.
149
+
150
+ ### Exported: `DC` Class
151
+
152
+ Class for DOM-aware components. Extends `McBase`. **Client-side only.**
153
+
154
+ - **Static Methods**:
155
+ - `DC.add(domElement, key, mcInstance)`: Attaches an `mcInstance` (should be a `DC` or `MC`) to a `domElement` under the specified `key`. Creates `domElement._mc` if needed and sets the `_mc` attribute.
156
+ - `DC.remove(domElement, key)`: Removes the MC instance associated with `key` from `domElement._mc`. Removes the `_mc` attribute if the collection becomes empty.
157
+ - `DC.trigger(domElement, eventName, data, bubble)`: Triggers an event on all MCs attached to `domElement`. Handles DOM bubbling (`'l'`, `'u'`, `'d'`).
158
+ - **Instance Properties**:
159
+ - `.target`: (Inherited from `McBase`) Refers to the DOM HTMLElement this `DC` instance is attached to (via `DC.add`).
160
+ - `._mc`: An object `{}` to hold nested microcomponent instances.
161
+ - **Instance Methods**:
162
+ - `.parent(search?)`: Gets MC instances from the closest parent element that has attached MCs. Optionally filters by `search` key.
163
+ - `.ancestors(search?)`: Gets MC instances from all ancestor elements with attached MCs. Optionally filters by `search` key.
164
+ - `.children(search?)`: Gets MC instances from direct child elements with attached MCs. Optionally filters by `search` key.
165
+ - `.descendants(search?)`: Gets MC instances from all descendant elements with attached MCs. Optionally filters by `search` key.
166
+ - `.trigger(eventName, data, bubble)`: Triggers an event on this `DC` instance and its nested `_mc` structure. Can initiate DOM bubbling (`'l'`, `'u'`, `'d'`).
167
+
168
+ ## Examples
169
+
170
+ ### Typical Workflow
171
+
172
+ 1. Define your component classes extending `MC` or `DC`.
173
+ 2. Attach top-level `DC` instances to HTMLElements using `DC.add()`.
174
+ 3. Nest `MC` or `DC` instances within others using the `._mc` property if needed.
175
+ 4. Access other components via the `_mc` property, DOM traversal methods (`ancestors()`, `children()`, etc.), or event communication (`trigger`).
176
+
177
+ ### Attach Micro Components (`DC.add`)
178
+
179
+ Use the static `DC.add()` method to attach a component (usually a `DC` instance) to an HTMLElement.
85
180
 
86
181
  ```javascript
87
182
  const myElement = document.getElementById('myDiv');
88
183
 
89
- /*
90
- usage with classes, both PUBLIC and PRIVATE
91
- */
92
-
93
- // internal MC class
94
- MyInnerClass = class extends MC{
95
- constructor(target){
96
- }
184
+ // Define an inner MC (doesn't need DOM access itself)
185
+ class MyInnerClass extends MC {
186
+ constructor(target) {
187
+ // target will be the parent MyPublicClass instance
188
+ super(target);
189
+ console.log('Inner MC target:', this.target);
190
+ }
191
+ doSomethingInner() {
192
+ console.log('Inner action!');
193
+ }
97
194
  }
98
195
 
99
- // external DC class
100
- MyPublicClass = class extends DC{
101
- constructor(target){
102
- // add a internal inner MC
103
- this._mc.myInnerComponent = new MyInnerClass( this );
104
- }
196
+ // Define an outer DC (needs DOM access or is top-level)
197
+ class MyPublicClass extends DC {
198
+ constructor(target) {
199
+ // target will be myElement
200
+ super(target);
201
+ console.log('Outer DC target:', this.target);
202
+ // Add an inner MC instance, nested within this DC instance
203
+ this._mc.myInner = new MyInnerClass(this); // 'this' becomes the target for MyInnerClass
204
+ }
205
+ doSomethingOuter() {
206
+ console.log('Outer action!');
207
+ }
208
+
209
+ // Example DOM event handler
210
+ onClick(event) {
211
+ console.log('Div clicked!', event);
212
+ // Access nested MC
213
+ this._mc.myInner?.doSomethingInner();
214
+ }
105
215
  }
106
216
 
107
- // attach a DC
108
- DC.add( myElement, 'myDcComponent', new MyPublicClass( myElement ) );
109
- ```
217
+ // Attach the outer DC instance to the DOM element
218
+ // The key 'myComponent' is used to access it later via myElement._mc.myComponent
219
+ DC.add(myElement, 'myComponent', new MyPublicClass(myElement));
110
220
 
111
- #### **Hint**
112
- - After you added a micro component using this function, the **HTMLElement will contain a property `_mc`** which contains the MC instances visible in the DOM.
113
- - Also the **HTMLElement then has an attribute '_mc'** to indicate that at least one micro component is attached to this dom element.
221
+ // Hint: After adding, myElement now has:
222
+ // 1. A property: myElement._mc = { myComponent: instanceOfMyPublicClass }
223
+ // 2. An attribute: <div id="myDiv" _mc>...</div>
224
+ ```
114
225
 
115
- ### Remove a top level Micro Component from a DOM element
226
+ ### Remove Micro Components (DC.remove)
116
227
 
117
- Micro components can be removed using the `DC.remove()` static method.
228
+ Use the static DC.remove() method to detach a top-level component.
118
229
 
119
230
  ```javascript
120
- DC.remove( myDomElement, 'myComponent');
231
+ const myElement = document.getElementById('myDiv');
232
+
233
+ DC.remove(myElement, 'myComponent');
234
+
235
+ // If myElement._mc is now empty, the '_mc' attribute is also removed.
121
236
  ```
122
237
 
123
- **When all micro components are removed** (the _mc object has no more properties), the **`_mc` attribute is also removed** from the HTML element.
238
+ ### Retrieve Micro Components
124
239
 
125
- ### Retrieve Micro Components from a DOM element
240
+ Access attached components via the \_mc property of the target element or parent component.
126
241
 
127
242
  ```javascript
128
- const target = document.querySelector( 'div' );
129
- console.log(target._mc);
243
+ // Get the container object for all MCs on an element
244
+ const myElement = document.getElementById('myDiv');
245
+ const mcContainer = myElement._mc;
246
+ console.log(mcContainer); // { myComponent: instanceOfMyPublicClass, ... }
247
+
248
+ // Get a specific instance by its key
249
+ const specificInstance = myElement._mc?.myComponent;
250
+ if (specificInstance) {
251
+ specificInstance.doSomethingOuter();
252
+ }
130
253
  ```
131
254
 
132
- To retrieve a specific micro component by its key:
255
+ ### Triggering Events
256
+
257
+ 1. Triggering from outside onto components on an element:
258
+
133
259
  ```javascript
134
- const target = document.querySelector( 'div' );
135
- const specificInstance = target._mc?.myPublicComponent;
136
- console.log(specificInstance);
260
+ const targetElement = document.getElementById('myDiv');
261
+ const eventData = { message: 'Hello from outside!' };
262
+
263
+ // Trigger 'customEvent' locally on MCs attached to targetElement
264
+ DC.trigger(targetElement, 'customEvent', eventData, 'l');
265
+
266
+ // Trigger 'customEvent' and bubble up the DOM tree
267
+ DC.trigger(targetElement, 'customEvent', eventData, 'u');
268
+
269
+ // Trigger 'customEvent' locally, bubble up, and bubble down
270
+ DC.trigger(targetElement, 'customEvent', eventData, 'lud');
137
271
  ```
138
272
 
139
- ### Trigger an Event
273
+ 2. Triggering from inside a component instance:
140
274
 
141
275
  ```javascript
142
- const target = document.querySelector( 'div' );
143
- DC.trigger( target, '<eventName>', data | null, bubble );
276
+ class MyTriggeringComponent extends DC {
277
+ // ... constructor ...
144
278
 
145
- // bubble is any combination of 'lud', meaning [local|up|down]
146
- // local is only "this", "up" traverses towards root, "down" traverses the inner DOM.
147
- ```
279
+ someMethod() {
280
+ const eventData = { source: 'MyTriggeringComponent' };
148
281
 
149
- # Methods you can use in your Micro Component Instances
282
+ // Trigger 'internalEvent' only on this instance and its nested _mc components
283
+ this.trigger('internalEvent', eventData); // Default bubble 'l'
150
284
 
151
- ## Retrieve Inner Micro Components
285
+ // Trigger 'externalEvent' on sibling components attached to the same target element
286
+ // (and potentially bubble up/down based on the 'bubble' parameter)
287
+ DC.trigger(this.target, 'externalEvent', eventData, 'l'); // Trigger locally on siblings
152
288
 
153
- You can retrieve an inner micro component by using the ._mc property.
289
+ // Trigger 'downwardEvent' on components attached to descendant elements
290
+ this.trigger('downwardEvent', eventData, 'd'); // Bubbles down from this component's target
291
+ }
154
292
 
155
- ```javascript
156
- const innerComponent = this._mc.myInnerComponent;
157
- console.log(innerComponent);
158
- ```
293
+ // Event handler methods
294
+ onCustomEvent(event) {
295
+ console.log(`[${this.constructor.name}] received customEvent:`, event.data);
296
+ }
159
297
 
160
- **The following methods hop over HTMLElements that DO NOT contain micro components.**
298
+ onInternalEvent(event) {
299
+ console.log(
300
+ `[${this.constructor.name}] received internalEvent:`,
301
+ event.data
302
+ );
303
+ }
161
304
 
305
+ onExternalEvent(event) {
306
+ console.log(
307
+ `[${this.constructor.name}] received externalEvent:`,
308
+ event.data
309
+ );
310
+ }
162
311
 
163
- ## Navigate Parent and Ancestor Micro Components
312
+ onDownwardEvent(event) {
313
+ console.log(
314
+ `[${this.constructor.name}] received downwardEvent:`,
315
+ event.data
316
+ );
317
+ }
318
+ }
319
+ ```
164
320
 
165
- The `.parent()` and `.ancestors()` methods allow you to retrieve micro components attached to parent elements.
321
+ ### Retrieving Inner Micro Components
322
+
323
+ Access nested components directly via the parent's `_mc` property.
166
324
 
167
325
  ```javascript
168
- const parentMcs = this.parent();
169
- console.log(parentMcs); // all micro components of the closest ancestor that has an _mc attribute
326
+ class Inner extends MC {
327
+ constructor(target) {
328
+ super(target);
329
+ }
330
+ someInnerMethod() {
331
+ console.log('Inner method called!');
332
+ }
333
+ }
334
+
335
+ class Outer extends DC {
336
+ constructor(target) {
337
+ super(target);
338
+ this._mc.inner = new Inner(this);
339
+ }
170
340
 
171
- const allAncestorsMcs = this.ancestors();
172
- console.log(allAncestorsMcs); // all ancestor micro components up to document root.
341
+ accessInner() {
342
+ this._mc?.inner.someInnerMethod();
343
+ }
344
+ }
173
345
  ```
174
346
 
175
- To retrieve specific micro component(s) attached to ancestors:
347
+ ### Navigating Parent/Ancestor MCs
348
+
349
+ Use .parent() and .ancestors() (available on DC instances) to find components attached to elements higher up the DOM tree.
350
+
351
+ These methods skip elements that don't have any MCs attached.
352
+
176
353
  ```javascript
177
- const specificAncestorMc = this.ancestors('myComponent');
354
+ // Inside a method of a DC instance:
355
+ const parentMcs = this.parent(); // Array of MC instances on the first parent element with MCs
356
+ console.log(parentMcs);
357
+
358
+ const allAncestorMcs = this.ancestors(); // Array of all MC instances on all ancestor elements with MCs
359
+ console.log(allAncestorMcs);
360
+
361
+ // Find a specific component type/key among ancestors
362
+ const specificAncestor = this.ancestors('someSpecificKey')?.[0];
363
+
364
+ if (specificAncestor) {
365
+ console.log('Found specific ancestor:', specificAncestor);
366
+ }
178
367
  ```
179
368
 
180
- ## Retrieve Child and Descendant Micro Components
369
+ ### Retrieving Child/Descendant MCs
370
+
371
+ Use .children() and .descendants() (available on DC instances) to find components attached to elements lower down the DOM tree.
181
372
 
182
- The `.children()` and `.descendants()` methods retrieve micro components attached to child elements or any descendants.
183
373
  ```javascript
184
- const childComponents = this.children();
185
- console.log(childComponents); // an array of nearest micro components in the inner DOM
374
+ // Inside a method of a DC instance:
375
+ const childMcs = this.children(); // Array of MCs on direct child elements with MCs
376
+ console.log(childMcs);
186
377
 
187
- const descendantComponents = this.descendants();
188
- console.log(descendantComponents); // an array of all descendant micro components in the inner DOM
378
+ const descendantMcs = this.descendants(); // Array of all MCs on all descendant elements with MCs
379
+ console.log(descendantMcs);
189
380
 
190
- //To search for a specific micro component by key:
191
- const specificMcs = this.descenants('specificMc');
381
+ // Find specific components among descendants
382
+ const specificDescendants = this.descendants('someSpecificKey');
383
+ console.log(specificDescendants); // Array of matching descendant MCs
192
384
  ```
193
385
 
194
- ## Trigger an Event
386
+ ### Auto-attaching DOM Listeners
387
+
388
+ Methods defined in your DC class starting with `on` or `one` followed by a capital letter, which also match native DOM event names (case-insensitive check), will automatically have listeners attached to the target DOM element:
389
+
195
390
  ```javascript
196
- // trigger an event on yourself
197
- this
198
- .trigger('myEvent', data); // calls the "onMyEvent" callback
199
-
200
- // trigger an event on your external siblings
201
- DC
202
- .trigger( this.target, 'myEvent', data); // calls the "onMyEvent" callback on all external MCs that listen to it
203
-
204
- // trigger an event on some remote DOM instance(s)
205
- DC
206
- .trigger(
207
- this.target, // the DOM node your are in
208
- 'myEvent', // event name
209
- null, // no data
210
- 'd' // into descendants
211
- ); // calls the "onMyEvent" callback
212
-
213
- // trigger an event on some remote DC instance that you know the name of
214
- this
215
- .descendants('myRemoteInstance') // into my inner HTML
216
- ?.[0] // hopefully we found one
217
- .trigger(
218
- 'myEvent', // event name
219
- null, // no data
220
- );
391
+ class McWithHandlers extends DC {
392
+ constructor(target) {
393
+ super(target);
394
+ }
395
+
396
+ // This method name matches the native 'click' event.
397
+ // A listener will be automatically added to this.target.
398
+ onClick(domEvent) {
399
+ console.log('Target element clicked!', domEvent);
400
+ // 'this' refers to the MyClickHandler instance
401
+ this.target.style.backgroundColor = 'lightblue';
402
+ }
403
+
404
+ // This method name matches the native 'mouseover' event.
405
+ // 'one' means the listener will be removed after the first trigger.
406
+ oneMouseover(domEvent) {
407
+ console.log('Mouseover detected once!', domEvent);
408
+ this.target.style.border = '2px solid red';
409
+ }
410
+
411
+ // This is a custom event handler, not a native DOM event.
412
+ // It will be triggered by this.trigger('CustomAction') or DC.trigger(this.target, 'CustomAction')
413
+ onCustomAction(mcEvent) {
414
+ console.log('Custom action triggered!', mcEvent.data);
415
+ }
416
+ }
417
+
418
+ const myDiv = document.getElementById('clickableDiv');
419
+ DC.add(myDiv, 'clickHandler', new McWithHandlers(myDiv));
420
+ // Now clicking or mousing over 'clickableDiv' will trigger the methods.
221
421
  ```
222
422
 
223
- ## Automatically attach Listener Methods to the DOM
423
+ ### Lifecycle Events
424
+
425
+ The framework defines specific methods that are called at certain points in a component's life.
426
+
427
+ #### Init
428
+
429
+ Method Name: oneInit(event)
224
430
 
225
- On any **MC** and **DC** instance, the Superclass McBase calls **autoAttachListeners()** in the constructor.
431
+ Triggered: Asynchronously (setTimeout(0)) after the component instance is created (called from McBase constructor via the init helper).
226
432
 
227
- Any methods you define in your code that start with **"on"** or **"one"**, and also match DOM event names, will be called accordingly:
433
+ Execution Order:
434
+
435
+ The component's oneInit is called first, then it recursively calls oneInit on any components nested within its `_mc` property.
436
+
437
+ Requirement:
438
+
439
+ - You must define a method named `oneInit` in your class for it to be called.
440
+ - The `one` prefix implies it's intended to run once during initialization.
228
441
 
229
442
  ```javascript
230
- class MyEventTarget extends MC {
443
+ class MyLifecycleComponent extends DC {
231
444
  constructor(target) {
232
445
  super(target);
446
+ console.log('Constructor finished');
447
+ this._mc.nested = new NestedComponent(this);
233
448
  }
234
449
 
235
- onClick(ev) {
236
- console.log("onClick", ev);
450
+ oneInit(event) {
451
+ // This code runs shortly after the constructor finishes.
452
+ console.log('MyLifecycleComponent oneInit called!', event);
453
+ // Safe to access this.target or setup things that depend on the instance being fully constructed.
237
454
  }
238
455
  }
239
-
240
- let myFirstDiv = document.querySelector('div');
241
- DC.add( myFirstDiv, 'myEventTarget', new MyEventTarget( myFirstDiv ) );
242
- // now wait for somebody to click on that <div>
243
456
  ```
244
- # Lifecycle Events on **MC** and **DC**
245
-
246
- ## Init
247
- - "this" first
248
- - traverses recursively into the _mc structure.
249
- - callbacks will be executed **asynchronous**.
250
- - requires **method .oneInit()** to be present in your class definition.
251
-
252
- ## Destroy ( TBD )
253
- - deepest nested elements first.
254
- - callbacks will be executed **synchronous**.
255
- - then "this"
256
- - requires **method .oneDestroy()** to be present in your class definition.
457
+
458
+ #### Destroy (TBD)
459
+
460
+ Method Name: oneDestroy(event) (Proposed)
461
+
462
+ Triggered: When a component is removed (e.g., via DC.remove or potentially parent removal).
463
+
464
+ Execution Order:
465
+
466
+ Expected to run synchronously, starting from the deepest nested components upwards, finally calling oneDestroy on the component being removed itself.
467
+
468
+ Requirement:
469
+
470
+ - Would require defining a method named `oneDestroy` in your class.