customElements.define('cat-template', class extends HTMLElement { constructor() { super(); } cloneTo(target) { if (target.hasTemplated) return; target.hasTemplated = true; const dom = this.cloneNode(true); // oh boy, weird value inheritance code. var inherits = dom.getElementsByTagName('cat-inherits'); while (inherits.length > 0) { var item = inherits[0]; var parent = item.parentNode; if (!parent) continue; for (var j = 0; j < item.attributes.length; j++) { var prop = item.attributes[j]; (function(target, descriptor, parent, name, value) { Object.defineProperty(target, value, { configurable: true, set: function(val) { if (descriptor && descriptor.set) descriptor.set(val); if (name === 'content') { parent.innerHTML = val; } else { if (val === null) { parent.removeAttribute(name); } else { parent.setAttribute(name, val); } } } }) })(target, Object.getOwnPropertyDescriptor(target, prop.value), parent, prop.name, prop.value); } inherits[0].remove(); } // end the gross stuff // begin other weird stuff of moving childs var childrenNode = dom.getElementsByTagName('cat-children')[0]; if (childrenNode) { while (target.firstChild) childrenNode.parentNode.appendChild(target.firstChild); childrenNode.parentNode.removeChild(childrenNode); } // copy our template clone to our target while (dom.firstChild) target.appendChild(dom.firstChild); // finally copy our template's attributes over for (var i = 0; i < dom.attributes.length; i++) { target.setAttribute(dom.attributes[i].name, dom.attributes[i].value); } // if (target.templatedCallback) target.templatedCallback(); } });