@webqit/oohtml 3.1.0 → 3.1.2
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 +29 -28
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -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 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"!
|
|
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
|
-
Import *refs* are live
|
|
254
|
+
Import *refs* are live bindings that are highly sensitive to:
|
|
255
255
|
|
|
256
256
|
+ changes in the *ref* itself (in being defined/undefined/redefined)
|
|
257
257
|
+ changes in the referenced *defs* themselves (in 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. asynchronously loaded
|
|
309
|
+
**-->** *with the `moduleObject.value` property being a live property for when results are delivered asynchronous; e.g. with an asynchronously loaded module*:
|
|
309
310
|
|
|
310
311
|
```js
|
|
311
312
|
Observer.observe(moduleObject2, 'value', e => {
|
|
@@ -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 the below*:
|
|
341
342
|
|
|
342
343
|
```js
|
|
343
344
|
document.querySelector('template[def="foo"]').content.firstElementChild.remove();
|
|
@@ -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 -->
|
|
@@ -950,7 +951,7 @@ document.bind({ name: 'James Boye', cool: '100%' }, { merge: true });
|
|
|
950
951
|
console.log(document.bindings); // { signedIn: false, hot: '100%', name: 'James Boye', cool: '100%' }
|
|
951
952
|
```
|
|
952
953
|
|
|
953
|
-
**-->** *which also provides an easy way to
|
|
954
|
+
**-->** *which also provides an easy way to passing data down a component tree*:
|
|
954
955
|
|
|
955
956
|
```js
|
|
956
957
|
// Inside a custom element
|
|
@@ -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
|
|
1009
|
+
Interestingly, the Context API is the underlying resolution mechanism for 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*:
|
|
@@ -1057,7 +1058,7 @@ In the current OOHTML implementation, the Context API interfaces are exposed via
|
|
|
1057
1058
|
const { DOMContext, DOMContextRequestEvent, DOMContextResponse } = 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:
|
|
@@ -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
|
```
|
|
@@ -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,7 +1188,7 @@ 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
1194
|
+ now, when 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:
|
|
@@ -1212,7 +1213,7 @@ In addition...
|
|
|
1212
1213
|
|
|
1213
1214
|
</details>
|
|
1214
1215
|
|
|
1215
|
-
**-->** *all of which gives us the imperative equivalent of context-based
|
|
1216
|
+
**-->** *all of which gives us the imperative equivalent of declarative context-based features like HTMLImports and Data Binding*:
|
|
1216
1217
|
|
|
1217
1218
|
```html
|
|
1218
1219
|
<div contextname="vendor1">
|
|
@@ -1234,27 +1235,27 @@ 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
|