Files
vue3-tree-list/src/Tree.js
youxingzhi fbd370e9e5 feat: 🎸 #47
2020-01-03 23:19:55 +08:00

169 lines
3.5 KiB
JavaScript

import {traverseTree} from './tools'
/**
* Tree data struct
* Created by ayou on 2017/7/20.
* @param data: treenode's params
* name: treenode's name
* isLeaf: treenode is leaf node or not
* id: id
* dragDisabled: decide if it can be dragged
* disabled: desabled all operation
*/
export class TreeNode {
constructor(data) {
const {id, isLeaf} = data
this.id = typeof id === 'undefined' ? new Date().valueOf() : id
this.parent = null
this.children = null
this.isLeaf = !!isLeaf
// other params
for (var k in data) {
if (k !== 'id' && k !== 'children' && k !== 'isLeaf') {
this[k] = data[k]
}
}
}
changeName(name) {
this.name = name
}
addChildren(children) {
if (!this.children) {
this.children = []
}
if (Array.isArray(children)) {
for (let i = 0, len = children.length; i < len; i++) {
const child = children[i]
child.parent = this
child.pid = this.id
}
this.children.concat(children)
} else {
const child = children
child.parent = this
child.pid = this.id
this.children.push(child)
}
}
// remove self
remove() {
const parent = this.parent
const index = parent.findChildIndex(this)
parent.children.splice(index, 1)
}
// remove child
_removeChild(child) {
for (var i = 0, len = this.children.length; i < len; i++) {
if (this.children[i] === child) {
this.children.splice(i, 1)
break
}
}
}
isTargetChild(target) {
let parent = target.parent
while (parent) {
if (parent === this) {
return true
}
parent = parent.parent
}
return false
}
moveInto(target) {
if (this.name === 'root' || this === target) {
return
}
// cannot move ancestor to child
if (this.isTargetChild(target)) {
return
}
// cannot move to leaf node
if (target.isLeaf) {
return
}
this.parent._removeChild(this)
this.parent = target
this.pid = target.id
if (!target.children) {
target.children = []
}
target.children.unshift(this)
}
findChildIndex(child) {
var index
for (let i = 0, len = this.children.length; i < len; i++) {
if (this.children[i] === child) {
index = i
break
}
}
return index
}
_canInsert(target) {
if (this.name === 'root' || this === target) {
return false
}
// cannot insert ancestor to child
if (this.isTargetChild(target)) {
return false
}
this.parent._removeChild(this)
this.parent = target.parent
this.pid = target.parent.id
return true
}
insertBefore(target) {
if (!this._canInsert(target)) return
const pos = target.parent.findChildIndex(target)
target.parent.children.splice(pos, 0, this)
}
insertAfter(target) {
if (!this._canInsert(target)) return
const pos = target.parent.findChildIndex(target)
target.parent.children.splice(pos + 1, 0, this)
}
toString() {
return JSON.stringify(traverseTree(this))
}
}
export class Tree {
constructor(data) {
this.root = new TreeNode({name: 'root', isLeaf: false, id: 0})
this.initNode(this.root, data)
return this.root
}
initNode(node, data) {
for (let i = 0, len = data.length; i < len; i++) {
var _data = data[i]
var child = new TreeNode(_data)
if (_data.children && _data.children.length > 0) {
this.initNode(child, _data.children)
}
node.addChildren(child)
}
}
}