Created
June 13, 2019 09:49
-
-
Save michaelcpuckett/ddb282185a2ac960f250769e640b58c4 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<script> | |
class XTimestamp extends HTMLElement { | |
constructor() { | |
super() | |
this.attachShadow({ mode: 'open' }).appendChild(window.document.createElement('slot')) | |
} | |
connectedCallback() { | |
window.requestAnimationFrame(() => { | |
this.$dateTime = this.querySelector('slot').assignedNodes()[0].innerText.trim() | |
const templateEl = window.document.createElement('template') | |
templateEl.innerHTML = ` | |
<time datetime="${this.$datetime}"> | |
Published on [format: ${this.$dateTime}] | |
</time> | |
` | |
this.shadowRoot.firstChild.remove() | |
this.shadowRoot.appendChild(templateEl.content) | |
}) | |
} | |
} | |
class XIf extends HTMLElement { | |
constructor() { | |
super() | |
} | |
connectedCallback() { | |
window.requestAnimationFrame(() => { | |
const ifEl = this.querySelector('[data-if]') | |
const attachedEl = ifEl.querySelector('slot').assignedNodes()[0] | |
const slotEl = window.document.createElement('slot') | |
if (!attachedEl || !attachedEl.innerText.trim()) { | |
slotEl.setAttribute('name', 'x-inert') | |
} | |
this.attachShadow({ mode: 'open' }).appendChild(slotEl) | |
}) | |
} | |
} | |
class XArticleInner extends HTMLElement { | |
constructor() { | |
super() | |
this | |
.attachShadow({ mode: 'open' }) | |
.appendChild(window.document.getElementById('x-article-inner-template').content) | |
} | |
} | |
class XArticle extends HTMLElement { | |
constructor() { | |
super() | |
this | |
.attachShadow({ mode: 'open' }) | |
.appendChild(window.document.createElement('x-article-inner')) | |
this.$data = new Proxy({}, { | |
set: (_, prop, newVal) => { | |
const slot = this.shadowRoot.querySelector(`[slot="${prop}"]`) | |
if (slot) { | |
slot.innerHTML = newVal | |
} else { | |
const newSlot = window.document.createElement('data') | |
newSlot.setAttribute('slot', prop) | |
newSlot.innerHTML = typeof newVal === 'string' ? newVal : (Array.isArray(newVal) ? `<p>${newVal.join('</p><p>')}</p>` : newVal.name) | |
this.shadowRoot.querySelector('x-article-inner').appendChild(newSlot) | |
} | |
return newVal | |
} | |
}) | |
} | |
connectedCallback() { | |
window.requestAnimationFrame(() => { | |
this.$handleSlotChange(this.querySelector('script').innerHTML) | |
this.querySelector('script').addEventListener('slotchange', this.$handleSlotChange) | |
}) | |
} | |
$handleSlotChange(data) { | |
Object.assign(this.$data, { | |
...(JSON.parse(data)) | |
}) | |
} | |
} | |
customElements.define('x-if', XIf) | |
customElements.define('x-timestamp', XTimestamp) | |
customElements.define('x-article', XArticle) | |
customElements.define('x-article-inner', XArticleInner) | |
;((async function () { | |
await new Promise(done => window.setTimeout(done, 2000)) | |
window.document.querySelector('x-article').$data.headline = 'Replaced headline!' | |
})()) | |
</script> | |
<template id="x-article-inner-template"> | |
<style> | |
:host>* { | |
background: red; | |
--padding: 12px; | |
padding: var(--padding); | |
} | |
* { | |
margin: 0; | |
padding: 0; | |
} | |
h1 { | |
font-style: italic; | |
border-bottom: 1px solid; | |
padding-bottom: var(--padding); | |
margin-bottom: var(--padding); | |
} | |
</style> | |
<div role="region" tabindex="0" aria-labelledby="h1"> | |
<h1 id="h1"> | |
<slot name="headline"></slot> | |
</h1> | |
<x-timestamp> | |
<slot name="datePublished"></slot> | |
</x-timestamp> | |
<div role="presentation"> | |
<x-if> | |
By <span data-if><slot name="author"></slot></span> | |
</x-if> | |
</div> | |
<slot name="dateline"></slot> — | |
<slot name="articleBody"></slot> | |
</div> | |
</template> | |
<h1>PickPuck.com</h1> | |
<x-article id="article"> | |
<script type="application/ld+json"> | |
{ | |
"@context": "http://schema.org/", | |
"type": "NewsArticle", | |
"headline": "Lorem ipsum sigma fidelitdas sin Dolor policia", | |
"datePublished": "2019-06-12", | |
"articleBody": [ | |
"Foo bar", | |
"Foo bar", | |
"Foo bar" | |
], | |
"dateline": "WASHINGTON", | |
"author": { | |
"type": "Person", | |
"name": "Michael Puckett" | |
} | |
} | |
</script> | |
</x-article> | |
<style> | |
h1 { | |
color: green; | |
} | |
</style> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment