doc = document; let {entries,fromEntries} = Object; (()=>{ let ep = Element.prototype; ep.attr = function(name){ return this.getAttribute(name); }; ep.$attr = function(name, value) { this.setAttribute(name, value); return this; }; ep.$attrs = function(attrs) { entries(attrs).forEach(([attr, value]) => this.$attr(attr, value)); return this; } ep.$cls = function(cls) { return this.$attr("class", cls); } ep.$value = function(value) { this.value = value; return this; } ep.$click = function(callback) { this.onclick = callback; return this; } let getval = x => x.value; ep.$change2state = function(state, field, getter=getval) { this.oninput = () => { this.setCustomValidity(''); this.validity.valid && (state[field] = getter(this)) || this.reportValidity(); }; return this; } tag = (name, attrs, ...children) => { let el = doc.createElement(name); attrs && el.$attrs(attrs); for (let child of children.filter(x=>x)) { el.appendChild((typeof(child) === 'string') ? doc.createTextNode(child) : child); } return el; } ahref = (href, ...children) => tag("a", {href}, ...children); labelfor = (for_, ...children) => tag("label", {"for":for_}, ...children); img = (src) => tag("img", {src}); input = (type) => tag("input", {type}); let TRIVIAL = "main,section,nav,h1,h2,h3,p,b,div,span,form,select,button,table,tr,td"; for (let name of TRIVIAL.split(",")) { window[name] = (...children) => tag(name, null, ...children); } mount = (root, app) => { function reload() { let h = (location.pathname==='/')?(location.hash || "#"):"##"; root.replaceChildren(...app(h)); }; reload(); window.addEventListener("hashchange", reload); root.reload = reload; }; })();