@epa-wg/custom-element 0.0.18 → 0.0.20

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/demo/s.xslt CHANGED
@@ -1,3 +1,4 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
1
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">
2
3
  <xsl:template match="ignore">
3
4
  <xsl:choose>
@@ -5,14 +6,15 @@
5
6
  <xsl:otherwise><xsl:value-of select="def"/></xsl:otherwise>
6
7
  </xsl:choose>
7
8
  <xsl:value-of select="."/></xsl:template>
8
- <xsl:template mode="payload" match="attributes"><xsl:param xmlns:xsl="http://www.w3.org/1999/XSL/Transform" name="p1"><xsl:choose>
9
- <xsl:when test="//p1 "><xsl:value-of select="//p1 "/></xsl:when>
10
- <xsl:otherwise><xsl:value-of select=" 'def_p1' "/></xsl:otherwise>
11
- </xsl:choose></xsl:param><xsl:param xmlns:xsl="http://www.w3.org/1999/XSL/Transform" name="p2" select="'always_p2'"/><xsl:param xmlns:xsl="http://www.w3.org/1999/XSL/Transform" name="p3"><xsl:choose>
12
- <xsl:when test="//p3"><xsl:value-of select="//p3"/></xsl:when>
13
- <xsl:otherwise><xsl:value-of select="'default_P3 &#10; p1:{$p1"/> p2:<xsl:value-of select="$p2"/> p3:<xsl:value-of select="$p3"/>
14
- '}</xsl:otherwise>
15
- </xsl:choose></xsl:param><dce-root xmlns="http://www.w3.org/1999/xhtml" xmlns:xhtml="http://www.w3.org/1999/xhtml" data-dce-id="1"><xsl:attribute xmlns:xsl="http://www.w3.org/1999/XSL/Transform" name="p1" select="//p1 ?? 'def_p1' "/><xsl:attribute xmlns:xsl="http://www.w3.org/1999/XSL/Transform" name="p2" select="'always_p2'"/><xsl:attribute xmlns:xsl="http://www.w3.org/1999/XSL/Transform" name="p3"/></dce-root></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>
16
18
  <xsl:template match="/">
17
19
  <xsl:apply-templates mode="payload" select="/datadom/attributes"/>
18
20
  </xsl:template>
@@ -21,7 +23,7 @@
21
23
  <xsl:param name="defaultvalue"/>
22
24
  <xsl:choose>
23
25
  <xsl:when test="//payload/*[@slot=$slotname]">
24
- <xsl:copy-of select="//payload/*[@slot=$slotname]"/>
26
+ <xsl:copy-of select="//payload/*[@slot=$slotname]"/>
25
27
  </xsl:when>
26
28
  <xsl:otherwise>
27
29
  <xsl:copy-of select="$defaultvalue"/>
@@ -34,4 +36,4 @@
34
36
  <xsl:with-param name="defaultvalue"/>
35
37
  </xsl:call-template>
36
38
  </xsl:variable>
37
- </xsl:stylesheet>
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>
package/demo/ss.html CHANGED
@@ -1,32 +1,52 @@
1
- <!DOCTYPE html>
2
- <html lang="en" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xhtml="http://www.w3.org/1999/xhtml">
3
- <head>
4
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
5
- <title>CSS scoping - Declarative Custom Element implementation demo</title>
6
- <link rel="icon" href="./wc-square.svg"/>
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="">
7
27
 
8
- <script type="module" src="../http-request.js"></script>
9
- <script type="module" src="../input-text.js"></script>
10
- <script type="module" src="../custom-element.js"></script>
11
- <style>
12
- @import "./demo.css";
13
- </style>
14
- </head>
15
- <body>
16
28
 
17
-
18
- <custom-element src="hex-grid-dce.html#hex-grid-template">
19
- <template>
20
- <style>nav{--hex-grid-size: 4rem;}</style>
21
- <img src="wc-square.svg" alt="DCE" href="https://github.com/EPA-WG/custom-element"/>
22
- <img src="https://upload.wikimedia.org/wikipedia/commons/a/a7/React-icon.svg" alt="React" href="https://react.dev/"/>
23
- <img src="https://angularjs.org/favicon.ico" alt="Angular" href="https://angularjs.org/"/>
24
- <img src="https://open-wc.org/35ded306.svg" alt="Open WC" href="https://open-wc.org/"/>
25
- <img src="https://storage.googleapis.com/cms-storage-bucket/4fd0db61df0567c0f352.png" alt="Flutter" href="https://flutter.dev/"/>
26
- <img src="https://lit.dev/images/logo.svg#flame" alt="Lit"/>
27
- <img src="https://redux.js.org/img/redux.svg" alt="Redux"/>
28
- </template>
29
- </custom-element>
30
-
31
- </body>
32
- </html>
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>
package/demo/z.html CHANGED
@@ -1,48 +1,62 @@
1
- <!DOCTYPE html>
2
- <html lang="en" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xhtml="http://www.w3.org/1999/xhtml">
3
- <head>
4
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
5
- <title>CSS scoping - Declarative Custom Element implementation demo</title>
6
- <link rel="icon" href="./wc-square.svg"/>
7
-
8
- <script type="module" src="../http-request.js"></script>
9
- <script type="module" src="../input-text.js"></script>
10
- <script type="module" src="../custom-element.js"></script>
11
- <style>
12
- @import "./demo.css";
13
-
14
- button {
15
- display: inline-flex;
16
- flex-direction: column;
17
- align-items: center;
18
- flex: auto;
19
- box-shadow: inset silver 0 0 1rem;
20
- min-width: 12rem;
21
- padding: 1rem;
22
- color: coral;
23
- text-shadow: 1px 1px silver;
24
- font-weight: bolder;
25
- }
26
-
27
- caption {
28
- padding: 1rem;
29
- font-weight: bolder;
30
- font-family: sans-serif;
31
- }
32
-
33
- code {
34
- text-align: right;
35
- min-width: 3rem;
36
- }
37
-
38
- </style>
39
- </head>
40
- <body>
41
-
42
- <custom-element src="embed-1.html">
43
- loading from embed-1.html ...
44
- </custom-element>
45
-
46
-
47
- </body>
48
- </html>
1
+ <dce-root xmlns="http://www.w3.org/1999/xhtml" xmlns:xhtml="http://www.w3.org/1999/xhtml"
2
+ xmlns:dce="urn:schemas-epa-wg:dce" data-dce-id="1">
3
+ <location-element xmlns="" slice="window-url" live="" data-dce-id="2"></location-element>
4
+ <table xmlns="" data-dce-id="3">
5
+ <tbody data-dce-id="0-1">
6
+ <tr data-dce-id="4">
7
+ <th data-dce-id="5"><h3 data-dce-id="6"> URL properties </h3></th>
8
+ <td data-dce-id="7">9</td>
9
+ </tr>
10
+ <tr data-dce-id="10">
11
+ <th data-dce-id="11">href</th>
12
+ <td data-dce-id="12">http://localhost:63342/custom-element/demo/a.html?_ijt=dmv0p4go000q47lg48i5im92f7&amp;_ij_reload=RELOAD_ON_SAVE</td>
13
+ </tr>
14
+ <tr data-dce-id="10-1">
15
+ <th data-dce-id="11">origin</th>
16
+ <td data-dce-id="12">http://localhost:63342</td>
17
+ </tr>
18
+ <tr data-dce-id="10-2">
19
+ <th data-dce-id="11">protocol</th>
20
+ <td data-dce-id="12">http:</td>
21
+ </tr>
22
+ <tr data-dce-id="10-3">
23
+ <th data-dce-id="11">host</th>
24
+ <td data-dce-id="12">localhost:63342</td>
25
+ </tr>
26
+ <tr data-dce-id="10-4">
27
+ <th data-dce-id="11">hostname</th>
28
+ <td data-dce-id="12">localhost</td>
29
+ </tr>
30
+ <tr data-dce-id="10-5">
31
+ <th data-dce-id="11">port</th>
32
+ <td data-dce-id="12">63342</td>
33
+ </tr>
34
+ <tr data-dce-id="10-6">
35
+ <th data-dce-id="11">pathname</th>
36
+ <td data-dce-id="12">/custom-element/demo/a.html</td>
37
+ </tr>
38
+ <tr data-dce-id="10-7">
39
+ <th data-dce-id="11">search</th>
40
+ <td data-dce-id="12">?_ijt=dmv0p4go000q47lg48i5im92f7&amp;_ij_reload=RELOAD_ON_SAVE</td>
41
+ </tr>
42
+ <tr data-dce-id="10-8">
43
+ <th data-dce-id="11">hash</th>
44
+ <td data-dce-id="12"></td>
45
+ </tr>
46
+ </tbody>
47
+ </table>
48
+ <h3 data-dce-id="9"> URL parameters </h3>
49
+ <table xmlns="" data-dce-id="8">
50
+
51
+ <tbody data-dce-id="0-1">
52
+ <tr data-dce-id="10">
53
+ <th data-dce-id="11">_ijt</th>
54
+ <td data-dce-id="12">dmv0p4go000q47lg48i5im92f7</td>
55
+ </tr>
56
+ <tr data-dce-id="10-1">
57
+ <th data-dce-id="11">_ij_reload</th>
58
+ <td data-dce-id="12">RELOAD_ON_SAVE</td>
59
+ </tr>
60
+ </tbody>
61
+ </table>
62
+ </dce-root>
package/http-request.js CHANGED
@@ -2,14 +2,13 @@ const attr = (el, attr)=> el.getAttribute(attr);
2
2
 
3
3
  export class HttpRequestElement extends HTMLElement
4
4
  {
5
- static get observedAttributes() {
6
- return [ 'value' // populated from localStorage, if defined initially, sets the value in storage
7
- , 'slice'
8
- , 'url'
9
- , 'method'
10
- , 'header-accept'
11
- ]
12
- }
5
+ static observedAttributes =
6
+ [ 'value' // populated from localStorage, if defined initially, sets the value in storage
7
+ , 'slice'
8
+ , 'url'
9
+ , 'method'
10
+ , 'header-accept'
11
+ ];
13
12
 
14
13
  get requestHeaders()
15
14
  { const ret = {};
@@ -18,34 +17,64 @@ export class HttpRequestElement extends HTMLElement
18
17
  }
19
18
  get requestProps()
20
19
  { const ret = {};
21
- [...this.attributes].filter(a=>!a.name.startsWith('header-')).map( a => ret[a.name] = a.value );
20
+ [...this.attributes].filter(a=>!a.name.startsWith('header-'))
21
+ .filter(a=>!a.name.startsWith('slice')).map( a => ret[a.name] = a.value );
22
22
  return ret
23
23
  }
24
24
 
25
- disconnectedCallback(){ this._destroy?.(); }
25
+ disconnectedCallback(){ this.#destroy?.(); }
26
26
 
27
27
  connectedCallback()
28
- { const controller = new AbortController();
29
- this._destroy = ()=> controller.abort(this.localName+' disconnected');
28
+ {
29
+ setTimeout(()=>this.fetch(),0)
30
+ }
31
+ #inProgressUrl = ''
32
+ #destroy = ()=>{}
33
+
34
+ async fetch()
35
+ {
36
+ if( !this.closest('custom-element') )
37
+ return;
38
+ const url = attr(this, 'url') || '';
39
+ if( !url )
40
+ { this.#destroy?.();
41
+ return this.value = {};
42
+ }
43
+
44
+ if( this.#inProgressUrl === url )
45
+ return ;
46
+
47
+ this.#inProgressUrl = url;
48
+ const controller = new AbortController();
49
+ this.#destroy = ()=> controller.abort(this.localName+' disconnected');
30
50
 
31
- const url = attr(this, 'url') || ''
32
- , request = { ...this.requestProps, headers: this.requestHeaders }
51
+ const request = { ...this.requestProps, headers: this.requestHeaders }
33
52
  , slice = { request }
34
53
  , update = () => this.dispatchEvent( new Event('change') );
35
54
  this.value = slice;
36
- setTimeout( async ()=>
37
- { update();
38
- const response = await fetch(url,{ ...this.requestProps, signal: controller.signal, headers: this.requestHeaders })
39
- , r = {headers: {}};
40
- [...response.headers].map( ([k,v]) => r.headers[k] = v );
41
- 'ok,status,statusText,type,url,redirected'.split(',').map( k=> r[k] = response[k] )
42
-
43
- slice.response = r;
44
- update();
45
- slice.data = await response.json();
46
- update();
47
- },0 );
55
+
56
+ update();
57
+ const response = await fetch(url,{ ...this.requestProps, signal: controller.signal, headers: this.requestHeaders })
58
+ , r = {headers: {}};
59
+ [...response.headers].map( ([k,v]) => r.headers[k] = v );
60
+ 'ok,status,statusText,type,url,redirected'.split(',').map( k=> r[k] = response[k] )
61
+
62
+ slice.response = r;
63
+ update();
64
+ slice.data = await response.json();
65
+ update();
48
66
  }
67
+
68
+ attributeChangedCallback(name, oldValue, newValue)
69
+ { if( name === 'url' )
70
+ { if( newValue && oldValue !== newValue)
71
+ {
72
+ oldValue && this.#destroy?.();
73
+ setTimeout(()=>this.fetch(),0)
74
+ }
75
+ }
76
+ }
77
+
49
78
  }
50
79
 
51
80
  window.customElements.define( 'http-request', HttpRequestElement );
@@ -5,7 +5,7 @@
5
5
  "name": "slice",
6
6
  "description": {
7
7
  "kind": "markdown",
8
- "value": "Defines the name of data slice in DCE where the data from `value` will be propagated on `change` or by `slice-update` event\n\nOn: any component with `value` and associated change event"
8
+ "value": "Defines the name of data slice in DCE where the data from `value` will be propagated on `change` or by `slice-event` event\n\nOn: any component with `value` and associated change event"
9
9
  },
10
10
  "references": [
11
11
  {
@@ -15,7 +15,7 @@
15
15
  ]
16
16
  },
17
17
  {
18
- "name": "slice-update",
18
+ "name": "slice-event",
19
19
  "description": {
20
20
  "kind": "markdown",
21
21
  "value": "Defines the event name on which `value` would be synchronized with DCE slice\n\nOn: any component with `value` and associated change event"
@@ -26,6 +26,19 @@
26
26
  "url": "https://unpkg.com/@epa-wg/custom-element/demo/dom-merge.html"
27
27
  }
28
28
  ]
29
+ },
30
+ {
31
+ "name": "slice-value",
32
+ "description": {
33
+ "kind": "markdown",
34
+ "value": "XPath expression to populate into the slice"
35
+ },
36
+ "references": [
37
+ {
38
+ "name": "Demo",
39
+ "url": "https://unpkg.com/@epa-wg/custom-element/demo/data-slices.html"
40
+ }
41
+ ]
29
42
  }
30
43
  ],
31
44
  "tags": [
@@ -84,6 +97,16 @@
84
97
  "url": "https://developer.mozilla.org/en-US/docs/Web/XSLT/Element/for-each"
85
98
  }
86
99
  ]
100
+ },
101
+ {
102
+ "name": "slice",
103
+ "description": "Synthetic element for defining the slice-attributed when more then one slice/event/value associated with parent element",
104
+ "references": [
105
+ {
106
+ "name": "README",
107
+ "url": "https://github.com/EPA-WG/custom-element/tree/develop?tab=readme-ov-file#interactivity-via-data-slice-triggered-by-events"
108
+ }
109
+ ]
87
110
  }
88
111
  ]
89
112
  }
@@ -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.18",
4
+ "version": "0.0.20",
5
5
  "js-types-syntax": "typescript",
6
6
  "description-markup": "markdown",
7
7
  "contributions": {
@@ -9,13 +9,18 @@
9
9
  "attributes": [
10
10
  {
11
11
  "name": "slice",
12
- "description": "Defines the name of data slice in DCE where the data from `value` will be propagated on `change` or by `slice-update` event\n\nOn: any component with `value` and associated change event",
12
+ "description": "Defines the name of data slice in DCE where the data from `value` will be propagated on `change` or by `slice-event` event\n\nOn: any component with `value` and associated change event",
13
13
  "doc-url": "https://unpkg.com/@epa-wg/custom-element/demo/dom-merge.html"
14
14
  },
15
15
  {
16
- "name": "slice-update",
16
+ "name": "slice-event",
17
17
  "description": "Defines the event name on which `value` would be synchronized with DCE slice\n\nOn: any component with `value` and associated change event",
18
18
  "doc-url": "https://unpkg.com/@epa-wg/custom-element/demo/dom-merge.html"
19
+ },
20
+ {
21
+ "name": "slice-value",
22
+ "description": "XPath expression to populate into the slice",
23
+ "doc-url": "https://unpkg.com/@epa-wg/custom-element/demo/data-slices.html"
19
24
  }
20
25
  ],
21
26
  "elements": [
@@ -91,6 +96,14 @@
91
96
  }
92
97
  }
93
98
  ]
99
+ },
100
+ {
101
+ "name": "slice",
102
+ "description": "Synthetic element for defining the slice-attributed when more then one slice/event/value associated with parent element",
103
+ "doc-url": "https://github.com/EPA-WG/custom-element/tree/develop?tab=readme-ov-file#interactivity-via-data-slice-triggered-by-events",
104
+ "attributes": [
105
+
106
+ ]
94
107
  }
95
108
  ]
96
109
  }
@@ -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.18",
4
+ "version": "0.0.20",
5
5
  "js-types-syntax": "typescript",
6
6
  "description-markup": "markdown",
7
7
  "contributions": {
package/index.html CHANGED
@@ -9,7 +9,7 @@
9
9
  @import "demo/demo.css";
10
10
  </style>
11
11
  </head>
12
- <body>
12
+ <body xmlns:xhtml="http://www.w3.org/1999/xhtml">
13
13
  <nav>
14
14
  <h3><code>custom-element</code> demo</h3>
15
15
  <div><a href="https://github.com/EPA-WG/custom-element"
@@ -34,6 +34,7 @@
34
34
  <a href="./demo/hex-grid.html" >hex grid lib </a> |
35
35
  <a href="./demo/scoped-css.html" >scoped CSS </a> |
36
36
  <a href="./demo/parameters.html" >attributes </a> |
37
+ <a href="./demo/data-slices.html" >data slices/events </a> |
37
38
  <a href="./demo/dom-merge.html" >DOM merge on dynamic update </a>
38
39
  </section>
39
40
  </nav>
package/local-storage.js CHANGED
@@ -2,44 +2,81 @@ const string2value = (type, v) =>
2
2
  { if( type === 'text')
3
3
  return v;
4
4
  if( type === 'json')
5
- return JSON.parse( v );
5
+ try{ return JSON.parse( v );}
6
+ catch(err){ return null }
6
7
  const el = document.createElement('input');
7
8
  el.setAttribute('type',type);
8
- el.setAttribute('value', v );
9
- return type==='number'? el.valueAsNumber : 'date|time|dateTimeLocal'.includes(type)? el.valueAsDate: el.value;
9
+ if( 'number' === type )
10
+ { el.value = v;
11
+ return el.valueAsNumber;
12
+ }
13
+ if( 'date' === type )
14
+ { if(!v) return null;
15
+ el.valueAsDate = new Date( v );
16
+ return el.value;
17
+ }
18
+ el.value = v;
19
+ return el.value;
10
20
  };
11
21
 
22
+ let originalSetItem,originalRemoveItem,originalClear;
23
+
24
+ function ensureTrackLocalStorage()
25
+ { if( originalSetItem )
26
+ return;
27
+ originalSetItem = localStorage.setItem;
28
+ localStorage.setItem = function( key, value, ...rest )
29
+ { originalSetItem.apply(this, [ key, value, ...rest ]);
30
+ window.dispatchEvent( new CustomEvent('local-storage',{detail:{key,value}}) );
31
+ };
32
+ originalRemoveItem = localStorage.removeItem;
33
+ localStorage.removeItem = function( key, ...rest )
34
+ { originalRemoveItem.apply(this, [ key, ...rest ]);
35
+ window.dispatchEvent( new CustomEvent('local-storage',{detail:{key}}) );
36
+ };
37
+ originalClear = localStorage.clear;
38
+ localStorage.clear = function( ...rest )
39
+ { originalClear.apply(this, [ ...rest ]);
40
+ window.dispatchEvent( new CustomEvent('local-storage',{detail:{}}) );
41
+ };
42
+ }
43
+
12
44
  export function localStorageSetItem(key, value)
13
45
  { localStorage.setItem(key, value);
14
46
  window.dispatchEvent( new CustomEvent('local-storage',{detail:{key,value}}) );
15
47
  }
16
48
  export class LocalStorageElement extends HTMLElement
17
49
  {
18
- static get observedAttributes() {
19
- return [ 'value' // populated from localStorage, if defined initially, sets the value in storage
50
+ static observedAttributes=
51
+ [ 'value' // populated from localStorage, if defined initially, sets the value in storage
20
52
  , 'slice'
21
53
  , 'key'
22
54
  , 'type' // `text|json`, defaults to text, other types are compatible with INPUT field
23
55
  , 'live' // monitors localStorage change
24
56
  ];
25
- }
57
+
58
+ #value;
59
+ get value(){ return this.#value ===null ? undefined: this.#value }
60
+ set value(o){ return this.#value = o; }
26
61
 
27
62
  async connectedCallback()
28
63
  {
29
64
  const attr = attr => this.getAttribute(attr)
30
65
  , fromStorage = ()=>
31
- { this.value = string2value( attr('type'), localStorage.getItem( attr( 'key' ) ) );
66
+ { this.#value = string2value( attr('type'), localStorage.getItem( attr( 'key' ) ) );
32
67
  this.dispatchEvent( new Event('change') )
33
68
  }
34
- // todo apply type
69
+ this.#value = string2value( attr('type'), localStorage.getItem( attr( 'key' ) ) );
70
+
35
71
  if( this.hasAttribute('value'))
36
- localStorageSetItem( attr( this, 'key' ) )
72
+ localStorageSetItem( attr( 'key' ), this.#value = attr( 'value' ) )
37
73
  else
38
74
  fromStorage()
39
75
 
40
76
  if( this.hasAttribute('live') )
41
- { const listener = (e => e.detail.key === attr( 'key' ) && fromStorage());
77
+ { const listener = (e => (e.detail.key === attr( 'key' ) || !e.detail.key ) && fromStorage());
42
78
  window.addEventListener( 'local-storage', listener );
79
+ ensureTrackLocalStorage();
43
80
  this._destroy = ()=> window.removeEventListener('local-storage', listener );
44
81
  }
45
82
  }
@@ -2,13 +2,13 @@ const attr = (el, attr)=> el.getAttribute(attr);
2
2
 
3
3
  export class LocationElement extends HTMLElement
4
4
  {
5
- static get observedAttributes()
6
- { return [ 'value' // populated from localStorage, if defined initially, sets the value in storage
7
- , 'slice'
8
- , 'live' // monitors location change
9
- , 'src' // URL to be parsed, defaults to `window.location`
10
- ];
11
- }
5
+ static observedAttributes=
6
+ [ 'value' // populated from localStorage, if defined initially, sets the value in storage
7
+ , 'slice'
8
+ , 'key'
9
+ , 'type' // `text|json`, defaults to text, other types are compatible with INPUT field
10
+ , 'live' // monitors localStorage change
11
+ ];
12
12
 
13
13
  constructor()
14
14
  {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@epa-wg/custom-element",
3
- "version": "0.0.18",
3
+ "version": "0.0.20",
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",