Created
December 13, 2019 08:39
-
-
Save minecrawler/e988a1abc9dec09943b4a247faddf2a6 to your computer and use it in GitHub Desktop.
This file contains hidden or 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
export class BaseElement extends HTMLElement { | |
dirty: boolean = true; | |
root: ShadowRoot; | |
constructor(hideInternals: boolean = true) { | |
super(); | |
this.root = this.attachShadow({ mode: hideInternals ? 'closed' : 'open' }); | |
const observer = new MutationObserver(() => { | |
this.dirty = true; | |
this.tryRender().catch(err => this.fireError(err)); | |
}); | |
observer.observe(this, { | |
attributes: true, | |
childList: true, | |
subtree: true, | |
}); | |
} | |
clear() { | |
while (this.root.firstChild) { | |
this.root.removeChild(this.root.firstChild); | |
} | |
} | |
connectedCallback() { | |
this.tryRender().catch(err => this.fireError(err)); | |
} | |
protected draw(html: string = '', css: string = '') { | |
const styleEle = document.createElement('style'); | |
const contentFragment = document.createRange().createContextualFragment(html); | |
styleEle.innerHTML = css; | |
this.root.appendChild(styleEle); | |
this.root.appendChild(contentFragment); | |
} | |
protected fireError(error: Error) { | |
this.dispatchEvent(new ErrorEvent('error', { | |
error, | |
message: error.message, | |
})); | |
} | |
protected render() { /* overwrite me */ } | |
static get observedAttributes(): string[] { return []; /* overwrite me */ } | |
static registerTag(tagName: string) { | |
if (customElements.get(tagName)) return; | |
customElements.define(tagName, this); | |
} | |
async tryRender() { | |
if (this.dirty) { | |
this.clear(); | |
await this.render(); | |
this.dirty = false; | |
} | |
} | |
queryInternalElement<T extends Element>(query: string): T | null { | |
return this.root.querySelector<T>(query); | |
} | |
queryInternalElements<T extends Element>(query: string): NodeListOf<T> { | |
return this.root.querySelectorAll<T>(query); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment