UNPKG

remix-debugger

Version:

Ethereum IDE and tools for the web

187 lines (168 loc) 5.06 kB
'use strict' var yo = require('yo-yo') var csjs = require('csjs-inject') var css = csjs` .li_tv { list-style-type: none; -webkit-margin-before: 0px; -webkit-margin-after: 0px; -webkit-margin-start: 0px; -webkit-margin-end: 0px; -webkit-padding-start: 0px; margin-left: 10px; } .ul_tv { list-style-type: none; -webkit-margin-before: 0px; -webkit-margin-after: 0px; -webkit-margin-start: 0px; -webkit-margin-end: 0px; -webkit-padding-start: 0px; } .caret_tv { width: 10px; } .label_tv { display: flex; align-items: center; } ` var remixLib = require('remix-lib') var EventManager = remixLib.EventManager /** * TreeView * - extendable by specifying custom `extractData` and `formatSelf` function * - trigger `nodeClick` and `leafClick` */ class TreeView { constructor (opts) { this.event = new EventManager() this.extractData = opts.extractData || this.extractDataDefault this.formatSelf = opts.formatSelf || this.formatSelfDefault this.view = null } render (json, expand) { var view = this.renderProperties(json, expand) if (!this.view) { this.view = view } return view } update (json) { if (this.view) { yo.update(this.view, this.render(json)) } } renderObject (item, parent, key, expand, keyPath) { var data = this.extractData(item, parent, key) var children = (data.children || []).map((child, index) => { return this.renderObject(child.value, data, child.key, expand, keyPath + '/' + child.key) }) return this.formatData(key, data, children, expand, keyPath) } renderProperties (json, expand, key) { key = key || '' var children = Object.keys(json).map((innerkey) => { return this.renderObject(json[innerkey], json, innerkey, expand, innerkey) }) return yo`<ul key=${key} class="${css.ul_tv}">${children}</ul>` } formatData (key, data, children, expand, keyPath) { var self = this var li = yo`<li key=${keyPath} class=${css.li_tv}></li>` var caret = yo`<div class="fa fa-caret-right caret ${css.caret_tv}"></div>` var label = yo` <div key=${keyPath} class=${css.label_tv}> ${caret} <span>${self.formatSelf(key, data, li)}</span> </div>` li.appendChild(label) if (data.children) { var list = yo`<ul key=${keyPath} class=${css.ul_tv}>${children}</ul>` list.style.display = 'none' caret.className = list.style.display === 'none' ? `fa fa-caret-right caret ${css.caret_tv}` : `fa fa-caret-down caret ${css.caret_tv}` label.onclick = function () { self.expand(keyPath) } label.oncontextmenu = function (event) { self.event.trigger('nodeRightClick', [keyPath, data, label, event]) } li.appendChild(list) } else { caret.style.visibility = 'hidden' label.oncontextmenu = function (event) { self.event.trigger('leafRightClick', [keyPath, data, label, event]) } label.onclick = function (event) { self.event.trigger('leafClick', [keyPath, data, label, event]) } } return li } isExpanded (path) { var current = this.nodeAt(path) if (current) { return current.style.display !== 'none' } return false } expand (path) { var caret = this.caretAt(path) var node = this.nodeAt(path) if (node) { node.style.display = node.style.display === 'none' ? 'block' : 'none' caret.className = node.style.display === 'none' ? `fa fa-caret-right caret ${css.caret_tv}` : `fa fa-caret-down caret ${css.caret_tv}` this.event.trigger('nodeClick', [path, node]) } } caretAt (path) { var label = this.labelAt(path) if (label) { return label.querySelector('.caret') } } itemAt (path) { return this.view.querySelector(`li[key="${path}"]`) } labelAt (path) { return this.view.querySelector(`div[key="${path}"]`) } nodeAt (path) { return this.view.querySelector(`ul[key="${path}"]`) } updateNodeFromJSON (path, jsonTree, expand) { var newTree = this.renderProperties(jsonTree, expand, path) var current = this.nodeAt(path) if (current && current.parentElement) { current.parentElement.replaceChild(newTree, current) } } formatSelfDefault (key, data) { return yo`<label>${key}: ${data.self}</label>` } extractDataDefault (item, parent, key) { var ret = {} if (item instanceof Array) { ret.children = item.map((item, index) => { return {key: index, value: item} }) ret.self = 'Array' ret.isNode = true ret.isLeaf = false } else if (item instanceof Object) { ret.children = Object.keys(item).map((key) => { return {key: key, value: item[key]} }) ret.self = 'Object' ret.isNode = true ret.isLeaf = false } else { ret.self = item ret.children = null ret.isNode = false ret.isLeaf = true } return ret } } module.exports = TreeView