universal_table/app/assets/javascripts/mind_map/jsmind/jsmind.mind.js

255 lines
8.3 KiB
JavaScript
Executable File

import { Node } from './jsmind.node.js'
import { logger, Direction } from './jsmind.common.js'
export class Mind {
constructor() {
this.name = null
this.author = null
this.version = null
this.root = null
this.selected = null
this.nodes = {}
}
get_node(node_id) {
if (node_id in this.nodes) {
return this.nodes[node_id]
} else {
logger.warn('the node[id=' + node_id + '] can not be found')
return null
}
}
set_root(node_id, topic, data) {
if (this.root == null) {
this.root = new Node(node_id, 0, topic, data, true)
this._put_node(this.root)
return this.root
} else {
logger.error('root node is already exist')
return null
}
}
add_node(parent_node, node_id, topic, data, direction, expanded, idx) {
if (!Node.is_node(parent_node)) {
logger.error('the parent_node ' + parent_node + ' is not a node.')
return null
}
var node_index = idx || -1
var node = new Node(
node_id,
node_index,
topic,
data,
false,
parent_node,
parent_node.direction,
expanded
)
if (parent_node.isroot) {
node.direction = direction || Direction.right
}
if (this._put_node(node)) {
parent_node.children.push(node)
this._update_index(parent_node)
} else {
logger.error("fail, the node id '" + node.id + "' has been already exist.")
node = null
}
return node
}
insert_node_before(node_before, node_id, topic, data, direction) {
if (!Node.is_node(node_before)) {
logger.error('the node_before ' + node_before + ' is not a node.')
return null
}
var node_index = node_before.index - 0.5
return this.add_node(node_before.parent, node_id, topic, data, direction, true, node_index)
}
get_node_before(node) {
if (!Node.is_node(node)) {
var the_node = this.get_node(node)
if (!the_node) {
logger.error('the node[id=' + node + '] can not be found.')
return null
} else {
return this.get_node_before(the_node)
}
}
if (node.isroot) {
return null
}
var idx = node.index - 2
if (idx >= 0) {
return node.parent.children[idx]
} else {
return null
}
}
insert_node_after(node_after, node_id, topic, data, direction) {
if (!Node.is_node(node_after)) {
logger.error('the node_after ' + node_after + ' is not a node.')
return null
}
var node_index = node_after.index + 0.5
return this.add_node(node_after.parent, node_id, topic, data, direction, true, node_index)
}
get_node_after(node) {
if (!Node.is_node(node)) {
var the_node = this.get_node(node)
if (!the_node) {
logger.error('the node[id=' + node + '] can not be found.')
return null
} else {
return this.get_node_after(the_node)
}
}
if (node.isroot) {
return null
}
var idx = node.index
var brothers = node.parent.children
if (brothers.length > idx) {
return node.parent.children[idx]
} else {
return null
}
}
move_node(node, before_id, parent_id, direction) {
if (!Node.is_node(node)) {
logger.error('the parameter node ' + node + ' is not a node.')
return null
}
if (!parent_id) {
parent_id = node.parent.id
}
return this._move_node(node, before_id, parent_id, direction)
}
_flow_node_direction(node, direction) {
if (typeof direction === 'undefined') {
direction = node.direction
} else {
node.direction = direction
}
var len = node.children.length
while (len--) {
this._flow_node_direction(node.children[len], direction)
}
}
_move_node_internal(node, before_id) {
if (!!node && !!before_id) {
if (before_id == '_last_') {
node.index = -1
this._update_index(node.parent)
} else if (before_id == '_first_') {
node.index = 0
this._update_index(node.parent)
} else {
var node_before = !!before_id ? this.get_node(before_id) : null
if (
node_before != null &&
node_before.parent != null &&
node_before.parent.id == node.parent.id
) {
node.index = node_before.index - 0.5
this._update_index(node.parent)
}
}
}
return node
}
_move_node(node, before_id, parent_id, direction) {
if (!!node && !!parent_id) {
var parent_node = this.get_node(parent_id)
if (Node.inherited(node, parent_node)) {
logger.error('can not move a node to its children')
return null
}
if (node.parent.id != parent_id) {
// remove from parent's children
var sibling = node.parent.children
var si = sibling.length
while (si--) {
if (sibling[si].id == node.id) {
sibling.splice(si, 1)
break
}
}
let origin_parent = node.parent
node.parent = parent_node
parent_node.children.push(node)
this._update_index(origin_parent)
}
if (node.parent.isroot) {
if (direction == Direction.left) {
node.direction = direction
} else {
node.direction = Direction.right
}
} else {
node.direction = node.parent.direction
}
this._move_node_internal(node, before_id)
this._flow_node_direction(node)
}
return node
}
remove_node(node) {
if (!Node.is_node(node)) {
logger.error('the parameter node ' + node + ' is not a node.')
return false
}
if (node.isroot) {
logger.error('fail, can not remove root node')
return false
}
if (this.selected != null && this.selected.id == node.id) {
this.selected = null
}
// clean all subordinate nodes
var children = node.children
var ci = children.length
while (ci--) {
this.remove_node(children[ci])
}
// clean all children
children.length = 0
var node_parent = node.parent
// remove from parent's children
var sibling = node_parent.children
var si = sibling.length
while (si--) {
if (sibling[si].id == node.id) {
sibling.splice(si, 1)
break
}
}
// remove from global nodes
delete this.nodes[node.id]
// clean all properties
for (var k in node) {
delete node[k]
}
// remove it's self
node = null
this._update_index(node_parent)
return true
}
_put_node(node) {
if (node.id in this.nodes) {
logger.warn("the node_id '" + node.id + "' has been already exist.")
return false
} else {
this.nodes[node.id] = node
return true
}
}
_update_index(node) {
if (node instanceof Node) {
node.children.sort(Node.compare)
for (var i = 0; i < node.children.length; i++) {
node.children[i].index = i + 1
}
}
}
}