-
Notifications
You must be signed in to change notification settings - Fork 12
/
Copy pathdocumentation-original.html
558 lines (438 loc) · 20.3 KB
/
documentation-original.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>dom99</title>
<meta name="viewport" content="width=device-width">
<link rel="stylesheet" href="css/polyfill.css">
<link rel="stylesheet" href="css/documentation.css">
<link rel="icon" href="./images/99.jpg">
</head>
<body>
<script type="module" src="deps/documentation.min.js"></script>
<h1>dom99</h1>
<main>
<nav>
<a href="./" class="nav-ext">Overview</a>
<a href="#about">About</a>
<a href="#howto">How to</a>
<a href="#examples1">Examples</a>
<a href="#components">Components</a>
<a href="#plugins">Plugins</a>
<a href="#details">Details</a>
<a href="./changelog.html#timeline">Time-Line</a>
<a href="./api/global.html" hidden>API</a>
</nav>
<article id="about">
<h2>About</h2>
<img alt="dom99" src="./images/99.jpg">
<section>
<h3>What</h3>
<p>dom99 is a <a href="https://en.wikipedia.org/wiki/JavaScript">JavaScript</a>
framework that provides a nice API to manipulate the DOM: Select nodes, add event listeners, two-way data binding, populate HTML templates with data, leverage custom elements.</p>
</section>
<section>
<h3>Why</h3>
<p>To spend less time in the development. dom99 encourages you to link the UI and the logic declaratively. dom99 naturally promotes to put only markup in HTML, only styling in CSS, and only logic in JS, instead of mixing things up. That prevents a lot of bugs from even existing. dom99 is fast, the source file is small (about 3KB minified+ gziped), has no external dependencies and is written respecting modern ES and HTML standards. dom99 is simple by design. There are no build steps required.</p>
</section>
<section>
<h3>Why not</h3>
<ul>
<li>No support for some old browsers</li>
<li>Fear of the unknown</li>
<li>You have already a working code base that is maintainable</li>
<li>You need a comprehensive framework that has all the tools/components/CSS you need out of the box.</li>
<li>No built-in server side rendering mechanism</li>
</ul>
</section>
<section>
<h3>How</h3>
<p>dom99 exposes a JS API Using <code>d.start();</code> executes directives found in the HTML. After that, the DOM is linked to directly accessible JavaScript variables. Changing those JavaScript variables will propagate the changes to the DOM and vice versa.</p>
</section>
<section>
<h3>Download</h3>
<p><a href="https://github.com/GrosSacASac/DOM99">GitHub</a></p>
<ul>
<li><code><a href="https://www.npmjs.com/package/dom99">npm install dom99</a></code></li>
<li><a download="dom99.iife.js" href="https://unpkg.com/dom99/built/dom99.iife.js">dom99.iife.js</a></li>
<li><a download="dom99.es.js" href="https://unpkg.com/dom99/built/dom99.es.js">dom99.es.js</a></li>
<li>Use a <a href="https://github.com/GrosSacASac/create-dom99-app/">premade starter pack create-dom99-app</a></li>
</ul>
</section>
<section>
<h3>Browser Support</h3>
<ul>
<li>Chrome</li>
<li>Samsung Internet</li>
<li>Firefox</li>
<li>Opera</li>
<li>Safari</li>
<li>Edge</li>
<li>Internet Explorer 9+* </li>
</ul>
<p>* Supports also requires</p>
<p>Support may also require transpilation. You may also want to use built/dom99.iife.es5.min.js.Support may also require other polyfills and transpilation see documentation/examples/css/basics.css and polyfills/ and documentation/examples/</p>
<ol>
<li><a href="https://www.npmjs.com/package/@babel/polyfill">ES2015 polyfill found under node_modules/@babel/polyfill/dist/polyfill.min.js</a></li>
<li><a href="https://www.npmjs.com/package/template-mb">template-mb</a></li>
<li><a href="https://github.com/GrosSacASac/DOM99/blob/21.1.4/polyfills/template-mb-bootstrap.js">template-mb-bootstrap</a></li>
<li><a href="https://github.com/GrosSacASac/DOM99/blob/21.1.4/documentation/css/polyfill.css">polyfill.css</a></li>
<li><a href="https://github.com/GrosSacASac/DOM99/blob/21.1.4/polyfills/remove.js">remove.js</a></li>
<li><a href="https://github.com/GrosSacASac/DOM99/blob/21.1.4/polyfills/dom-hidden.js">dom-hidden.js</a></li>
</ol>
</section>
<section>
<h3>License</h3>
<p>Copyright GrosSacASacs</p>
<p>Distributed under the Boost Software License,
Version 1.0</p>
</section>
<section>
<h3>Community</h3>
<h4>Chat</h4>
<p><a href="https://miaou.dystroy.org/2813?dom99" title="Chat on Miaou"><img alt="Chat on Miaou" src="https://miaou.dystroy.org/static/shields/room-en.svg?v=1"></a></p>
<h4>Issues reports</h4>
<p><a href="https://github.com/GrosSacASac/DOM99/issues">Report issue</a></p>
<h4>Contributing</h4>
<p>Contributions are welcome. <a href="https://github.com/GrosSacASac/DOM99/blob/master/CONTRIBUTING.md">CONTRIBUTING.md</a></p>
</section>
</article>
<article id="howto">
<h2>How to</h2>
<h3>In HTML</h3>
<p>dom99 will browse the DOM and react if an element has one of the following attributes</p>
<ul>
<li>data-variable : Data binding between DOM element and JS variable</li>
<li>data-element : Select an element</li>
<li>data-function : Attaches an event listener</li>
<li>data-list : Display a JS Array as a list in the DOM</li>
<li>data-use: Which element to use a list item in combination with data-list</li>
<li>data-template : Declare a html template to build components</li>
<li>data-scope: Create a scope context</li>
</ul>
<p>The general syntax is</p>
<p><code><tag data-keyword="token1-token2" > text ... </tag></code></p>
<p>If you are not using browserify or ES modules you need to include this script tag in your html <strong>before</strong> other scripts that access dom99.</p>
<pre><code><script src="./node_modules/dom99/built/dom99.iife.js"></script>
<script src="js/yourJavascriptFile.js"></script></code></pre>
<h3>In JavaScript</h3>
<pre><code>import * as d from "./node_modules/dom99/source/dom99.js";
// to start using dom99 pre selected elements use this statement
d.start();</code></pre>
<h3>data-function and d.functions for event listeners</h3>
<p>Store functions in the d.functions object</p>
<pre><code class="js">d.functions.functionName = aFunction;</code></pre>
<p>aFunction is called when you click this button</p>
<pre><code><button data-function="click-functionName">Action</button></code></pre>
<h3>data-variable and d.variables and d.feed for data binding</h3>
<p>To changes the text of <code><p data-variable="talkings"></p></code> and all other element that share the variable "talkings"</p>
<p><code>d.feed({talkings: `Hi`});</code></p>
<p>Use the same data-variable="talkings" on <code><input></code> elements for two-way data-binding</p>
<h3>data-list and data-use to display a list</h3>
<pre><code><ol data-list="numbers" data-use="li"></ol></code></pre>
<pre><code>d.feed(`numbers`, [
1,
2,
3,
]);
</code></pre>
<h3>data-element and d.elements for direct element manipulation</h3>
<pre><code>d.elements.title.remove();</code></pre>
<p>Removes <code><h1 data-element="title">Hello</h1></code></p>
<h3>data-template to declare templates</h3>
<pre><code><template data-template="d-comment">
<p data-variable="text">default text</p>
<time data-variable="date">default time</time>
</template></code></pre>
<h3>data-scope to put html templates copies</h3>
<pre><code class="html"><d-comment data-scope="first"></d-comment>
<d-comment data-scope="second"></d-comment></code></pre>
<p>To edit the first <d-comment></p>
<pre><code>d.feed(`first`, {
text: `A new comment`,
date: `Today`
});</code></pre>
<h2>Complete overview</h2>
<pre><code>d.start();</code></pre>
<p>Use start after having stored all the event handlers in d.functions, and before using references to nodes stored in d.elements.</p>
<p>This will look the for dom99 directives in the document tree.</p>
<h3>Use HTML templates, it is healthy</h3>
<p>There are 2 ways to use HTML templates</p>
<ul><li>Static Load time template rendering with custom elements</li><li>Run time template rendering and insertion</li></ul>
<p>Both ways are <strong>complementary</strong> and use the same core ideas. To illustrate this imagine you want to have a web page with an article and comments.
When the page loads you want to display the article and already display the 2 last comments without another client-server round-trip, later when the user scrolls down or clicks a button to show more
comments we load more comments into the page with dynamic template insertion. We here define a comment as some text and a date. What we want initially is something like this</p>
<h3>Dynamic template injection in general</h3>
<pre><code><body>
<template data-template="d-tagname">
<p data-variable="text" ></p>
Any HTML ...
</template>
...
<div data-element="target"></div>
</body>
// manual, see templates3.html to see how to use shortcuts
// 0 make a description
let customElementDescription = {
[`tagName`]: `d-tagname`,
[`data-scope`]: `key`
}
// 1 create HTML Element
let customElement = d.createElement2(customElementDescription);
// 2 link it
d.start({ startElement: customElement });
// 3 insert the Element that has a clone as a child in the DOM
d.elements[`target`].appendChild(customElement);</code></pre>
<p>I encourage you to encapsulate what changes in functions.</p>
<h4>About templates</h4>
<p>If you have a <code><template></code> in your page, it is inert and not rendered. However the template itself with a <code>data-template</code> can be used to create copies of the content of the template. These copies can be inserted in your document. The value of the attribute data-scope is called the key in this documentation. You can use d.variables d.elements and d.functions inside templates. To differentiate the multiple template clones you use the key. For instance:</p>
<pre><code>d.variables[`key>text`] = `A string`;
d.elements[`key>elementName`].className = `class-fun`;</code></pre>
<p>Or</p>
<pre><code>d.variables[d.scopeFromArray([`key`, `text`])] = `A string`;
d.elements[d.scopeFromArray([`key`, `elementName`])].className = ...</code></pre>
<p>d.functions function the other way around. You use the same event handlers for all template copies
and handle differences with <code>d.scopeFromEvent(event)</code>. Example</p>
<pre><code><!-- HTML -->
<template data-template="d-tagname">
<button data-function="close" >CLOSE (X)</button>
<button data-function="update" >Update (X)</button>
<p data-variable="text" >Default Text</p>
<div data-element="status" class="status" ></div>
<ul data-list="myList" data-use="li" >
<li>Default List Item</li>
</ul>
<div data-scope="encapsulated" >
<p data-variable="text" >Other Default Text</p>
</div>
Any HTML ...
</template>
<!-- used like -->
<d-tagName data-scope="myKey0"></d-tagName>
<!-- or -->
<div is="d-tagName" data-scope="myKey1"></div>
<!-- or -->
<div data-list="listKey" data-use="d-tagName"></div>
// JS
d.functions.update = function (event) {
const scope = d.scopeFromEvent(event);
// you can access variables, elements, lists scopes with d.scopeFromArray
// - text -
const textScope = d.scopeFromArray([scope, `text`]);
const textVariable = d.variables[textScope]; // read
d.feed(textScope, `New Text`); // write
// - elements -
const statusScope = d.scopeFromArray([scope, `status`]);
const statusDiv = d.variables[statusScope]; // read
statusDiv.classList.add(`updated`) // use
// - list -
const listScope = d.scopeFromArray([scope, `myList`]);
const listVariable = d.variables[listScope]; // read
d.feed(listScope, [
`a`,
`b`,
`c`
]); // write with side effect
// - encapsulated -
// here d.contextFromArray takes a 3 item list to go 1 level deeper the tree
const encapsulatedTextScope = d.contextFromArray([scope, `encapsulated`, `text`]);
const textVariable2 = d.variables[encapsulatedTextScope]; // read
d.feed(encapsulatedTextScope, `New Encapsulated Text`); // write
// this looks verbose but it works for any kind of deep html composition.
//If you want to target a specific element or variable you can directly write
d.variables[`key>text`];
};</code></pre>
<p>Note that d.scopeFromEvent only works on child of an element that use data-scope or equivalent, not on the element with scopeFromEvent itself</p>
</article>
<article id="examples1">
<h2>Some Examples</h2>
<p>
<a href="./examples">Even more examples</a>
</p>
<p id="errors"><noscript>Enable JavaScript to view certain part of this page.</noscript></p>
<template data-template="d-htmljsresult">
<article class="htmljsandoutput" data-element="penContainer">
<h3 data-variable="title"></h3>
<section>
<h4>HTML</h4>
<pre><code data-variable="HtmlSourceDisplay"></code></pre>
</section>
<section>
<h4>JS</h4>
<pre><code data-variable="JsSourceDisplay"></code></pre>
</section>
<section>
<h4>Result</h4>
<div data-element="ResultDisplay"></div>
</section>
</article>
</template>
<d-htmljsresult data-scope="Hello World"></d-htmljsresult>
<d-htmljsresult data-scope="Hello World 2"></d-htmljsresult>
<d-htmljsresult data-scope="Multiplier"></d-htmljsresult>
<d-htmljsresult data-scope="Lists"></d-htmljsresult>
<d-htmljsresult data-scope="Lists2"></d-htmljsresult>
<d-htmljsresult data-scope="Composition"></d-htmljsresult>
</article>
<article id="components">
<h2>Components</h2>
<h3>Dialogs</h3>
<p><a href="https://github.com/GrosSacASac/DOM99/tree/master/components/yesNoDialog">Readme (Markdown)</a></p>
<h3>ReadTextFile</h3>
<p><a href="https://github.com/GrosSacASac/DOM99/tree/master/components/readTextFile">Readme</a></p>
</article>
<article id="plugins">
<h2>Plugins</h2>
<h3>Keyboard</h3>
<p><a href="https://github.com/GrosSacASac/DOM99/tree/master/plugins/keyboard">Readme</a></p>
<h3>Shake</h3>
<p><a href="https://github.com/GrosSacASac/DOM99/tree/master/plugins/shake">Readme</a></p>
</article>
<article id="details">
<h2>Details</h2>
<article id="extra-tips">
<h3>Extra Tips</h3>
<p>View components in components/ folder</p>
<p>You can handle new HTML with <code>d.start({ startElement: document.body });</code>. Already processed elements won't be affected at all because the * is added to the attribute value after that.</p>
<p>Open your console, handy warnings may appear to help.</p>
<p>You can add a class to your app element container like "not-ready". Then in your CSS display that .not-ready with a loading animation. Once you have initialized everything you can remove the "not-ready" class name.</p>
<p>You can change the dom99 syntax. To do that follow the instructions in js/dom99ConfigurationExample.js</p>
<p>Server side rendering is compatible with dom99, but you have to glue it together yourself. A future version will make this built in with a node extension.</p>
</article>
<article id="performance">
<h2>Performance</h2>
<h3>General Tips</h3>
<p>In short: Rendering and painting the DOM is slow,
JavaScript itself is fast.
Simply changing a class name of an element can cause the browser to do heavy computation under the hood.
For very simple programs, performance may not be an issue at all.</p>
<ul><li>Avoid Document Object Model (DOM) Access in big loops</li>
<li>Instead compute the result in your loop first, then assign the final result to the DOM</li>
<li>Avoid read/write alternations with the DOM</li>
<li>Instead chain reads, then chain writes </li>
<li>Use callbacks or Promises or equivalent for future events (example XMLHttpRequest), never block !</li>
<li>If you have more performance issues, profile first to know what is the cause</li>
<li>If you need to do heavy computation, consider using Web Workers</li>
<li><a href="http://www.html5rocks.com/en/features/performance">More tips</a></li>
<li><a href="https://gist.github.com/paulirish/5d52fb081b3570c81e3a">About layout trashing</a></li></ul>
<h3>How is dom99 fast ?</h3>
<ul><li>Load time element selection and binding instead of runtime element selection and binding </li><li>The abstraction layer is small, no assumptions are made</li><li>No complexity, no dirty checking, no separate model under the hood</li></ul>
</article>
</article>
<!-- Usually inline scripts are bad, but here we use them to display the source of the script with .textContent as well as executing it. Without need to use extra XHRs Also not indented first for pre tags -->
<!-- Hello World -->
<template data-element="Hello WorldHtml">
<span data-variable="myVariable"></span>
</template>
<script type="module" data-element="Hello WorldJs">
d.feed({myVariable : "Hello World"});
</script>
<!-- Hello World 2-->
<template data-element="Hello World 2Html">
<label>Input: <input data-variable="text"></label>
<p data-variable="text"></p>
</template>
<script type="module" data-element="Hello World 2Js">
d.feed({text : "Hello dom99"});
</script>
<!-- Multiplier-->
<template data-element="MultiplierHtml">
<label>a<input data-variable="a" data-function="calculate" type="range" min="-1" max="12" step="1"></label>
<span>X</span>
<label>b: <input data-variable="b" data-function="calculate" type="range" min="-1" max="12" step="1"></label>
<span data-variable="a"></span>
<span>X</span>
<span data-variable="b"></span>
<span>=</span>
<output data-variable="result"></output>
</template>
<script type="module" data-element="MultiplierJs">
d.functions.calculate = function (event) {
d.feed({
result: String(Number(d.variables.a) * Number(d.variables.b))
});
};
d.feed({
a: "7",
b: "6"
});
//invoke event handler to compute the first result
d.functions.calculate();
</script>
<!-- Lists -->
<template data-element="ListsHtml">
<ul data-list="fruits" data-use="li"></ul>
</template>
<script type="module" data-element="ListsJs">
d.feed("fruits", ["apple", "kiwi", "banana", "orange"]);
</script>
<!-- Lists2 -->
<template data-element="Lists2Html">
<img data-variable="image" alt="">
<label>Favourite image
<select data-variable="image" data-list="images" data-use="option"></select>
</label>
<p>You selected <span data-variable="image"></span></p>
</template>
<script type="module" data-element="Lists2Js">
d.feed("images", [
{
textContent: "you",
value: "./images/you.jpg"
},
{
textContent: "boss",
value: "./images/boss.jpg"
},
{
textContent: "sister",
value: "./images/sister.jpg"
}
]);
d.feed("image", d.variables.images[0].value);
</script>
<!-- Composition -->
<!-- Template inside template causes problems in IE -->
<template data-template="user-element">
<div class="user">
<img data-variable="picture" alt="user-picture" class="user-picture">
<p data-variable="bio" class="user-bio">SHORT BIO</p>
<button class="user-contact">Contact</button>
</div>
</template>
<template data-element="CompositionHtml">
<!-- Define the template for an user
every user has a picture, a short biography, and a contact button -->
<!-- <template data-template="user-element">
<div class="user">
<img data-variable="picture" alt="user-picture" class="user-picture">
<p data-variable="bio" class="user-bio">SHORT BIO</p>
<button class="user-contact">Contact</button>
</div>
</template> -->
<!-- This div is the container for each user.
The list variable name is "users" and the template used is "user-element"
native html elements can also be used to display a list -->
<div data-list="users" data-use="user-element"></div>
</template>
<script type="module" data-element="CompositionJs">
d.feed({users :
[
{
picture: "./images/boss.jpg",
bio: "Loves biking and skating"
},
{
picture: "./images/sister.jpg",
bio: "Drinks tons of café."
}
]});
</script>
<script type="module">
d.start();
</script>
<link rel="stylesheet" media="(prefers-color-scheme: light)" href="./deps/tomorrow.css">
<link rel="stylesheet" media="(prefers-color-scheme: dark)" href="./deps/solarized-dark.css">
</main>
</body>
</html>