Skip to content

Commit

Permalink
Merge pull request #64 from EPA-WG/develop
Browse files Browse the repository at this point in the history
0.0.25
  • Loading branch information
sashafirsov authored Aug 6, 2024
2 parents 78dad3d + 6256ced commit 265465c
Show file tree
Hide file tree
Showing 7 changed files with 409 additions and 120 deletions.
20 changes: 16 additions & 4 deletions custom-element.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,22 @@ const attr = (el, attr)=> el.getAttribute?.(attr)
, isText = e => e.nodeType === 3
, isString = s => typeof s === 'string'
, isNode = e => e && typeof e.nodeType === 'number'
, create = ( tag, t = '', d=document ) => ( e => ((t && e.append(createText(d.ownerDocument||d, t))),e) )((d.ownerDocument || d ).createElement( tag ))
, createText = ( d, t) => (d.ownerDocument || d ).createTextNode( t )
, removeChildren = n => { while(n.firstChild) n.firstChild.remove(); return n; }
, emptyNode = n => { n.getAttributeNames().map( a => n.removeAttribute(a) ); return removeChildren(n); }
, xslNs = x => ( x?.setAttribute('xmlns:xsl', XSL_NS_URL ), x )
, xslHtmlNs = x => ( x?.setAttribute('xmlns:xhtml', HTML_NS_URL ), xslNs(x) )
, isValidTagName = tag=> ( /^[_a-zA-Z][-_:a-zA-Z0-9]*$/ .test(tag) )
, create = ( tag, t = '', d=document ) =>
{
const create = tag => ( e => ((t && e.append(createText(d.ownerDocument||d, t))),e) )((d.ownerDocument || d ).createElement( tag ))

if( isValidTagName(tag) )
return create(tag)
const e = create('dce-object');
e.setAttribute('dce-object-name',tag)
return e;
}
, cloneAs = (p,tag) =>
{ const px = p.ownerDocument.createElementNS(p.namespaceURI,tag);
for( let a of p.attributes)
Expand Down Expand Up @@ -86,7 +96,7 @@ obj2node( o, tag, doc )
if( isNode(o[k]) || typeof o[k] ==='function' || o[k] instanceof Window )
continue
else
if( typeof o[k] !== "object" )
if( typeof o[k] !== "object" && isValidTagName(k) )
ret.setAttribute(k, o[k] );
else
ret.append(obj2node(o[k], k, doc))
Expand Down Expand Up @@ -594,7 +604,9 @@ CustomElement extends HTMLElement
e.append( createText( x, t ))
return e;
})(x.ownerDocument.createElement( tag ))
injectData( x, 'payload' , payload , assureSlot );
const payloadNode = injectData( x, 'payload' , payload , assureSlot );
xslNs(payloadNode);
xslHtmlNs(payloadNode);
this.innerHTML='';
const attrsRoot = injectData( x, 'attributes' , this.attributes, e => createXmlNode( e.nodeName, e.value ) );
injectData( x, 'dataset', Object.keys( this.dataset ), k => createXmlNode( k, this.dataset[ k ] ) );
Expand Down Expand Up @@ -654,7 +666,7 @@ CustomElement extends HTMLElement
{ if( !el.dceInitialized )
{ el.dceInitialized = 1;
let evs = attr(el,'slice-event');
if( attr(el,'custom-validity') )
if( el.hasAttribute('custom-validity') )
evs += ' change submit';

[...new Set((evs || 'change') .split(' '))]
Expand Down
21 changes: 17 additions & 4 deletions demo/location-element.html
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,19 @@
<nav>
<a href="../index.html"><h3><code>custom-element</code> demo</h3></a>
</nav>
<html-demo-element legend="Change window URL">
<main>
<h3>How to get the page URL by location-element?</h3>
Answer: by defining following attributes:
<ol>
<li><code>slice</code> to one of values provided bellow</li>
<li><code>src</code> optionally with URL, If omitted, it would match the <code>window.location.href</code> </li>
</ol>
URL properties would be a part of slice data.
<p><a href="./set-url.html">Set page URL demo</a> </p>
</main>
<html-demo-element legend="Change window URL"
description="use browser URL bar or those controls to change the page URL"
>
<template>
<a href="#dce2">#dce2</a>
<form method="get">
Expand All @@ -40,15 +52,16 @@


<html-demo-element legend="1. window.location live update"
description="In the page beginning change the window URL via link or by history change"
description="Change the window URL via link or history change by controls in #1.
Observe the changes detected by location-element slice."
id="dce2"
>
<p>Has to produce URL properties</p>
<template>
<custom-element tag="dce-2" hidden>
<template>

<location-element slice="window-url" live></location-element>
<location-element slice="window-url" live method="" src=""></location-element>

<xhtml:table>
<xhtml:tbody>
Expand Down Expand Up @@ -121,7 +134,7 @@
<custom-element tag="dce-3" hidden>
<template>

<location-element slice="href-url" href="https://my.example?a=1&b=2#3"></location-element>
<location-element slice="href-url" href="https://my.example?a=1&b=2#3" ></location-element>

<xhtml:table>
<xhtml:tbody>
Expand Down
141 changes: 141 additions & 0 deletions demo/set-url.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
<!DOCTYPE html>
<html lang="en" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xhtml="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title>custom-element Declarative Custom Element implementation demo</title>
<link rel="icon" href="./wc-square.svg"/>
<script type="module" src="../location-element.js"></script>
<script type="module" src="../custom-element.js"></script>
<style>
@import "./demo.css";
input[type="text"]{ min-width: 30rem; }

.infolink {
&:before {
content: '❔';
display: inline-block;
border-radius: 1.2em;
}

&:hover:before {
background: blue;
}
}
</style>
</head>
<body>
<nav>
<a href="../index.html"><h3><code>custom-element</code> demo</h3></a>
</nav>
<main>
<h3>How to set the page URL by location-element?</h3>
Answer: by defining following attributes:
<ol>
<li><code>method</code> to one of values provided bellow</li>
<li><code>src</code> with URL </li>
</ol>
<p> &lt;location-element&gt; is safe to be used unconditionally as long as `src` is missing or same as page URL.
Otherwise it can be injected by event driven condition as in sample <a href="#dce3">#3</a> </p>
</main>
<html-demo-element legend="1. Set the page URL by location.hash"
description="click on 'set' button and observe hash value change in url"
id="dce1">
<template>
<custom-element>
<template>
<button value="#dce1" slice="set-button" slice-event="click">#dce1</button>
<button value="#dce2" slice="set-button" slice-event="click">#dce2</button>
<location-element method="location.href" src="{//set-button/@value}"></location-element>
</template>
</custom-element>
</template>
</html-demo-element>

<html-demo-element legend="2. Set the page URL by method"
description="click on 'set' button and observe hash value change in url"
id="dce2">
<template>
<custom-element>
<template>
<style>
button{ display: block; width: 100%; }
</style>
<button value="location.href" slice="set-button" slice-event="click"> location.href </button>
<button value="location.hash" slice="set-button" slice-event="click"> location.hash </button>
<button value="location.assign" slice="set-button" slice-event="click"> location.assign </button>
<button value="location.replace" slice="set-button" slice-event="click"> location.replace </button>
<button value="history.pushState" slice="set-button" slice-event="click"> history.pushState </button>
<button value="history.replaceState" slice="set-button" slice-event="click"> history.replaceState </button>
<location-element method="{//set-button/@value}" src="#dce2"></location-element>
</template>
</custom-element>
</template>
</html-demo-element>

<html-demo-element legend="3. Set the page URL by location.href in conditionally injected location-element"
description="click on 'set' button and observe in url #dce3"
id="dce3">
<p>Has to produce URL properties</p>
<template>
<custom-element>
<template>
<button value="#dce3" slice="set-button" slice-event="click">set</button>
<if test="//set-button/@slice-event">
<location-element method="location.href" src="#dce3"></location-element>
look for <b>#dce3</b> in URL which is set by <code>location-element</code>
</if>
</template>
</custom-element>
</template>
</html-demo-element>

<html-demo-element legend="4. Set page URL methods"
description="To define the URL, fill input field or click the radio button, then 'set' button. "
id="dce4">
<template>
<custom-element>
<template>
<xsl:variable name="methods">
<a href="https://developer.mozilla.org/en-US/docs/Web/API/Location/href"
title="./set-url.html?a=A">location.href</a>
<a href="https://developer.mozilla.org/en-US/docs/Web/API/Location/hash"
title="#dec4">location.hash</a>
<a href="https://developer.mozilla.org/en-US/docs/Web/API/Location/assign"
title="./set-url.html?assign=1">location.assign</a>
<a href="https://developer.mozilla.org/en-US/docs/Web/API/Location/replace"
title="./set-url.html?replace=location">location.replace</a>
<a href="https://developer.mozilla.org/en-US/docs/Web/API/History/pushState"
title="./set-url.html?history=pushState">history.pushState</a>
<a href="https://developer.mozilla.org/en-US/docs/Web/API/History/replaceState"
title="./set-url.html?history=replaceState">history.replaceState</a>
</xsl:variable>
<form slice="url-form" custom-validity="'invalid'" method="post">
<fieldset>
<legend><b>set-by</b></legend>
<for-each select="exsl:node-set($methods)/*">
<p><label><input type="radio" name="method" value="{.}"/> {.} </label>
<a class="infolink" href="{@href}">mdn</a>
</p>
</for-each>
</fieldset>
<variable name="selected-method" select="//form-data/method/text()"></variable>
<variable name="selected-url"
select="exsl:node-set($methods)/*[text() = $selected-method ]/@title"></variable>

<label><input name="url" value="{//url ?? $selected-url }" type="text"/></label>
<button name="submit-btn" value="by-submit" type="submit">set</button>
<if test="//form-data/url">
<location-element method="{$selected-method}" src="{//form-data/url}"></location-element>
{$selected-method} = {//form-data/url}
</if>
</form>
</template>
</custom-element>
</template>
</html-demo-element>

<script type="module" src="https://unpkg.com/html-demo-element@1/html-demo-element.js"></script>

</body>
</html>
56 changes: 56 additions & 0 deletions ide/customData-dce.json
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,62 @@
"url": "https://github.com/EPA-WG/custom-element/tree/develop?tab=readme-ov-file#interactivity-via-data-slice-triggered-by-events"
}
]
},
{
"name": "location-element",
"description": "get/set window URL parts or from SRC URL",
"attributes": [
{
"name": "href",
"description": "url to be parsed. When omitted window.location is used.",
"type": "string",
"references": [
{
"name": "MDN docs",
"url": "https://developer.mozilla.org/en-US/docs/Web/API/Location/href"
}
]
},
{
"name": "live",
"description": "monitors history change, applicable only when href is omitted.",
"type": "string",
"references": [
{
"name": "docs",
"url": "https://unpkg.com/@epa-wg/custom-element@0/demo/location-element.html"
}
]
},
{
"name": "src",
"description": "sets the window URL",
"type": "string",
"references": [
{
"name": "docs",
"url": "https://unpkg.com/@epa-wg/custom-element@0/demo/set-url.html"
}
]
},
{
"name": "method",
"description": "when defined, changes URL by one of predefined methods.",
"type": "string",
"references": [
{
"name": "docs",
"url": "https://unpkg.com/@epa-wg/custom-element@0/demo/set-url.html"
}
]
}
],
"references": [
{
"name": "docs",
"url": "https://github.com/EPA-WG/custom-element"
}
]
}
]
}
Loading

0 comments on commit 265465c

Please sign in to comment.