当前位置 : 主页 > 网络编程 > JavaScript >

一个Javascript的树操作

来源:互联网 收集:自由互联 发布时间:2021-07-03
写着玩的 1. [代码] [JavaScript]代码 // @author yanming// @email arist1213@163.com// @time 2016/06/18var data = [{'id': 0,'text': 'Root','children': [{'id': 1,'text': 'Child 1'},{'id': 2,'text': 'Child 2','children': [{'id': 6,'text'
写着玩的

1. [代码][JavaScript]代码    

// @author yanming
// @email arist1213@163.com
// @time 2016/06/18

var data = [{
	'id': 0,
	'text': 'Root',
	'children': [{
			'id': 1,
			'text': 'Child 1'
		},
		{
			'id': 2,
			'text': 'Child 2',
			'children': [
				{
					'id': 6,
					'text': 'Child 6'
				},
				{
					'id': 7,
					'text': 'Child 5',
					'children': [

					]					
				}
			]
		},

		{
			'id': 3,
			'text': 'Child 3',
			'children': [
				{
					'id': 4,
					'text': 'Child 4'
				},
				{
					'id': 5,
					'text': 'Child 5'
				}
			]
		}
	]
}];



var Tree = function(tree) {
	this.TYPE = {MOVE_NODE: "move_node",COPY_NODE: "copy_node",DELETE_NODE: "delete_node",CUT_NODE: "cut_node",PASTE_NODE: "paste_node",};
	this.tree = tree || [{'id': 0, 'text': 'Root'}];
	this.type = null;
	this.id = null;

	this.prefix = "node_";
	this.delimiter = "_";

	// 在数组指定位置插入元素
	Array.prototype.insertNode = function (index, item) {  
	  this.splice(index, 0, item);  
	};
}

Tree.prototype = {
	// 打印树
	output: function(tree, level) {	
		var _this = this;
		tree = tree || this.tree;
		level = level || 0;	

		if (tree) {						
			tree.forEach(function(node){
				console.log('-'.repeat(level)+''+node.text+' - id:'+node.id);
				if (node.children && node.children.length > 0) {					
					_this.output(node.children, level+1);
				}
			})			
		}		
	},
	// 遍历树
	traverse: function(tree, fn) {	
		var _this = this;
		tree = tree || this.tree;

		if (tree && Array.isArray(tree)) {						
			tree.forEach(function(node, index){				
				fn.call(_this, node, tree, index);
				if (node && node.children && Array.isArray(node.children) ) {					
					_this.traverse(node.children, fn);
				}
			})			
		} else {
			fn.call(_this, tree);
		}
	},

	// 深度克隆一个节点
	// clone 'from' object with members from 'to'. If 'to' is null, a deep clone of 'from' is returned
	// @reference http://stackoverflow.com/questions/122102/what-is-the-most-efficient-way-to-clone-an-object
	_clone: function(from, to) {		
		var _this  = this;
		if (from == null || typeof from != "object") return from;
	    if (from.constructor != Object && from.constructor != Array) return from;
	    if (from.constructor == Date || from.constructor == RegExp || from.constructor == Function ||
	        from.constructor == String || from.constructor == Number || from.constructor == Boolean)
	        return new from.constructor(from);

	    to = to || new from.constructor();

	    for (var name in from)
	    {
	        to[name] = typeof to[name] == "undefined" ? _this._clone(from[name], null) : to[name];
	    }

	    return to;
	},

	// 获取节点
	_get: function(id, fn) {
		var _this = this;
		var found = false;
		this.traverse(this.tree, function(node, tree, index) {
			if (node.id === id) {				
				found = true;
				fn.call(_this, node, tree, index);
			}
		})

		if (!found) { 
			throw new Error("can get node id "+id);
		}
	},	

	// 添加子节点指定位置节点
	_move: function(id, _node, pos) {		
		this.traverse(this.tree, function(node, tree, index) {
			if (node.id === id) {				
				if (node.children && Array.isArray(node.children)) {

					if (pos !== undefined) {
						node.children.insertNode(pos, _node);
					} else {
						node.children.push(_node);
					}					

				} else {
					node.children = [];
					node.children.push(_node);
				}
			}
		})
	},

	// 删除所有子节点及当前节点
	_deleteNodeTree: function(tree) {
		var _this = this;
		this.traverse(tree, function(node, tree, index) {			
			if (node.children && node.children.length > 0) {				
				_this._deleteNode(node.children);
			}
			// 移除当前节点
			tree.splice(index, 1);				
		})
	},
	
	// 移动节点
	moveNode: function(from, to, pos) {				
		var move_node;
		this._get(from, function(node, tree, index){
			tree.splice(index, 1);
			move_node = node;
		});
		this._move(to, move_node, pos);
	},	

	// 移除当前节点
	// @param deleteChildren true 移除所有子节点
	// TODO 如果不移除子节点,需要把子节点添加到当前移除节点的父节点中
	deleteNode: function(deleteId, deleteChildren) {
		deleteChildren = deleteChildren || true;
		var _this = this;
		this.traverse(this.tree, function(node, tree, index) {
			if (node.id == deleteId) {
				if (deleteChildren && node.children && node.children.length > 0) {					
					_this._deleteNodeTree(node.children);
				}								
				tree.splice(index, 1);							
			}
		})	
	},

	copyNode: function(id) {
		this.type = this.TYPE.COPY_NODE;
		this.id = id;
		return this;
	},	

	cutNode: function(id) {
		this.type = this.TYPE.CUT_NODE;
		this.id = id;
		return this;
	},

	createNode: function(pid, node, pos) {
		this._move(pid, node, pos);
	},

	// 更新节点
	updateNode: function(id, fn) {
		var _this = this;
		this._get(id, function(node, tree, index){
			fn.call(_this, node, tree, index);
		})
	},

	pasteTo: function(pid, pos) {
		if (this.id) {
			switch(this.type) {

				case this.TYPE.CUT_NODE:

					this.moveNode(this.id, pid, pos);	
					this.reset();				

				break;

				case this.TYPE.COPY_NODE:					
					var copy, parent;
					this._get(this.id, function(node, tree, index){
						copy = node;						
					});
					this._get(pid, function(node, tree, index){
						parent = node;						
					});	

					// generate new id							
					var suffix = parent.id;					
					var counter = 1;
					// TODO _clone
					var copied = this._clone(copy);

					copied.id = this.prefix+suffix+this.delimiter+(counter);
					if (copied.children && Array.isArray(copied.children)) {												
						this.traverse(copied.children, function(node, tree, index) {							
							node.id = this.prefix+suffix+this.delimiter+(++counter);														
						})
					} else {
						copied.id = this.prefix+suffix+this.delimiter+counter;
					}					

					this._move(pid, copied, pos);										
					this.reset();

				break;										

				default:
				throw new Error("illeage action type!");
				break;
			}
		}
	},

	reset: function() {
		this.id = null;
		this.type = null;
	}
}

var tree = new Tree();
tree.output();

//tree.updateNode(5, "Node5");
//tree.moveNode(4, 2, 2);
//tree.deleteNode(3);
//tree.copyNode(3).pasteTo(2, 1);

// tree.deleteNode("node_0_2");

// tree.deleteNode("7");

// tree.moveNode("node_0_3", 2);

//tree.cutNode(5).pasteTo(2);

//tree.createNode(0, {text: 'hello', id: 11});

console.log('-'.repeat(20));
tree.output();
网友评论