Skip to content

Instantly share code, notes, and snippets.

@rndme
Created November 15, 2022 07:40
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rndme/487634e3fd861dd67144be8cdc770694 to your computer and use it in GitHub Desktop.
Save rndme/487634e3fd861dd67144be8cdc770694 to your computer and use it in GitHub Desktop.
function wc(name, def) { // webcomponent wrapper by dandavis. MIT.
const PROPS = Object.keys(def.props || {});
class wcMaker extends HTMLElement {
constructor() {
super();
console.info("constrtr", this.constructor);
const shadow = this.attachShadow({
mode: "open"
});
shadow.appendChild(document.createElement("style"));
this.root = shadow.appendChild(document.createElement("root"));
PROPS.forEach(key => {
if (!this.hasAttribute(key)) {
this.setAttribute(key, def.props[key] === false ? "" : def.props[key]);
}
Object.defineProperty(this, key, {
get() {
return this.getAttribute(key);
},
set(v) {
this.setAttribute(key, v === false ? "" : v);
}
});
}, this);
Object.keys(def.events || {}).forEach(type => {
this.addEventListener(type, def.events[type]);
}, this);
def.create?.call(this, {
target: this,
type: "create",
detail: def
});
}
connectedCallback(e) {
this.initialContent = this.innerHTML;
if (def.content) this.shadowRoot.children[1].innerHTML = def.content;
if (def.css) this.shadowRoot.children[0].textContent = def.css;
def.insert?.apply(this, arguments);
}
attributeChangedCallback(name, was, is) {
if (this[name] != is) this[name] = is;
def.change?.apply(this, arguments);
this.raise("change", {name, was, is});
}
disconnectedCallback(e) {
def.remove?.apply(this, arguments);
}
adoptedCallback(e) {
def.adopt?.apply(this, arguments);
}
static get observedAttributes() {
return PROPS;
}
raise(name, details) {
this.dispatchEvent(new CustomEvent(name, {
detail: details || {}
}));
return this;
}
} //end class wcMaker
customElements.define("wc-" + name, wcMaker);
}
/*
// simple demo using most of the supported features:
// <wc-test id=test1 dan=Testing>Nobody</wc-test>
wc("test", {
create: console.info.bind(console, "Custom Element created"),
remove: console.info.bind(console, "Custom Element removed from page"),
change: function() {
this.root.innerHTML = "Hello " + this.dan
},
css: `root { color: red; }`,
content: "Hello World",
props: {
dan: 101
},
events: {
klick: function(e) {
this.setAttribute("dan", e.detail + Math.random());
//this.dan = Math.random(); // works too
},
click: function() {
this.raise("klick", "WooHoo");
},
change: function(e){ // optional catch-all attr change userland event
console.log("elmement changed", e);
}
}
});
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment