@webqit/oohtml 3.1.0 → 3.1.3
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 +68 -67
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -7,13 +7,13 @@
|
|
|
7
7
|
|
|
8
8
|
**[On the Agenda](#on-the-agenda) • [Modular HTML](#modular-html) • [HTML Imports](#html-imports) • [Data Binding](#data-binding) • [Data Plumbing](#data-plumbing) • [Polyfill](#polyfill) • [Examples](#examples) • [License](#license)**
|
|
9
9
|
|
|
10
|
-
Object-Oriented HTML (OOHTML) is a set of features that extend standard HTML and the DOM to enable authoring modular, reusable and reactive markup - with a "buildless", web-native workflow as design goal! This project presents what "modern HTML" could
|
|
10
|
+
Object-Oriented HTML (OOHTML) is a set of features that extend standard HTML and the DOM to enable authoring modular, reusable and reactive markup - with a "buildless", web-native workflow as design goal! This project presents what "modern HTML" could mean today!
|
|
11
11
|
|
|
12
12
|
Building Single Page Applications? OOHTML is a special love letter!
|
|
13
13
|
|
|
14
14
|
<details><summary>Versions</summary>
|
|
15
15
|
|
|
16
|
-
*This is documentation for `OOHTML@
|
|
16
|
+
*This is documentation for `OOHTML@3`. (Looking for [`OOHTML@1`](https://github.com/webqit/oohtml/tree/v1.10.4)?)*
|
|
17
17
|
|
|
18
18
|
</details>
|
|
19
19
|
|
|
@@ -21,7 +21,7 @@ Building Single Page Applications? OOHTML is a special love letter!
|
|
|
21
21
|
|
|
22
22
|
<details><summary>Show</summary>
|
|
23
23
|
|
|
24
|
-
Vanilla HTML is unsurprisingly becoming
|
|
24
|
+
Vanilla HTML is unsurprisingly becoming the most compelling option for an increasing number of developers! But the current authoring experience still leaves much to be desired in how the language lacks modularity, reusability, and other fundamental capabilities like data binding! Authors still have to rely on tools - or, to say the least, have to do half of the work in HTML and half in JS - to get even basic things working!
|
|
25
25
|
|
|
26
26
|
This project pursues an object-oriented approach to HTML and implicitly revisits much of what inhibits the idea of a *component* architecture for HTML!
|
|
27
27
|
|
|
@@ -42,13 +42,13 @@ This project pursues an object-oriented approach to HTML and implicitly revisits
|
|
|
42
42
|
|
|
43
43
|
Modular HTML is a markup pattern that lets us write arbitrary markup as self-contained objects - with each *encapsulating* their own structure, styling and logic!
|
|
44
44
|
|
|
45
|
-
OOHTML makes this possible
|
|
45
|
+
OOHTML makes this possible by introducing "namespacing" and style and script scoping!
|
|
46
46
|
|
|
47
47
|
### Namespacing
|
|
48
48
|
|
|
49
49
|
Naming things is hard! That's especially so where you have one global namespace and a miriad of potentially conflicting names to coordinate!
|
|
50
50
|
|
|
51
|
-
Here, we get the `namespace` attribute for designating an element as own naming context for identifiers instead of the global namespace:
|
|
51
|
+
Here, we get the `namespace` attribute for designating an element as own naming context for identifiers instead of the global document namespace:
|
|
52
52
|
|
|
53
53
|
```html
|
|
54
54
|
<div id="user" namespace>
|
|
@@ -124,11 +124,11 @@ console.log(window.foo); // div
|
|
|
124
124
|
|
|
125
125
|
</details>
|
|
126
126
|
|
|
127
|
-
### Scoping
|
|
127
|
+
### Style and Script Scoping
|
|
128
128
|
|
|
129
|
-
We often need a way to keep things like
|
|
129
|
+
We often need a way to keep things like component-specific stylesheets and scripts [scoped to a component](https://vuejs.org/guide/scaling-up/sfc.html).
|
|
130
130
|
|
|
131
|
-
Here, we get the `scoped` attribute for
|
|
131
|
+
Here, we get the `scoped` attribute for doing just that:
|
|
132
132
|
|
|
133
133
|
```html
|
|
134
134
|
<div>
|
|
@@ -144,7 +144,7 @@ Here, we get the `scoped` attribute for *scoping* said element-specific styleshe
|
|
|
144
144
|
</div>
|
|
145
145
|
```
|
|
146
146
|
|
|
147
|
-
**-->** *with a complementary API that exposes said assets
|
|
147
|
+
**-->** *with a complementary API that exposes said assets for low-level access*:
|
|
148
148
|
|
|
149
149
|
```js
|
|
150
150
|
let { styleSheets, scripts } = user; // APIs that are analogous to the document.styleSheets, document.scripts properties
|
|
@@ -152,9 +152,9 @@ let { styleSheets, scripts } = user; // APIs that are analogous to the document.
|
|
|
152
152
|
|
|
153
153
|
<details><summary>Learn more</summary>
|
|
154
154
|
|
|
155
|
-
|
|
155
|
+
Here, the `scoped` has two effects on the `<script>` element:
|
|
156
156
|
|
|
157
|
-
+ The `this` keyword is
|
|
157
|
+
+ The `this` keyword is implicitly bound to the script's host element
|
|
158
158
|
+ The `<script>` element is executed again on each re-insertion to the DOM
|
|
159
159
|
|
|
160
160
|
</details>
|
|
@@ -169,7 +169,7 @@ OOHTML makes this possible in just simple conventions - via a new `def` attribut
|
|
|
169
169
|
|
|
170
170
|
A module here is any piece of markup that can be reused.
|
|
171
171
|
|
|
172
|
-
Here, we get the `def` attribute for defining those -
|
|
172
|
+
Here, we get the `def` attribute for defining those - both at the `<template>` element level and at its contents (*fragment*) level:
|
|
173
173
|
|
|
174
174
|
```html
|
|
175
175
|
<head>
|
|
@@ -203,7 +203,7 @@ Here, we get the `def` attribute for defining those - either as whole *module* o
|
|
|
203
203
|
|
|
204
204
|
We shouldn't need a different mechanism to work with remote content.
|
|
205
205
|
|
|
206
|
-
Here, we get
|
|
206
|
+
Here, we get remote-loading modules with same `<template>` element using the `src` attribute:
|
|
207
207
|
|
|
208
208
|
```html
|
|
209
209
|
<template def="foo" src="/foo.html"></template>
|
|
@@ -222,7 +222,7 @@ Here, we get the `<template src>` element for that:
|
|
|
222
222
|
<div def="fragment2"></div>
|
|
223
223
|
```
|
|
224
224
|
|
|
225
|
-
**-->** *which
|
|
225
|
+
**-->** *which borrow from how `src` works in elements like `<img>`; terminating with either a `load` or an `error` event*:
|
|
226
226
|
|
|
227
227
|
```js
|
|
228
228
|
foo.addEventListener('load', loadCallback);
|
|
@@ -231,9 +231,9 @@ foo.addEventListener('error', errorCallback);
|
|
|
231
231
|
|
|
232
232
|
### Declarative Module Imports
|
|
233
233
|
|
|
234
|
-
|
|
234
|
+
HTML snippets should be reusable in HTML itself!
|
|
235
235
|
|
|
236
|
-
Here, we get an `<import>` element that lets us do that
|
|
236
|
+
Here, we get an `<import>` element that lets us do just that:
|
|
237
237
|
|
|
238
238
|
```html
|
|
239
239
|
<body>
|
|
@@ -251,13 +251,14 @@ Here, we get an `<import>` element that lets us do that declaratively:
|
|
|
251
251
|
|
|
252
252
|
<details><summary>All in realtime</summary>
|
|
253
253
|
|
|
254
|
-
|
|
254
|
+
Here, import *refs* are live bindings that are highly sensitive to:
|
|
255
255
|
|
|
256
|
-
+ changes in the *ref* itself (
|
|
257
|
-
+ changes in the referenced *defs* themselves (
|
|
256
|
+
+ changes in the *ref* itself (on being defined/undefined/redefined)
|
|
257
|
+
+ changes in the referenced *defs* themselves (on being added/removed/loaded)
|
|
258
258
|
|
|
259
259
|
And an `<import>` element that has been resolved will self-restore in the event that:
|
|
260
260
|
|
|
261
|
+
+ the above changes resolve to no imports.
|
|
261
262
|
+ the previously slotted contents have *all* been programmatically removed and slot is empty.
|
|
262
263
|
|
|
263
264
|
</details>
|
|
@@ -277,13 +278,13 @@ The above resolved imports would thus give us something like:
|
|
|
277
278
|
</body>
|
|
278
279
|
```
|
|
279
280
|
|
|
280
|
-
But they also will need to remember the exact imported nodes that they manage so as to be able to re-establish
|
|
281
|
+
But they also will need to remember the exact imported nodes that they manage so as to be able to re-establish relevant relationships on getting to the client. This information is automatically encoded as part of the serialised element itself, in something like:
|
|
281
282
|
|
|
282
283
|
```html
|
|
283
284
|
<!--<import ref="/foo/nested#fragment2" nodecount="1"></import>-->
|
|
284
285
|
```
|
|
285
286
|
|
|
286
|
-
Now, on getting to the client and "
|
|
287
|
+
Now, on getting to the client and getting "hydrated" back into an `<import>` element, that extra bit of information is decoded, and original relationships are formed again. But, the `<import>` element itself stays invisible in the DOM while still continuing to kick as above!
|
|
287
288
|
|
|
288
289
|
> Note: We know we're on the server when `window.webqit.env === 'server'`. This flag is automatically set by OOHTML's current SSR engine: [OOHTML-SSR](https://github.com/webqit/oohtml-ssr)
|
|
289
290
|
|
|
@@ -305,7 +306,7 @@ const moduleObject2 = document.import('/foo/nested#fragment2');
|
|
|
305
306
|
console.log(moduleObject2.value); // divElement
|
|
306
307
|
```
|
|
307
308
|
|
|
308
|
-
**-->** *with the `moduleObject.value` property being a live property for when results are asynchronous; e.g.
|
|
309
|
+
**-->** *with the `moduleObject.value` property being a live property for when results are delivered asynchronous; e.g. in the case of remote modules*:
|
|
309
310
|
|
|
310
311
|
```js
|
|
311
312
|
Observer.observe(moduleObject2, 'value', e => {
|
|
@@ -313,7 +314,7 @@ Observer.observe(moduleObject2, 'value', e => {
|
|
|
313
314
|
});
|
|
314
315
|
```
|
|
315
316
|
|
|
316
|
-
**-->** *with an equivalent `callback` option on the `import()`
|
|
317
|
+
**-->** *with an equivalent `callback` option on the `import()` API itself*:
|
|
317
318
|
|
|
318
319
|
```js
|
|
319
320
|
document.import('/foo#fragment1', divElement => {
|
|
@@ -321,7 +322,7 @@ document.import('/foo#fragment1', divElement => {
|
|
|
321
322
|
});
|
|
322
323
|
```
|
|
323
324
|
|
|
324
|
-
**-->** *with an optional `live` parameter for staying subscribed to
|
|
325
|
+
**-->** *with an optional `live` parameter for staying subscribed to live results*:
|
|
325
326
|
|
|
326
327
|
```js
|
|
327
328
|
const moduleObject2 = document.import('/foo/nested#fragment2', true/*live*/);
|
|
@@ -337,7 +338,7 @@ document.import('/foo#fragment1', true/*live*/, divElement => {
|
|
|
337
338
|
});
|
|
338
339
|
```
|
|
339
340
|
|
|
340
|
-
*...both of which
|
|
341
|
+
*...both of which get notified on doing something like the below*:
|
|
341
342
|
|
|
342
343
|
```js
|
|
343
344
|
document.querySelector('template[def="foo"]').content.firstElementChild.remove();
|
|
@@ -362,9 +363,9 @@ setTimeout(() => {
|
|
|
362
363
|
|
|
363
364
|
### Lazy-Loading Modules
|
|
364
365
|
|
|
365
|
-
We
|
|
366
|
+
We should be able to defer module loading until we really need them.
|
|
366
367
|
|
|
367
|
-
Here, we get the `loading="lazy"` directive for that; and loading is only then triggered on the first attempt to import
|
|
368
|
+
Here, we get the `loading="lazy"` directive for that; and loading is only then triggered on the first attempt to import those or their contents:
|
|
368
369
|
|
|
369
370
|
```html
|
|
370
371
|
<!-- Loading doesn't happen until the first time this is being accessed -->
|
|
@@ -382,9 +383,9 @@ const moduleObject2 = document.import('/foo#fragment1'); // Triggers module load
|
|
|
382
383
|
|
|
383
384
|
### Module Inheritance
|
|
384
385
|
|
|
385
|
-
We'll often have repeating markup structures.
|
|
386
|
+
We'll often have repeating markup structures across component layouts.
|
|
386
387
|
|
|
387
|
-
Here, we get module nesting with inheritance to
|
|
388
|
+
Here, we get module nesting with inheritance to facilitate more reusability:
|
|
388
389
|
|
|
389
390
|
```html
|
|
390
391
|
<template def="foo">
|
|
@@ -432,14 +433,14 @@ Here, we get module nesting with inheritance to simplify that:
|
|
|
432
433
|
|
|
433
434
|
We should be able to have *relative* import refs that resolve against local contexts in the document tree.
|
|
434
435
|
|
|
435
|
-
Here, we
|
|
436
|
+
Here, we get just that - as "Imports Contexts", which could be:
|
|
436
437
|
|
|
437
438
|
+ Simple Base Path Contexts ([below](#base-path-contexts))
|
|
438
439
|
+ Scoped Module Contexts ([below](#scoped-module-contexts))
|
|
439
440
|
+ Named Contexts ([below](#named-contexts))
|
|
440
441
|
+ Extended Scoped Module Contexts ([below](#extended-scoped-module-contexts))
|
|
441
442
|
|
|
442
|
-
|
|
443
|
+
And to facilitate thinking in contexts, we also get an `Element.prototype.import()` API for context-based module imports.
|
|
443
444
|
|
|
444
445
|
#### "Base Path" Contexts
|
|
445
446
|
|
|
@@ -499,7 +500,7 @@ const response = contextElement.import('#fragment1'); // Relative path (beginnin
|
|
|
499
500
|
|
|
500
501
|
Some modules will only be relevant within a specific context in the page, and those wouldn't need to have a business with the global scope.
|
|
501
502
|
|
|
502
|
-
Here, we get the `scoped` attribute for scoping those to their respective contexts, to give us an *object-scoped* module system (like what Scoped Registries
|
|
503
|
+
Here, we get the `scoped` attribute for scoping those to their respective contexts, to give us an *object-scoped* module system (like what Scoped Registries seek to be to Custom Elements):
|
|
503
504
|
|
|
504
505
|
```html
|
|
505
506
|
<section> <!-- Host object -->
|
|
@@ -532,7 +533,7 @@ const globalModule = contextElement.import('/foo#fragment1'); // Absolute path,
|
|
|
532
533
|
|
|
533
534
|
#### Named Contexts
|
|
534
535
|
|
|
535
|
-
Imports Contexts may be named:
|
|
536
|
+
Imports Contexts may be named for direct referencing:
|
|
536
537
|
|
|
537
538
|
```html
|
|
538
539
|
<body contextname="context1" importscontext="/foo/nested">
|
|
@@ -598,7 +599,7 @@ Data binding is about declaratively binding the UI to application data, wherein
|
|
|
598
599
|
|
|
599
600
|
OOHTML makes this possible in just simple conventions - via a new comment-based data-binding syntax `<?{ }?>` and a complementary new `expr` attribute!
|
|
600
601
|
|
|
601
|
-
And there's one more: Quantum Scripts
|
|
602
|
+
And there's one more: Quantum Scripts for when we need to write extended reactive logic on the UI!
|
|
602
603
|
|
|
603
604
|
### Discrete Data-Binding
|
|
604
605
|
|
|
@@ -761,7 +762,7 @@ Bindings are resolved in realtime! And in fact, for lists, in-place mutations -
|
|
|
761
762
|
|
|
762
763
|
<details><summary>With SSR support</summary>
|
|
763
764
|
|
|
764
|
-
For lists, generated item elements are automatically assigned a corresponding key with a `data-key` attribute! This helps in remapping generated item nodes to their
|
|
765
|
+
For lists, generated item elements are automatically assigned a corresponding key with a `data-key` attribute! This helps in remapping generated item nodes to their corresponding entry in *iteratee* during a rerendering or during hydration.
|
|
765
766
|
|
|
766
767
|
</details>
|
|
767
768
|
|
|
@@ -769,7 +770,7 @@ For lists, generated item elements are automatically assigned a corresponding ke
|
|
|
769
770
|
|
|
770
771
|
We often still need to write more serious reactive logic on the UI than a declarative data-binding language can provide for. But we shouldn't need to reach for special tooling or some "serious" programming paradigm on top of JavaScript.
|
|
771
772
|
|
|
772
|
-
Here, from the same `<script>` element we already write, we get a direct upgrade path to reactive programming in just the addition of an attribute: `quantum
|
|
773
|
+
Here, from the same `<script>` element we already write, we get a direct upgrade path to reactive programming in just the addition of an attribute: `quantum` - for [Quantum Scripts](https://github.com/webqit/quantum-js):
|
|
773
774
|
|
|
774
775
|
```html
|
|
775
776
|
<script quantum>
|
|
@@ -785,7 +786,7 @@ Here, from the same `<script>` element we already write, we get a direct upgrade
|
|
|
785
786
|
</script>
|
|
786
787
|
```
|
|
787
788
|
|
|
788
|
-
**-->** *which gives us fine-grained reactivity on top of literal JavaScript syntax; and which adds up really well with the `scoped` attribute*:
|
|
789
|
+
**-->** *which gives us fine-grained reactivity on top of literal JavaScript syntax; and which adds up really well with the `scoped` attribute for Single Page Applications*:
|
|
789
790
|
|
|
790
791
|
```html
|
|
791
792
|
<main>
|
|
@@ -880,7 +881,7 @@ But while that is automatic, DOM event handlers bound via `addEventListener()` w
|
|
|
880
881
|
|
|
881
882
|
## Data Plumbing
|
|
882
883
|
|
|
883
|
-
Components often need to manage,
|
|
884
|
+
Components often need to manage, and be managed by, dynamic data. That could get pretty problematic and messy if all of that should go on DOM nodes as direct properties:
|
|
884
885
|
|
|
885
886
|
<details><summary>Example</summary>
|
|
886
887
|
|
|
@@ -960,7 +961,7 @@ connectedCallback() {
|
|
|
960
961
|
}
|
|
961
962
|
```
|
|
962
963
|
|
|
963
|
-
**-->** *and with the Observer API in the picture for reactivity*:
|
|
964
|
+
**-->** *and with the Observer API in the picture all the way for reactivity*:
|
|
964
965
|
|
|
965
966
|
```js
|
|
966
967
|
Observer.observe(document.bindings, mutations => {
|
|
@@ -992,7 +993,7 @@ node.bindings.style = 'tall-dark'; // Reactive assignment
|
|
|
992
993
|
delete node.bindings.style; // Reactive deletion
|
|
993
994
|
```
|
|
994
995
|
|
|
995
|
-
For mutations at a deeper level to be reactive, the corresponding Observer API method
|
|
996
|
+
For mutations at a deeper level to be reactive, the corresponding Observer API method would need to be used:
|
|
996
997
|
|
|
997
998
|
```js
|
|
998
999
|
Observer.set(document.bindings.app, 'title', 'Demo App!!!');
|
|
@@ -1003,9 +1004,9 @@ Observer.deleteProperty(document.bindings.app, 'title');
|
|
|
1003
1004
|
|
|
1004
1005
|
### The Context API
|
|
1005
1006
|
|
|
1006
|
-
|
|
1007
|
+
Component trees on the typical UI often call for more than the normal top-down flow of data that the Bindings API facilitates. A child may 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.
|
|
1007
1008
|
|
|
1008
|
-
Interestingly, the Context API is the resolution mechanism behind HTML Imports and Data Binding in OOHTML!
|
|
1009
|
+
Interestingly, the Context API is the underlying resolution mechanism behind HTML Imports and Data Binding in OOHTML!
|
|
1009
1010
|
|
|
1010
1011
|
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.
|
|
1011
1012
|
|
|
@@ -1019,11 +1020,11 @@ const node = document.querySelector('my-element');
|
|
|
1019
1020
|
// ------------
|
|
1020
1021
|
// Prepare and fire request event
|
|
1021
1022
|
const requestParams = { kind: 'html-imports', detail: '/foo#fragment1' };
|
|
1022
|
-
const
|
|
1023
|
+
const response = node.contexts.request(requestParams);
|
|
1023
1024
|
|
|
1024
1025
|
// ------------
|
|
1025
1026
|
// Handle response
|
|
1026
|
-
console.log(
|
|
1027
|
+
console.log(response.value); // It works!
|
|
1027
1028
|
```
|
|
1028
1029
|
|
|
1029
1030
|
**-->** *and the `contexts.attach()` and `contexts.detach()` methods for attaching/detaching providers at arbitrary levels in the DOM tree*:
|
|
@@ -1054,10 +1055,10 @@ document.contexts.detach(fakeImportsContext);
|
|
|
1054
1055
|
In the current OOHTML implementation, the Context API interfaces are exposed via the global `webqit` object:
|
|
1055
1056
|
|
|
1056
1057
|
```js
|
|
1057
|
-
const { DOMContext, DOMContextRequestEvent, DOMContextResponse } = window.webqit;
|
|
1058
|
+
const { DOMContext, DOMContextRequestEvent, DOMContextResponse, DuplicateContextError } = window.webqit;
|
|
1058
1059
|
```
|
|
1059
1060
|
|
|
1060
|
-
|
|
1061
|
+
Now, by design...
|
|
1061
1062
|
|
|
1062
1063
|
+ a provider will automatically adopt the `contextname`, if any, of its host element:
|
|
1063
1064
|
|
|
@@ -1078,7 +1079,7 @@ In addition...
|
|
|
1078
1079
|
|
|
1079
1080
|
```js
|
|
1080
1081
|
const requestParams = { kind: FakeImportsContext.kind, targetContext: 'context1', detail: '/foo#fragment1' };
|
|
1081
|
-
const
|
|
1082
|
+
const response = node.contexts.request(requestParams);
|
|
1082
1083
|
```
|
|
1083
1084
|
|
|
1084
1085
|
+ and providers of same kind could be differentiated by an extra "detail" - an arbitrary value passed to the constructor:
|
|
@@ -1096,7 +1097,7 @@ In addition...
|
|
|
1096
1097
|
static kind = 'html-imports';
|
|
1097
1098
|
matchEvent(event) {
|
|
1098
1099
|
// The default request matching algorithm + "detail" matching
|
|
1099
|
-
return super.matchEvent() && event.detail === this.detail;
|
|
1100
|
+
return super.matchEvent(event) && event.detail === this.detail;
|
|
1100
1101
|
}
|
|
1101
1102
|
handle(event) {
|
|
1102
1103
|
console.log(event.detail);
|
|
@@ -1116,9 +1117,9 @@ In addition...
|
|
|
1116
1117
|
|
|
1117
1118
|
```js
|
|
1118
1119
|
// Handle response without a callback
|
|
1119
|
-
const
|
|
1120
|
-
console.log(
|
|
1121
|
-
Observer.observe(
|
|
1120
|
+
const response = node.contexts.request(requestParams);
|
|
1121
|
+
console.log(response.value); // It works!
|
|
1122
|
+
Observer.observe(response, 'value', e => {
|
|
1122
1123
|
console.log(e.value); // It works live!
|
|
1123
1124
|
});
|
|
1124
1125
|
```
|
|
@@ -1149,7 +1150,7 @@ In addition...
|
|
|
1149
1150
|
}
|
|
1150
1151
|
```
|
|
1151
1152
|
|
|
1152
|
-
...
|
|
1153
|
+
...or optionally implement a `subscribed` and `unsubscribed` lifecycle hook for when a "live" event enters and leaves the instance:
|
|
1153
1154
|
|
|
1154
1155
|
```js
|
|
1155
1156
|
// Define a CustomContext class
|
|
@@ -1175,7 +1176,7 @@ In addition...
|
|
|
1175
1176
|
+ live requests are terminated via the returned `DOMContextResponse` object...
|
|
1176
1177
|
|
|
1177
1178
|
```js
|
|
1178
|
-
|
|
1179
|
+
response.abort();
|
|
1179
1180
|
```
|
|
1180
1181
|
|
|
1181
1182
|
...or via an initially specified custom `AbortSignal`:
|
|
@@ -1187,10 +1188,10 @@ In addition...
|
|
|
1187
1188
|
```
|
|
1188
1189
|
|
|
1189
1190
|
```js
|
|
1190
|
-
abortController.abort(); // Which also calls
|
|
1191
|
+
abortController.abort(); // Which also calls response.abort();
|
|
1191
1192
|
```
|
|
1192
1193
|
|
|
1193
|
-
+ now,
|
|
1194
|
+
+ now, where a node in a provider's subtree is suddenly attached an identical provider, any live requests the super provider may be serving are automatically "claimed" by the sub provider:
|
|
1194
1195
|
|
|
1195
1196
|
```js
|
|
1196
1197
|
document: // 'fake-provider' here
|
|
@@ -1199,7 +1200,7 @@ In addition...
|
|
|
1199
1200
|
└── body: // 'fake-provider' here. Our request above is now served from here.
|
|
1200
1201
|
```
|
|
1201
1202
|
|
|
1202
|
-
And
|
|
1203
|
+
And where the sub provider is suddenly detached from said node, any live requests it may have served are automatically hoisted back to super provider.
|
|
1203
1204
|
|
|
1204
1205
|
```js
|
|
1205
1206
|
document: // 'fake-provider' here. Our request above is now served from here.
|
|
@@ -1208,11 +1209,11 @@ In addition...
|
|
|
1208
1209
|
└── body:
|
|
1209
1210
|
```
|
|
1210
1211
|
|
|
1211
|
-
While, in all,
|
|
1212
|
+
While, in all, the requesting code is saved that "admin" work!
|
|
1212
1213
|
|
|
1213
1214
|
</details>
|
|
1214
1215
|
|
|
1215
|
-
**-->** *all of which gives us
|
|
1216
|
+
**-->** *all of which gives us a standardized API underneath context-based features in HTML - like HTMLImports and Data Binding*:
|
|
1216
1217
|
|
|
1217
1218
|
```html
|
|
1218
1219
|
<div contextname="vendor1">
|
|
@@ -1234,35 +1235,35 @@ In addition...
|
|
|
1234
1235
|
```js
|
|
1235
1236
|
// ------------
|
|
1236
1237
|
// Equivalent import() approach
|
|
1237
|
-
const
|
|
1238
|
+
const response = myElement.import('@vendor1/foo#fragment1');
|
|
1238
1239
|
|
|
1239
1240
|
// ------------
|
|
1240
1241
|
// Equivalent Context API approach
|
|
1241
1242
|
const requestParams = { kind: 'html-imports', targetContext: 'vendor1', detail: 'foo#fragment1' };
|
|
1242
|
-
const
|
|
1243
|
+
const response = myElement.contexts.request(requestParams);
|
|
1243
1244
|
|
|
1244
1245
|
// ------------
|
|
1245
1246
|
// Handle response
|
|
1246
|
-
console.log(
|
|
1247
|
+
console.log(response.value);
|
|
1247
1248
|
```
|
|
1248
1249
|
|
|
1249
1250
|
```js
|
|
1250
1251
|
// ------------
|
|
1251
1252
|
// Context API request for bindings
|
|
1252
1253
|
const requestParams = { kind: 'bindings', targetContext: 'vendor2', detail: 'app' };
|
|
1253
|
-
const
|
|
1254
|
+
const response = myElement.contexts.request(requestParams);
|
|
1254
1255
|
|
|
1255
1256
|
// ------------
|
|
1256
1257
|
// Handle response
|
|
1257
|
-
console.log(
|
|
1258
|
+
console.log(response.value.title);
|
|
1258
1259
|
```
|
|
1259
1260
|
|
|
1260
1261
|
## Polyfill
|
|
1261
1262
|
|
|
1262
|
-
OOHTML is being developed as something to be used today—via a polyfill. This is an intentional effort that
|
|
1263
|
+
OOHTML is being developed as something to be used today—via a polyfill. This is an intentional effort that has continued to ensure that the proposal evolves through a practice-driven process.
|
|
1263
1264
|
|
|
1264
1265
|
<details><summary>Load from a CDN<br>
|
|
1265
|
-
└───────── <a href="https://bundlephobia.com/result?p=@webqit/oohtml"><img align="right" src="https://img.shields.io/badge/21.
|
|
1266
|
+
└───────── <a href="https://bundlephobia.com/result?p=@webqit/oohtml"><img align="right" src="https://img.shields.io/badge/21.8%20kB-black"></a></summary>
|
|
1266
1267
|
|
|
1267
1268
|
```html
|
|
1268
1269
|
<script src="https://unpkg.com/@webqit/oohtml/dist/main.lite.js"></script>
|
|
@@ -1354,7 +1355,7 @@ If you'll be going ahead to build a real app with OOHTML, you may want to consid
|
|
|
1354
1355
|
|
|
1355
1356
|
...still gives the `window` object in the console.
|
|
1356
1357
|
|
|
1357
|
-
+ **Scoped CSS**. This feature is only in "concept" implementation and doesn't work right now as is. The current implementation simply wraps `<style scoped>` blocks in an `@scope {}` block - which itself isn't supported in any browser
|
|
1358
|
+
+ **Scoped CSS**. This feature is only in "concept" implementation and doesn't work right now as is. The current implementation simply wraps `<style scoped>` blocks in an `@scope {}` block - which itself isn't supported in any browser *yet*. To try this "concept" implementation, set the `style.strategy` config to `@scope`:
|
|
1358
1359
|
|
|
1359
1360
|
```html
|
|
1360
1361
|
<head>
|
|
@@ -1381,7 +1382,7 @@ If you'll be going ahead to build a real app with OOHTML, you may want to consid
|
|
|
1381
1382
|
</style>
|
|
1382
1383
|
```
|
|
1383
1384
|
|
|
1384
|
-
|
|
1385
|
+
Browser support for `@scope {}` style blocks may be coming soon, but in the meantime, you could try one of the polyfills for `<style scoped>` out there; e.g. [samthor/scoped](https://github.com/samthor/scoped):
|
|
1385
1386
|
|
|
1386
1387
|
```html
|
|
1387
1388
|
<script src="https://unpkg.com/style-scoped/scoped.min.js"></script>
|