100 lines
2.7 KiB
JavaScript
100 lines
2.7 KiB
JavaScript
export class TreeNode {
|
|
constructor(parent, data) {// {{{
|
|
this.data = data
|
|
this.parent = parent
|
|
this.childrenFetched = false
|
|
this.children = null
|
|
|
|
this.sortChildren()
|
|
}// }}}
|
|
|
|
render() {// {{{
|
|
const nodeHTML = `
|
|
<div class="node">
|
|
<div class="expand-status"><img /></div>
|
|
<div class="icon"><img /></div>
|
|
<div class="name">${this.name()}</div>
|
|
<div class="children"></div>
|
|
</div>
|
|
`
|
|
this.name()
|
|
const tmpl = document.createElement('template')
|
|
tmpl.innerHTML = nodeHTML
|
|
this.children = tmpl.content.querySelector('.children')
|
|
|
|
// data.NumChildren is set regardless of having fetched the children or not.
|
|
if (this.hasChildren()) {
|
|
const img = tmpl.content.querySelector('.expand-status img')
|
|
img.setAttribute('src', `/images/${_VERSION}/node_modules/@mdi/svg/svg/plus-box-outline.svg`)
|
|
img.addEventListener('click', event => this.toggleExpand(event))
|
|
} else
|
|
tmpl.content.querySelector('.expand-status').classList.add('leaf')
|
|
|
|
if (this.data.TypeIcon) {
|
|
const img = tmpl.content.querySelector('.icon img')
|
|
img.setAttribute('src', `/images/${_VERSION}/node_modules/@mdi/svg/svg/${this.data.TypeIcon}.svg`)
|
|
}
|
|
|
|
this.parent.appendChild(tmpl.content)
|
|
|
|
for (const c of this.data.Children || []) {
|
|
(new TreeNode(this.children, c)).render()
|
|
}
|
|
}// }}}
|
|
name() {// {{{
|
|
if (this.data.TypeName === 'root_node')
|
|
return 'Start'
|
|
return this.data.Name
|
|
}// }}}
|
|
hasChildren() {// {{{
|
|
return this.data.NumChildren > 0
|
|
}// }}}
|
|
sortChildren() {// {{{
|
|
this.data.Children.sort((a, b) => {
|
|
console.log(a.Name, b.Name)
|
|
if (a.TypeName < b.TypeName) return -1
|
|
if (a.TypeName > b.TypeName) return 1
|
|
|
|
if (a.Name < b.Name) return -1
|
|
if (a.Name > b.Name) return 1
|
|
|
|
return 0
|
|
})
|
|
}// }}}
|
|
|
|
toggleExpand(event) {// {{{
|
|
const node = event.target.closest('.node')
|
|
node?.classList.toggle('expanded')
|
|
|
|
const img = node?.classList.contains('expanded') ? 'minus-box-outline' : 'plus-box-outline'
|
|
event.target.setAttribute('src', `/images/${_VERSION}/node_modules/@mdi/svg/svg/${img}.svg`)
|
|
|
|
if (!this.childrenFetched && this.data.NumChildren > 0 && this.data.Children.length == 0) {
|
|
this.fetchChildren()
|
|
.then(data => {
|
|
this.childrenFetched = true
|
|
this.data.Children = data.Children
|
|
this.sortChildren()
|
|
|
|
for (const nodeData of this.data.Children) {
|
|
const node = new TreeNode(this.children, nodeData)
|
|
node.render()
|
|
}
|
|
})
|
|
.catch(err => {
|
|
alert(err)
|
|
console.error(err)
|
|
})
|
|
}
|
|
}// }}}
|
|
async fetchChildren() {// {{{
|
|
return new Promise((resolve, reject) => {
|
|
fetch(`/nodes/tree/${this.data.ID}?depth=2`)
|
|
.then(data => data.json())
|
|
.then(json => resolve(json))
|
|
.catch(err => reject(err))
|
|
})
|
|
}// }}}
|
|
}
|
|
|
|
// vim: foldmethod=marker
|