light dom render custom element
// adapted from example https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_templates_and_slots | |
document.body.insertAdjacentHTML( | |
'beforeend', | |
` | |
<template id="element-details-template"> | |
<style> | |
details {font-family: "Open Sans Light",Helvetica,Arial} | |
.name {font-weight: bold; color: #217ac0; font-size: 120%} | |
h4 { margin: 10px 0 -8px 0; } | |
h4 span { background: #217ac0; padding: 2px 6px 2px 6px } | |
h4 span { border: 1px solid #cee9f9; border-radius: 4px } | |
h4 span { color: white } | |
.attributes { margin-left: 22px; font-size: 90% } | |
.attributes p { margin-left: 16px; font-style: italic } | |
</style> | |
<slot name="omg"><i>multiple</i><b>nodes</b></slot> | |
<details> | |
<summary> | |
<span> | |
<code class="name"><<slot name="element-name">NEED NAME</slot>></code> | |
<i class="desc"><slot name="description">NEED DESCRIPTION</slot></i> | |
</span> | |
</summary> | |
<div class="attributes"> | |
<h4><span>Attributes</span></h4> | |
<slot name="attributes"><p>None</p></slot> | |
</div> | |
</details> | |
<hr> | |
</template>` | |
); | |
customElements.define( | |
'element-details', | |
class extends HTMLElement { | |
constructor() { | |
super(); | |
} | |
renderLight() { | |
const templateId = `${this.localName}-template`; | |
const template = document.getElementById(templateId).content; | |
const content = template.cloneNode(true); | |
const style = content.querySelector('style'); | |
if (style) style.parentNode.removeChild(style); | |
if (style && !document.querySelector(`#${this.localName}-style`)) { | |
style.id = `${this.localName}-style`; | |
document.body.insertAdjacentElement('afterbegin', style); | |
} | |
const defaultSlot = content.querySelector('slot:not([name])'); | |
if (defaultSlot) { | |
const fragment = document.createDocumentFragment(); | |
while (this.firstChild) { | |
fragment.appendChild(this.firstChild); | |
} | |
this.appendChild(content); | |
return; | |
} | |
const slots = content.querySelectorAll('slot[name]'); | |
slots.forEach((slot) => { | |
const el = this.querySelector(`[slot="${slot.name}"]`); | |
const parent = slot.parentNode; | |
if (el) return parent.replaceChild(el, slot); | |
// handle missing slots with default content | |
const fragment = document.createDocumentFragment(); | |
while (slot.firstChild) { | |
fragment.appendChild(slot.firstChild); | |
} | |
parent.replaceChild(fragment, slot); | |
}); | |
this.appendChild(content); | |
} | |
renderShadow() { | |
const templateId = `${this.localName}-template`; | |
var template = document.getElementById(templateId).content; | |
this.attachShadow({ mode: 'open' }).appendChild(template.cloneNode(true)); | |
} | |
connectedCallback() { | |
if (this.hasAttribute('light')) return this.renderLight(); | |
this.renderShadow(); | |
} | |
} | |
); | |
document.body.insertAdjacentHTML( | |
'beforeend', | |
` | |
<element-details light> | |
<span slot="omg">test a top-level slot</span> | |
<span slot="element-name">slot</span> | |
<span slot="description">A placeholder inside a web | |
component that users can fill with their own markup, | |
with the effect of composing different DOM trees | |
together.</span> | |
<dl slot="attributes"> | |
<dt>name</dt> | |
<dd>The name of the slot.</dd> | |
</dl> | |
</element-details>` | |
); | |
// make sure we only inject the style once | |
document.body.insertAdjacentHTML( | |
'beforeend', | |
` | |
<element-details light> | |
<span slot="element-name">template (light)</span> | |
<span slot="description">A mechanism for holding client- | |
side content that is not to be rendered when a page is | |
loaded but may subsequently be instantiated during | |
runtime using JavaScript.</span> | |
</element-details> ` | |
); | |
document.body.insertAdjacentHTML( | |
'beforeend', | |
` | |
<element-details> | |
<span slot="element-name">template (shadow)</span> | |
<span slot="description">A mechanism for holding client- | |
side content that is not to be rendered when a page is | |
loaded but may subsequently be instantiated during | |
runtime using JavaScript.</span> | |
</element-details>` | |
); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment