joicomponents
Version:
Design patterns to build native web components
76 lines (68 loc) • 1.87 kB
HTML
<script>
class TreeNode extends HTMLElement {
constructor() {
super();
this.attachShadow({mode: "open"});
this.shadowRoot.innerHTML = `
<style>
:host {
display: block;
}
span {
cursor: pointer;
display: inline-block;
transform: rotate(45deg);
transition: 300ms ease-in-out;
}
:host([open]) span {
transform: rotate(0deg);
}
slot {
display: none;
}
:host([open]) slot {
display: inline;
}
</style>
<span>+</span>
<slot></slot>`;
this.shadowRoot.querySelector("span").addEventListener("click", this.onClick.bind(this));
}
static get observedAttributes() {
return ["open"];
}
attributeChangedCallback(name, oldValue, newValue) {
if (name === "open")
newValue === null ? this.closeChildren() : this.openParent();
}
closeChildren() {
for (let child of this.children) {
if (child.tagName === "TREE-NODE" && child.hasAttribute("open"))
child.removeAttribute("open");
}
}
openParent() {
const parent = this.parentNode;
if (parent.tagName && parent.tagName === "TREE-NODE" && !parent.hasAttribute("open"))
parent.setAttribute("open", "");
}
onClick(e) {
e.stopPropagation();
this.hasAttribute("open") ? this.removeAttribute("open") : this.setAttribute("open", "");
}
}
customElements.define("tree-node", TreeNode);
</script>
<style>
tree-node {
border: 2px solid grey;
padding: 10px;
}
</style>
<tree-node>
<tree-node>hello world</tree-node>
<tree-node>
<tree-node>hello sunshine</tree-node>
<tree-node>hello blue skies</tree-node>
</tree-node>
</tree-node>