@twobirds/microcomponents 0.0.12 → 0.0.15

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 (37) hide show
  1. package/README.md +28 -44
  2. package/assets/documentation/ajaxian-1.png +0 -0
  3. package/assets/documentation/ajaxian-2.png +0 -0
  4. package/assets/documentation/ajaxian-3.png +0 -0
  5. package/assets/documentation/history.md +436 -0
  6. package/assets/documentation/how_tos.md +0 -0
  7. package/assets/documentation/introduction.md +0 -0
  8. package/{microcomponents_magic.md → assets/documentation/magic.md} +1 -1
  9. package/assets/documentation/rnd0023-1.jpg +0 -0
  10. package/assets/documentation/rnd0023-2.jpg +0 -0
  11. package/assets/documentation/rnd0023-3.jpg +0 -0
  12. package/assets/documentation/tB_react.md +204 -0
  13. package/package.json +2 -2
  14. package/public/documentation/ajaxian-1.png +0 -0
  15. package/public/documentation/ajaxian-2.png +0 -0
  16. package/public/documentation/ajaxian-3.png +0 -0
  17. package/public/documentation/functional_requirements.md +8 -0
  18. package/public/documentation/history.md +436 -0
  19. package/public/documentation/how_tos.md +0 -0
  20. package/public/documentation/introduction.md +0 -0
  21. package/public/documentation/magic.md +87 -0
  22. package/public/documentation/proposal_draft.md +37 -0
  23. package/public/documentation/rnd0023-1.jpg +0 -0
  24. package/public/documentation/rnd0023-2.jpg +0 -0
  25. package/public/documentation/rnd0023-3.jpg +0 -0
  26. package/public/documentation/tB_react.md +233 -0
  27. package/public/documentation/usage.md +142 -0
  28. package/public/documentation/why.md +25 -0
  29. package/public/test.js +20 -18
  30. package/src/test.js +22 -20
  31. package/dist/test.d.ts +0 -36
  32. package/dist/test.d.ts.map +0 -1
  33. package/dist/test.js +0 -214
  34. /package/{microcomponents_functional_requirements.md → assets/documentation/functional_requirements.md} +0 -0
  35. /package/{MicroComponentProposal_draft.md → assets/documentation/proposal_draft.md} +0 -0
  36. /package/{microcomponents_usage.md → assets/documentation/usage.md} +0 -0
  37. /package/{microcomponents_why.md → assets/documentation/why.md} +0 -0
@@ -0,0 +1,204 @@
1
+ # Discussing React Prop Drilling with ChatGPT
2
+
3
+ This is an interesting read where I wanted ChatGPT to come up with a Micro Component solution for a React problem.
4
+
5
+ To be honest, I knew MCs can solve it. But I wanted to know what ChatGPT can make of it. Spoiler: it got remarkably close on the first try. The second try was spot on.
6
+
7
+ Please mind I have a trained session with a backlog. So you wont get the same answers.
8
+
9
+ ***( Cut outs and comments are in parentheses...)***
10
+
11
+ ## Start Session
12
+
13
+ Me:
14
+ **Do you remember our chat regarding Micro Components vs. existing frameworks?**
15
+
16
+ ChatGPT:
17
+
18
+ Yes, I remember our discussion! We talked about your approach to microcomponents as distinct from established frameworks, with a focus on smaller, modular, data-driven components that are stored in a hash attached to DOM elements (specifically in a _tb property in twoBirds or _mc for microcomponents). Your system emphasizes manual wiring, observability, and ease of interaction across components, making it different from React, Vue, or other component libraries that depend heavily on virtual DOMs, JSX, or hooks.
19
+
20
+ Your components follow principles of separation of concerns and DRY by keeping interactions modular but flexible, and they use observables to trigger functions in other components, which can be linked in chains. Your approach allows a component-based design that integrates deeply into the DOM without the overhead of larger frameworks. And while existing frameworks typically follow a top-down data flow, your system allows bi-directional, observable properties that automatically update the DOM when data changes.
21
+
22
+ Would you like to revisit any specific aspect, or compare further?
23
+
24
+
25
+ ## React
26
+
27
+ Me:
28
+ **There was something about React specifically?**
29
+
30
+
31
+ ChatGPT:
32
+
33
+ (...)
34
+
35
+ ### Manual Wiring vs. React’s Context and Hooks:
36
+ React uses Context and hooks (like useState and useEffect) to manage data flow and lifecycle.
37
+
38
+ Your approach leans on manual wiring for connecting data across microcomponents, avoiding the abstraction of hooks and allowing direct, observable-driven updates. This can make the flow of data more transparent and easier to trace in complex applications, whereas hooks can sometimes add complexity or obscurity when trying to understand data dependencies.
39
+
40
+ ### Component Reusability and Scaling:
41
+ Both React and Micro Components support component-based architecture.
42
+
43
+ However, Micro Components allows multiple microcomponents on a single DOM element, and each microcomponent is responsible for specific tasks, making scaling in large applications more modular and straightforward. React encourages separation at the component level, whereas Micro Components does so at the microcomponent level, with direct chaining possible between components.
44
+
45
+ (...)
46
+
47
+ Each of these aspects underlines Micro Components’ focus on minimalism, modularity, and developer control. These are different from React's abstraction and tooling-heavy approach, making your framework potentially more transparent and lightweight for specific use cases.
48
+
49
+ Would you like to dive into any of these differences in more detail?
50
+
51
+
52
+ ## Prop Drilling
53
+
54
+ Me:
55
+ **In general there was a problem regarding carrying properties from a component close to the root of the document to a component that is much deeper into the DOM tree, do you remember that?**
56
+
57
+ ChatGPT:
58
+
59
+ Yes, I remember!
60
+
61
+ We discussed the challenges in carrying properties or state from a root-level component down to deeply nested components. In React, this kind of deep property sharing can become cumbersome and often requires additional tools or patterns, such as:
62
+
63
+ ### Prop Drilling:
64
+ React requires passing data through each level of components in the tree via props, a process known as prop drilling. This can lead to complex and hard-to-manage code, especially when the data isn’t relevant to every component in the chain.
65
+
66
+ (...)
67
+
68
+ In contrast, your Micro Components microcomponents have an alternative approach that makes it easier to pass properties throughout the DOM tree:
69
+
70
+ ### Direct Microcomponent Selectors:
71
+ Micro Components includes selector methods (like .parents() and .descendants()) that allow components to access any microcomponent within the tree without explicit data passing. This capability enables deeply nested components to retrieve properties from higher-level components directly, bypassing the need to route data through intermediary components.
72
+
73
+ (...)
74
+
75
+ ### Manual Wiring for Control:
76
+
77
+ **Because Micro Components rely on manual wiring, you can set up specific connections between components as needed.** This gives you fine-grained control over where and how data flows through the app without involving a top-level state or intermediary components, making it more scalable for larger apps without the need for a Context API or state library.
78
+
79
+ (...)
80
+
81
+ This structure offers a highly flexible, context-free solution for deep property sharing, making it an efficient alternative to prop drilling or global state libraries in many scenarios. Would you like more details on how Micro Components selectors work with observables to achieve this?
82
+
83
+
84
+ ## Generate Code
85
+
86
+ Me:
87
+ **Can you give an example of 2 react components that interact with each other using micro components? Give me the code of both components, using microomponents to exchange data**
88
+
89
+ ***( it took some further hinting, but in the end ChatGPT came up with this: )***
90
+
91
+
92
+ ChatGPT:
93
+
94
+ Here's the updated code:
95
+ Parent Micro Component
96
+
97
+ This component will receive a target DOM node and set a value that propagates down to its descendants:
98
+
99
+ ```javascript
100
+
101
+ // Parent Micro Component
102
+ class ParentMC extends MC {
103
+ constructor(targetNode) {
104
+ super(targetNode); // Receive and pass the target DOM node to the MC constructor
105
+ }
106
+
107
+ set value(newValue) {
108
+ // Send value to all descendants named "targetMC"
109
+ this.descendants("targetMC").forEach(descendant => descendant.data = newValue);
110
+ }
111
+ }
112
+ ```
113
+
114
+ Child Micro Component
115
+
116
+ This component has a data setter that updates the internal React state in each child:
117
+
118
+ ```javascript
119
+
120
+ // Child Micro Component
121
+ class ChildMC extends MC {
122
+ constructor(targetNode, setReactState) {
123
+ super(targetNode); // Receive the target DOM node to be managed by MC
124
+ this.setReactState = setReactState;
125
+ }
126
+
127
+ set data(newValue) {
128
+ this.setReactState(newValue); // Update React state when data is set
129
+ }
130
+ }
131
+ ```
132
+
133
+ React Components Using Micro Components
134
+
135
+ The following React setup attaches ParentMC and ChildMC to their respective DOM elements, using the parent DOM node to instantiate the micro components.
136
+ Parent Component
137
+
138
+ The parent component attaches an instance of ParentMC to the DOM node and sets its value based on inputValue.
139
+
140
+ ```javascript
141
+
142
+ import React, { useState, useRef, useEffect } from 'react';
143
+ import { MC } from '@Micro Components/microcomponents';
144
+
145
+ const ParentComponent = () => {
146
+ const [inputValue, setInputValue] = useState("");
147
+ const parentRef = useRef(null);
148
+
149
+ useEffect(() => {
150
+ const parentMC = new ParentMC(parentRef.current); // Pass the DOM node to ParentMC
151
+ MC.add(parentRef.current, 'parentMC', parentMC);
152
+
153
+ // Update value in ParentMC whenever inputValue changes
154
+ parentMC.value = inputValue;
155
+ }, [inputValue]);
156
+
157
+ return (
158
+ <div ref={parentRef}>
159
+ <input
160
+ type="text"
161
+ value={inputValue}
162
+ onChange={(e) => setInputValue(e.target.value)}
163
+ placeholder="Type to send data to children"
164
+ />
165
+ <ChildComponent />
166
+ </div>
167
+ );
168
+ };
169
+ ```
170
+
171
+ Child Component
172
+
173
+ The child component attaches an instance of ChildMC, which updates its state whenever data is set.
174
+
175
+ ```javascript
176
+
177
+ const ChildComponent = () => {
178
+ const [childData, setChildData] = useState("");
179
+ const childRef = useRef(null);
180
+
181
+ useEffect(() => {
182
+ const childMC = new ChildMC(childRef.current, setChildData); // Pass DOM node and state setter to ChildMC
183
+ MC.add(childRef.current, 'targetMC', childMC);
184
+ }, []);
185
+
186
+ return (
187
+ <div ref={childRef}>
188
+ <h3>Received Data:</h3>
189
+ <p>{childData}</p>
190
+ </div>
191
+ );
192
+ };
193
+ ```
194
+
195
+ ***( ... I cannot tell about the react part, but the micro coomponent code is spot on. Like WLAN on the DOM :-) )***
196
+
197
+
198
+ **ChatGPT can produce errors. Check the information.**
199
+
200
+ ## ... yes I do :-)
201
+
202
+ ***( ... but it was right on the money in the end. I love AI, albeit with a healthy grain of sceptic salt. )***
203
+
204
+ ***( ... and I asked about MCs and Angular likewise, and it directly pointed me to a NG module problem that can also be solved. It even came up with sample code. )***
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@twobirds/microcomponents",
3
- "version": "0.0.12",
3
+ "version": "0.0.15",
4
4
  "description": "Micro Components Organization Class",
5
5
  "main": "microcomponents.js",
6
6
  "sideEffects": false,
@@ -10,7 +10,7 @@
10
10
  "prep": "cp -R assets/* public || true; cp src/* build || true;",
11
11
  "build": "npm run clean; npm run prep; tsc; npm run minify; npm run copyToDist;",
12
12
  "minify": "jsmin -o build/microcomponents.es3.min.js ./src/microcomponents.es3.js;jsmin -o build/microcomponents.min.js build/microcomponents.js;",
13
- "copyToDist": "cp -R assets/* public || true; cp build/* dist; cp build/microcomponents.js public; cp build/test.js public; cp MicroComponents.svg dist; cp MicroComponents.svg public/fiddle;"
13
+ "copyToDist": "cp -R assets/* public || true; cp build/micro* dist; cp build/microcomponents.js public; cp build/test.js public; cp MicroComponents.svg dist; cp MicroComponents.svg public/fiddle;"
14
14
  },
15
15
  "author": "",
16
16
  "license": "ISC",
@@ -0,0 +1,8 @@
1
+ ## Functional Requirements
2
+
3
+ - I want to **enrich a standard HTMLElement instance or any object with encapsuled and modular javascript**, without having to resort to web components or big frameworks.
4
+ - I want to have an **interface** into this functionality that I can both tight and loosely couple.
5
+ - I want to **import and use Micro Components in any framework** that allows for direct DOM access.
6
+ - I want **a single location** in an HTMLElement instance where all this functionality is **stored and sufficiently organized**.
7
+ - I want to be able to use **selectors** to find those instances in the DOM.
8
+ - All this must stricly follow **web standards**.
@@ -0,0 +1,436 @@
1
+ ## History
2
+
3
+ ### Content
4
+
5
+ - [Before 2006](#before-2006)
6
+ - [DOM and Javascript in 2006](#dom-and-javascript-in-2006)
7
+ - [How it started](#how-it-started)
8
+ - [Initial Specification](#initial-specification)
9
+ - [Unforeseen Problems](#unforeseen-problems)
10
+ - [The Result](#the-result)
11
+ - [Release on Ajaxian](#release-on-ajaxian)
12
+ - [First SPA ever](#first-spa-ever)
13
+ - [Some Code Snippets](#some-code-snippets)
14
+ - [The Fallout](#the-fallout)
15
+
16
+
17
+ ## Before 2006
18
+
19
+ Starting 1980, I programmed client-server or standalone applications for DOS and MS Windows.
20
+
21
+ Around 1995 I switched to web programming.
22
+
23
+ Before 2006 I was working on server side modular components using PHP, with little client side automation using Javascript.
24
+
25
+ Starting 2004 I developed twoBirds v1, vaguely centered around a web component idea.
26
+
27
+
28
+ ## DOM and Javascript in 2006
29
+
30
+ The Internet has just existed for a couple of years for private use.
31
+
32
+ Douglas Crockford had released the [JSON specification](https://en.wikipedia.org/wiki/JSON) in 2000.
33
+
34
+ The [XMLHttpRequest](https://en.wikipedia.org/wiki/XMLHttpRequest) was specified by Microsoft in 2001. As of IE7 (2006) it was adopted by every browser, albeit buggy in IE(!).
35
+
36
+ The Javascript engines and the DOM model in contemporary browsers slightly differed from each other then.
37
+
38
+ John Resig had released [jQuery](https://en.wikipedia.org/wiki/JQuery). [Prototype](https://en.wikipedia.org/wiki/Prototype_JavaScript_Framework) was its main competitor then.
39
+
40
+ Both of these libraries were immensely helpful, since they allowed for cross-browser access to the DOM and leveraged Javascript inconsistencies.
41
+
42
+ I was a self-employed full-stack programmer then. **PHP** and **Javascript** knowledge was all it took in these lucky days to call yourself a full stack programmer.
43
+
44
+
45
+ ## How it started
46
+
47
+ With a call, obviously. The requirements were: convert an Excel sheet into a web application, so insurance company staff could plan customer appointments and the company could automate monthly travel expense refunds.
48
+
49
+ Easy, of course I can do that. LAMP and jQuery will do it for me. Until it didn't.
50
+
51
+ jQuery doesn't help you in any way structuring complex code. But my existing twoBirds v1 could. I saw the chance to let this project fund twoBirds v2.
52
+
53
+ I called back the customer and explained. In essence we agreed to this: the customer will pay the same sum, but it will take double as long. The updated twoBirds v2 library will continue to be my royalty, but he is given a lifelong license to it.
54
+
55
+ The project was a grossly underestimated, as I found out. Estimated at 6 month, it finally took 12 and most of this was twoBirds, especially the cross-browser part. Spoiler: it worked in the end.
56
+
57
+
58
+ ## Initial Specification
59
+
60
+ twoBirds was to fulfill these requirements:
61
+
62
+ - **cross browser**.
63
+
64
+ This led to some unforseen consequences, which I will describe below.
65
+ - **on-demand loading** of Javascript files.
66
+
67
+ Also on-demand loading of associated **HTML templates** and **CSS**. This must be **recursive**, so MCs can recursively load other MCs and their requirements.
68
+ - **internal Micro Component repository** in the resulting application to avoid multiple loading for multiple instances of a MC in the page.
69
+ - **leverage XMLHttpRequest inconsistencies**, especially the famous "closure bug" that led to memory leaks in IE.
70
+ - **jQuery** as the selector engine.
71
+
72
+ Thanks again John, without your code it would have been much harder. We all stand on the shoulders of giants.
73
+
74
+
75
+ ## Unforseen Problems
76
+
77
+ Browsers tested:
78
+ - **IE5.5**+
79
+ - **Netscape Communicator**, later **Firefox** also
80
+ - **Chrome**
81
+ - **Opera**
82
+ - **Safari** ( Safari for Windows at least, see below)
83
+ - **Konqueror**, since I was working on OpenSUSE.
84
+
85
+ This resulted in some problems, i.e. (list is not complete):
86
+
87
+ ### No debuggers
88
+
89
+ Firebug wasn't there yet. When it finally arrived as a firefox extension, I was really cooking.
90
+
91
+ Other than that there was no reflection mechanism, so no runtime introspection for most browsers. The Proxy() class didn't exist yet.
92
+
93
+ Microsofts skript debugger didnt help a lot with other browsers.
94
+
95
+ ### Missing equipment
96
+
97
+ Since I had no Apple hardware, I couldn't reliably test for Safari on MAC. Safari for Windows was slightly different from Safari on MAC.
98
+
99
+ At least I got it working there but could not promise for MAC hardware. I was told by others it worked there as well, though.
100
+
101
+ ### Meager internal documentation for browsers
102
+
103
+ It took me month to find out the best way to on-demand load Javascript code, templates and CSS, and how to avoid FOUC.
104
+
105
+ ### timeout()
106
+
107
+ Cross-browser support in 2006 meant Konqueror also.
108
+
109
+ But Konqueror v1 had a funny bug: it could only handle one (1) timeout via setTimeout() at a time. I had to come up with a workaround.
110
+
111
+ So I implemented tb.timer() which used a single timeout to poll a list of timestamped callbacks every 100 ms.
112
+
113
+ ```javascript
114
+ tb.timer = {
115
+ destroylist: [],
116
+ addlist: [],
117
+ list: [],
118
+ ms: 100,
119
+
120
+ // public
121
+
122
+ add: function( pCallback, pTimeMs ) {
123
+ var myDate = new Date();
124
+ var myIdentifier = '_to'+tb.misc.getid();
125
+ var myTime = myDate.getTime() + pTimeMs;
126
+ var myArray = [ myTime, '( '+pCallback+' )', myIdentifier ];
127
+ tb.timer.addlist.push( myArray );
128
+ if (tb.timer.list.length === 0 ) {
129
+ window.setTimeout( 'tb.timer.timeout()', 10);
130
+ }
131
+ return myIdentifier;
132
+ },
133
+
134
+ abort: function( pIdentifier ) {
135
+ tb.timer.destroylist.push( pIdentifier );
136
+ },
137
+
138
+ //private
139
+
140
+ destroy: function( pIdentifier ) {
141
+ var myNewlist = [];
142
+ var i=0;
143
+ for ( i in tb.timer.list ) {
144
+ if ( tb.timer.list[i][2] !== pIdentifier ) {
145
+ var myObj = tb.misc.cloneObj( tb.timer.list[i] );
146
+ myNewlist.push( myObj );
147
+ }
148
+ }
149
+ tb.timer.list = myNewlist;
150
+ },
151
+
152
+ timeout: function() {
153
+ while ( tb.timer.addlist.length > 0 ) {
154
+ tb.timer.list.push( tb.timer.addlist.pop() );
155
+ }
156
+ while ( tb.timer.destroylist.length > 0 ) {
157
+ tb.timer.destroy( tb.timer.destroylist.pop() );
158
+ }
159
+ if ( tb.timer.list.length < 1 ) {
160
+ tb.timer.ms = 100;
161
+ return;
162
+ }
163
+ else {
164
+ var myNewList = [];
165
+ var myMinVal = 0;
166
+ while ( tb.timer.list.length > 0 ) {
167
+ var myDate = new Date();
168
+ var myTime = myDate.getTime();
169
+ if ( tb.timer.list[0][0] <= myTime ) {
170
+ var myEval = tb.timer.list[0][1];
171
+ eval( '( ' + myEval + ' )' );
172
+ }
173
+ else {
174
+ if ( tb.timer.list[0][1] < myMinVal || myMinVal === 0 ) {
175
+ myMinVal = tb.timer.list[0][1];
176
+ }
177
+ myNewList.push( tb.timer.list[0] );
178
+ }
179
+ tb.timer.list.shift();
180
+ }
181
+ tb.timer.list = myNewList;
182
+ if ( myMinVal > 0 ) {
183
+ myDate = new Date();
184
+ tb.timer.ms = myMinVal - myDate.getTime();
185
+ }
186
+ else {
187
+ tb.timer.ms = 100;
188
+ }
189
+ while ( tb.timer.addlist.length > 0 ) {
190
+ tb.timer.list.push( tb.timer.addlist.pop() );
191
+ }
192
+ window.setTimeout( 'tb.timer.timeout()', tb.timer.ms);
193
+ }
194
+ }
195
+
196
+ };
197
+ window.setTimeout( 'tb.timer.timeout()', 0);
198
+ ```
199
+
200
+ Then I implemented ...
201
+ - **tb.timeout()** to use tb.timer().
202
+
203
+ - **tb.interval()** also, which used tb.timeout(). This I did with the added benefit that my implementation avoided runovers if the implemented functionality lasted longer than the interval.
204
+
205
+ While I was at it, I also implemented...
206
+ - **tb.wait()**, which used tb.interval() to wait for a condition to be true, and then called the callback.
207
+
208
+ - **tb.observe()**, which was a tb.interval() implementation of tb.wait().
209
+
210
+ At this point I had a solution polling **Observables** in 2006.
211
+
212
+
213
+ ## The Result
214
+
215
+ So far I had a solution for **requirement loading**, **templating**, **observables** and **web components** as early as 2006.
216
+
217
+ - **tb.require()** probably influenced [requireJs](https://requirejs.org/) and in turn the CommonJS specification.
218
+
219
+ - **Templates** are now a coding standard and implemented in various ways using backtick strings ( `string with ${placeholder}` ) and the DOM template tag.
220
+
221
+ - **Observables** are now a coding standard and implemented in various ways using getters/setters or the Proxy() object.
222
+
223
+ - [Web Components](https://developer.mozilla.org/en-US/docs/Web/API/Web_components) initially contained a definition for user built in custom elements, which was a functional copy of twoBirds web components.
224
+
225
+ Look at the screenshots attached at the end of this document. That is the application I developed, with a code example attached.
226
+
227
+ ## Release on Ajaxian
228
+
229
+ twoBirds v2 was open sourced and anounced on ajaxian.com on April 2nd 2007, you can find the original article on archive.org.
230
+
231
+ ![Ajaxian Screenshot 1](./ajaxian-1.png)
232
+ ![Ajaxian Screenshot 2](./ajaxian-2.png)
233
+
234
+ Which led to this comment:
235
+
236
+ ![Ajaxian Screenshot 3](./ajaxian-3.png)
237
+
238
+ RTFM, man. Oh nevermind, Dean. I forget to add one. Autists...
239
+
240
+ twoBirds as a framework will be dissolved into modular micro component based functionality. RIP. It served me well for 20 years.
241
+
242
+
243
+ ## First SPA ever
244
+
245
+ The first web component based single page application (SPA) that ever existed - to my knowledge. Prove me otherwise ;-).
246
+
247
+ ![app1](./rnd0023-1.jpg);
248
+ ![app2](./rnd0023-2.jpg);
249
+ ![app3](./rnd0023-3.jpg);
250
+
251
+ Yes, I contemplated programming a web based Excel, as in Google Calc.
252
+
253
+ And web component based cockpit instruments for airplanes.
254
+
255
+ As I think of it: **SpaceX** uses **Web Components** for cockpit instruments in their **Dragon Capsule**. ;-)
256
+
257
+ ## Some Code Snippets
258
+
259
+ This is the code for the left part of the table shown in the pictures above.
260
+
261
+ ```javascript
262
+ self.tourtable.leftcolumn = { // new object
263
+
264
+ showcounter: 0,
265
+ datecache: [], // cache für HTML code
266
+
267
+ init: function (pDivId) {
268
+ //tb.element.show( null, 'tourtable', 'leftcolumnline'); // preload line code
269
+ tb.element.require(
270
+ [ [ 'css', 'tourtable', 'leftcolumn'],
271
+ [ 'tpl', 'tourtable', 'leftcolumn'] ],
272
+ 'tourtable.leftcolumn.display("' + pDivId + '")',
273
+ true );
274
+ },
275
+
276
+ display: function (pDivId) {
277
+
278
+ if ( tourtable.middlecolumn.day == -1 ) { // clear HTML array
279
+ tourtable.leftcolumn.datecache = [];
280
+ }
281
+ else {
282
+ tourtable.leftcolumn.datecache[tourtable.middlecolumn.day] = '';
283
+ var pDay = tourtable.middlecolumn.day;
284
+ }
285
+
286
+ try {
287
+ var myDiv = document.getElementById( pDivId );
288
+ }
289
+ catch (e) {
290
+ tb.timer.add( 'tourtable.leftcolumn.display("'+pDivId+'")', 100 );
291
+ return;
292
+ }
293
+ tourtable.leftcolumn.showcounter = 1;
294
+ //tb.debug.add("<p>Element <font color='magenta'><b> display: </b></font> tourtable.leftcolumn in " + pDivId + "</p>");
295
+ var myHtml = tb.loader.tplget('tourtable','leftcolumn');
296
+ var myNewRegEx = new RegExp('%tourtableleftrows%');
297
+ myHtml = myHtml.replace(myNewRegEx, '');
298
+ tb.div.replace(pDivId,myHtml);
299
+ myHtml = tb.loader.tplget('tourtable','leftcolumn');
300
+
301
+ var myDate = new tb.tbDate();
302
+ myDate.setDate(1);
303
+ var myMonth = myDate.getMonth();
304
+ var myRows = '';
305
+ var myDateRows = '';
306
+ var myId = 1;
307
+ var myLastDate='';
308
+ var createDate='';
309
+
310
+ //tb.debug.add('<p>leftcolumn <font color="blue">Act:</font> '+middlecolumn.getlength()+'</p>');
311
+
312
+ //var myDateList = '';
313
+ if ( tourtable.middlecolumn.getlength() > 0 )
314
+ for ( x=0; x < tourtable.middlecolumn.getlength(); x++ ) {
315
+ var thisRecord = tourtable.middlecolumn.act.Data.data[0][x];
316
+ if ( tourtable.middlecolumn.currentId == null ) {
317
+ tourtable.middlecolumn.currentId = thisRecord.id;
318
+ }
319
+ var myDate = new tb.tbDate();
320
+ myDate.setFromMysqlDateString( thisRecord.datum );
321
+ var thisDateIndex = myDate.getDate();
322
+ if ( ! tourtable.leftcolumn.datecache[thisDateIndex] ) { // create if necessary
323
+ tourtable.leftcolumn.datecache[thisDateIndex] = '';
324
+ }
325
+ if ( tourtable.leftcolumn.datecache[thisDateIndex] == '') { // create if necessary
326
+ createDate = thisDateIndex;
327
+ }
328
+ var myNextDate = ( x == tourtable.middlecolumn.getlength()-1 || tourtable.middlecolumn.act.Data.data[0][x+1].datum != thisRecord.datum ) ? true : false;
329
+ if ( !pDay || thisDateIndex == pDay || createDate == thisDateIndex ) { // pdate not given or this is the given date
330
+ tourtable.leftcolumn.datecache[thisDateIndex] += tourtable.leftcolumnline.make( thisRecord.id, ( myLastDate == thisRecord.datum ? false : true ), myNextDate, myDate, thisRecord.ort );
331
+ }
332
+ myLastDate = thisRecord.datum;
333
+ }
334
+
335
+ myRows = tourtable.leftcolumn.datecache.join('');
336
+
337
+ myNewRegEx = new RegExp('%tourtableleftrows%');
338
+ myHtml = myHtml.replace(myNewRegEx, myRows);
339
+
340
+ //tb.div.replace(pDivId,myHtml);
341
+ tb.misc.innerHTML(pDivId,myHtml);
342
+
343
+ tourtable.leftcolumn.showcounter = 0;
344
+ }
345
+
346
+ };
347
+ ```
348
+
349
+ This is the example code they referred to on ajaxian.com:
350
+
351
+ ```javascript
352
+ index = {};
353
+
354
+ user = {};
355
+
356
+ tourtable = {};
357
+
358
+ index.index_body = {
359
+
360
+ init: function (pDivId) {
361
+ tb.element.require(
362
+ [ [ 'css', 'index', 'index_body'],
363
+ [ 'tpl', 'index', 'index_body']
364
+ ],
365
+ 'index.index_body.display("' + pDivId + '")',
366
+ true );
367
+ },
368
+
369
+ display: function (pDivId) {
370
+ var myHtml = tb.loader.tplget('index','index_body');
371
+ tb.div.replace( pDivId, myHtml );
372
+ tb.element.require(
373
+ [ [ 'js', 'tourtable', 'ddata'] ,
374
+ [ 'js', 'tourtable', 'rightcolumn'] ,
375
+ [ 'js', 'tourtable', 'leftcolumn'] ,
376
+ [ 'js', 'tourtable', 'leftcolumnline'] ,
377
+ [ 'js', 'tourtable', 'middlecolumn1line'] ,
378
+ [ 'js', 'tourtable', 'middlecolumn2line'] ,
379
+ [ 'js', 'tourtable', 'middlecolumn3line'] ,
380
+ [ 'js', 'tourtable', 'middlecolumn1'] ,
381
+ [ 'js', 'tourtable', 'middlecolumn2'] ,
382
+ [ 'js', 'tourtable', 'middlecolumn3'] ,
383
+ [ 'js', 'user', 'user_login'] ,
384
+ [ 'js', 'tb', 'pos'] ,
385
+ [ 'js', 'tb', 'md5'] ,
386
+ [ 'js', 'tb', 'tbDate'] ,
387
+ [ 'js', 'tb', 'tbCurrency'] ,
388
+ [ 'css', 'tourtable', 'middlecolumn'] ,
389
+ [ 'css', 'tourtable', 'rightcolumn'] ,
390
+ [ 'css', 'tourtable', 'leftcolumn'] ,
391
+ [ 'css', 'tourtable', 'leftcolumnline'] ,
392
+ [ 'css', 'tourtable', 'middlecolumn1'] ,
393
+ [ 'css', 'tourtable', 'middlecolumn2'] ,
394
+ [ 'css', 'tourtable', 'middlecolumn3'] ,
395
+ [ 'css', 'tourtable', 'middlecolumn1line'] ,
396
+ [ 'css', 'tourtable', 'middlecolumn2line'] ,
397
+ [ 'css', 'tourtable', 'middlecolumn3line'] ,
398
+ [ 'tpl', 'tourtable', 'rightcolumn'] ,
399
+ [ 'tpl', 'tourtable', 'leftcolumn'] ,
400
+ [ 'tpl', 'tourtable', 'leftcolumnline'] ,
401
+ [ 'tpl', 'tourtable', 'middlecolumn1line'] ,
402
+ [ 'tpl', 'tourtable', 'middlecolumn2line'] ,
403
+ [ 'tpl', 'tourtable', 'middlecolumn3line'] ,
404
+ [ 'tpl', 'tourtable', 'middlecolumn1'] ,
405
+ [ 'tpl', 'tourtable', 'middlecolumn2'] ,
406
+ [ 'tpl', 'tourtable', 'middlecolumn3'] ,
407
+ [ 'tpl', 'tourtable', 'middlecolumn'] ,
408
+ [ 'js', 'tourtable', 'middlecolumn']
409
+ ] );
410
+ tb.element.show( 'toprightcontainer', 'user', 'user_login' );
411
+ }
412
+
413
+ };
414
+
415
+ ```
416
+
417
+ When I find the time I will turn into standalone web component using local storage, since it is a historic archievement IMHO. For now I have more pressing tasks to do.
418
+
419
+
420
+ ## The Fallout
421
+
422
+ I am an autist, which I didn't know back then BTW.
423
+
424
+ Above all that means, if you focus on something, you keep focussed for life. And I focused on twoBirds, really.
425
+
426
+ So I was burnt as a programmer, because I have a hard time working with the current standard frameworks.
427
+
428
+ Now try to find a programmer job without using standard frameworks.
429
+
430
+ In the end I lost my existence 3 times over the past 20 years, with all the consequences.
431
+
432
+ No pity requested, I always pulled myself out of the mud. Thats just the way things go. But if feel tempted, you can [fund this](https://gofund.me/076c614c).
433
+
434
+ I really want **Micro Components** to become a web standard also.
435
+
436
+ I don't regret still working on the basic idea. As long as I can, I will continue doing so.
File without changes
File without changes