@webqit/oohtml 3.1.17 → 3.1.19
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.
- package/README.md +98 -43
- package/dist/main.js +18 -14
- package/dist/main.js.map +2 -2
- package/dist/main.lite.js +15 -11
- package/dist/main.lite.js.map +2 -2
- package/dist/namespaced-html.js +1 -1
- package/dist/namespaced-html.js.map +2 -2
- package/dist/scoped-css.js +5 -1
- package/dist/scoped-css.js.map +2 -2
- package/package.json +1 -1
- package/src/namespaced-html/index.js +100 -100
- package/src/scoped-css/index.js +3 -3
package/README.md
CHANGED
|
@@ -143,16 +143,16 @@ If you'll be going ahead to build a real app with OOHTML, you may want to consid
|
|
|
143
143
|
+ `document.bindings` now becomes: `document.wqBindings`,
|
|
144
144
|
+ etc.
|
|
145
145
|
|
|
146
|
-
|
|
146
|
+
<details><summary>Show the full syntax table</summary>
|
|
147
147
|
|
|
148
|
-
Spec:
|
|
148
|
+
**Spec: `<meta name="data-binding">`**
|
|
149
149
|
|
|
150
150
|
| Config | Default Syntax | Description |
|
|
151
151
|
| :----- | :------------- | :---------- |
|
|
152
152
|
| `attr.expr` | `expr` | The "expr" attribute for inline data binding. ([Docs](#inline-data-binding)) |
|
|
153
153
|
| `attr.itemIndex` | `data-index` | The "item index" attribute for assigning indexes to list items. ([Docs](#inline-data-binding)) |
|
|
154
154
|
|
|
155
|
-
Spec:
|
|
155
|
+
**Spec: `<meta name="bindings-api">`**
|
|
156
156
|
|
|
157
157
|
| Config | Default Syntax | Description |
|
|
158
158
|
| :----- | :------------- | :---------- |
|
|
@@ -160,14 +160,14 @@ If you'll be going ahead to build a real app with OOHTML, you may want to consid
|
|
|
160
160
|
| `api.bind` | `bind` | The `document.bind()` and `Element.prototype.bind()` methods. ([Docs](#the-bindings-api)) |
|
|
161
161
|
| `api.bindings` | `bindings` | The `document.bindings` and `Element.prototype.bindings` object properties. ([Docs](#the-bindings-api)) |
|
|
162
162
|
|
|
163
|
-
Spec:
|
|
163
|
+
**Spec: `<meta name="context-api">`**
|
|
164
164
|
|
|
165
165
|
| Config | Default Syntax | Description |
|
|
166
166
|
| :----- | :------------- | :---------- |
|
|
167
167
|
| `attr.contextname` | `contextname` | The "context name" attribute on arbitrary elements. ([Docs](#the-context-api)) |
|
|
168
168
|
| `api.contexts` | `contexts` | The `document.contexts` and `Element.prototype.contexts` object properties. ([Docs](#the-context-api)) |
|
|
169
169
|
|
|
170
|
-
Spec:
|
|
170
|
+
**Spec: `<meta name="html-imports">`**
|
|
171
171
|
|
|
172
172
|
| Config | Default Syntax | Description |
|
|
173
173
|
| :----- | :------------- | :---------- |
|
|
@@ -182,7 +182,8 @@ If you'll be going ahead to build a real app with OOHTML, you may want to consid
|
|
|
182
182
|
| `api.defs` | `defs` | The readonly object property for accessing a `<template>`'s list of definitions. ([Docs](#module-definition)) |
|
|
183
183
|
| `api.import` | `import` | The `document.import()` and `Element.prototype.import()` methods. ([Docs](#imperative-module-imports)) |
|
|
184
184
|
|
|
185
|
-
|
|
185
|
+
|
|
186
|
+
**Spec: `<meta name="namespaced-html">`**
|
|
186
187
|
|
|
187
188
|
| Config | Default Syntax | Description |
|
|
188
189
|
| :----- | :------------- | :---------- |
|
|
@@ -190,9 +191,11 @@ If you'll be going ahead to build a real app with OOHTML, you may want to consid
|
|
|
190
191
|
| `attr.id` | `id` | The "id" attribute on arbitrary elements. ([Docs](#namespacing)) |
|
|
191
192
|
| `api.namespace` | `namespace` | The "namespace" object property on arbitrary elements. ([Docs](#namespacing)) |
|
|
192
193
|
|
|
193
|
-
Spec:
|
|
194
|
+
**Spec: `<meta name="scoped-css">`** (TODO)
|
|
195
|
+
|
|
196
|
+
**Spec: `<meta name="scoped-js">`** (TODO)
|
|
194
197
|
|
|
195
|
-
|
|
198
|
+
</details>
|
|
196
199
|
|
|
197
200
|
</details>
|
|
198
201
|
|
|
@@ -219,7 +222,7 @@ OOHTML is effectively different from Web Components (and from the related Declar
|
|
|
219
222
|
|
|
220
223
|
## Modular HTML
|
|
221
224
|
|
|
222
|
-
|
|
225
|
+
The modern UI is best approached with a modular architecture (think UI component frameworks) wherein we are able to author the bits and pieces as self-contained objects - enabling us *encapsulate* structure, styling and logic!
|
|
223
226
|
|
|
224
227
|
OOHTML makes this possible by introducing "namespacing" and style and script scoping!
|
|
225
228
|
|
|
@@ -227,7 +230,23 @@ OOHTML makes this possible by introducing "namespacing" and style and script sco
|
|
|
227
230
|
|
|
228
231
|
Naming things is hard! That's especially so where you have one global namespace and a miriad of potentially conflicting identifiers to coordinate!
|
|
229
232
|
|
|
230
|
-
|
|
233
|
+
<details><summary>Learn more</summary>
|
|
234
|
+
|
|
235
|
+
You want to see how IDs are, in fact, by default, exposed as global variables:
|
|
236
|
+
|
|
237
|
+
```html
|
|
238
|
+
<div id="foo"><div>
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
```js
|
|
242
|
+
console.log(window.foo); // div
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
[Read more](https://stackoverflow.com/questions/6381425/is-there-a-spec-that-the-id-of-elements-should-be-made-global-variable)
|
|
246
|
+
|
|
247
|
+
</details>
|
|
248
|
+
|
|
249
|
+
Here, we get a modular naming convention that let's us create a naming context for identifiers in a given subtree - by means of a new `namespace` attribute:
|
|
231
250
|
|
|
232
251
|
```html
|
|
233
252
|
<form>
|
|
@@ -276,14 +295,21 @@ And when used from the document context, these are resolved against top-level ID
|
|
|
276
295
|
```
|
|
277
296
|
|
|
278
297
|
```js
|
|
279
|
-
|
|
280
|
-
|
|
298
|
+
// Namespace aware ID selectors
|
|
299
|
+
console.log(document.querySelector('#user')); // div#user
|
|
300
|
+
console.log(document.querySelector('#~user')); // div#user
|
|
281
301
|
|
|
282
|
-
|
|
283
|
-
|
|
302
|
+
console.log(document.getElementById('user')); // div#user
|
|
303
|
+
console.log(document.getElementById('~user')); // div#user
|
|
304
|
+
|
|
305
|
+
console.log(document.querySelector('#url')); // a#url
|
|
306
|
+
console.log(document.querySelector('#~url')); // null... not directly in the "document" namespace
|
|
307
|
+
|
|
308
|
+
console.log(document.getElementById('url')); // a#url
|
|
309
|
+
console.log(document.getElementById('~url')); // null... not directly in the "document" namespace
|
|
284
310
|
```
|
|
285
311
|
|
|
286
|
-
And these also play well as
|
|
312
|
+
And these also play well as navigation targets, with additional support for path expressions given a hierarchy of namespaces:
|
|
287
313
|
|
|
288
314
|
```html
|
|
289
315
|
<a href="#~user/email">Jump to Email</a>
|
|
@@ -334,27 +360,55 @@ function changeCallback(changes) {
|
|
|
334
360
|
}
|
|
335
361
|
```
|
|
336
362
|
|
|
337
|
-
</details>
|
|
363
|
+
</details>
|
|
338
364
|
|
|
339
|
-
<details><summary>
|
|
365
|
+
<details><summary>Implementation details</summary>
|
|
340
366
|
|
|
341
|
-
|
|
367
|
+
In the current implementation, a small random string is automatically prepended to each ID and IDREF token in the DOM to give the browser something "unique" to work with, but without that implementation detail leaking into your application. So, while an element may be seen in the browser console as having a random hash prepended to their ID or IDREF:
|
|
342
368
|
|
|
343
369
|
```html
|
|
344
|
-
|
|
370
|
+
<!-- Original -->
|
|
371
|
+
<label for="~real-id">Question 1:</label>
|
|
372
|
+
<input id="real-id">
|
|
373
|
+
```
|
|
374
|
+
|
|
375
|
+
```html
|
|
376
|
+
<!-- Transformed -->
|
|
377
|
+
<label for="~hg3j:real-id">Question 1:</label>
|
|
378
|
+
<input id="~hg3j:real-id">
|
|
345
379
|
```
|
|
346
380
|
|
|
381
|
+
the values your application sees are the unprefixed IDs and IDREFs:
|
|
382
|
+
|
|
347
383
|
```js
|
|
348
|
-
console.log(
|
|
384
|
+
console.log(label.htmlFor); // ~real-id
|
|
385
|
+
console.log(input.id); // real-id
|
|
386
|
+
|
|
387
|
+
console.log(label.getAttribute('for')); // ~real-id
|
|
388
|
+
console.log(input.attributes[0].value); // real-id
|
|
349
389
|
```
|
|
350
390
|
|
|
351
|
-
|
|
391
|
+
Now, for URL targets, e.g. `#~user/email`, the "target" element is given a custom `:target` class while it matches the URL fragment, and this may be accessed in CSS as:
|
|
392
|
+
|
|
393
|
+
```css
|
|
394
|
+
.\:target {
|
|
395
|
+
background-color: whitesmoke;
|
|
396
|
+
}
|
|
397
|
+
```
|
|
398
|
+
|
|
399
|
+
or, to be more complete:
|
|
400
|
+
|
|
401
|
+
```css
|
|
402
|
+
:target, .\:target {
|
|
403
|
+
background-color: whitesmoke;
|
|
404
|
+
}
|
|
405
|
+
```
|
|
352
406
|
|
|
353
407
|
</details>
|
|
354
408
|
|
|
355
409
|
### Style and Script Scoping
|
|
356
410
|
|
|
357
|
-
We often need a way to keep component-specific
|
|
411
|
+
We often need a way to keep component-specific style sheets and scripts [scoped to a component](https://vuejs.org/guide/scaling-up/sfc.html). **This is especially crucial to "page components" in an SPA architecture.**
|
|
358
412
|
|
|
359
413
|
Here, we get a new `scoped` attribute that lets us do just that:
|
|
360
414
|
|
|
@@ -372,7 +426,7 @@ Here, we get a new `scoped` attribute that lets us do just that:
|
|
|
372
426
|
</div>
|
|
373
427
|
```
|
|
374
428
|
|
|
375
|
-
And the special
|
|
429
|
+
And the special namespace-aware ID selector is supported from within scoped style sheets:
|
|
376
430
|
|
|
377
431
|
```html
|
|
378
432
|
<div namespace>
|
|
@@ -398,15 +452,15 @@ let { styleSheets, scripts } = user; // APIs that are analogous to the document.
|
|
|
398
452
|
Here, the `scoped` attribute has two effects on the `<script>` element:
|
|
399
453
|
|
|
400
454
|
+ The `this` keyword is implicitly bound to the script's host element
|
|
401
|
-
+ The `<script>` element is executed
|
|
455
|
+
+ The `<script>` element is (re)executed on each re-insertion into the DOM
|
|
402
456
|
|
|
403
457
|
</details>
|
|
404
458
|
|
|
405
459
|
## HTML Imports
|
|
406
460
|
|
|
407
|
-
HTML Imports is a realtime *import* system for HTML that's drawn entirely on HTML - and
|
|
461
|
+
HTML Imports is a realtime *import* system for HTML that's drawn entirely on HTML - and which addresses a different pain point in comparison to [the abandoned `<link type="import">` feature](https://www.w3.org/TR/html-imports/) and the [HTML Modules proposal](https://github.com/WICG/webcomponents/blob/gh-pages/proposals/html-modules-explainer.md)! **Something like it is the [`<defs>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/defs) and [`<use>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/use) system in SVG.**
|
|
408
462
|
|
|
409
|
-
Here, we get a way to both define and
|
|
463
|
+
Here, we get a way to both define and reuse a snippet out of *same* document:
|
|
410
464
|
|
|
411
465
|
```html
|
|
412
466
|
<head>
|
|
@@ -423,7 +477,7 @@ Here, we get a way to both define and use a snippet within *same* document:
|
|
|
423
477
|
</body>
|
|
424
478
|
```
|
|
425
479
|
|
|
426
|
-
...
|
|
480
|
+
...while optionally supporting remote content without a change in paradigm:
|
|
427
481
|
|
|
428
482
|
```html
|
|
429
483
|
<head>
|
|
@@ -479,7 +533,7 @@ Here, we get the `def` attribute for defining those - both at the `<template>` e
|
|
|
479
533
|
|
|
480
534
|
We shouldn't need a different mechanism to work with remote content.
|
|
481
535
|
|
|
482
|
-
Here, OOHTML
|
|
536
|
+
Here, OOHTML extends the `<template>` with an `src` attribute that lets us have self-loading `<template>` elements:
|
|
483
537
|
|
|
484
538
|
```html
|
|
485
539
|
<template def="foo" src="/foo.html"></template>
|
|
@@ -633,7 +687,7 @@ setTimeout(() => {
|
|
|
633
687
|
}, 1000);
|
|
634
688
|
```
|
|
635
689
|
|
|
636
|
-
|
|
690
|
+
<!--<details><summary>Extended Imports concepts</summary>-->
|
|
637
691
|
|
|
638
692
|
### Lazy-Loading Modules
|
|
639
693
|
|
|
@@ -865,19 +919,19 @@ const contextElement = document.querySelector('div');
|
|
|
865
919
|
const result = contextElement.import('foo#fragment2'); // the local module: foo#fragment2, and if not found, the inherited module: /bar/nested#fragment2
|
|
866
920
|
```
|
|
867
921
|
|
|
868
|
-
|
|
922
|
+
<!--</details>-->
|
|
869
923
|
|
|
870
924
|
## Data Binding
|
|
871
925
|
|
|
872
|
-
Data binding is
|
|
926
|
+
Data binding is the idea of declaratively binding the UI to application data, wherein the relevant parts of the UI *automatically* update as application state changes.
|
|
873
927
|
|
|
874
928
|
OOHTML makes this possible in just simple conventions - via a new comment-based data-binding syntax `<?{ }?>` and a complementary new `expr` attribute!
|
|
875
929
|
|
|
876
|
-
And for when we need to write
|
|
930
|
+
And for when we need to write extensive reactive logic on the UI, a perfect answer: Quantum Scripts!
|
|
877
931
|
|
|
878
932
|
### Discrete Data-Binding
|
|
879
933
|
|
|
880
|
-
Here, we get a comment-based data-binding
|
|
934
|
+
Here, we get a comment-based data-binding syntax `<?{ }?>` (or `<!--?{ }?-->`), **which works as a regular HTML comment** but also as an insertion point for application data:
|
|
881
935
|
|
|
882
936
|
```js
|
|
883
937
|
<html>
|
|
@@ -1147,10 +1201,11 @@ Now, in each case above, reactivity terminates on script's removal from the DOM
|
|
|
1147
1201
|
```js
|
|
1148
1202
|
const script = document.querySelector('script[quantum]');
|
|
1149
1203
|
// const script = document.querySelector('main').scripts[0];
|
|
1150
|
-
script.
|
|
1204
|
+
script.state.dispose();
|
|
1205
|
+
// which also happens on doing script.remove()
|
|
1151
1206
|
```
|
|
1152
1207
|
|
|
1153
|
-
But
|
|
1208
|
+
But note that while said termination is automatic on script's removal, DOM event handlers bound via `addEventListener()` would still need to be terminated in their own way.
|
|
1154
1209
|
|
|
1155
1210
|
</details>
|
|
1156
1211
|
|
|
@@ -1206,7 +1261,7 @@ node.bindings.style = 'tall-dark';
|
|
|
1206
1261
|
node.bindings.normalize = true;
|
|
1207
1262
|
```
|
|
1208
1263
|
|
|
1209
|
-
**-->** *with a complementary `bind()` method that lets us make mutations in batch*:
|
|
1264
|
+
**-->** *with a complementary `bind()` method that lets us make multiple mutations in one batch*:
|
|
1210
1265
|
|
|
1211
1266
|
```js
|
|
1212
1267
|
// ------------
|
|
@@ -1259,7 +1314,7 @@ const node = document.querySelector('my-element');
|
|
|
1259
1314
|
node.bindings.style = 'tall-dark';
|
|
1260
1315
|
```
|
|
1261
1316
|
|
|
1262
|
-
<details><summary>
|
|
1317
|
+
<details><summary>Implementation details</summary>
|
|
1263
1318
|
|
|
1264
1319
|
In the current OOHTML implementation, the `document.bindings` and `Element.prototype.bindings` APIs are implemented as proxies over their actual bindings interface to enable some interface-level reactivity. This lets us have reactivity over literal property assignments and deletions on these interfaces:
|
|
1265
1320
|
|
|
@@ -1279,9 +1334,9 @@ Observer.deleteProperty(document.bindings.app, 'title');
|
|
|
1279
1334
|
|
|
1280
1335
|
### The Context API
|
|
1281
1336
|
|
|
1282
|
-
Component trees on the typical UI often call for more than the normal top-down flow of data that the Bindings API facilitates.
|
|
1337
|
+
Component trees on the typical UI often call for more than the normal "top-down" flow of data that the Bindings API facilitates. We still often require the ability to "look up" the component tree to directly access specific data, or in other words, get data from "context". This is where a Context API comes in.
|
|
1283
1338
|
|
|
1284
|
-
Interestingly, the Context API is the underlying resolution
|
|
1339
|
+
Interestingly, the Context API is the underlying "resolution" infrastructure for the Namespace API and the Data Binding and HTML Imports features in OOHTML!
|
|
1285
1340
|
|
|
1286
1341
|
Here, we simply leverage the DOM's existing event system to fire a "request" event and let an arbitrary "provider" in context fulfill the request. This becomes very simple with the Context API which is exposed on the document object and on element instances as a readonly `contexts` property.
|
|
1287
1342
|
|
|
@@ -1610,8 +1665,8 @@ The following is a Listbox component lifted directly from the [ARIA Authoring Pr
|
|
|
1610
1665
|
<div id="ss_elem_list"
|
|
1611
1666
|
tabindex="0"
|
|
1612
1667
|
role="listbox"
|
|
1613
|
-
aria-labelledby="ss_elem">
|
|
1614
|
-
<ul role="group" aria-labelledby="cat"
|
|
1668
|
+
aria-labelledby="~ss_elem">
|
|
1669
|
+
<ul role="group" namespace aria-labelledby="~cat">
|
|
1615
1670
|
<li role="presentation" id="cat">
|
|
1616
1671
|
Land
|
|
1617
1672
|
</li>
|
|
@@ -1631,7 +1686,7 @@ The following is a Listbox component lifted directly from the [ARIA Authoring Pr
|
|
|
1631
1686
|
Raccoon
|
|
1632
1687
|
</li>
|
|
1633
1688
|
</ul>
|
|
1634
|
-
<ul role="group" aria-labelledby="cat"
|
|
1689
|
+
<ul role="group" namespace aria-labelledby="~cat">
|
|
1635
1690
|
<li role="presentation" id="cat">
|
|
1636
1691
|
Water
|
|
1637
1692
|
</li>
|
|
@@ -1645,7 +1700,7 @@ The following is a Listbox component lifted directly from the [ARIA Authoring Pr
|
|
|
1645
1700
|
Eel
|
|
1646
1701
|
</li>
|
|
1647
1702
|
</ul>
|
|
1648
|
-
<ul role="group" aria-labelledby="cat"
|
|
1703
|
+
<ul role="group" namespace aria-labelledby="~cat">
|
|
1649
1704
|
<li role="presentation" id="cat">
|
|
1650
1705
|
Air
|
|
1651
1706
|
</li>
|