Tree render and navigation with note rendering
This commit is contained in:
parent
dd27be67b9
commit
1ce8e29e37
7 changed files with 515 additions and 62 deletions
|
|
@ -8,10 +8,6 @@ export class TreeNative {
|
|||
this.selectedNode = null
|
||||
this.rendered = false
|
||||
|
||||
window._mbus.subscribe('TREE_TRUNK_FETCHED', ()=>{
|
||||
document.getElementById('tree').append(this.render())
|
||||
})
|
||||
|
||||
this.populateFirstLevel()
|
||||
}// }}}
|
||||
render() {// {{{
|
||||
|
|
@ -19,10 +15,25 @@ export class TreeNative {
|
|||
alert('Tree should only be rendered once.')
|
||||
|
||||
const tmpl = document.createElement('template')
|
||||
tmpl.innerHTML = '<div id="tree-nodes" tabindex=0><div>'
|
||||
tmpl.innerHTML = `
|
||||
<div id="tree-nodes" tabindex=0>
|
||||
<div id="logo"><img src="/images/${_VERSION}/logo.svg" /></div>
|
||||
<div class="icons">
|
||||
<img src="/images/${_VERSION}/icon_search.svg" style="height: 22px" />
|
||||
<img src="/images/${_VERSION}/icon_refresh.svg" />
|
||||
</div>
|
||||
<div>`
|
||||
|
||||
/*
|
||||
onclick=${() => _mbus.dispatch('op-search')}
|
||||
onclick=${() => _sync.run()}
|
||||
*/
|
||||
|
||||
const treeEl = tmpl.content.getElementById('tree-nodes')
|
||||
treeEl.addEventListener('keydown', event=>this.keyHandler(event))
|
||||
|
||||
tmpl.content.getElementById('logo').addEventListener('click', ()=>_app.goToNode(ROOT_NODE, false, false))
|
||||
|
||||
for (const node of this.treeTrunk) {
|
||||
const treenode = new TreeNodeNative(this, node)
|
||||
this.treeNodeComponents[node.UUID] = treenode
|
||||
|
|
@ -57,12 +68,23 @@ export class TreeNative {
|
|||
return this.expandedNodes[UUID]
|
||||
}//}}}
|
||||
setNodeExpanded(node, value) {//{{{
|
||||
// Creating a default value if it doesn't exist already.
|
||||
this.getNodeExpanded(node.UUID)
|
||||
let expanded = this.expandedNodes[node.UUID]
|
||||
|
||||
if (expanded === undefined) {
|
||||
this.expandedNodes[node.UUID] = false
|
||||
expanded = false
|
||||
}
|
||||
|
||||
if (expanded === value)
|
||||
return
|
||||
|
||||
this.expandedNodes[node.UUID] = value
|
||||
_mbus.dispatch(`NODE_EXPAND_${node.UUID}`, value)
|
||||
}//}}}
|
||||
setSelected(node, dontExpand) {//{{{
|
||||
if (node === undefined)
|
||||
return
|
||||
|
||||
// The previously selected node, if any, needs to be rerendered
|
||||
// to not retain its 'selected' class.
|
||||
const prevUUID = this.selectedNode?.UUID
|
||||
|
|
@ -143,7 +165,7 @@ export class TreeNative {
|
|||
}
|
||||
}//}}}
|
||||
async navigateLeft(n) {//{{{
|
||||
if (n === null)
|
||||
if (n === null || n === undefined)
|
||||
return
|
||||
|
||||
const expanded = this.getNodeExpanded(n.UUID)
|
||||
|
|
@ -153,7 +175,7 @@ export class TreeNative {
|
|||
}
|
||||
|
||||
if (n.isFirstSibling() && n.getParent().UUID !== ROOT_NODE) {
|
||||
await _notes2.current.goToNode(n.getParent()?.UUID, true, true)
|
||||
_mbus.dispatch("GO_TO_NODE", { nodeUUID: n.getParent()?.UUID, dontPush: true, dontExpand: true })
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -161,14 +183,14 @@ export class TreeNative {
|
|||
const siblingExpanded = this.getNodeExpanded(siblingBefore?.UUID)
|
||||
if (siblingBefore !== null && siblingExpanded && siblingBefore.hasChildren()) {
|
||||
const siblingAbove = this.getLastExpandedNode(siblingBefore)
|
||||
await _notes2.current.goToNode(siblingAbove?.UUID, true, true)
|
||||
_mbus.dispatch("GO_TO_NODE", { nodeUUID: siblingAbove?.UUID, dontPush: true, dontExpand: true })
|
||||
return
|
||||
}
|
||||
|
||||
await _notes2.current.goToNode(n.getSiblingBefore()?.UUID, true, true)
|
||||
_mbus.dispatch("GO_TO_NODE", { nodeUUID: n.getSiblingBefore()?.UUID, dontPush: true, dontExpand: true })
|
||||
}//}}}
|
||||
async navigateRight(n) {//{{{
|
||||
if (n === null)
|
||||
if (n === null || n === undefined)
|
||||
return
|
||||
|
||||
const siblingAfter = n.getSiblingAfter()
|
||||
|
|
@ -180,20 +202,20 @@ export class TreeNative {
|
|||
}
|
||||
|
||||
if (expanded && n.hasChildren()) {
|
||||
await _notes2.current.goToNode(n.Children[0]?.UUID, true, true)
|
||||
_mbus.dispatch("GO_TO_NODE", { nodeUUID: n.Children[0]?.UUID, dontPush: true, dontExpand: true })
|
||||
return
|
||||
}
|
||||
|
||||
if (n.isLastSibling()) {
|
||||
const nextNode = this.getParentWithNextSibling(n)
|
||||
await _notes2.current.goToNode(nextNode?.UUID, true, true)
|
||||
_mbus.dispatch("GO_TO_NODE", { nodeUUID: nextNode?.UUID, dontPush: true, dontExpand: true })
|
||||
return
|
||||
}
|
||||
|
||||
await _notes2.current.goToNode(n.getSiblingAfter()?.UUID, true, true)
|
||||
_mbus.dispatch("GO_TO_NODE", { nodeUUID: n.getSiblingAfter()?.UUID, dontPush: true, dontExpand: true })
|
||||
}//}}}
|
||||
async navigateUp(n) {//{{{
|
||||
if (n === null)
|
||||
if (n === null || n === undefined)
|
||||
return
|
||||
|
||||
let parent = null
|
||||
|
|
@ -206,22 +228,22 @@ export class TreeNative {
|
|||
parent = n.getParent()
|
||||
if (parent?.UUID === ROOT_NODE)
|
||||
return
|
||||
await _notes2.current.goToNode(parent?.UUID, true, true)
|
||||
_mbus.dispatch("GO_TO_NODE", { nodeUUID: parent?.UUID, dontPush: true, dontExpand: true })
|
||||
return
|
||||
}
|
||||
|
||||
if (siblingBefore !== null && siblingExpanded && siblingBefore.hasChildren()) {
|
||||
await _notes2.current.goToNode(siblingBefore.Children[siblingBefore.Children.length - 1]?.UUID, true, true)
|
||||
_mbus.dispatch("GO_TO_NODE", { nodeUUID: siblingBefore.Children[siblingBefore.Children.length - 1]?.UUID, dontPush: true, dontExpand: true })
|
||||
return
|
||||
}
|
||||
|
||||
if (siblingBefore) {
|
||||
await _notes2.current.goToNode(siblingBefore.UUID, true, true)
|
||||
_mbus.dispatch("GO_TO_NODE", { nodeUUID: siblingBefore.UUID, dontPush: true, dontExpand: true })
|
||||
return
|
||||
}
|
||||
}//}}}
|
||||
async navigateDown(n) {//{{{
|
||||
if (n === null)
|
||||
if (n === null || n === undefined)
|
||||
return
|
||||
|
||||
const nodeExpanded = this.getNodeExpanded(n.UUID)
|
||||
|
|
@ -230,27 +252,27 @@ export class TreeNative {
|
|||
// Traverse upward to nearest parent with next sibling.
|
||||
if (!nodeExpanded && n.isLastSibling()) {
|
||||
const wantedNode = this.getParentWithNextSibling(n)
|
||||
await _notes2.current.goToNode(wantedNode?.UUID, true, true)
|
||||
_mbus.dispatch("GO_TO_NODE", { nodeUUID: wantedNode?.UUID, dontPush: true, dontExpand: true })
|
||||
return
|
||||
}
|
||||
|
||||
if (nodeExpanded && n.isLastSibling() && !n.hasChildren()) {
|
||||
const wantedNode = this.getParentWithNextSibling(n)
|
||||
await _notes2.current.goToNode(wantedNode?.UUID, true, true)
|
||||
_mbus.dispatch("GO_TO_NODE", { nodeUUID: wantedNode?.UUID, dontPush: true, dontExpand: true })
|
||||
return
|
||||
}
|
||||
|
||||
// Node not expanded. Go to this node's next sibling.
|
||||
// GoToNode will abort if given null.
|
||||
if (!nodeExpanded || !n.hasChildren()) {
|
||||
await _notes2.current.goToNode(n.getSiblingAfter()?.UUID, true, true)
|
||||
_mbus.dispatch("GO_TO_NODE", { nodeUUID: n.getSiblingAfter()?.UUID, dontPush: true, dontExpand: true })
|
||||
return
|
||||
}
|
||||
|
||||
// Node is expanded.
|
||||
// Children will be visually beneath this node, if any.
|
||||
if (nodeExpanded && n.hasChildren()) {
|
||||
await _notes2.current.goToNode(n.Children[0].UUID, true, true)
|
||||
_mbus.dispatch("GO_TO_NODE", { nodeUUID: n.Children[0].UUID, dontPush: true, dontExpand: true })
|
||||
return
|
||||
}
|
||||
}//}}}
|
||||
|
|
@ -258,7 +280,7 @@ export class TreeNative {
|
|||
const root = await nodeStore.get(ROOT_NODE)
|
||||
if (root.Children.length === 0)
|
||||
return
|
||||
await _notes2.current.goToNode(root.Children[0]?.UUID, true, true)
|
||||
_mbus.dispatch("GO_TO_NODE", { nodeUUID: root.Children[0]?.UUID, dontPush: true, dontExpand: true })
|
||||
}//}}}
|
||||
async navigateBottom() {//{{{
|
||||
const root = await nodeStore.get(ROOT_NODE)
|
||||
|
|
@ -270,9 +292,9 @@ export class TreeNative {
|
|||
|
||||
if (toplevelExpanded) {
|
||||
const lastnode = this.getLastExpandedNode(toplevel)
|
||||
await _notes2.current.goToNode(lastnode?.UUID, true, true)
|
||||
_mbus.dispatch("GO_TO_NODE", { nodeUUID: lastnode?.UUID, dontPush: true, dontExpand: true })
|
||||
} else
|
||||
await _notes2.current.goToNode(root.Children[root.Children.length - 1]?.UUID, true, true)
|
||||
_mbus.dispatch("GO_TO_NODE", { nodeUUID: root.Children[root.Children.length - 1]?.UUID, dontPush: true, dontExpand: true })
|
||||
}//}}}
|
||||
|
||||
getParentWithNextSibling(node) {//{{{
|
||||
|
|
@ -299,6 +321,17 @@ export class TreeNative {
|
|||
if (!state)
|
||||
await this.setNodeExpanded(node, false)
|
||||
}//}}}
|
||||
async makeVisible(node) {// {{{
|
||||
const treenode = this.treeNodeComponents[node.UUID]
|
||||
|
||||
const ancestors = await nodeStore.getNodeAncestry(node)
|
||||
for (const ancestor of ancestors.reverse()) {
|
||||
this.setNodeExpanded(ancestor, true)
|
||||
}
|
||||
|
||||
// The ROOT_NODE for example hasn't got a treenode.
|
||||
treenode?.element.scrollIntoView({ block: 'nearest' })
|
||||
}// }}}
|
||||
}
|
||||
|
||||
export class TreeNodeNative {
|
||||
|
|
@ -312,6 +345,7 @@ export class TreeNodeNative {
|
|||
this.icon_expand = document.createElement('img')
|
||||
|
||||
this.children_populated = false
|
||||
this.rendered = false
|
||||
|
||||
this.createElements()
|
||||
|
||||
|
|
@ -323,7 +357,8 @@ export class TreeNodeNative {
|
|||
this.render(true)
|
||||
})
|
||||
|
||||
this.rendered = false
|
||||
if (this.node.Level === 0 || this.tree.getNodeExpanded(this.node.UUID))
|
||||
this.fetchChildren()
|
||||
}//}}}
|
||||
createElements() {// {{{
|
||||
this.element.innerHTML = `
|
||||
|
|
@ -334,8 +369,13 @@ export class TreeNodeNative {
|
|||
|
||||
this.element.children[0].addEventListener('click', ()=>this.tree.setNodeExpanded(this.node, !this.tree.getNodeExpanded(this.node.UUID)))
|
||||
this.element.children[0].appendChild(this.icon_expand)
|
||||
this.element.children[1].addEventListener('click', ()=>window._notes2.current.goToNode(this.node.UUID))
|
||||
|
||||
this.element.children[1].addEventListener('click', ()=>_mbus.dispatch('TREE_NODE_SELECTED', this.node))
|
||||
}// }}}
|
||||
async fetchChildren() {//{{{
|
||||
await this.node.fetchChildren()
|
||||
this.children_populated = true
|
||||
}//}}}
|
||||
render(force_update) {//{{{
|
||||
if (this.rendered && force_update !== true)
|
||||
return this.element
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue