一个简单的树插件

/**
 * 所包括的功能:
 * 1.对标准数据格式及简单数据格式
 * 2.树的外观支持自定义设置(在treeStyle中设置每级树的样式/leafStyle设置叶子的样式/在数据中附加样式信息)
 * 3.支持两种数据载入方式(直接传入数据/设置url加载数据)
 * 4.外部对树的操作(全部展开\全部收缩\刷新)
 * 5.结点的点击事件(beforeClock和onClick)
 * 6.复选框的显示、隐藏、禁用
 * 7.复选框的关联方式(例如:选父-->子全选)
 * 8.得到复选框所选中的结点(getCheckedNodes)
 * 9.选中结点(不是选中复选框,只是添加上选中样式那种),获取选中的结点
 * 10.树的结点的id:给树的地点单独创建id,与data中的id无关。id命名取绑定的dom元素的id,
 * 11.要在每次运用变量前,先判定变量是否存在
 * 12.右键+拖动
 * 
 */

;(function($){
	var defaults = {
		ajax : {
			enable : false,
			url : "", //请求数据的url
			method : "POST",
			sync : true,
			dataType : "json",
			param : ""
		},
		data : {
			data : null, //传入的数据 (数组类型,支持一次传入多棵树)
			format : "normal", //标准数据格式or简单数据格式
			normal : {
				id : "id",
				name : "name",
				children : "children"
			},
			simple : {
				id : "id",
				pId : "pId",
				level : "level"
			}
		},
		callback : {
			beforeClick : null,
			onClick : null, //点击结点调用此方法
			initTree : null, //树初始化完成调用此方法
			onRClick : {
				addCallback : null,
				editCallback : null,
				delCallback : null
			},
			onDrag : null
		},
		view : { //style的格式为{style : "", expand : "", collapse : ""}
			initState : "expand", //展开or收缩(默认状态为全部展开)
			showLine : true,
			showIcon : true,
			iconStyle : null, //没有设置默认样式
			textStyle : null,
			leafIconStyle : null,
			leafTextStyle : null
		},
		checkbox : {
			enable : true,
			checkboxType : { //默认不存在关联
				Y : "",
				N : ""
			}
		},
		/*root : { //动态加入一个根结点
			enable : false,
			data : null, //此处的key必须与数据的key相同
			rootIconStyle : null,
			rootTextStyle : null
		}*/
		root : null,
		rclick : true, //是否支持右键
		drag : true //是否支持拖动
	};
	
	function makeVdiTree(dom, opt){
		var options = $.extend(true, {}, defaults, opt); //此处要进行深度拷贝
		var treeDom = dom;
		var treeId = $(treeDom).attr('id');
		
		var count = 0; //记录结点的数量,命名结点id
		var menu = null; //设置成全局变量,保证页面上仅会有一个右键菜单
		
		var normalData = null; //存储转换后的数据,刷新时使用
		
		var tMethods = {
			_initTree : function(data){
				var tmpData = (data ? data : options.data.data);
				
				if("simple" == options.data.format){
					normalData = tMethods._changeData(tmpData);
					//$(treeDom).append(tMethods._createNodes(normalData));
				}else{
					normalData = tmpData;
					//$(treeDom).append(tMethods._createNodes(tmpData));
				}
				
				if(options.root){
					tmpData = tMethods._insertRoot(normalData);
				}else{
					tmpData = normalData;
				}
				
				$(treeDom).append(tMethods._createNodes(tmpData));
				
				if(options.callback.initTree) options.callback.initTree.call(treeDom); //树初始化完成,调用此方法
			},
			_createNodes : function(data){ //生成树的接口,传入标准数据
				var treeul = document.createElement('ul');
				
				$.each(data, function(idx, node){
					var treeli = document.createElement('li');
					node = tMethods._addProperties(node, 0, "root");
					treeli = tMethods._initNode(treeli, node);
					treeli = tMethods._initEvent(treeli, node);
					
					if(node[node.key.children]){
						var cDom = tMethods._appendNodes(node[node.key.children], 0+1);
						$(treeli).append(cDom);
					}
					
					$(treeul).append(treeli);
				});
				
				return treeul;
			},
			_appendNodes : function(children, level){ //生成树的迭代方法,返回一层的结点
				var treeul = document.createElement('ul');
				var length = children.length;
				
				$.each(children, function(idx, child){
					var treeli = document.createElement('li');
					child = tMethods._addProperties(child, level, (idx == length -1 ? "bottom" : "center"));
					treeli = tMethods._initNode(treeli, child);
					treeli = tMethods._initEvent(treeli, child);
					
					if(child[child.key.children]){
						var cDom = tMethods._appendNodes(child[child.key.children], level+1);
						$(treeli).append(tMethods._initState(cDom, child));
					}
					
					$(treeul).append(treeli);
				});
				
				return treeul;
			},
			_addProperties : function(node, level, style) {
				node["key"] = tMethods._getNormalKey();
				node["level"] = level;
				node["style"] = style;
				node["line"] = (options.view.showLine ? true : false);
				node["state"] = (options.view.initState ? options.view.initState : "expand");
				node["leaf"] = (node[node.key.children] ? false : true);
				
				return node;
			},
			_initNode : function(dom, node){ //初始化单个结点,添加图片、样式等(node结点中有key、level、style、line、state、leaf这几个属性)
				$(dom).attr('id', treeId + "_" + count);
				count ++;
				
				$(dom).append(tMethods._newLine(node));
				
				if(options.checkbox.enable){
					$(dom).append(tMethods._newCheckBox(dom));
				}
				
				$(dom).append(tMethods._newClick(node));
				
				if(!node.leaf){ //在初始化结点的时候标明该结点的状态
					if("expand" == node.state){
						$(dom).addClass("vdiopen");
					}else if("collapse" == node.state){
						$(dom).addClass("vdiclose");
					}
				}
				
				$(dom).data("node", node); //将数据存储到dom中
				
				return dom;
			},
			_initEvent : function(dom, node){ //初始化结点上的事件
				var nodeDom = tMethods._getNodeDom(dom);
				
				//要判断此结点是否是叶子结点
				if(nodeDom.linespan.length > 0 && !node.leaf){ //点击图片展开收缩的功能,叶子结点不存在此功能
					$(nodeDom.linespan).bind("click", function(){
						tMethods._changeState(dom, node);
					});
				}
				
				if(nodeDom.clicka.length > 0){
					$(nodeDom.clicka).bind("click", function(){
						var callbackflag = true;
						if(options.callback.beforeClick) callbackflag = options.callback.beforeClick.call(dom, node);
						
						if(callbackflag){ //如果beforeClick返回false或什么都不返回,则结点不会被选中且不触发onClick
							$(treeDom).find('a.selected').removeClass("selected");
							$(this).addClass("selected");
							
							if(options.callback.onClick) options.callback.onClick.call(dom, node);
						}
					});
				}
				
				if(options.rclick){ //右键点击事件
					tMethods._initRClickEvent(dom, node);
				}
				
				if(options.drag){
					tMethods._initDragEvent(dom, node);
				}
				
				return dom;
			},
			_initRClickEvent : function(dom, node){
				var nodeDom = tMethods._getNodeDom(dom);
				
				$(nodeDom.clicka).bind("contextmenu", function(e){
					$(treeDom).find('a.selected').removeClass("selected"); //右键点击也要加上选中样式
					$(this).addClass("selected");
					
					if(menu) tMethods._destoryMenu(menu);
					menu = tMethods._createMenu(dom, node, e);
					
					return false;
				});
				
				$("body").bind("click", function(){
					if(menu) tMethods._destoryMenu(menu);
				}).bind("contextmenu", function(){
					if(menu) tMethods._destoryMenu(menu);
				});
			},
			_initDragEvent : function(dom, node){
				var $doc = $(document);
				var nodeDom = tMethods._getNodeDom(dom);
				$(nodeDom.clicka).mousedown(function(e){ //鼠标在结点上按按下,触发拖动
					// 拖动时,将选中的样式清除
					$(treeDom).find('a.selected').removeClass("selected");
					
					// 点击时产生一个临时拖动结点
					var tmpNode = $(dom).clone();
					var dragUl = $('<ul class="vdiTree vdiTreeDragUL"></ul>').append(tmpNode);
					$(dragUl).appendTo('body').hide();
					
					$doc.mousemove(function(e){
						// 拖动时鼠标状态为小手
						$("body").css('cursor', 'pointer');
						// 临时拖动结点跟随鼠标移动
						var dX = (document.body.scrollLeft == 0) ? document.documentElement.scrollLeft: document.body.scrollLeft;
						var dY = (document.body.scrollTop == 0) ? document.documentElement.scrollTop: document.body.scrollTop;
						dragUl.css({
							"top": (e.clientY + dY + 3) + "px",
							"left": (e.clientX + dX + 3) + "px"
						}).show();
						// 拖动事件发生时调用
						if(options.callback.onDrag) {
							options.callback.onDrag.call(dom, node);
						}
						
						$(treeDom).find('a').mouseover(function(){
							$(treeDom).find('a.targetNode').removeClass("targetNode");
							$(this).addClass("targetNode");
							return false;
						});
						
						return false;
						
					}).mouseup(function(e){
						// 临时拖动结点
						$(this).unbind("mousemove").unbind("mouseup");
						$(nodeDom.clicka).unbind("mousemove");
						$("body").css("cursor", "auto");
						$(dragUl).remove();
						// 目标结点
						$(treeDom).find('a').unbind("mouseover");
						var clicka = $(treeDom).find('a.targetNode');
						if(clicka.length > 0) {
							$(clicka).removeClass("targetNode");
							var treeli = $(clicka).parent('li');
							
							if(tMethods._chkDragAvailable(dom, treeli)) {
								tMethods._moveNode(dom, treeli); //将结点移动到新位置
							}
						}
						
						return false;
					});

					return false; // 阻止拖动事件触发(不会出现禁止拖动的图标了)
				});
				
			},
			_chkDragAvailable : function(drag, target) {
				// 拖动不起作用的情况:1.将结点拖动到自身或者是自身的子结点上面 2.将结点拖动到自己的父节点上面
				var available = true;
				var targetId = $(target).attr('id');
				if($(drag).attr('id') == targetId) {
					available = false;
				}
				$(drag).find('li').each(function(idx, treeli){
					if($(treeli).attr('id') == targetId) {
						available = false;
						return false;
					}
				});
				if($(drag).parent('ul').parent('li').attr('id') == targetId) {
					available = false;
				}
				
				return available;
			},
			_initState : function(dom, node){ //初始化状态(展开or收缩)
				//是否添加虚线
				if(node.line && "center" == node.style) {
					$(dom).addClass("line");
				}else {
					$(dom).removeClass("line");
				}
				//要判断结点此时是展开的还是收缩的
				if("expand" == options.view.initState){
					$(dom).css("display", "block");
				}else if("collapse" == options.view.initState){
					$(dom).css("display", "none");
				}
				
				return dom;
			},
			_ajaxData : function(){
				$.ajax({
					type : options.ajax.method,
					url : options.ajax.url,
					data : options.ajax.param,
					async : options.ajax.sync,
					dataType : options.ajax.dataType,
					success : function(data){
						tMethods._initTree(data);
					},
					error : function(){
						
					}
				});
			},
			_changeData : function(simpleData){ //传入简单数据,返回标准数据
				var skey = tMethods._getSimpleKey();
				var levelObj = {};
				
				var maxLevel = 0;
				//第一步:先按level给对象分类
				$.each(simpleData, function(idx, data){
					if(levelObj[data.level]){ //如果存在,则将此对象放入改数组中
						levelObj[data.level].push(data);
					}else{ //如果不存在,则新建一个数组,将此对象放入改数组中,并将该数组放入大对象中
						var levelArr = [];
						levelArr.push(data);
						levelObj[data.level] = levelArr;
					}
					if(data.level > maxLevel){ //记录最大level值
						maxLevel = data.level;
					}
				});
				//第二步:将子结点按照映射插入到父节点中
				for(var i = maxLevel; i > 0; i --){
					$.each(levelObj[i], function(idx, child){
						var pId = child[skey.pId];
						$.each(levelObj[i-1], function(idx, parent){
							var id = parent[skey.id];
							if(pId == id){
								if(parent.children){ //parent中存在children这个属性
									parent.children.push(child);
								}else{ //不存在
									var childrenArr = [];
									childrenArr.push(child);
									parent.children = childrenArr;
								}
								
								return false;
							}
						});
					});
				}
				
				return levelObj[0];
			},
			_getNormalKey : function(){ //获取数据的key,肯定有值返回,不用再进行判断
				var key = {};
				key.id = (options.data.normal.id ? options.data.normal.id : "id");
				key.name = (options.data.normal.name ? options.data.normal.name : "name");
				key.children = (options.data.normal.children ? options.data.normal.children : "children");
				
				return key;
			},
			_getSimpleKey : function(){
				var key = {};
				key.id = (options.data.simple.id ? options.data.simple.id : "id");
				key.pId = (options.data.simple.pId ? options.data.simple.pId : "pId");
				key.level = (options.data.simple.level ? options.data.simple.level : "level");
				
				return key;
			},
			_getLineStyle : function(line){
				var lineStyle = {};
				if(line){ //存在虚线
					lineStyle.open = {
						center : "center_open",
						root : "root_open",
						bottom : "bottom_open"
					};
					lineStyle.close = {
						center : "center_close",
						root : "root_close",
						bottom : "bottom_close"
					};
					lineStyle.leaf = {
						center : "center_docu",
						bottom : "bottom_docu"
					};
				}else{ //不存在虚线
					lineStyle.open = "noline_open";
					lineStyle.close = "noline_close";
					lineStyle.leaf = "noline_docu";
				}
				
				return lineStyle;
			},
			_getIconStyle : function(level){
				var iconStyle = {};
				if(options.view.iconStyle){
					iconStyle.style = ("string" == typeof options.view.iconStyle[level].style ? tMethods._strToArr(options.view.iconStyle[level].style) : []);
					iconStyle.expand = ("string" == typeof options.view.iconStyle[level].expand ? tMethods._strToArr(options.view.iconStyle[level].expand) : []);
					iconStyle.collapse = ("string" == typeof options.view.iconStyle[level].collapse ? tMethods._strToArr(options.view.iconStyle[level].collapse) : []);
				}
				
				return iconStyle;
			},
			_getTextStyle : function(){
				var textStyle = {};
				if(options.view.textStyle){
					textStyle.style = ("string" == typeof options.view.textStyle[level].style ? tMethods._strToArr(options.view.textStyle[level].style) : []);
					textStyle.expand = ("string" == typeof options.view.textStyle[level].expand ? tMethods._strToArr(options.view.textStyle[level].expand) : []);
					textStyle.collapse = ("string" == typeof options.view.textStyle[level].collapse ? tMethods._strToArr(options.view.textStyle[level].collapse) : []);
				}
				
				return textStyle;
			},
			_getLeafIconStyle : function(){
				var leafIconStyle = {};
				if(options.view.leafIconStyle){
					leafIconStyle.style = ("string" == typeof options.view.leafIconStyle.style ? tMethods._strToArr(options.view.leafIconStyle.style) : []);
					leafIconStyle.leaf = ("string" == typeof options.view.leafIconStyle.leaf ? tMethods._strToArr(options.view.leafIconStyle.leaf) : []);
				}
				
				return leafIconStyle;
			},
			_getLeafTextStyle : function(){
				var leafTextStyle = {};
				if(options.view.leafTextStyle){
					leafTextStyle.style = ("string" == typeof options.view.leafTextStyle.style ? tMethods._strToArr(options.view.leafTextStyle.style) : []);
					leafTextStyle.leaf = ("string" == typeof options.view.leafTextStyle.leaf ? tMethods._strToArr(options.view.leafTextStyle.leaf) : []);
				}
				
				return leafTextStyle;
			},
			_newLine : function(node){
				var linespan = document.createElement('span'); //显示虚线
				var lineStyle = tMethods._getLineStyle(node.line);
				
				$(linespan).addClass("button").addClass("switch");
				if(node.leaf){
					$(linespan).addClass(lineStyle.leaf[node.style]);
				}else{
					if("expand" == node.state){
						$(linespan).addClass(lineStyle.open[node.style]);
					}else if("collapse" == node.state){
						$(linespan).addClass(lineStyle.close[node.style]);
					}
				}
				
				return linespan;
			},
			_newIcon : function(node){
				var iconspan = document.createElement('span'); //显示图片
				
				if(!node.leaf){
					var iconStyle = tMethods._getIconStyle(node.level);
					if(iconStyle.style){
						$.each(iconStyle.style, function(idx, clss){
							$(iconspan).addClass(clss);
						});
					}
					
					if(iconStyle[node.state]){
						$.each(iconStyle[node.state], function(idx, clss){
							$(iconspan).addClass(clss);
						});
					}
				}else{
					var leafIconStyle = tMethods._getLeafIconStyle();
					if(leafIconStyle.style){
						$.each(leafIconStyle.style, function(idx, clss){
							$(iconspan).addClass(clss);
						});
					}
					
					if(leafIconStyle.leaf){
						$.each(leafIconStyle.leaf, function(idx, clss){
							$(iconspan).addClass(clss);
						});
					}
				}
				
				return iconspan;
			},
			_newText : function(node){
				var textspan = document.createElement('span'); //显示文字
				$(textspan).html(node[node.key.name]);
				
				if(!node.leaf){
					var textStyle = tMethods._getTextStyle(node.level);
					if(textStyle.style){
						$.each(textStyle.style, function(idx, clss){
							$(textspan).addClass(clss);
						});
					}
					
					if(textStyle[node.state]){
						$.each(textStyle[node.state], function(idx, clss){
							$(textspan).addClass(clss);
						});
					}
				}else{
					var leafTextStyle = tMethods._getLeafTextStyle();
					if(leafTextStyle.style){
						$.each(leafTextStyle.style, function(idx, clss){
							$(textspan).addClass(clss);
						});
					}
					
					if(leafTextStyle.leaf){
						$.each(leafTextStyle.leaf, function(idx, clss){
							$(textspan).addClass(clss);
						});
					}
				}
				
				return textspan;
			},
			_newCheckBox : function(dom){
				var checkboxspan = document.createElement("span");
				$(checkboxspan).addClass("button").addClass("chk");
				checkboxspan = tMethods._bindCheckBoxEvent(dom, checkboxspan);
				
				return checkboxspan;
			},
			_newClick : function(node){
				var clicka = document.createElement("a");
				clicka.setAttribute('href', "#");
				
				if(options.view.showIcon){
					$(clicka).append(tMethods._newIcon(node));
				}
				$(clicka).append(tMethods._newText(node));
				
				return clicka;
			},
			_bindCheckBoxEvent : function(dom, checkbox){
				var selectflag;
				$(checkbox).bind("click", function(){ //最基本的选中
					if($(this).hasClass("checkbox_true_full")){
						$(this).removeClass("checkbox_true_full");
						selectflag = false;
					}else{
						$(this).addClass("checkbox_true_full");
						selectflag = true;
					}
					
					if (!selectflag && options.checkbox.checkboxType.N.indexOf("s") > -1){
						tMethods._setChildCheckBox(dom);
					}
					if (!selectflag && options.checkbox.checkboxType.N.indexOf("p") > -1){
						tMethods._setParentCheckBox(dom);
					}
					if (selectflag && options.checkbox.checkboxType.Y.indexOf("s") > -1){
						tMethods._setChildCheckBox(dom);
					}
					if (selectflag && options.checkbox.checkboxType.Y.indexOf("p") > -1){
						tMethods._setParentCheckBox(dom);
					}
				});
				
				return checkbox;
			},
			_setParentCheckBox : function(dom){ //关联父
				if($(dom).data("node").level > 0){
					var parentflag = false;
					$(dom).siblings('li').add(dom).each(function(idx, brother){
						if($(brother).children('span:eq(1)').hasClass("checkbox_true_full")){
							parentflag = true;
							return false;
						}
					});
					var parent = $(dom).parents('li:first');
					var chkbox = parent.children('span:eq(1)');
					parentflag ? $(chkbox).addClass("checkbox_true_full") : $(chkbox).removeClass("checkbox_true_full");
					
					tMethods._setParentCheckBox(parent);
				}
			},
			_setChildCheckBox : function(dom){ //关联子
				if(!$(dom).data("node").leaf){
					var chkbox = $(dom).children('span:eq(1)');
					$(dom).children('ul:first').find('span.chk').each(function(idx, child){
						if($(chkbox).hasClass("checkbox_true_full")){
							$(child).addClass("checkbox_true_full");
						}else{
							$(child).removeClass("checkbox_true_full");
						}
					});
				}
			},
			_strToArr : function(str){ //工具方法,将字符串转化成数组
				
				return str.split(",");
			},
			_getNodeDom : function(dom) {
				return {
					linespan : $(dom).children('span:first'),
					clicka : $(dom).children('a:first'),
					iconspan : $(dom).children('a:first').children('span:first'),
					textspan : $(dom).children('a:first').children('span:eq(1)')
				};
			},
			_expandNode : function(dom, node){
				var lineStyle = tMethods._getLineStyle(node.line);
				var iconStyle = tMethods._getIconStyle(node.level);
				var textStyle = tMethods._getTextStyle(node.level);
				
				var nodeDom = tMethods._getNodeDom(dom);
				
				$(nodeDom.linespan).removeClass(lineStyle.close[node.style]).addClass(lineStyle.open[node.style]);
				if(iconStyle.style){
					$.each(iconStyle.collapse, function(idx, clss){
						$(nodeDom.iconspan).removeClass(clss);
					});
					$.each(iconStyle.expand, function(idx, clss){
						$(nodeDom.iconspan).addClass(clss);
					});
				}
				if(textStyle.style){
					$.each(textStyle.collapse, function(idx, clss){
						$(nodeDom.textspan).removeClass(clss);
					});
					$.each(textStyle.expand, function(idx, clss){
						$(nodeDom.textspan).addClass(clss);
					});
				}
				
				var child = $(dom).children('ul:first');
				if(child.length > 0){
					$(child).slideToggle("normal");
				}
			},
			_collapseNode : function(dom, node){
				var lineStyle = tMethods._getLineStyle(node.line);
				var iconStyle = tMethods._getIconStyle(node.level);
				var textStyle = tMethods._getTextStyle(node.level);
				
				var nodeDom = tMethods._getNodeDom(dom);
				
				$(nodeDom.linespan).removeClass(lineStyle.open[node.style]).addClass(lineStyle.close[node.style]);
				if(iconStyle.style){
					$.each(iconStyle.expand, function(idx, clss){
						$(nodeDom.iconspan).removeClass(clss);
					});
					$.each(iconStyle.collapse, function(idx, clss){
						$(nodeDom.iconspan).addClass(clss);
					});
				}
				if(textStyle.style){
					$.each(textStyle.expand, function(idx, clss){
						$(nodeDom.textspan).removeClass(clss);
					});
					$.each(textStyle.collapse, function(idx, clss){
						$(nodeDom.textspan).addClass(clss);
					});
				}
				
				var child = $(dom).children('ul:first');
				if(child.length > 0){
					$(child).slideToggle("normal");
				}
			},
			_changeState : function(dom, node){ //改变结点的状态(展开or收缩)
				if($(dom).hasClass("vdiclose")){
					$(dom).removeClass("vdiclose").addClass("vdiopen");
					tMethods._expandNode(dom, node);
				}else if($(dom).hasClass("vdiopen")){
					$(dom).removeClass("vdiopen").addClass("vdiclose");
					tMethods._collapseNode(dom, node);
				}
			},
			_removeTree : function(){ //将树清空
				$(treeDom).empty();
			},
			/*v0.2:鼠标右键操纵树结点的增删改 */
			_getSettings : function(){ //对右键弹出菜单进行设置
				var operate = [
					{
						text : "add",
						callback : function(node){
							tMethods._addNode(this, node);
						}
					},{
						text : "delete",
						callback : function(node){
							tMethods._deleteNode(this, node);
						}
					},{
						text : "edit",
						callback : function(node){
							tMethods._editNode(this, node);
						}
					}
				];
				
				return operate;
			},
			_createMenu : function(dom, node, event){ //创建右键弹出菜单
				var operate = tMethods._getSettings();
				
				var menudiv = document.createElement('div');
				$(menudiv).addClass("menu");
				
				var menuul = document.createElement('ul');
				$.each(operate, function(idx, op){
					var menuli = document.createElement('li');
					menuli = tMethods._initOption(menuli, op, dom, node);
					
					$(menuul).append(menuli);
				});
				$(menudiv).append(menuul).css({
					top : event.pageY,
					left : event.pageX
				});
				
				$('body').append(menudiv);
				
				return menudiv;
			},
			_destoryMenu : function(menu){
				$(menu).remove();
				menu = null;
			},
			_initOption : function(option, operate, dom, node){ //初始化每个菜单选项
				$(option).html(operate.text).bind("click", function(){
					if(operate.callback){
						operate.callback.call(dom, node);
					}
				});
				
				return option;
			},
			_addNode : function(dom, node){ //增加结点操作
				var callbackflag = true;
				// 判断被插入结点是否为父结点(1.是,不变;2,不是,则变为父结点,并插入ul)
				if(node.leaf) {
					dom = tMethods._leafToParent(dom);
				}
				// 插入叶子结点
				var leaf = tMethods._insertLeaf(dom, node);
				
				// 如果叶子结点有兄弟结点,则紧邻的兄弟结点要改变样式
				var lastLeaf = $(leaf).prev('li');
				if(lastLeaf.length > 0) {
					tMethods._bottomToCenter(lastLeaf);
				}
				
				// 创建input框(传入的是父结点的node)
				if(options.callback.onRClick.addCallback) callbackflag = options.callback.onRClick.addCallback.call(leaf, node);
				
				if(callbackflag) { //如果addCallback返回false或什么都不返回,则不会触发以下操作
					tMethods._createInput(leaf);
				}
				
			},
			_deleteNode : function(dom, node){ //删除结点操作:1.子结点会一并删除;2.父节点会产生变化
				var brothers = $(dom).siblings('li');
				var parent = $(dom).parent('ul').parent('li');
				var lastLeaf = $(dom).prev('li');
				
				$(dom).remove(); //删除该结点
				
				if(brothers.length == 0 && parent.length > 0) { // 删除的结点没有兄弟结点,则将父节点改为叶子结点
					tMethods._parentToLeaf(parent);
					$(dom).parent('ul').remove();
				}
				if(lastLeaf.length > 0) { //删除的结点有前一个结点,将前一个结点的样式由center改为bottom
					tMethods._centerToBottom(lastLeaf);
				}
				
				if(options.callback.onRClick.delCallback) options.callback.onRClick.delCallback.call(dom, node);
			},
			_editNode : function(dom, node){ //编辑结点操作, 优先调用
				var callbackflag = true;
				if(options.callback.onRClick.editCallback) callbackflag = options.callback.onRClick.editCallback.call(dom, node);
				
				if(callbackflag) { //如果editCallback返回false或什么都不返回,则不会触发以下操作
					tMethods._createInput(dom, node);
				}
			},
			_moveNode : function(drag, target) {
				var brothers = $(drag).siblings('li');
				var parent = $(drag).parent('ul').parent('li');
				var lastLeaf = $(drag).prev('li');
				
				// 拖动结点的style=bottom
				drag = tMethods._centerToBottom(drag);
				
				var targetNode = $(target).data("node");
				if(targetNode.leaf) {
					target = tMethods._leafToParent(target);
				}else { // 目标结点如果有子结点,则最后一个子结点style=center
					tMethods._bottomToCenter($(target).children('ul:first').children('li:last'));
				}
				$(target).find('ul:first').append(drag);
				
				if(brothers.length == 0 && parent.length > 0) {
					tMethods._parentToLeaf(parent);
					$(dom).parent('ul').remove();
				}
				if(lastLeaf.length > 0) {
					tMethods._centerToBottom(lastLeaf);
				}
			},
			_createInput : function(dom, node){ //在给定的dom中插入一个input框,并将原有内容写入input框,脱离焦点时候则删除input框,并将内容写会dom(可以再addNode和editNode上复用该方法)
				if(!node) node = $(dom).data("node");
				var input = document.createElement('input');
				var nodeDom = tMethods._getNodeDom(dom);
				
				$(input).val(nodeDom.textspan.html());
				$(nodeDom.textspan).html(input);
				
				$(input).select().bind("blur", function(){
					$(nodeDom.textspan).html($(this).val());
					node[node.key.name] = $(this).val();
					$(dom).data("node", node);
					$(this).remove();
				});
			},
			_insertLeaf : function(dom, node){ //addNode时,插入一个叶子结点
				if(!node) node = $(dom).data("node");
				var leafNode = tMethods._addProperties({}, node.level + 1, "bottom");
				var treeli = tMethods._initEvent(tMethods._initNode(document.createElement('li'), leafNode), leafNode);
				$(dom).find('ul:first').append(treeli);
				
				return treeli;
			},
			_leafToParent : function(dom, node){ //addNode时,叶子结点变为父结点
				if(!node) node = $(dom).data("node");
				//将现有结点删除,换成新的结点
				node["state"] = "expand";
				node["leaf"] = false;
				var treeli = tMethods._initEvent(tMethods._initNode(document.createElement('li'), node), node);
				$(treeli).attr("id", $(dom).attr("id")).replaceAll(dom);
				// 创建一个ul
				var treeul = document.createElement('ul');
				$(treeli).append(tMethods._initState(treeul, node));
				
				return treeli;
			},
			_parentToLeaf : function(dom, node){ //deleteNode时,父结点变为叶子结点
				if(!node) node = $(dom).data("node");
				node["leaf"] = true;
				var treeli = tMethods._initEvent(tMethods._initNode(document.createElement('li'), node), node);
				$(treeli).attr("id", $(dom).attr("id")).replaceAll(dom);
				
				return treeli;
			},
			_bottomToCenter : function(dom, node){ //结点的位置有最底部改为中间
				if(!node) node = $(dom).data("node");
				node["style"] = "center";
				var treeli = tMethods._initEvent(tMethods._initNode(document.createElement('li'), node), node);
				var children = $(dom).children('ul');
				if(children.length > 0) {
					$(treeli).append(tMethods._initState(children, node));
				}
				$(treeli).attr("id", $(dom).attr("id")).replaceAll(dom);
				
				return treeli;
			},
			_centerToBottom : function(dom, node){
				if(!node) node = $(dom).data("node");
				node["style"] = "bottom";
				var treeli = tMethods._initEvent(tMethods._initNode(document.createElement('li'), node), node);
				var children = $(dom).children('ul');
				if(children.length > 0) {
					$(treeli).append(tMethods._initState(children, node));
				}
				$(treeli).attr("id", $(dom).attr("id")).replaceAll(dom);
				
				return treeli;
			},
			_refreshOperate : function(){ //在结点增删改之后的刷新,只操作存储数据
				
			},
			//一下方法为动态加载根结点的方法
			/*_getRootIconStyle : function(){
				var rootIconStyle = {};
				if(options.root.rootIconStyle){
					rootIconStyle.style = ("string" == typeof options.root.rootIconStyle.style ? tMethods._strToArr(options.root.rootIconStyle.style) : []);
					rootIconStyle.expand = ("string" == typeof options.root.rootIconStyle.expand ? tMethods._strToArr(options.root.rootIconStyle.expand) : []);
					rootIconStyle.collapse = ("string" == typeof options.root.rootIconStyle.collapse ? tMethods._strToArr(options.root.rootIconStyle.collapse) : []);
				}
				
				return rootIconStyle;
			},
			_getRootTextStyle : function(){
				var rootTextStyle = {};
				if(options.root.rootTextStyle){
					rootTextStyle.style = ("string" == typeof options.root.rootTextStyle.style ? tMethods._strToArr(options.root.rootTextStyle.style) : []);
					rootTextStyle.expand = ("string" == typeof options.root.rootTextStyle.expand ? tMethods._strToArr(options.root.rootTextStyle.expand) : []);
					rootTextStyle.collapse = ("string" == typeof options.root.rootTextStyle.collapse ? tMethods._strToArr(options.root.rootTextStyle.collapse) : []);
				}
				
				return rootTextStyle;
			},*/
			_insertRoot : function(data){ //为整棵树增加一个根节点
				var key = tMethods._getNormalKey();
				var obj = options.root;
				obj[key.children] = data;
				var arr = [];
				arr.push(obj);
				
				return arr;
			}
		};
		
		//树的初始化
		if(options.ajax.enable){ //通过ajax请求得到数据
			tMethods._ajaxData();
		}else{ //传入数据
			tMethods._initTree();
		}
		
		return {
			refresh : function(){ //ajax刷新:重新请求数据;data传入刷新:重新画树
				tMethods._removeTree();
				if(options.ajax.enable){
					tMethods._ajaxData();
				}else{
					tMethods._initTree();
				}
			},
			expandAll : function(){
				$(treeDom).find('li.vdiclose').each(function(idx, dom){
					
					tMethods._changeState(dom, $(dom).data("node"));
	            });
			},
			collapseAll : function(){
				$(treeDom).find('li.vdiopen').each(function(idx, dom){
					
					tMethods._changeState(dom, $(dom).data("node"));
	            });
			},
			getCheckedNodes : function(){
				var res = [];
				$(treeDom).find("span.checkbox_true_full").parent('li').each(function(idx, dom){
					res.push($(dom).data("node"));
				});
				
				return res;
			},
			getSelectedNodes : function(){
				var res = [];
				$(treeDom).find("a.selected").parent('li').each(function(idx, dom){
					res.push($(dom).data("node"));
				});
				
				return res;
			},
			changeState : function(nodeid){
				var dom = $(treeDom).find('#' + nodeid);
				var node = $(node).data("node");
				if(!node.leaf){
					tMethods._changeState(dom, node);
				}
			}
		};
	}
	
	$.fn.vdiTree = function(options){
		
		var $this = $(this);
		return this.each(function(){
			$(this).data("vdiTree", makeVdiTree($this, options));
		});
	};
})(jQuery);

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值