@epa-wg/custom-element 0.0.20 → 0.0.21

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/.editorconfig ADDED
@@ -0,0 +1,11 @@
1
+ root = true
2
+
3
+ [*]
4
+ charset = utf-8
5
+ end_of_line = lf
6
+ indent_size = 4
7
+ indent_style = space
8
+ insert_final_newline = true
9
+ max_line_length = 120
10
+ tab_width = 4
11
+ trim_trailing_whitespace = true
package/README.md CHANGED
@@ -1,9 +1,9 @@
1
1
  # custom-element
2
- `Declarative Custom Element` (DCE) is a part of pure `Declarative Web Application` stack. A proof of concept as a part of
2
+ `Declarative Custom Element` (DCE) is a part of pure `Declarative Web Application` stack. A proof of concept as a part of
3
3
  [WCCG in Declarative custom elements](https://github.com/w3c/webcomponents-cg/issues/32#issuecomment-1321037301) and [Declarative Web Application](https://github.com/EPA-WG/dwa#readme)
4
- discussion. **NO-JS** The functionality of DCE and its data access does not require programming using JavaScript.
4
+ discussion. **NO-JS** The functionality of DCE and its data access does not require programming using JavaScript.
5
5
 
6
- It allows to define custom HTML tag with template filled from slots, attributes and data `slice` as of now from
6
+ It allows to define custom HTML tag with template filled from slots, attributes and data `slice` as of now from
7
7
  [local-storage][local-storage-demo], [http-request][http-request-demo], [location][location-demo].
8
8
  UI is re-rendered on each data slice change triggered by initialization or DOM event.
9
9
 
@@ -13,16 +13,16 @@ UI is re-rendered on each data slice change triggered by initialization or DOM e
13
13
  | [tests project][git-test-url]
14
14
  | [Chrome devtools pugin][plugin-url]
15
15
 
16
- [![NPM version][npm-image]][npm-url]
17
- [![coverage][coverage-image]][coverage-url]
16
+ [![NPM version][npm-image]][npm-url]
17
+ [![coverage][coverage-image]][coverage-url]
18
18
  [![Published on webcomponents.org][webcomponents-img]][webcomponents-url]
19
19
 
20
20
 
21
21
 
22
22
  <details>
23
23
  <summary> What is DCE? </summary>
24
- DCE provides the next level of abstraction in HTML - native composition. With native implementation which is
25
- streaming parser, streaming transformation, multithreading. native assumes the C/Rust compiled code.
24
+ DCE provides the next level of abstraction in HTML - native composition. With native implementation which is
25
+ streaming parser, streaming transformation, multithreading. native assumes the C/Rust compiled code.
26
26
  There is no place for JavaScript except of polyfill and ability to extend DCE, which otherwise has to be native.
27
27
 
28
28
  The composition assumes the fully functional template and ability to call the template with parameters( custom tag + attributes) .
@@ -113,11 +113,11 @@ comes from XSLT and XPath. Which is natively implemented in all current browsers
113
113
  the seed grows in size as the Pokémon does.</p>
114
114
  </pokemon-tile>
115
115
 
116
- <pokemon-tile title="ninetales" pokemon-id="38" ></pokemon-tile>
116
+ <pokemon-tile title="ninetales" pokemon-id="38" ></pokemon-tile>
117
117
  ```
118
118
  generates HTML
119
119
  ```html
120
- <pokemon-tile title="bulbasaur" data-smile="👼"
120
+ <pokemon-tile title="bulbasaur" data-smile="👼"
121
121
  image-src="https://unpkg.com/pokeapi-sprites@2.0.2/sprites/pokemon/other/dream-world/1.svg"
122
122
  >
123
123
  <h3>bulbasaur</h3>
@@ -126,7 +126,7 @@ generates HTML
126
126
  <p>Bulbasaur is a cute Pokémon born with a large seed firmly affixed to its back;
127
127
  the seed grows in size as the Pokémon does.</p>
128
128
  </pokemon-tile>
129
- <pokemon-tile title="ninetales"
129
+ <pokemon-tile title="ninetales"
130
130
  image-src="https://unpkg.com/pokeapi-sprites@2.0.2/sprites/pokemon/other/dream-world/38.svg"
131
131
  >
132
132
  <h3>ninetales</h3>
@@ -146,16 +146,16 @@ generates HTML
146
146
  * creates a class for custom element extending HTMLElement
147
147
  * registers element by `tag` attribute
148
148
 
149
- NOTE: attempt to register custom element with already registered tag name would fail due to w3c standard limitations.
149
+ NOTE: attempt to register custom element with already registered tag name would fail due to w3c standard limitations.
150
150
  The scoped custom element registry is still a proposal.
151
151
 
152
152
  ### omitting `tag` leads to template instantiation
153
- Whether template is inline or given by `src` attribute, the `custom-element` would be instantiated inline if no `tag`
153
+ Whether template is inline or given by `src` attribute, the `custom-element` would be instantiated inline if no `tag`
154
154
  attribute is given.
155
155
 
156
156
  ### custom element instance
157
- constructor creates XML with
158
- * root matching the tag
157
+ constructor creates XML with
158
+ * root matching the tag
159
159
  * payload
160
160
  * dom nodes with `slot` attribute stay inside
161
161
  * attributes
@@ -180,7 +180,7 @@ See [demo](https://unpkg.com/@epa-wg/custom-element@0.0/demo/external-template.h
180
180
  ## types of template
181
181
  * HTML with DCE syntax ( slots, data slices, xslt operators, etc. )
182
182
  * SVG image, MathML, etc.
183
- * XSLT template. The `datadom` is the XML payload for transformation. In order to be embedded into external document,
183
+ * XSLT template. The `datadom` is the XML payload for transformation. In order to be embedded into external document,
184
184
  this document has to have XML syntax like XHTML. Attempt of including XSLT within HTML file would break the template
185
185
  integrity by parser.
186
186
 
@@ -198,7 +198,7 @@ allows to refer the template withing external document
198
198
  # template syntax
199
199
  [Scoped CSS][css-demo-url] live demo
200
200
  ## styles encapsulation
201
- DCE can have the own styles which would be scoped to the instances.
201
+ DCE can have the own styles which would be scoped to the instances.
202
202
  In order to prevent the style leaking, it has to be defined withing `template` tag:
203
203
  ```html
204
204
  <custom-element>
@@ -250,15 +250,15 @@ The curly braces `{}` in attributes implemented as [attribute value template](ht
250
250
 
251
251
  The names in curly braces are matching the instance attributes. I.e. in XML node `/my-component/attributes/`.
252
252
 
253
- To access payload XPath could start with `/*/payload/`. I.e. `{/*/payload//label}` refers to all `label` tags in payload.
253
+ To access payload XPath could start with `/*/payload/`. I.e. `{/*/payload//label}` refers to all `label` tags in payload.
254
254
 
255
255
  ## Slots
256
- `<slot name="xxx">` is replaced by payload top elements with `slot` attribute matching the name,
256
+ `<slot name="xxx">` is replaced by payload top elements with `slot` attribute matching the name,
257
257
  i.e. slot `xxx` is matching `<i slot="xxx">...</i>` in payload.
258
258
  ```html
259
259
  <custom-element tag="with-description" >
260
260
  <slot name="description">description is not available</slot>
261
- <!-- same as
261
+ <!-- same as
262
262
  <value-of select='/*/payload/*[@slot="description"]'/>
263
263
  -->
264
264
  </custom-element>
@@ -270,7 +270,7 @@ i.e. slot `xxx` is matching `<i slot="xxx">...</i>` in payload.
270
270
  ## loops, variables
271
271
  Loop implemented via [for-each](https://developer.mozilla.org/en-US/docs/Web/XSLT/Element/for-each)
272
272
 
273
- [Variables in XSLT](https://developer.mozilla.org/en-US/docs/Web/XSLT/Element/variable)
273
+ [Variables in XSLT](https://developer.mozilla.org/en-US/docs/Web/XSLT/Element/variable)
274
274
 
275
275
  ## [XPath](https://developer.mozilla.org/en-US/docs/Web/XSLT/Transforming_XML_with_XSLT/The_Netscape_XSLT_XPath_Reference)
276
276
  is available in `{}` in attributes, in `for-each`, `if`, `value-of`, and other XSL tags.
@@ -278,13 +278,13 @@ is available in `{}` in attributes, in `for-each`, `if`, `value-of`, and other X
278
278
  XPath is a selector language to navigate over custom element instance data, attributes, and payload.
279
279
 
280
280
  ## XSLT 1.0
281
- The in-browser native implementation as of now supports [XSLT 1.0](https://www.w3.org/TR/xslt-10/).
282
- File the [change request](https://github.com/EPA-WG/custom-element/issues) for support of another XSLT version or
281
+ The in-browser native implementation as of now supports [XSLT 1.0](https://www.w3.org/TR/xslt-10/).
282
+ File the [change request](https://github.com/EPA-WG/custom-element/issues) for support of another XSLT version or
283
283
  template engine.
284
284
 
285
285
  # troubleshooting
286
286
  ## HTML parser is not compatible with templates
287
- On many tags like `table`, or link `a` the attempt to use XSLT operations could lead to DOM order mismatch to given
287
+ On many tags like `table`, or link `a` the attempt to use XSLT operations could lead to DOM order mismatch to given
288
288
  in template. In such cases the `xhtml:` prefix in front of troubled tag would solve the parsing.
289
289
 
290
290
  ```html
@@ -324,19 +324,19 @@ See [demo source](demo/local-storage.html) for detailed sample.
324
324
  ## template debugging
325
325
  `xml` and `xslt` can be saved to file via for "_copy string contents_" into clipboard.
326
326
 
327
- The XSLT debugger from your favorite IDE can set the breakpoints withing those files and
327
+ The XSLT debugger from your favorite IDE can set the breakpoints withing those files and
328
328
  run transformation under debugger.
329
329
 
330
330
 
331
331
  ## `{}` does not give a value
332
- * try to add as attribute you could observe and put the value of node name or text to identify the current location in data
332
+ * try to add as attribute you could observe and put the value of node name or text to identify the current location in data
333
333
  within template
334
334
  ```xml
335
335
  <b title="{name(*)} : {text()}">xml tag name: <value-of select='name()'/></b>
336
336
  ```
337
337
 
338
338
  [git-url]: https://github.com/EPA-WG/custom-element
339
- [git-test-url]: https://github.com/EPA-WG/custom-element-test
339
+ [git-test-url]: https://github.com/EPA-WG/custom-element-dist
340
340
  [demo-url]: https://unpkg.com/@epa-wg/custom-element@0.0/index.html
341
341
  [css-demo-url]: https://unpkg.com/@epa-wg/custom-element@0.0/demo/scoped-css.html
342
342
  [slice-demo-url]: https://unpkg.com/@epa-wg/custom-element@0.0/demo/data-slices.html
@@ -348,9 +348,9 @@ within template
348
348
  [github-image]: https://cdnjs.cloudflare.com/ajax/libs/octicons/8.5.0/svg/mark-github.svg
349
349
  [npm-image]: https://img.shields.io/npm/v/@epa-wg/custom-element.svg
350
350
  [npm-url]: https://npmjs.org/package/@epa-wg/custom-element
351
- [coverage-image]: https://unpkg.com/@epa-wg/custom-element-test@0.0.20/coverage/coverage.svg
352
- [coverage-url]: https://unpkg.com/@epa-wg/custom-element-test@0.0.20/coverage/lcov-report/index.html
353
- [storybook-url]: https://unpkg.com/@epa-wg/custom-element-test@0.0.20/storybook-static/index.html?path=/story/welcome--introduction
351
+ [coverage-image]: https://unpkg.com/@epa-wg/custom-element-dist@0.0.21/coverage/src/custom-element/coverage.svg
352
+ [coverage-url]: https://unpkg.com/@epa-wg/custom-element-dist@0.0.21/coverage/src/custom-element/index.html
353
+ [storybook-url]: https://unpkg.com/@epa-wg/custom-element-dist@0.0.21/storybook-static/index.html?path=/story/welcome--introduction
354
354
  [sandbox-url]: https://stackblitz.com/github/EPA-WG/custom-element?file=index.html
355
355
  [webcomponents-url]: https://www.webcomponents.org/element/@epa-wg/custom-element
356
356
  [webcomponents-img]: https://img.shields.io/badge/webcomponents.org-published-blue.svg
@@ -116,7 +116,7 @@ writeFileSync( '.././ide/customData-xsl.json', JSON.stringify( vsCode, undefined
116
116
  const intelliJ = {
117
117
  "$schema": "http://json.schemastore.org/web-types",
118
118
  "name": "@epa-wg/custom-element",
119
- "version": "0.0.20",
119
+ "version": "0.0.21",
120
120
  "js-types-syntax": "typescript",
121
121
  "description-markup": "markdown",
122
122
  "contributions": {
@@ -1,4 +1,5 @@
1
1
  export function log(x: any): void;
2
+ export function deepEqual(a: any, b:any): boolean|0;
2
3
 
3
4
  /**
4
5
  * @summary Declarative Custom Element as W3C proposal PoC with native(XSLT) based templating
package/custom-element.js CHANGED
@@ -63,37 +63,6 @@ assureSlot( e )
63
63
  return e;
64
64
  }
65
65
 
66
- export function
67
- Json2Xml( o, tag )
68
- {
69
- if( typeof o === 'string' )
70
- return o;
71
-
72
- const noTag = "string" != typeof tag;
73
-
74
- if( o instanceof Array )
75
- { noTag && (tag = 'array');
76
- return "<"+tag+">"+o.map(function(el){ return Json2Xml(el,tag); }).join()+"</"+tag+">";
77
- }
78
- noTag && (tag = 'r');
79
- tag=tag.replace( /[^a-z0-9\-]/gi,'_' );
80
- var oo = {}
81
- , ret = [ "<"+tag+" "];
82
- for( let k in o )
83
- if( typeof o[k] == "object" )
84
- oo[k] = o[k];
85
- else
86
- ret.push( k.replace( /[^a-z0-9\-]/gi,'_' ) + '="'+o[k].toString().replace(/&/gi,'&#38;')+'"');
87
- if( oo )
88
- { ret.push(">");
89
- for( let k in oo )
90
- ret.push( Json2Xml( oo[k], k ) );
91
- ret.push("</"+tag+">");
92
- }else
93
- ret.push("/>");
94
- return ret.join('\n');
95
- }
96
-
97
66
  export function
98
67
  obj2node( o, tag, doc )
99
68
  { const t = typeof o;
@@ -166,8 +135,8 @@ createXsltFromDom( templateNode, S = 'xsl:stylesheet' )
166
135
  <xsl:template match="*[name()='template']"><xsl:apply-templates mode="sanitize" select="*|text()"/></xsl:template>
167
136
  <xsl:template match="*"><xsl:apply-templates mode="sanitize" select="*|text()"/></xsl:template>
168
137
  <xsl:template match="*[name()='svg']|*[name()='math']"><xsl:apply-templates mode="sanitize" select="."/></xsl:template>
169
- <xsl:template mode="sanitize" match="*[count(text())=1 and count(*)=0]"><xsl:copy><xsl:apply-templates mode="sanitize" select="@*"/><xsl:value-of select="text()"/></xsl:copy></xsl:template>
170
- <xsl:template mode="sanitize" match="xhtml:*[count(text())=1 and count(*)=0]"><xsl:element name="{local-name()}"><xsl:apply-templates mode="sanitize" select="@*"/><xsl:value-of select="text()"/></xsl:element></xsl:template>
138
+ <xsl:template mode="sanitize" match="*[count(text())=1 and count(*)=0]"><xsl:copy><xsl:apply-templates mode="sanitize" select="@*"/><xsl:value-of select="text()"></xsl:value-of></xsl:copy></xsl:template>
139
+ <xsl:template mode="sanitize" match="xhtml:*[count(text())=1 and count(*)=0]"><xsl:element name="{local-name()}"><xsl:apply-templates mode="sanitize" select="@*"/><xsl:value-of select="text()"></xsl:value-of></xsl:element></xsl:template>
171
140
  <xsl:template mode="sanitize" match="*|@*"><xsl:copy><xsl:apply-templates mode="sanitize" select="*|@*|text()"/></xsl:copy></xsl:template>
172
141
  <xsl:template mode="sanitize" match="text()[normalize-space(.) = '']"/>
173
142
  <xsl:template mode="sanitize" match="text()"><dce-text><xsl:copy/></dce-text></xsl:template>
@@ -206,8 +175,7 @@ createXsltFromDom( templateNode, S = 'xsl:stylesheet' )
206
175
  <xsl:choose>
207
176
  <xsl:when test="//attr">{//attr}</xsl:when>
208
177
  <xsl:otherwise>{def}</xsl:otherwise>
209
- </xsl:choose>
210
- <xsl:value-of select="."/></xsl:template>
178
+ </xsl:choose><xsl:value-of select="."></xsl:value-of></xsl:template>
211
179
  <xsl:template mode="payload" match="attributes"></xsl:template>
212
180
  <xsl:template match="/">
213
181
  <xsl:apply-templates mode="payload" select="/datadom/attributes"/>
@@ -693,12 +661,17 @@ CustomElement extends HTMLElement
693
661
 
694
662
  get dce(){ return dce }
695
663
  }
664
+ const registerTag = tag =>
665
+ {
666
+ if( window.customElements.get(tag) !== DceElement )
667
+ window.customElements.define( tag, DceElement);
668
+ };
696
669
  if(tag)
697
- window.customElements.define( tag, DceElement);
670
+ registerTag(tag);
698
671
  else
699
672
  { const t = tagName;
700
673
  this.setAttribute('tag', t );
701
- window.customElements.define( t, DceElement);
674
+ registerTag(t);
702
675
  const el = document.createElement(t);
703
676
  this.getAttributeNames().forEach(a=>el.setAttribute(a,this.getAttribute(a)));
704
677
  el.append(...[...this.childNodes].filter( e => e.localName!=='style') );
package/demo/a.html CHANGED
@@ -41,33 +41,23 @@
41
41
  </head>
42
42
  <body>
43
43
 
44
- <custom-element>
45
- <template>
46
- <button slice="url-string" slice-value="'https://pokeapi.co/api/v2/pokemon?limit=6'" slice-event="click"
47
- >⬇️https://pokeapi.co/api/v2/pokemon?limit=6</button>
48
- <input slice="url-string" value="{ //url-string ?? '' }" style="width:100%"/>
49
- <button slice="fetch-url" slice-event="click" slice-value="//url-string"> GET </button>
50
- <http-request
51
- url="{//fetch-url}"
52
- slice="request_slice"
53
- type="text"
54
- mode="cors"
55
- ></http-request>
56
- //fetch-url : <code>{//fetch-url}</code>
57
- <!-- <for-each select="//slice/request_slice/value/*">-->
58
- <!-- <ul>-->
59
- <!-- <var data-testid="request-section"><value-of select='name(.)'/></var>-->
60
- <!-- <for-each select="@*">-->
61
- <!-- <div>-->
62
- <!-- <var data-testid="section-attribute">@<value-of select='local-name(.)'/></var>-->
63
- <!-- =-->
64
- <!-- <code><value-of select='.'/></code>-->
65
- <!-- </div>-->
66
- <!-- </for-each>-->
67
- <!-- </ul>-->
68
- <!-- </for-each>-->
44
+
45
+ <custom-element tag="dce-1">
46
+ <template >
47
+ <style >
48
+ color:red;
49
+ </style>
50
+
51
+ <u ><slot>red</slot></u>
69
52
  </template>
70
53
  </custom-element>
71
-
54
+ <dce-1></dce-1> *
55
+ <dce-1><template >
56
+ <style >
57
+ color:green;
58
+ </style>
59
+
60
+ <u >green</u>
61
+ </template></dce-1>
72
62
  </body>
73
63
  </html>
@@ -6,7 +6,6 @@
6
6
  <link rel="icon" href="./wc-square.svg"/>
7
7
 
8
8
  <script type="module" src="../http-request.js"></script>
9
- <script type="module" src="../input-text.js"></script>
10
9
  <script type="module" src="../custom-element.js"></script>
11
10
  <style>
12
11
  @import "./demo.css";
@@ -6,7 +6,6 @@
6
6
  <link rel="icon" href="./wc-square.svg"/>
7
7
 
8
8
  <script type="module" src="../http-request.js"></script>
9
- <script type="module" src="../input-text.js"></script>
10
9
  <script type="module" src="../custom-element.js"></script>
11
10
  <style>
12
11
  @import "./demo.css";
@@ -38,7 +38,9 @@
38
38
  <custom-element>
39
39
  <template>
40
40
 
41
+ <button slice="url-string" slice-value="''" slice-event="click">⬇️set blank</button>
41
42
  <button slice="url-string" slice-value="'https://pokeapi.co/api/v2/pokemon?limit=6'" slice-event="click">⬇️https://pokeapi.co/api/v2/pokemon?limit=6</button>
43
+ <button slice="url-string" slice-value="'https://pokeapi.co/api/v2/pokemon?limit=3'" slice-event="click">⬇️https://pokeapi.co/api/v2/pokemon?limit=3</button>
42
44
  <input slice="url-string" value="{ //url-string ?? '' }" style="width:100%"/>
43
45
  <button slice="fetch-url" slice-event="click" slice-value="//url-string"> GET </button>
44
46
  <http-request
@@ -48,11 +50,9 @@
48
50
  mode="cors"
49
51
  ></http-request>
50
52
  <code>//fetch-url</code> from <code>{//fetch-url}</code><br/>
51
- <for-each select="//results">
52
- <var>
53
- *{@name}
54
- </var>
55
- </for-each>
53
+ <ul><for-each select="//results">
54
+ <li>{@name}</li>
55
+ </for-each></ul>
56
56
  </template>
57
57
  </custom-element>
58
58
  </template>
@@ -51,10 +51,10 @@
51
51
  <custom-element>
52
52
  <template>
53
53
  <!-- always reset -->
54
- <local-storage key="overrideKey" slice="override-key" type="text" value="ABC"></local-storage>
55
- <button onclick="localStorage.setItem('overrideKey','text value')">text value</button>
56
- <button onclick="localStorage.removeItem('attrKey')">clear key</button>
57
- //override-key: <code>{//override-key}</code>
54
+ <local-storage slice="override-key" key="overrideKey" type="text" value="ABC"></local-storage>
55
+ <button onclick="localStorage.setItem( 'overrideKey','text value')">text value</button>
56
+ <button onclick="localStorage.removeItem('overrideKey' )">clear key</button>
57
+ //override-key: <code>{ //override-key }</code>
58
58
  </template>
59
59
  </custom-element>
60
60
  </template>
@@ -30,9 +30,9 @@
30
30
  <input name="p2" value="def"/>
31
31
  <input type="submit" value="params"/>
32
32
  </form>
33
- <button onclick="history.pushState( {},'', 'location.html?pushstate')"
33
+ <button onclick="history.pushState( {},'', 'location-element.html?pushstate')"
34
34
  >history.pushState</button>
35
- <button onclick="history.replaceState( {},'', 'location.html?replaceState#dce1')"
35
+ <button onclick="history.replaceState( {},'', 'location-element.html?replaceState#dce1')"
36
36
  >history.replaceState</button>
37
37
 
38
38
  </template>
@@ -113,7 +113,7 @@
113
113
  </html-demo-element>
114
114
 
115
115
 
116
- <html-demo-element legend="3. External URL as SRC attribute"
116
+ <html-demo-element legend="3. External URL as HREF attribute"
117
117
  description="url parsed and populated into slice."
118
118
  id="dce3">
119
119
  <p>Has to produce URL properties</p>
@@ -121,12 +121,12 @@
121
121
  <custom-element tag="dce-3" hidden>
122
122
  <template>
123
123
 
124
- <location-element slice="src-url" src="https://my.example?a=1&b=2#3"></location-element>
124
+ <location-element slice="href-url" href="https://my.example?a=1&b=2#3"></location-element>
125
125
 
126
126
  <xhtml:table>
127
127
  <xhtml:tbody>
128
128
  <xhtml:tr><xhtml:th><h3>URL properties</h3></xhtml:th></xhtml:tr>
129
- <for-each select="//slice/src-url/value/@*">
129
+ <for-each select="//slice/href-url/value/@*">
130
130
  <xhtml:tr>
131
131
  <xhtml:th>{name()}</xhtml:th>
132
132
  <xhtml:td>{.}</xhtml:td>
@@ -135,7 +135,7 @@
135
135
  </xhtml:tbody>
136
136
  <xhtml:tbody>
137
137
  <xhtml:tr><xhtml:th><h3>URL parameters</h3></xhtml:th></xhtml:tr>
138
- <for-each select="//slice/src-url/value/params/*">
138
+ <for-each select="//slice/href-url/value/params/*">
139
139
  <xhtml:tr>
140
140
  <xhtml:th>{name()}</xhtml:th>
141
141
  <xhtml:td>{.}</xhtml:td>
package/demo/s.xml CHANGED
@@ -1,93 +1,14 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <datadom>
3
- <payload>
4
- <span xmlns="http://www.w3.org/1999/xhtml" slot=""></span>
5
- <button xmlns="http://www.w3.org/1999/xhtml" slice="url-string"
6
- slice-value="'https://pokeapi.co/api/v2/pokemon?limit=6'" slice-event="click" slot="">
7
- ⬇️https://pokeapi.co/api/v2/pokemon?limit=6
8
- </button>
9
- <span xmlns="http://www.w3.org/1999/xhtml" slot=""></span>
10
- <input xmlns="http://www.w3.org/1999/xhtml" slice="url-string" value="{ //url-string ?? '' }" style="width:100%"
11
- slot=""/>
12
- <span xmlns="http://www.w3.org/1999/xhtml" slot=""></span>
13
- <button xmlns="http://www.w3.org/1999/xhtml" slice="fetch-url" slice-event="click" slice-value="//url-string"
14
- slot="">GET
15
- </button>
16
- <span xmlns="http://www.w3.org/1999/xhtml" slot=""></span>
17
- <http-request xmlns="http://www.w3.org/1999/xhtml" url="{//fetch-url}" slice="request_slice" type="text"
18
- mode="cors" slot=""></http-request>
19
- <span xmlns="http://www.w3.org/1999/xhtml" slot=""></span>
20
- <code xmlns="http://www.w3.org/1999/xhtml" slot="">//fetch-url</code>
21
- <span xmlns="http://www.w3.org/1999/xhtml" slot="">from</span>
22
- <code xmlns="http://www.w3.org/1999/xhtml" slot="">{//fetch-url}</code>
23
- <span xmlns="http://www.w3.org/1999/xhtml" slot=""></span>
24
- <xsl:for-each xmlns="http://www.w3.org/1999/xhtml" select="//slice/request_slice/value/*" slot="">
25
- <ul>
26
- <var data-testid="request-section">
27
- <xsl:value-of select="name(.)"></xsl:value-of>
28
- </var>
29
- <xsl:for-each select="@*">
30
- <div>
31
- <var data-testid="section-attribute">@
32
- <xsl:value-of select="local-name(.)"></xsl:value-of>
33
- </var>
34
- =
35
- <code>
36
- <xsl:value-of select="."></xsl:value-of>
37
- </code>
38
- </div>
39
- </xsl:for-each>
40
- </ul>
41
- </xsl:for-each>
42
- <span xmlns="http://www.w3.org/1999/xhtml" slot=""></span>
43
- </payload>
44
- <attributes>
45
- <tag>dce-5dc8d4a0-d545-4498-9de5-eec25c2b232f</tag>
46
- </attributes>
47
- <dataset/>
48
- <slice>
49
- <url-string xmlns="" slice="url-string" value="" style="width:100%" data-dce-id="2"
50
- slice-value="'https://pokeapi.co/api/v2/pokemon?limit=6'" slice-event="click">
51
- <event isTrusted="true" pointerId="1" width="1" height="1" pressure="0" tiltX="0" tiltY="0" azimuthAngle="0"
52
- altitudeAngle="1.5707963267948966" tangentialPressure="0" twist="0" pointerType="mouse"
53
- isPrimary="false" screenX="94" screenY="186" clientX="94" clientY="99" ctrlKey="false"
54
- shiftKey="false" altKey="false" metaKey="false" button="0" buttons="0" pageX="94" pageY="99" x="94"
55
- y="99" offsetX="60" offsetY="6" movementX="0" movementY="0" layerX="94" layerY="99" detail="1"
56
- which="1" type="click" eventPhase="0" bubbles="true" cancelable="true" defaultPrevented="false"
57
- composed="true" timeStamp="5596.5" returnValue="true" cancelBubble="false" NONE="0"
58
- CAPTURING_PHASE="1" AT_TARGET="2" BUBBLING_PHASE="3">
59
- <relatedTarget/>
60
- <fromElement/>
61
- <toElement/>
62
- <sourceCapabilities firesTouchEvents="false"/>
63
- <currentTarget/>
64
- </event>
65
- https://pokeapi.co/api/v2/pokemon?limit=6
66
- </url-string>
67
- <fetch-url xmlns="" slice="fetch-url" slice-event="click" slice-value="//url-string" data-dce-id="4" value="">
68
- <event isTrusted="true" pointerId="1" width="1" height="1" pressure="0" tiltX="0" tiltY="0" azimuthAngle="0"
69
- altitudeAngle="1.5707963267948966" tangentialPressure="0" twist="0" pointerType="mouse"
70
- isPrimary="false" screenX="56" screenY="232" clientX="56" clientY="145" ctrlKey="false"
71
- shiftKey="false" altKey="false" metaKey="false" button="0" buttons="0" pageX="56" pageY="145" x="56"
72
- y="145" offsetX="23" offsetY="8" movementX="0" movementY="0" layerX="56" layerY="145" detail="1"
73
- which="1" type="click" eventPhase="0" bubbles="true" cancelable="true" defaultPrevented="false"
74
- composed="true" timeStamp="6699.100000023842" returnValue="true" cancelBubble="false" NONE="0"
75
- CAPTURING_PHASE="1" AT_TARGET="2" BUBBLING_PHASE="3">
76
- <relatedTarget/>
77
- <fromElement/>
78
- <toElement/>
79
- <sourceCapabilities firesTouchEvents="false"/>
80
- <currentTarget/>
81
- </event>
82
- https://pokeapi.co/api/v2/pokemon?limit=6
83
- </fetch-url>
84
- <request_slice xmlns="" url="" slice="request_slice" type="text" mode="cors" data-dce-id="5">
85
- <event type="init"/>
86
- <value>
87
- <request xmlns="" url="" type="text" mode="cors" data-dce-id="5">
88
- <headers/>
89
- </request>
90
- </value>
91
- </request_slice>
92
- </slice>
93
- </datadom>
1
+ <div xmlns="http://www.w3.org/1999/xhtml" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"><!-- wrapping into template to prevent images loading within DCE declaration -->
2
+ <local-storage key="undefined" slice="s" }=""></local-storage>
3
+
4
+ <input placeholder="value for localStorage" slice="s" value="{ //s ?? 'undefined' }" />
5
+ <button>set</button>
6
+ <button slice="sv" slice-value="''" slice-event="click">set blank</button>
7
+ <button slice="sv" slice-value="'/reflect'" slice-event="click">/reflect</button>
8
+ <button slice="sv" slice-value="'/pokemon?limit=6'" slice-event="click">/pokemon?limit=6</button>
9
+ <button slice="sv" slice-value="'/pokemon?limit=3'" slice-event="click">/pokemon?limit=3</button>
10
+ <br />
11
+ <var>undefined</var>:<code>{ //slice/s }</code>
12
+ <br />
13
+ undefined
14
+ </div>
package/demo/s.xslt CHANGED
@@ -1,20 +1,57 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:dce="urn:schemas-epa-wg:dce" xmlns:exsl="http://exslt.org/common" version="1.0" exclude-result-prefixes="exsl">
1
+ <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xhtml="http://www.w3.org/1999/xhtml"
2
+ xmlns:dce="urn:schemas-epa-wg:dce" xmlns:exsl="http://exslt.org/common" version="1.0"
3
+ exclude-result-prefixes="exsl">
3
4
  <xsl:template match="ignore">
4
5
  <xsl:choose>
5
- <xsl:when test="//attr"><xsl:value-of select="//attr"/></xsl:when>
6
- <xsl:otherwise><xsl:value-of select="def"/></xsl:otherwise>
6
+ <xsl:when test="//attr">
7
+ <xsl:value-of select="//attr"/>
8
+ </xsl:when>
9
+ <xsl:otherwise>
10
+ <xsl:value-of select="def"/>
11
+ </xsl:otherwise>
7
12
  </xsl:choose>
8
- <xsl:value-of select="."/></xsl:template>
9
- <xsl:template mode="payload" match="attributes"><dce-root xmlns="http://www.w3.org/1999/xhtml" xmlns:xhtml="http://www.w3.org/1999/xhtml" data-dce-id="1"><local-storage xmlns="" key="dateKey" slice="date-key" type="date" live="live" data-dce-id="2"/><local-storage xmlns="" key="timeKey" slice="time-key" type="time" live="live" data-dce-id="3"/><local-storage xmlns="" key="localDateTimeKey" slice="local-date-time" type="datetime-local" live="live" data-dce-id="4"/><local-storage xmlns="" key="numberKey" slice="number-key" type="number" live="live" data-dce-id="5"/><local-storage xmlns="" key="jsonKey" slice="json-key" type="json" live="live" data-dce-id="6"/><input xmlns="" id="typesinput" placeholder="set value" data-dce-id="7"/><button xmlns="" onclick="&#10; 'dateKey,timeKey,localDateTimeKey,numberKey,jsonKey'.split(',')&#10; .map( k=&gt; localStorage.setItem(k, typesinput.value) )&#10; " data-dce-id="8"> set to all</button><br xmlns="" data-dce-id="9"/><hr xmlns="" data-dce-id="10"/><dce-text xmlns="" data-dce-id="11">
10
- date-key:
11
- </dce-text><button xmlns="" onclick="localStorage.setItem('dateKey', '2024-04-20T03:58:42.131Z')" data-dce-id="12">2024-04-21T03:58:42.131Z </button><button xmlns="" onclick="localStorage.setItem('dateKey', new Date(Date.now()).toISOString())" data-dce-id="13">now </button><button xmlns="" onclick="localStorage.setItem('dateKey', 'ABC' )" data-dce-id="14">date ABC - invalid </button><code xmlns="" data-dce-id="15"><xsl:value-of select="//date-key "/></code><br xmlns="" data-dce-id="16"/><dce-text xmlns="" data-dce-id="17">
12
- time-key:
13
- </dce-text><button xmlns="" onclick="localStorage.setItem('timeKey', '13:30')" data-dce-id="18">13:30 </button><code xmlns="" data-dce-id="19"><xsl:value-of select="//time-key "/></code><br xmlns="" data-dce-id="20"/><dce-text xmlns="" data-dce-id="21">
14
- local-date-time:
15
- </dce-text><button xmlns="" onclick="localStorage.setItem('localDateTimeKey', '1977-04-01T14:00:30')" data-dce-id="22">21977-04-01T14:00:30 - local </button><code xmlns="" data-dce-id="23"><xsl:value-of select="//local-date-time"/></code><br xmlns="" data-dce-id="24"/><dce-text xmlns="" data-dce-id="25">
16
- number-key:
17
- </dce-text><button xmlns="" onclick="localStorage.setItem('numberKey', '2024')" data-dce-id="26">2024 - number </button><button xmlns="" onclick="localStorage.setItem('numberKey', '24')" data-dce-id="27">24 - number </button><code xmlns="" data-dce-id="28"><xsl:value-of select="//number-key "/></code><br xmlns="" data-dce-id="29"/><fieldset xmlns="" data-dce-id="30"><legend data-dce-id="31">json-key: </legend><button onclick="localStorage.setItem('jsonKey', jsonStringSample)" data-dce-id="32"> a:1,b:'B' - json </button><xsl:apply-templates xmlns:xsl="http://www.w3.org/1999/XSL/Transform" select="//json-key/value/@*" mode="json"/></fieldset></dce-root></xsl:template>
13
+ <xsl:value-of select="."/>
14
+ </xsl:template>
15
+ <xsl:template mode="payload" match="attributes">
16
+ <dce-root xmlns="http://www.w3.org/1999/xhtml" xmlns:xhtml="http://www.w3.org/1999/xhtml" data-dce-id="1">
17
+ <http-request xmlns="" url="{concat(//s , '') }" slice="s" data-dce-id="2"/>
18
+ <p xmlns="" data-dce-id="3">Pokemon Count:
19
+ <xsl:value-of select="count(/datadom/slice/s//results)"/>
20
+ </p>
21
+ <xsl:if xmlns:xsl="http://www.w3.org/1999/XSL/Transform" test="count(/datadom/slice/s//results) &lt; 0">
22
+ <h3 xmlns="" data-dce-id="4">loading...</h3>
23
+ </xsl:if>
24
+ <xsl:for-each xmlns:xsl="http://www.w3.org/1999/XSL/Transform" select="/datadom/slice/s//results">
25
+ <xsl:variable name="pokeid"
26
+ select="substring-before( substring-after( @url, 'https://pokeapi.co/api/v2/pokemon/'),'/')"/>
27
+ <button xmlns="" data-dce-id="5">
28
+ <xsl:value-of select="@name">
29
+ </xsl:value-of>
30
+ </button>
31
+ </xsl:for-each>
32
+ <xsl:for-each xmlns:xsl="http://www.w3.org/1999/XSL/Transform" select="//slice/s/value/*">
33
+ <ul xmlns="" data-dce-id="6">
34
+ <var data-testid="request-section" data-dce-id="7">
35
+ <dce-text data-dce-id="8">
36
+ <xsl:value-of select="name(.)"/>
37
+ </dce-text>
38
+ </var>
39
+ <xsl:for-each select="@*">
40
+ <div data-dce-id="9">
41
+ <var data-dce-id="10">@<xsl:value-of select="local-name(.)"/>
42
+ </var>
43
+ <dce-text data-dce-id="11">
44
+ =
45
+ </dce-text>
46
+ <code data-testid="attr-{local-name(.)}" data-dce-id="12">
47
+ <xsl:value-of select="."/>
48
+ </code>
49
+ </div>
50
+ </xsl:for-each>
51
+ </ul>
52
+ </xsl:for-each>
53
+ </dce-root>
54
+ </xsl:template>
18
55
  <xsl:template match="/">
19
56
  <xsl:apply-templates mode="payload" select="/datadom/attributes"/>
20
57
  </xsl:template>
@@ -23,7 +60,7 @@
23
60
  <xsl:param name="defaultvalue"/>
24
61
  <xsl:choose>
25
62
  <xsl:when test="//payload/*[@slot=$slotname]">
26
- <xsl:copy-of select="//payload/*[@slot=$slotname]"/>
63
+ <xsl:copy-of select="//payload/*[@slot=$slotname]"/>
27
64
  </xsl:when>
28
65
  <xsl:otherwise>
29
66
  <xsl:copy-of select="$defaultvalue"/>
@@ -36,4 +73,4 @@
36
73
  <xsl:with-param name="defaultvalue"/>
37
74
  </xsl:call-template>
38
75
  </xsl:variable>
39
- <xsl:template xmlns:xsl="http://www.w3.org/1999/XSL/Transform" mode="json" match="*|@*"><div xmlns="" data-dce-id="33"><xsl:value-of select="name()"/> : <xsl:value-of select="."/></div></xsl:template></xsl:stylesheet>
76
+ </xsl:stylesheet>
@@ -6,7 +6,6 @@
6
6
  <link rel="icon" href="./wc-square.svg"/>
7
7
 
8
8
  <script type="module" src="../http-request.js"></script>
9
- <script type="module" src="../input-text.js"></script>
10
9
  <script type="module" src="../custom-element.js"></script>
11
10
  <style>
12
11
  @import "./demo.css";
package/demo/ss.html CHANGED
@@ -1,52 +1,57 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <dce-root data-dce-id="1" xmlns="http://www.w3.org/1999/xhtml" xmlns:dce="urn:schemas-epa-wg:dce"
3
- xmlns:xhtml="http://www.w3.org/1999/xhtml">
4
- <local-storage key="dateKey" slice="date-key" type="date" live="live" data-dce-id="2" xmlns=""/>
5
- <local-storage key="timeKey" slice="time-key" type="time" live="live" data-dce-id="3" xmlns=""/>
6
- <local-storage key="localDateTimeKey" slice="local-date-time" type="datetime-local" live="live" data-dce-id="4"
7
- xmlns=""/>
8
- <local-storage key="numberKey" slice="number-key" type="number" live="live" data-dce-id="5" xmlns=""/>
9
- <local-storage key="jsonKey" slice="json-key" type="json" live="live" data-dce-id="6" xmlns=""/>
10
- <input id="typesinput" placeholder="set value" data-dce-id="7" xmlns=""/>
11
- <button onclick="&#10; 'dateKey,timeKey,localDateTimeKey,numberKey,jsonKey'.split(',')&#10; .map( k=&gt; localStorage.setItem(k, typesinput.value) )&#10; "
12
- data-dce-id="8" xmlns=""> set to all
13
- </button>
14
- <br data-dce-id="9" xmlns=""/>
15
- <hr data-dce-id="10" xmlns=""/>
16
- <dce-text data-dce-id="11" xmlns="">
17
- date-key:
18
- </dce-text>
19
- <button onclick="localStorage.setItem('dateKey', '2024-04-20T03:58:42.131Z')" data-dce-id="12" xmlns="">
20
- 2024-04-21T03:58:42.131Z
21
- </button>
22
- <button onclick="localStorage.setItem('dateKey', new Date(Date.now()).toISOString())" data-dce-id="13" xmlns="">
23
- now
24
- </button>
25
- <button onclick="localStorage.setItem('dateKey', 'ABC' )" data-dce-id="14" xmlns="">date ABC - invalid</button>
26
- <code data-dce-id="15" xmlns="">
27
-
28
-
29
- </code><br data-dce-id="16" xmlns=""/>
30
- <dce-text data-dce-id="17" xmlns="">
31
- time-key:
32
- </dce-text>
33
- <button onclick="localStorage.setItem('timeKey', '13:30')" data-dce-id="18" xmlns="">13:30</button>
34
- <code data-dce-id="19" xmlns=""/><br data-dce-id="20" xmlns=""/>
35
- <dce-text data-dce-id="21" xmlns="">
36
- local-date-time:
37
- </dce-text>
38
- <button onclick="localStorage.setItem('localDateTimeKey', '1977-04-01T14:00:30')" data-dce-id="22" xmlns="">
39
- 21977-04-01T14:00:30 - local
40
- </button>
41
- <code data-dce-id="23" xmlns=""/><br data-dce-id="24" xmlns=""/>
42
- <dce-text data-dce-id="25" xmlns="">
43
- number-key:
44
- </dce-text>
45
- <button onclick="localStorage.setItem('numberKey', '2024')" data-dce-id="26" xmlns="">2024 - number</button>
46
- <button onclick="localStorage.setItem('numberKey', '24')" data-dce-id="27" xmlns="">24 - number</button>
47
- <code data-dce-id="28" xmlns=""/><br data-dce-id="29" xmlns=""/>
48
- <fieldset data-dce-id="30" xmlns="">
49
- <legend data-dce-id="31">json-key:</legend>
50
- <button onclick="localStorage.setItem('jsonKey', jsonStringSample)" data-dce-id="32"> a:1,b:'B' - json</button>
51
- </fieldset>
52
- </dce-root>
1
+ <dce-root xmlns="http://www.w3.org/1999/xhtml" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:dce="urn:schemas-epa-wg:dce" data-dce-id="1"><http-request xmlns="" url="/reflect" slice="page" data-dce-id="2"></http-request><p xmlns="" data-dce-id="3">Pokemon Count: 6</p>
2
+ <ul xmlns="" data-dce-id="6">
3
+ <var data-testid="request-section" data-dce-id="7"><dce-text data-dce-id="8">request</dce-text></var><div data-dce-id="9">
4
+ <var data-dce-id="10">@url</var><dce-text data-dce-id="11">
5
+ =
6
+ </dce-text><code data-testid="attr-url" data-dce-id="12">/reflect</code>
7
+ </div>
8
+ <div data-dce-id="9-1">
9
+ <var data-dce-id="10">@data-dce-id</var><dce-text data-dce-id="11">
10
+ =
11
+ </dce-text><code data-testid="attr-data-dce-id" data-dce-id="12">2</code>
12
+ </div>
13
+ </ul>
14
+ <ul xmlns="" data-dce-id="6-1">
15
+ <var data-testid="request-section" data-dce-id="7"><dce-text data-dce-id="8">response</dce-text></var><div data-dce-id="9">
16
+ <var data-dce-id="10">@ok</var><dce-text data-dce-id="11">
17
+ =
18
+ </dce-text><code data-testid="attr-ok" data-dce-id="12">true</code>
19
+ </div>
20
+ <div data-dce-id="9-1">
21
+ <var data-dce-id="10">@status</var><dce-text data-dce-id="11">
22
+ =
23
+ </dce-text><code data-testid="attr-status" data-dce-id="12">200</code>
24
+ </div>
25
+ <div data-dce-id="9-2">
26
+ <var data-dce-id="10">@statusText</var><dce-text data-dce-id="11">
27
+ =
28
+ </dce-text><code data-testid="attr-statusText" data-dce-id="12">OK</code>
29
+ </div>
30
+ <div data-dce-id="9-3">
31
+ <var data-dce-id="10">@type</var><dce-text data-dce-id="11">
32
+ =
33
+ </dce-text><code data-testid="attr-type" data-dce-id="12">basic</code>
34
+ </div>
35
+ <div data-dce-id="9-4">
36
+ <var data-dce-id="10">@url</var><dce-text data-dce-id="11">
37
+ =
38
+ </dce-text><code data-testid="attr-url" data-dce-id="12">http://localhost:5173/reflect</code>
39
+ </div>
40
+ <div data-dce-id="9-5">
41
+ <var data-dce-id="10">@redirected</var><dce-text data-dce-id="11">
42
+ =
43
+ </dce-text><code data-testid="attr-redirected" data-dce-id="12">false</code>
44
+ </div>
45
+ </ul><button xmlns="" data-dce-id="5">bulbasaur</button><button xmlns="" data-dce-id="5-1">ivysaur</button><button xmlns="" data-dce-id="5-2">venusaur</button><button xmlns="" data-dce-id="5-3">charmander</button><button xmlns="" data-dce-id="5-4">charmeleon</button><button xmlns="" data-dce-id="5-5">charizard</button>
46
+ <ul xmlns="" data-dce-id="6-2">
47
+ <var data-testid="request-section" data-dce-id="7"><dce-text data-dce-id="8">data</dce-text></var><div data-dce-id="9">
48
+ <var data-dce-id="10">@count</var><dce-text data-dce-id="11">
49
+ =
50
+ </dce-text><code data-testid="attr-count" data-dce-id="12">1279</code>
51
+ </div>
52
+ <div data-dce-id="9-1">
53
+ <var data-dce-id="10">@next</var><dce-text data-dce-id="11">
54
+ =
55
+ </dce-text><code data-testid="attr-next" data-dce-id="12">https://pokeapi.co/api/v2/pokemon?offset=6&amp;limit=6</code>
56
+ </div>
57
+ </ul></dce-root>
package/http-request.js CHANGED
@@ -33,7 +33,7 @@ export class HttpRequestElement extends HTMLElement
33
33
 
34
34
  async fetch()
35
35
  {
36
- if( !this.closest('custom-element') )
36
+ if( !this.closest('body') )
37
37
  return;
38
38
  const url = attr(this, 'url') || '';
39
39
  if( !url )
@@ -46,7 +46,7 @@ export class HttpRequestElement extends HTMLElement
46
46
 
47
47
  this.#inProgressUrl = url;
48
48
  const controller = new AbortController();
49
- this.#destroy = ()=> controller.abort(this.localName+' disconnected');
49
+ this.#destroy = ()=> { controller.abort(this.localName+' disconnected'); this.#inProgressUrl = ''; }
50
50
 
51
51
  const request = { ...this.requestProps, headers: this.requestHeaders }
52
52
  , slice = { request }
@@ -61,16 +61,24 @@ export class HttpRequestElement extends HTMLElement
61
61
 
62
62
  slice.response = r;
63
63
  update();
64
- slice.data = await response.json();
65
- update();
64
+ if( r.headers['content-type']?.includes('json'))
65
+ try
66
+ { slice.data = await response.json();
67
+ update();
68
+ }catch(_e){}
66
69
  }
67
70
 
68
71
  attributeChangedCallback(name, oldValue, newValue)
69
72
  { if( name === 'url' )
70
- { if( newValue && oldValue !== newValue)
73
+ { if( oldValue !== newValue)
71
74
  {
72
75
  oldValue && this.#destroy?.();
73
- setTimeout(()=>this.fetch(),0)
76
+ if( newValue )
77
+ setTimeout(()=>this.fetch(),10)
78
+ else
79
+ { this.value = {}
80
+ setTimeout(()=>this.dispatchEvent( new Event('change') ),10)
81
+ }
74
82
  }
75
83
  }
76
84
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "http://json.schemastore.org/web-types",
3
3
  "name": "@epa-wg/custom-element",
4
- "version": "0.0.20",
4
+ "version": "0.0.21",
5
5
  "js-types-syntax": "typescript",
6
6
  "description-markup": "markdown",
7
7
  "contributions": {
@@ -108,4 +108,4 @@
108
108
  ]
109
109
  }
110
110
  }
111
- }
111
+ }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "http://json.schemastore.org/web-types",
3
3
  "name": "@epa-wg/custom-element",
4
- "version": "0.0.20",
4
+ "version": "0.0.21",
5
5
  "js-types-syntax": "typescript",
6
6
  "description-markup": "markdown",
7
7
  "contributions": {
@@ -864,4 +864,4 @@
864
864
  ]
865
865
  }
866
866
  }
867
- }
867
+ }
package/index.js ADDED
@@ -0,0 +1,7 @@
1
+ import CustomElement from "./custom-element.js";
2
+ export default CustomElement;
3
+
4
+ export * from "./custom-element.js";
5
+ export * from "./http-request.js";
6
+ export * from "./local-storage.js";
7
+ export * from "./location-element.js";
package/local-storage.js CHANGED
@@ -62,7 +62,7 @@ export class LocalStorageElement extends HTMLElement
62
62
  async connectedCallback()
63
63
  {
64
64
  const attr = attr => this.getAttribute(attr)
65
- , fromStorage = ()=>
65
+ , fromStorage = ()=>
66
66
  { this.#value = string2value( attr('type'), localStorage.getItem( attr( 'key' ) ) );
67
67
  this.dispatchEvent( new Event('change') )
68
68
  }
@@ -84,4 +84,4 @@ export class LocalStorageElement extends HTMLElement
84
84
  }
85
85
 
86
86
  window.customElements.define( 'local-storage', LocalStorageElement );
87
- export default LocalStorageElement;
87
+ export default LocalStorageElement;
@@ -1,23 +1,42 @@
1
- const attr = (el, attr)=> el.getAttribute(attr);
1
+ const attr = ( el, attr )=> el.getAttribute( attr );
2
+
3
+ let originalHistory;
4
+
5
+ function ensureTrackLocationChange()
6
+ { if( originalHistory )
7
+ return;
8
+ originalHistory = {};
9
+ 'back,forward,go,pushState,replaceState'.split(',').forEach( k =>
10
+ {
11
+ originalHistory[ k ] = history[ k ];
12
+ history[ k ] = function(...rest )
13
+ {
14
+ originalHistory[k].apply( history, rest );
15
+ window.dispatchEvent( new CustomEvent('dce-location',{detail:{ k }}) );
16
+ }
17
+ });
18
+ }
2
19
 
3
20
  export class LocationElement extends HTMLElement
4
21
  {
5
22
  static observedAttributes=
6
- [ 'value' // populated from localStorage, if defined initially, sets the value in storage
23
+ [ 'value' // populated from url
7
24
  , 'slice'
8
- , 'key'
25
+ , 'href' // url to be parsed. When omitted window.location is used.
9
26
  , 'type' // `text|json`, defaults to text, other types are compatible with INPUT field
10
- , 'live' // monitors localStorage change
27
+ , 'live' // monitors history change, applicable only when href is omitted.
11
28
  ];
12
29
 
13
30
  constructor()
14
31
  {
15
32
  super();
16
33
  const state = {}
17
- , listener = e=> propagateSlice(e)
34
+ , listener = () => setTimeout( propagateSlice,1 )
18
35
  , propagateSlice = ()=>
19
- { const urlStr = attr(this,'src')
20
- const url = urlStr? new URL(urlStr) : window.location
36
+ { const urlStr = attr(this,'href')
37
+ if(!urlStr)
38
+ ensureTrackLocationChange();
39
+ const url = urlStr? new URL(urlStr, window.location) : window.location;
21
40
 
22
41
  const params= {}
23
42
  const search = new URLSearchParams(url.search);
@@ -36,24 +55,30 @@ export class LocationElement extends HTMLElement
36
55
  {
37
56
  if( !state.listener && this.hasAttribute('live') )
38
57
  { state.listener = 1;
39
- window.addEventListener( 'popstate' , listener );
40
- window.addEventListener( 'hashchange', listener );
58
+ window.navigation?.addEventListener("navigate", listener );
59
+ window.addEventListener( 'popstate' , listener );
60
+ window.addEventListener( 'hashchange' , listener );
61
+ window.addEventListener( 'dce-location' , listener );
41
62
  }
42
63
  propagateSlice();
43
64
  return s || {}
44
65
  }
45
66
  this._destroy = ()=>
46
67
  {
47
- if( !state.listener )
48
- return;
49
- if(state.listener)
50
- { window.removeEventListener('popstate' , listener);
51
- window.removeEventListener('hashchange', listener);
52
- }
68
+ window.removeEventListener('popstate' , listener);
69
+ window.removeEventListener('hashchange' , listener);
70
+ window.removeEventListener('dce-location', listener);
53
71
  delete state.listener;
54
72
  };
55
73
 
56
74
  }
75
+ attributeChangedCallback(name, oldValue, newValue)
76
+ {
77
+ if('href'!== name)
78
+ return;
79
+ this.sliceInit && this.sliceInit();
80
+ }
81
+
57
82
  connectedCallback(){ this.sliceInit() }
58
83
  disconnectedCallback(){ this._destroy() }
59
84
  }
package/package.json CHANGED
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "name": "@epa-wg/custom-element",
3
- "version": "0.0.20",
3
+ "version": "0.0.21",
4
4
  "description": "Declarative Custom Element as W3C proposal PoC with native(XSLT) based templating",
5
5
  "browser": "custom-element.js",
6
6
  "module": "custom-element.js",
7
7
  "exports": {
8
- ".": "./custom-element.js",
8
+ ".": "./index.js",
9
9
  "./package.json": "./package.json",
10
10
  "./CustomElement": "./custom-element.js"
11
11
  },
@@ -16,7 +16,7 @@
16
16
  "dev:help": "echo \"needed for sandbox demo\"",
17
17
  "dev": "bash bin/stackblitz.sh",
18
18
  "start": "npm i --no-save @web/dev-server && web-dev-server --node-resolve",
19
- "test": "echo \"test would reside in https://github.com/EPA-WG/custom-element-test\" && exit 0",
19
+ "test": "echo \"test would reside in https://github.com/EPA-WG/custom-element-dist\" && exit 0",
20
20
  "typings": "npx -p typescript tsc custom-element.js --declaration --allowJs --emitDeclarationOnly "
21
21
  },
22
22
  "type": "module",
package/input-text.js DELETED
@@ -1,17 +0,0 @@
1
- export class InputTextElement extends HTMLElement
2
- {
3
- constructor()
4
- {
5
- super();
6
- const i = this.ownerDocument.createElement('input');
7
- for(let a of this.attributes)
8
- a.namespaceURI ? i.setAttributeNS(a.namespaceURI,a.name,a.value) : i.setAttribute(a.name,a.value)
9
- this.append(i)
10
- }
11
- get value(){ return this.firstChild.value }
12
- set value(v){ return this.firstChild.value = v }
13
- disconnectedCallback(){ }
14
- }
15
-
16
- window.customElements.define( 'input-text', InputTextElement );
17
- export default InputTextElement;