@epa-wg/custom-element 0.0.8 → 0.0.10

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 CHANGED
@@ -1,8 +1,11 @@
1
1
  # custom-element
2
- `Declarative Custom Element` proof of concept as a part of [WCCG in Declarative custom elements](https://github.com/w3c/webcomponents-cg/issues/32#issuecomment-1321037301)
3
- discussion.
2
+ `Declarative Custom Element` is a part of pure `Declarative Web Application` stack. A proof of concept as a part of
3
+ [WCCG in Declarative custom elements](https://github.com/w3c/webcomponents-cg/issues/32#issuecomment-1321037301)
4
+ discussion. The functionality of DCE and its data access does not require programming using JavaScript.
4
5
 
5
- It allows to define custom HTML tag with template filled from slots and attributes.
6
+ It allows to define custom HTML tag with template filled from slots, attributes and data `slice` as of now from
7
+ [local-storage][local-storage-demo], [http-request][http-request-demo], [location][location-demo].
8
+ UI is re-rendered on each data slice change.
6
9
 
7
10
  [![git][github-image] GitHub][git-url]
8
11
  | Live demo: [custom-element][demo-url]
@@ -182,12 +185,15 @@ within template
182
185
  [git-url]: https://github.com/EPA-WG/custom-element
183
186
  [git-test-url]: https://github.com/EPA-WG/custom-element-test
184
187
  [demo-url]: https://unpkg.com/@epa-wg/custom-element@0.0/index.html
188
+ [local-storage-demo]: https://unpkg.com/@epa-wg/custom-element@0.0/demo/local-storage.html
189
+ [http-request-demo]: https://unpkg.com/@epa-wg/custom-element@0.0/demo/http-request.html
190
+ [location-demo]: https://unpkg.com/@epa-wg/custom-element@0.0/demo/location.html
185
191
  [github-image]: https://cdnjs.cloudflare.com/ajax/libs/octicons/8.5.0/svg/mark-github.svg
186
192
  [npm-image]: https://img.shields.io/npm/v/@epa-wg/custom-element.svg
187
193
  [npm-url]: https://npmjs.org/package/@epa-wg/custom-element
188
- [coverage-image]: https://unpkg.com/@epa-wg/custom-element-test@0.0.8/coverage/coverage.svg
189
- [coverage-url]: https://unpkg.com/@epa-wg/custom-element-test@0.0.8/coverage/lcov-report/index.html
190
- [storybook-url]: https://unpkg.com/@epa-wg/custom-element-test@0.0.8/storybook-static/index.html?path=/story/welcome--introduction
194
+ [coverage-image]: https://unpkg.com/@epa-wg/custom-element-test@0.0.10/coverage/coverage.svg
195
+ [coverage-url]: https://unpkg.com/@epa-wg/custom-element-test@0.0.10/coverage/lcov-report/index.html
196
+ [storybook-url]: https://unpkg.com/@epa-wg/custom-element-test@0.0.10/storybook-static/index.html?path=/story/welcome--introduction
191
197
  [sandbox-url]: https://stackblitz.com/github/EPA-WG/custom-element?file=index.html
192
198
  [webcomponents-url]: https://www.webcomponents.org/element/@epa-wg/custom-element
193
199
  [webcomponents-img]: https://img.shields.io/badge/webcomponents.org-published-blue.svg
package/custom-element.js CHANGED
@@ -17,7 +17,9 @@ bodyXml( dce )
17
17
  {
18
18
  const t = dce.firstElementChild
19
19
  , sanitize = s => s.replaceAll("<html:","<")
20
- .replaceAll("</html:","</");
20
+ .replaceAll("</html:","</")
21
+ .replaceAll( />\s*<\/xsl:value-of>/g ,"/>")
22
+ .replaceAll( />\s*<\/(br|hr|img|area|base|col|embed|input|link|meta|param|source|track|wbr)>/g ,"/>");
21
23
  if( t?.tagName === 'TEMPLATE')
22
24
  return sanitize( new XMLSerializer().serializeToString( t.content ) );
23
25
 
@@ -71,17 +73,17 @@ Json2Xml( o, tag )
71
73
  return "<"+tag+">"+o.map(function(el){ return Json2Xml(el,tag); }).join()+"</"+tag+">";
72
74
  }
73
75
  noTag && (tag = 'r');
74
- tag=tag.replace( /[^a-z0-9]/gi,'_' );
76
+ tag=tag.replace( /[^a-z0-9\-]/gi,'_' );
75
77
  var oo = {}
76
78
  , ret = [ "<"+tag+" "];
77
- for( var k in o )
79
+ for( let k in o )
78
80
  if( typeof o[k] == "object" )
79
81
  oo[k] = o[k];
80
82
  else
81
- ret.push( k.replace( /[^a-z0-9]/gi,'_' ) + '="'+o[k].toString().replace(/&/gi,'&#38;')+'"');
83
+ ret.push( k.replace( /[^a-z0-9\-]/gi,'_' ) + '="'+o[k].toString().replace(/&/gi,'&#38;')+'"');
82
84
  if( oo )
83
85
  { ret.push(">");
84
- for( var k in oo )
86
+ for( let k in oo )
85
87
  ret.push( Json2Xml( oo[k], k ) );
86
88
  ret.push("</"+tag+">");
87
89
  }else
@@ -92,12 +94,13 @@ Json2Xml( o, tag )
92
94
  function
93
95
  injectSlice( x, s, data )
94
96
  {
95
- const el = create(s)
96
- , isString = typeof data === 'string' ;
97
- el.innerHTML = isString? data : Json2Xml( data, s );
98
- const slice = isString? el : el.firstChild;
97
+ const isString = typeof data === 'string' ;
98
+
99
+ const el = isString
100
+ ? create(s, data)
101
+ : document.adoptNode( xml2dom( Json2Xml( data, s ) ).documentElement);
99
102
  [...x.children].filter( e=>e.localName === s ).map( el=>el.remove() );
100
- x.append(slice);
103
+ x.append(el);
101
104
  }
102
105
 
103
106
  export class
@@ -142,7 +145,7 @@ CustomElement extends HTMLElement
142
145
  }
143
146
  let timeoutID;
144
147
 
145
- const onSlice = ev=>
148
+ this.onSlice = ev=>
146
149
  { ev.stopPropagation?.();
147
150
  sliceEvents.push(ev);
148
151
  if( !timeoutID )
@@ -151,7 +154,6 @@ CustomElement extends HTMLElement
151
154
  timeoutID =0;
152
155
  },10);
153
156
  };
154
- this.onSlice = onSlice;
155
157
  const transform = ()=>
156
158
  {
157
159
  const f = p.transformToFragment( x, document );
Binary file
@@ -3,6 +3,8 @@
3
3
  <head>
4
4
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
5
5
  <title>http-request Declarative Custom Element implementation demo</title>
6
+ <link rel="icon" href="./wc-square.svg" />
7
+
6
8
  <script type="module" src="../http-request.js"></script>
7
9
  <script type="module" src="../custom-element.js"></script>
8
10
  <style>
@@ -25,6 +27,9 @@
25
27
  </head>
26
28
  <body>
27
29
 
30
+ <nav>
31
+ <a href=".."><h3><code>custom-element</code> demo</h3></a>
32
+ </nav>
28
33
 
29
34
  <html-demo-element legend="1. http-request simplest"
30
35
  description="load the list of pokemons">
@@ -35,6 +40,8 @@
35
40
  <http-request
36
41
  url="https://pokeapi.co/api/v2/pokemon?limit=6&offset=0"
37
42
  slice="page"
43
+ method="GET"
44
+ header-accept="application/json"
38
45
  ></http-request>
39
46
  <xsl:for-each select="//slice/page/data/results/*">
40
47
  <xsl:variable name="slides-url"
@@ -54,6 +61,65 @@
54
61
  </template>
55
62
  </html-demo-element>
56
63
 
64
+ <html-demo-element legend="1. http-request headers"
65
+ description="request and response headers access demo">
66
+
67
+ <template>
68
+ <custom-element
69
+ tag="headers-demo"
70
+ hidden
71
+ >
72
+ <http-request
73
+ url="https://pokeapi.co/api/v2/pokemon?offset=6&limit=6"
74
+ slice="request_slice"
75
+ type="text"
76
+ mode="cors"
77
+ header-x-test="testing"
78
+ ></http-request>
79
+ Content of <code>//slice/request_slice</code> is filled by <b>request</b> and <b>response</b>
80
+ from <code>${url}</code>
81
+
82
+ <h3>Samples</h3>
83
+ <table>
84
+ <tr><th>//slice/request_slice/request/headers/@mode</th>
85
+ <td><xsl:value-of select="//slice/request_slice/request/@mode"/></td></tr>
86
+ <tr><th>//slice/request_slice/response/headers/@content-type</th>
87
+ <td><xsl:value-of select="//slice/request_slice/response/headers/@content-type"/></td></tr>
88
+ <tr><th>//slice/request_slice/response/@status</th>
89
+ <td><xsl:value-of select="//slice/request_slice/response/@status"/></td></tr>
90
+ </table>
91
+ <xsl:for-each select="//slice/request_slice/*">
92
+ <ul data-request-section="{name(.)}">
93
+ <b data-testid="request-section"><xsl:value-of select='name(.)'/></b>
94
+ <xsl:for-each select="@*">
95
+ <div>
96
+ <var data-testid="section-attribute">@<xsl:value-of select='local-name(.)'/></var>
97
+ =
98
+ <code><xsl:value-of select='.'/></code>
99
+ </div>
100
+ </xsl:for-each>
101
+ <xsl:for-each select="*">
102
+ <div>
103
+ <b data-testid="section-deep"><xsl:value-of select='local-name(.)'/></b>
104
+ <ul>
105
+ <xsl:for-each select="@*">
106
+ <li>
107
+ <var data-testid="section-attribute">@<xsl:value-of select='local-name(.)'/></var>
108
+ =
109
+ <code><xsl:value-of select='.'/></code>
110
+ </li>
111
+ </xsl:for-each>
112
+ <code><xsl:value-of select='.'/></code>
113
+ </ul>
114
+ </div>
115
+ </xsl:for-each>
116
+ </ul>
117
+ </xsl:for-each>
118
+ </custom-element>
119
+ <headers-demo></headers-demo>
120
+ </template>
121
+ </html-demo-element>
122
+
57
123
 
58
124
  <script type="module" src="https://unpkg.com/html-demo-element@1/html-demo-element.js"></script>
59
125
 
@@ -3,6 +3,7 @@
3
3
  <head>
4
4
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
5
5
  <title>custom-element Declarative Custom Element implementation demo</title>
6
+ <link rel="icon" href="./wc-square.svg" />
6
7
  <script type="module" src="../local-storage.js"></script>
7
8
  <script type="module" src="../custom-element.js"></script>
8
9
  <style>
@@ -18,6 +19,9 @@
18
19
  </head>
19
20
  <body>
20
21
 
22
+ <nav>
23
+ <a href=".."><h3><code>custom-element</code> demo</h3></a>
24
+ </nav>
21
25
 
22
26
  <html-demo-element legend="1. localStorage simplest"
23
27
  description="local-storage read only during initial and only render, does not track the changes.">
@@ -0,0 +1,149 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:html="http://www.w3.org/1999/xhtml">
3
+ <head>
4
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
5
+ <title>custom-element Declarative Custom Element implementation demo</title>
6
+ <link rel="icon" href="./wc-square.svg" />
7
+ <script type="module" src="../location-element.js"></script>
8
+ <script type="module" src="../custom-element.js"></script>
9
+ <style>
10
+ @import "./demo.css";
11
+
12
+ button{ background: forestgreen; }
13
+ table{ min-width: 16rem; }
14
+ td{ border-bottom: 1px solid silver; }
15
+ tfoot td{ border-bottom: none; }
16
+ td,th{text-align: right; }
17
+ caption{ padding: 1rem; font-weight: bolder; font-family: sans-serif; }
18
+ </style>
19
+ </head>
20
+ <body>
21
+ <nav>
22
+ <a href=".."><h3><code>custom-element</code> demo</h3></a>
23
+ </nav>
24
+ <html-demo-element legend="Change window URL">
25
+ <template>
26
+ <a href="#dce2">#dce2</a>
27
+ <form >
28
+ <input name="p1" value="abc"/>
29
+ <input name="p2" value="def"/>
30
+ <input type="submit" value="params"/>
31
+ </form>
32
+ <button onclick="history.pushState( {},'', 'location.html?pushstate')"
33
+ >history.pushState</button>
34
+ <button onclick="history.replaceState( {},'', 'location.html?replaceState#dce1')"
35
+ >history.replaceState</button>
36
+
37
+ </template>
38
+ </html-demo-element>
39
+
40
+
41
+ <html-demo-element legend="2. window.location live update"
42
+ description="In the page beginning change the window URL via link or by history change"
43
+ id="dce2"
44
+ >
45
+ <p>Has to produce URL properties</p>
46
+ <template>
47
+ <custom-element tag="dce-2" hidden>
48
+ <template>
49
+
50
+ <location-element slice="window-url" live></location-element>
51
+
52
+ <html:table>
53
+ <xsl:for-each select="//slice/window-url/@*">
54
+ <html:tr>
55
+ <html:th><xsl:value-of select="name()"/></html:th>
56
+ <html:td><xsl:value-of select="."/></html:td>
57
+ </html:tr>
58
+ </xsl:for-each>
59
+ <html:tr>
60
+ <html:th><u>params</u></html:th>
61
+ <html:th></html:th>
62
+ </html:tr>
63
+ <xsl:for-each select="//slice/window-url/params/*">
64
+ <html:tr>
65
+ <html:th><xsl:value-of select="name()"/></html:th>
66
+ <html:td><xsl:value-of select="."/></html:td>
67
+ </html:tr>
68
+ </xsl:for-each>
69
+ </html:table>
70
+ </template>
71
+ </custom-element>
72
+ <dce-2>?</dce-2>
73
+ </template>
74
+ </html-demo-element>
75
+
76
+
77
+ <html-demo-element legend="1. window.location simplest"
78
+ description="location read only during initial and only render, does not track the changes."
79
+ id="dce1">
80
+ <p>Has to produce URL properties</p>
81
+ <template>
82
+ <custom-element tag="dce-1" hidden>
83
+ <template>
84
+
85
+ <location-element slice="window-url"></location-element>
86
+
87
+ <html:table>
88
+ <xsl:for-each select="//slice/window-url/@*">
89
+ <html:tr>
90
+ <html:th><xsl:value-of select="name()"/></html:th>
91
+ <html:td><xsl:value-of select="."/></html:td>
92
+ </html:tr>
93
+ </xsl:for-each>
94
+ <html:tr>
95
+ <html:th><u>params</u></html:th>
96
+ <html:th></html:th>
97
+ </html:tr>
98
+ <xsl:for-each select="//slice/window-url/params/*">
99
+ <html:tr>
100
+ <html:th><xsl:value-of select="name()"/></html:th>
101
+ <html:td><xsl:value-of select="."/></html:td>
102
+ </html:tr>
103
+ </xsl:for-each>
104
+ </html:table>
105
+ </template>
106
+ </custom-element>
107
+ <dce-1>?</dce-1>
108
+ </template>
109
+ </html-demo-element>
110
+
111
+
112
+ <html-demo-element legend="3. External URL as SRC attribute"
113
+ description="url parsed and populated into slice."
114
+ id="dce3">
115
+ <p>Has to produce URL properties</p>
116
+ <template>
117
+ <custom-element tag="dce-3" hidden>
118
+ <template>
119
+
120
+ <location-element slice="src-url" src="https://my.example?a=1&b=2#3"></location-element>
121
+
122
+ <html:table>
123
+ <xsl:for-each select="//slice/src-url/@*">
124
+ <html:tr>
125
+ <html:th><xsl:value-of select="name()"/></html:th>
126
+ <html:td><xsl:value-of select="."/></html:td>
127
+ </html:tr>
128
+ </xsl:for-each>
129
+ <html:tr>
130
+ <html:th><u>params</u></html:th>
131
+ <html:th></html:th>
132
+ </html:tr>
133
+ <xsl:for-each select="//slice/src-url/params/*">
134
+ <html:tr>
135
+ <html:th><xsl:value-of select="name()"/></html:th>
136
+ <html:td><xsl:value-of select="."/></html:td>
137
+ </html:tr>
138
+ </xsl:for-each>
139
+ </html:table>
140
+ </template>
141
+ </custom-element>
142
+ <dce-3>?</dce-3>
143
+ </template>
144
+ </html-demo-element>
145
+
146
+ <script type="module" src="https://unpkg.com/html-demo-element@1/html-demo-element.js"></script>
147
+
148
+ </body>
149
+ </html>
package/demo/logo.png ADDED
Binary file
@@ -0,0 +1 @@
1
+ <?xml version="1.0" encoding="UTF-8"?><svg id="Artwork" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 216 209.18"><defs><style>.cls-1{fill:#c2e6f1;}.cls-2{fill:#dcf1f7;}.cls-3{fill:#2d4554;}.cls-4{fill:#60cae5;}</style></defs><polygon class="cls-3" points="0 82.47 0 126.71 34.84 146.83 34.84 187.06 73.16 209.18 108 189.07 142.84 209.18 181.16 187.06 181.16 146.83 216 126.71 216 82.47 181.16 62.35 181.16 22.12 142.84 0 108 20.12 73.16 0 34.84 22.12 34.84 62.35 0 82.47"/><path class="cls-2" d="m114.33,56.69l20.64-11.92c.47-.27.47-.79,0-1.06l-20.65-11.92h0c-4.44-2.57-8.22-2.57-12.67,0l-20.65,11.92c-.47.27-.47.79,0,1.06l20.64,11.92c4.44,2.57,8.22,2.57,12.67,0h0Z"/><path class="cls-2" d="m98.19,62.71h0s-20.64-11.92-20.64-11.92c-.47-.27-.92-.01-.92.53v23.84s0,0,0,0c0,5.13,1.89,8.4,6.33,10.97l20.65,11.92c.47.27.92,0,.92-.54v-23.84c0-5.13-1.89-8.4-6.33-10.97Z"/><path class="cls-1" d="m48.12,66.01l20.65,11.92c.47.27.92,0,.92-.54v-23.84c0-5.13-1.89-8.4-6.33-10.97h0s-20.64-11.92-20.64-11.92c-.47-.27-.92-.01-.92.53v23.84s0,0,0,0c0,5.13,1.89,8.4,6.33,10.97Z"/><path class="cls-2" d="m46.18,24.66l20.64,11.92c4.44,2.57,8.22,2.57,12.67,0h0s20.64-11.92,20.64-11.92c.47-.27.47-.79,0-1.06l-20.65-11.92h0c-4.44-2.57-8.22-2.57-12.67,0l-20.65,11.92c-.47.27-.47.79,0,1.06Z"/><path class="cls-2" d="m115.87,24.66l20.64,11.92c4.44,2.57,8.22,2.57,12.67,0h0s20.64-11.92,20.64-11.92c.47-.27.47-.79,0-1.06l-20.65-11.92h0c-4.44-2.57-8.22-2.57-12.67,0l-20.65,11.92c-.47.27-.47.79,0,1.06Z"/><path class="cls-2" d="m152.65,42.59c-4.44,2.56-6.33,5.84-6.33,10.97v23.84c0,.54.45.8.92.54l20.65-11.92c4.44-2.57,6.33-5.84,6.33-10.97h0v-23.84c0-.54-.45-.8-.92-.53l-20.64,11.92h0Z"/><path class="cls-2" d="m77.55,158.4l20.65-11.92h0c4.44-2.57,6.33-5.84,6.33-10.97v-23.84c0-.54-.45-.8-.92-.53l-20.64,11.92c-4.44,2.57-6.33,5.84-6.33,10.97h0s0,23.84,0,23.84c0,.54.45.8.92.54Z"/><path class="cls-4" d="m146.31,134.03v23.84c0,.54.45.8.92.54l20.65-11.92c4.44-2.57,6.33-5.84,6.33-10.97h0s0-23.84,0-23.84c0-.54-.45-.8-.92-.53l-20.64,11.92h0c-4.44,2.57-6.33,5.84-6.33,10.97Z"/><path class="cls-4" d="m63.35,123.06h0s-20.64-11.92-20.64-11.92c-.47-.27-.92-.01-.92.53v23.84s0,0,0,0c0,5.13,1.89,8.4,6.33,10.97l20.65,11.92c.47.27.92,0,.92-.54v-23.84c0-5.13-1.89-8.4-6.33-10.97Z"/><path class="cls-4" d="m103.61,151.37l-20.64,11.92c-4.44,2.57-6.33,5.84-6.33,10.97h0s0,23.84,0,23.84c0,.54.45.8.92.54l20.65-11.92h0c4.44-2.57,6.33-5.84,6.33-10.97v-23.84c0-.54-.45-.8-.92-.53Z"/><path class="cls-4" d="m63.35,163.29h0s-20.64-11.92-20.64-11.92c-.47-.27-.92-.01-.92.53v23.84s0,0,0,0c0,5.13,1.89,8.4,6.33,10.97l20.65,11.92c.47.27.92,0,.92-.54v-23.84c0-5.13-1.89-8.4-6.33-10.97Z"/><path class="cls-4" d="m28.51,102.94h0s-20.64-11.92-20.64-11.92c-.47-.27-.92-.01-.92.53v23.84s0,0,0,0c0,5.13,1.89,8.4,6.33,10.97l20.65,11.92c.47.27.92,0,.92-.54v-23.84c0-5.13-1.89-8.4-6.33-10.97Z"/><path class="cls-4" d="m133.04,163.29l-20.64-11.92c-.47-.27-.92-.01-.92.53v23.84c0,5.13,1.89,8.4,6.33,10.97h0s20.65,11.92,20.65,11.92c.47.27.92,0,.92-.54v-23.84s0,0,0,0c0-5.13-1.89-8.4-6.33-10.97Z"/><path class="cls-4" d="m173.29,151.37l-20.64,11.92h0c-4.44,2.57-6.33,5.84-6.33,10.97v23.84c0,.54.45.8.92.54l20.65-11.92c4.44-2.57,6.33-5.84,6.33-10.97h0s0-23.84,0-23.84c0-.54-.45-.8-.92-.53Z"/><path class="cls-4" d="m209.06,91.55c0-.54-.45-.8-.92-.53l-20.64,11.92h0c-4.44,2.57-6.33,5.84-6.33,10.97v23.84c0,.54.45.8.92.54l20.65-11.92c4.44-2.57,6.33-5.84,6.33-10.97h0v-23.84Z"/><path class="cls-2" d="m149.18,117.04l20.64-11.92c.47-.27.47-.79,0-1.06l-20.65-11.92h0c-4.44-2.57-8.22-2.57-12.67,0l-20.65,11.92c-.47.27-.47.79,0,1.06l20.64,11.92c4.44,2.57,8.22,2.57,12.67,0h0Z"/><path class="cls-1" d="m112.39,98.05l20.65-11.92c4.44-2.57,6.33-5.84,6.33-10.97h0v-23.84c0-.54-.45-.8-.92-.53l-20.64,11.92h0c-4.44,2.57-6.33,5.84-6.33,10.97v23.84c0,.54.45.8.92.54Z"/><path class="cls-1" d="m100.13,105.12c.47-.27.47-.79,0-1.06l-20.65-11.92c-4.44-2.57-8.22-2.57-12.67,0h0s-20.65,11.92-20.65,11.92c-.47.27-.47.79,0,1.06l20.64,11.92h0c4.44,2.57,8.22,2.57,12.67,0l20.64-11.92Z"/><path class="cls-2" d="m65.29,85.01c.47-.27.47-.79,0-1.06l-20.65-11.92c-4.44-2.57-8.22-2.57-12.67,0h0s-20.65,11.92-20.65,11.92c-.47.27-.47.79,0,1.06l20.64,11.92h0c4.44,2.57,8.22,2.57,12.67,0l20.64-11.92Z"/><path class="cls-1" d="m133.04,123.06l-20.64-11.92c-.47-.27-.92-.01-.92.53v23.84c0,5.13,1.89,8.4,6.33,10.97h0s20.65,11.92,20.65,11.92c.47.27.92,0,.92-.54v-23.84s0,0,0,0c0-5.13-1.89-8.4-6.33-10.97Z"/><path class="cls-1" d="m184.02,96.93l20.64-11.92c.47-.27.47-.79,0-1.06l-20.65-11.92h0c-4.44-2.57-8.22-2.57-12.67,0l-20.65,11.92c-.47.27-.47.79,0,1.06l20.64,11.92c4.44,2.57,8.22,2.57,12.67,0h0Z"/></svg>
package/http-request.js CHANGED
@@ -6,6 +6,16 @@ export class HttpRequestElement extends HTMLElement
6
6
  constructor() {
7
7
  super();
8
8
  }
9
+ get requestHeaders()
10
+ { const ret = {};
11
+ [...this.attributes].filter(a=>a.name.startsWith('header-')).map( a => ret[a.name.substring(7)] = a.value );
12
+ return ret;
13
+ }
14
+ get requestProps()
15
+ { const ret = {};
16
+ [...this.attributes].filter(a=>!a.name.startsWith('header-')).map( a => ret[a.name] = a.value );
17
+ return ret;
18
+ }
9
19
  sliceInit( s )
10
20
  { if( !s )
11
21
  s = {};
@@ -18,7 +28,7 @@ export class HttpRequestElement extends HTMLElement
18
28
  controller.abort();
19
29
  };
20
30
  const url = attr(this, 'url') || ''
21
- , request = { url }
31
+ , request = { ...this.requestProps, headers: this.requestHeaders }
22
32
  , slice = { detail: { request }, target: this }
23
33
  , updateSlice = slice =>
24
34
  { for( let parent = s.element.parentElement; parent; parent = parent.parentElement )
@@ -30,9 +40,14 @@ export class HttpRequestElement extends HTMLElement
30
40
 
31
41
  setTimeout( async ()=>
32
42
  { updateSlice( slice );
33
- slice.detail.response = await fetch(url,{ signal: controller.signal });
43
+ const response = await fetch(url,{ ...this.requestProps, signal: controller.signal, headers: this.requestHeaders })
44
+ , r= {headers: {}};
45
+ [...response.headers].map( ([k,v]) => r.headers[k]=v );
46
+ 'ok,status,statusText,type,url,redirected'.split(',').map(k=>r[k]=response[k])
47
+
48
+ slice.detail.response = r;
34
49
  updateSlice( slice );
35
- slice.detail.data = await slice.detail.response.json();
50
+ slice.detail.data = await response.json();
36
51
  updateSlice( slice );
37
52
  },0 );
38
53
 
@@ -41,4 +56,4 @@ export class HttpRequestElement extends HTMLElement
41
56
  }
42
57
 
43
58
  window.customElements.define( 'http-request', HttpRequestElement );
44
- export default HttpRequestElement;
59
+ export default HttpRequestElement;
package/index.html CHANGED
@@ -3,6 +3,7 @@
3
3
  <head>
4
4
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
5
5
  <title>custom-element Declarative Custom Element implementation demo</title>
6
+ <link rel="icon" href="demo/wc-square.svg" />
6
7
  <script type="module" src="custom-element.js"></script>
7
8
  <style>
8
9
  @import "demo/demo.css";
@@ -26,7 +27,8 @@
26
27
  <section>
27
28
  <b>Data layer demo</b>
28
29
  <a href="./demo/local-storage.html">local-storage</a> |
29
- <a href="./demo/http-request.html">http-request</a>
30
+ <a href="./demo/http-request.html">http-request</a> |
31
+ <a href="./demo/location-element.html">location-element</a>
30
32
  </section>
31
33
  </nav>
32
34
  <html-demo-element legend="1. simple payload"
@@ -0,0 +1,63 @@
1
+ const attr = (el, attr)=> el.getAttribute(attr);
2
+
3
+ export class LocationElement extends HTMLElement
4
+ {
5
+ // @attribute live - monitors localStorage change
6
+ // @attribute src - URL to be parsed, defaults to `window.location`
7
+
8
+ constructor()
9
+ {
10
+ super();
11
+ const state = {}
12
+ , listener = e=> propagateSlice(e)
13
+ , propagateSlice = (e)=>
14
+ { const urlStr = attr(this,'src')
15
+ const url = urlStr? new URL(urlStr) : window.location
16
+
17
+ const params= {}
18
+ const search = new URLSearchParams(url.search);
19
+ for (const key of search.keys())
20
+ params[key] = search.getAll(key)
21
+
22
+ const detail = {params}
23
+ for( const k in url )
24
+ { if ('string' === typeof url[k])
25
+ detail[k] = url[k]
26
+ }
27
+ for( let parent = this.parentElement; parent; parent = parent.parentElement)
28
+ { if (parent.onSlice)
29
+ return parent.onSlice(
30
+ { detail
31
+ , target: this
32
+ });
33
+ }
34
+ console.error(`${this.localName} used outside of custom-element`)
35
+ debugger;
36
+ };
37
+ this.sliceInit = s =>
38
+ {
39
+ if( !state.listener && this.hasAttribute('live') )
40
+ { state.listener = 1;
41
+ window.addEventListener( 'popstate', listener );
42
+ window.addEventListener( 'hashchange', listener );
43
+ }
44
+ propagateSlice();
45
+ return s || {}
46
+ }
47
+ this._destroy = ()=>
48
+ {
49
+ if( !state.listener )
50
+ return;
51
+ if(state.listener)
52
+ { window.removeEventListener('popstate', listener);
53
+ window.removeEventListener('hashchange', listener);
54
+ }
55
+ delete state.listener;
56
+ };
57
+ this.sliceInit()
58
+ }
59
+ disconnectedCallback(){ this._destroy(); }
60
+ }
61
+
62
+ window.customElements.define( 'location-element', LocationElement );
63
+ export default LocationElement;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@epa-wg/custom-element",
3
- "version": "0.0.8",
3
+ "version": "0.0.10",
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",