const $id = document.getElementById.bind(document); const $query = document.querySelector.bind(document); const $queryAll = document.querySelectorAll.bind(document); const $text = document.createTextNode.bind(document); const $insertBefore = function(ref, elem) { ref.parentNode.insertBefore(elem, ref); }; const $removeChildren = function(element) { while(element.firstChild) element.firstChild.remove(); }; const $jsx = (type, props, ...children) => $create({ tag: type, attrs: props, child: children }); const $create = function(info, attrs, child, created) { info = info || {}; if(typeof info === 'string') { info = {tag: info}; if(attrs) info.attrs = attrs; if(child) info.child = child; if(created) info.created = created; } const elem = document.createElement(info.tag || 'div'); if(info.attrs) { const attrs = info.attrs; for(let key in attrs) { const attr = attrs[key]; if(attr === undefined || attr === null) continue; switch(typeof attr) { case 'function': if(key.substring(0, 2) === 'on') key = key.substring(2).toLowerCase(); elem.addEventListener(key, attr); break; case 'object': if(attr instanceof Array) { if(key === 'class') key = 'classList'; const prop = elem[key]; let addFunc = null; if(prop instanceof Array) addFunc = prop.push.bind(prop); else if(prop instanceof DOMTokenList) addFunc = prop.add.bind(prop); if(addFunc !== null) { for(let j = 0; j < attr.length; ++j) addFunc(attr[j]); } else { if(key === 'classList') key = 'class'; elem.setAttribute(key, attr.toString()); } } else { for(const attrKey in attr) elem[key][attrKey] = attr[attrKey]; } break; case 'boolean': if(attr) elem.setAttribute(key, ''); break; default: if(key === 'className') key = 'class'; elem.setAttribute(key, attr.toString()); break; } } } if(info.child) { let children = info.child; if(!Array.isArray(children)) children = [children]; for(const child of children) { switch(typeof child) { case 'string': elem.appendChild(document.createTextNode(child)); break; case 'object': if(child instanceof Element) { elem.appendChild(child); } else if('element' in child) { const childElem = child.element; if(childElem instanceof Element) elem.appendChild(childElem); else elem.appendChild($create(child)); } else if('getElement' in child) { const childElem = child.getElement(); if(childElem instanceof Element) elem.appendChild(childElem); else elem.appendChild($create(child)); } else { elem.appendChild($create(child)); } break; default: elem.appendChild(document.createTextNode(child.toString())); break; } } } if(info.created) info.created(elem); return elem; };