class View { constructor(tag = 'div') { this.root = document.createElement(tag) } $(sel) { return this.root.querySelector(sel) } $$(sel) { return this.root.querySelectorAll(sel) } on(elm, evt, cb) { if (typeof elm === 'string') { elm = this.$(elm) } elm.addEventListener(evt, cb) } } class DefaultView extends View{ constructor(object) { super('div') this.object = object; this.fields = {} this.subviews = {} } render() { Object.keys(this.object.json).forEach( key => this.root.appendChild(this.getNode(key)) ) } getNode(name, value=null) { if (this.fields[name]) { return this.fields[name] } value = value === null ? this.object.json[name] : value if (value instanceof StructuredNode) { this.subviews[name] = new DefaultView(value) this.fields[name] = this.subviews[name].root } else if (value instanceof Array) { const elm = document.createElement('ul') value.forEach((elm, i) => { const li = document.createElement('li') li.appendChild(this.getNode(name+'['+i+']',elm)) elm.appendChild(li) }) this.fields[name] = elm } else { const elm = document.createElement('p') elm.innerHTML = `${name}: ${value}` this.fields[name] = elm } return this.fields[name] } }