From bbbb23427aa5b65a8d1a90628d58cfa611e9ae1d Mon Sep 17 00:00:00 2001 From: DarkWiiPlayer Date: Tue, 27 Oct 2020 16:40:38 +0100 Subject: [PATCH] Add Better HTML element class for custom elements --- BetterHTMLElement.js | 47 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 BetterHTMLElement.js diff --git a/BetterHTMLElement.js b/BetterHTMLElement.js new file mode 100644 index 0000000..9469631 --- /dev/null +++ b/BetterHTMLElement.js @@ -0,0 +1,47 @@ +class BetterHTMLElement extends HTMLElement { + attributeChangedCallback(name, old, value) { this[name+"Changed"](value, old) } + + // Array of connected callbacks + #connected = []; + + // connectedCallback but as a promise. + // Resolves instantly when already connected and can be used more than once. + get connected() { + if (this.isConnected) return Promise.resolve(this) + else return new Promise( (yes, no) => this.#connected.push({yes, no}) ) + } + + // Resolves all `connected promises + connectedCallback() { + this.#connected.forEach( e => e.yes(this) ); + this.#connected = []; + } + + // Fancier way to register an element + // TODO: Unregister old names first + // TODO: Register name internally + static set tagName(name) { customElements.define(name, this) } + + // Adds property/attribute mappings to the object. + static addProps(fields = this.observedAttributes) { + fields.forEach( attr => Object.defineProperty(this.prototype, attr, { + get() { return this.getAttribute(attr) }, + set(val) { this.setAttribute(attr, val) } + })) + } +} + +/* Example: + class FooBar extends BetterHTMLElement { + static get observedAttributes() { return [ "name" ] } + + constructor() { + super(); + this.attachShadow({mode: "open"}); + this.shadowRoot.innerHTML = `

Hello,

` + } + nameChanged(name) { this.shadowRoot.querySelector("#name").innerHTML=name; } + } + FooBar.addProps() + FooBar.tagName = "foo-bar" +*/