原文出处:空空儿http://www.cnblogs.com/doll-net/archive/2007/07/29/749282.html
最近做项目要用TreeView,开始用VS自带的TreeView控件,发现不大好扩展,索性自己写了一个,这个DEMO很简单,但已经有了最基本的方法,实现了动态读取自节点数据,鼠标经过时节点变背景色,选中节点变背景色,左键菜单,根据URL上传递的参数在页面刷新的时候展开相应的节点,可以根据自己的实际需求进行修改或者扩展。
这个JS只可运行于IE,其他浏览器不支持
TreeView.js的代码 :
浏览页HTML的代码:
XmlHttp.js 请见 ajax中获取xmlHttp对象方法
GetCityData.aspx返回一个XML文件,截图:
运行效果截图: 菜单截图:
最近做项目要用TreeView,开始用VS自带的TreeView控件,发现不大好扩展,索性自己写了一个,这个DEMO很简单,但已经有了最基本的方法,实现了动态读取自节点数据,鼠标经过时节点变背景色,选中节点变背景色,左键菜单,根据URL上传递的参数在页面刷新的时候展开相应的节点,可以根据自己的实际需求进行修改或者扩展。
这个JS只可运行于IE,其他浏览器不支持
TreeView.js的代码 :
TreeView.js
function Tree(objTreeID)
{
this.objTree = getObjById(objTreeID);
this.IMG = [{id:1,imgSrc:"../images/open.gif",imgTitle:"点击折叠"},{id:2,imgSrc:"../images/close.gif",imgTitle:"点击展开"}];
this.TagName = [{id:1,name:"Tbl"},{id:2,name:"Td"},{id:3,name:"Img"}];
this.outBgColor = "#FFF";
this.clickBgColor = "#4c4c4c";
this.overBgColor = "#D4D4D4";
this.target = "_self";
this.pageUrl = "#";
this.isFirstLoad = true;
this.selectNodeID = "";//存放选中的节点值
this.menuNodeID = "";
this.html = "";
this.getXmlData = function(qid,objTree)
{
var _this = this;
var url = "GetCityData.aspx?id="+qid+"&" + Math.random();
var xmlHttp = new xmlHTTP();
xmlHttp.open("GET",url,true);
xmlHttp.onreadystatechange = function()
{
if(xmlHttp.ReadyState == 4)
{
if(xmlHttp.responseXML.childNodes.length == 0)
return;
var nodeData = xmlHttp.responseXML.getElementsByTagName("NodeData");// alert(nodeData[0].getAttribute("result"));
var childNodeData = nodeData[0].getElementsByTagName("node");
_this.foreachXmlNode(childNodeData);
//显示
objTree.innerHTML = _this.html;
//没有数据则将DIV的高度设为1
if(_this.html.length==0)
{
objTree.style.height = "1px";
objTree.style.overflow="hidden";
}
if(_this.isFirstLoad)
{
_this.orientationNode();
}
}
};
xmlHttp.send(null);
}
this.foreachXmlNode = function(nodeData)
{
var _this = this;
var nodeValue,nodeName;
if(_this.html != "")
_this.html = "";
for( var i=0;i<nodeData.length;i++)
{
nodeName = nodeData[i].childNodes[0].childNodes[0].nodeValue;
nodeValue = nodeData[i].childNodes[1].childNodes[0].nodeValue;
_this.html += _this.createNode(nodeValue,nodeName);
}
}
this.createNode = function(nodeValue,nodeName)
{
var _this = this;
var imgSrc=_this.IMG[1].imgSrc,imgTitle=_this.IMG[1].imgTitle;
return "<table border=0 cellpadding='1' cellspacing='1' id='Tbl"+nodeValue+"'><tr><td>"
+"<img id='Img"+nodeValue+"' onclick=\""+objTreeID+".openNode(this,'Img')\" src='"+imgSrc+"' title='"+imgTitle+"' hspace='0' vspace='0' style='cursor:hand'>"
+"</td><td nowrap id='Td"+nodeValue+"' onmouseup="+objTreeID+".showMenu('"+nodeValue+"') onclick=\""+objTreeID+".tdClick(this)\" onmouseover="+objTreeID+".mouseOver(this) onmouseout="+objTreeID+".mouseOut(this) style='cursor:hand'>"
+"<a href='"+_this.pageUrl+nodeValue+"' target='"+_this.target+"'>"
+nodeName+"</a></td></tr></table><div id='"+nodeValue+"' style=\"display: none; margin-left: 1em;\"></div>";
}
this.openNode = function(objNode)
{
var _this = this;
try{
if(event.button == 2 || event.button == 1)
_this.isFirstLoad = false;
if(event.button == 2)
return;
}catch(ex){}
var divObj = getObjById((objNode.id).Replace(_this.TagName[2].name,""));
if(_this.isFirstLoad || objNode.title == _this.IMG[1].imgTitle)
{
objNode.src = _this.IMG[0].imgSrc;
objNode.title = _this.IMG[0].imgTitle;
divObj.style.display = "block";
if(!divObj.innerHTML.length>0)
{
divObj.innerHTML="loading.";
_this.getXmlData(divObj.id,divObj);
}
}
else
{
objNode.src = _this.IMG[1].imgSrc;
objNode.title = _this.IMG[1].imgTitle;
divObj.style.display = "none";
}
}
this.tdClick = function(objNode)
{
var _this = this;
if(_this.selectNodeID == "")
{
_this.selectNodeID = objNode.id;
}
else if(objNode.id != _this.selectNodeID)
{
getObjById(_this.selectNodeID).style.backgroundColor = _this.outBgColor;
_this.selectNodeID = objNode.id;
}
objNode.style.backgroundColor = _this.clickBgColor;
_this.openNode(getObjById(objNode.id.Replace(_this.TagName[1].name,_this.TagName[2].name)));
}
this.mouseOver = function(objNode,type)
{
var _this = this;
if(type==1 && objNode.id != _this.selectNodeID)
{
objNode.style.backgroundColor="#d1d1d1";
}
else
{
if(objNode.id != _this.selectNodeID)
{
objNode.style.backgroundColor = _this.overBgColor;
}
}
}
this.mouseOut = function(objNode,type)
{
var _this = this;
if(type==1)
{
objNode.style.backgroundColor="#ACD3E2";
}
else
{
if( objNode.id != _this.selectNodeID)
{
objNode.style.backgroundColor = _this.outBgColor;
}
}
}
//根据URL上的参数,让相应的节点展开
this.orientationNode = function(nodeId)
{
var _this = this;
try{
var nodeId = window.location.href.match(/#([^&?].)*/g)[0];
if(nodeId.length>0)
{
nodeId = nodeId.substring(1);
if(!(/^\d{4}0{2}$/).test(nodeId))
{
_this.openNode(getObjById(_this.TagName[2].name+nodeId.substring(0,4)+"00"));
}
_this.openNode(getObjById(_this.TagName[2].name+nodeId));
_this.isFirstLoad = false;
}
}catch(e){}
}
//显示菜单
this.showMenu = function(nodeID)
{
if(event.button == 1)
return;
var _this = this;
_this.tdClick(eval(_this.TagName[1].name+nodeID));
var divElement=eval("menu");
var rightedge = document.body.clientWidth + document.documentElement.clientWidth - event.clientX ;
var bottomedge = document.body.clientHeight + document.documentElement.clientHeight - event.clientY ;
if (rightedge < divElement.offsetWidth)
{
divElement.style.left = document.body.scrollLeft + event.clientX - divElement.offsetWidth + "px";
}
else
{
divElement.style.left = document.body.scrollLeft + event.clientX + "px";
}
if (bottomedge < divElement.offsetHeight)
{
divElement.style.top = document.body.scrollTop + document.documentElement.scrollTop + event.clientY - divElement.offsetHeight + "px";
}
else
{
divElement.style.top = document.body.scrollTop + document.documentElement.scrollTop + event.clientY + "px";
}
_this.menuNodeID = nodeID;
divElement.style.visibility = "visible";
}
}
function Tree(objTreeID)
{
this.objTree = getObjById(objTreeID);
this.IMG = [{id:1,imgSrc:"../images/open.gif",imgTitle:"点击折叠"},{id:2,imgSrc:"../images/close.gif",imgTitle:"点击展开"}];
this.TagName = [{id:1,name:"Tbl"},{id:2,name:"Td"},{id:3,name:"Img"}];
this.outBgColor = "#FFF";
this.clickBgColor = "#4c4c4c";
this.overBgColor = "#D4D4D4";
this.target = "_self";
this.pageUrl = "#";
this.isFirstLoad = true;
this.selectNodeID = "";//存放选中的节点值
this.menuNodeID = "";
this.html = "";
this.getXmlData = function(qid,objTree)
{
var _this = this;
var url = "GetCityData.aspx?id="+qid+"&" + Math.random();
var xmlHttp = new xmlHTTP();
xmlHttp.open("GET",url,true);
xmlHttp.onreadystatechange = function()
{
if(xmlHttp.ReadyState == 4)
{
if(xmlHttp.responseXML.childNodes.length == 0)
return;
var nodeData = xmlHttp.responseXML.getElementsByTagName("NodeData");// alert(nodeData[0].getAttribute("result"));
var childNodeData = nodeData[0].getElementsByTagName("node");
_this.foreachXmlNode(childNodeData);
//显示
objTree.innerHTML = _this.html;
//没有数据则将DIV的高度设为1
if(_this.html.length==0)
{
objTree.style.height = "1px";
objTree.style.overflow="hidden";
}
if(_this.isFirstLoad)
{
_this.orientationNode();
}
}
};
xmlHttp.send(null);
}
this.foreachXmlNode = function(nodeData)
{
var _this = this;
var nodeValue,nodeName;
if(_this.html != "")
_this.html = "";
for( var i=0;i<nodeData.length;i++)
{
nodeName = nodeData[i].childNodes[0].childNodes[0].nodeValue;
nodeValue = nodeData[i].childNodes[1].childNodes[0].nodeValue;
_this.html += _this.createNode(nodeValue,nodeName);
}
}
this.createNode = function(nodeValue,nodeName)
{
var _this = this;
var imgSrc=_this.IMG[1].imgSrc,imgTitle=_this.IMG[1].imgTitle;
return "<table border=0 cellpadding='1' cellspacing='1' id='Tbl"+nodeValue+"'><tr><td>"
+"<img id='Img"+nodeValue+"' onclick=\""+objTreeID+".openNode(this,'Img')\" src='"+imgSrc+"' title='"+imgTitle+"' hspace='0' vspace='0' style='cursor:hand'>"
+"</td><td nowrap id='Td"+nodeValue+"' onmouseup="+objTreeID+".showMenu('"+nodeValue+"') onclick=\""+objTreeID+".tdClick(this)\" onmouseover="+objTreeID+".mouseOver(this) onmouseout="+objTreeID+".mouseOut(this) style='cursor:hand'>"
+"<a href='"+_this.pageUrl+nodeValue+"' target='"+_this.target+"'>"
+nodeName+"</a></td></tr></table><div id='"+nodeValue+"' style=\"display: none; margin-left: 1em;\"></div>";
}
this.openNode = function(objNode)
{
var _this = this;
try{
if(event.button == 2 || event.button == 1)
_this.isFirstLoad = false;
if(event.button == 2)
return;
}catch(ex){}
var divObj = getObjById((objNode.id).Replace(_this.TagName[2].name,""));
if(_this.isFirstLoad || objNode.title == _this.IMG[1].imgTitle)
{
objNode.src = _this.IMG[0].imgSrc;
objNode.title = _this.IMG[0].imgTitle;
divObj.style.display = "block";
if(!divObj.innerHTML.length>0)
{
divObj.innerHTML="loading.";
_this.getXmlData(divObj.id,divObj);
}
}
else
{
objNode.src = _this.IMG[1].imgSrc;
objNode.title = _this.IMG[1].imgTitle;
divObj.style.display = "none";
}
}
this.tdClick = function(objNode)
{
var _this = this;
if(_this.selectNodeID == "")
{
_this.selectNodeID = objNode.id;
}
else if(objNode.id != _this.selectNodeID)
{
getObjById(_this.selectNodeID).style.backgroundColor = _this.outBgColor;
_this.selectNodeID = objNode.id;
}
objNode.style.backgroundColor = _this.clickBgColor;
_this.openNode(getObjById(objNode.id.Replace(_this.TagName[1].name,_this.TagName[2].name)));
}
this.mouseOver = function(objNode,type)
{
var _this = this;
if(type==1 && objNode.id != _this.selectNodeID)
{
objNode.style.backgroundColor="#d1d1d1";
}
else
{
if(objNode.id != _this.selectNodeID)
{
objNode.style.backgroundColor = _this.overBgColor;
}
}
}
this.mouseOut = function(objNode,type)
{
var _this = this;
if(type==1)
{
objNode.style.backgroundColor="#ACD3E2";
}
else
{
if( objNode.id != _this.selectNodeID)
{
objNode.style.backgroundColor = _this.outBgColor;
}
}
}
//根据URL上的参数,让相应的节点展开
this.orientationNode = function(nodeId)
{
var _this = this;
try{
var nodeId = window.location.href.match(/#([^&?].)*/g)[0];
if(nodeId.length>0)
{
nodeId = nodeId.substring(1);
if(!(/^\d{4}0{2}$/).test(nodeId))
{
_this.openNode(getObjById(_this.TagName[2].name+nodeId.substring(0,4)+"00"));
}
_this.openNode(getObjById(_this.TagName[2].name+nodeId));
_this.isFirstLoad = false;
}
}catch(e){}
}
//显示菜单
this.showMenu = function(nodeID)
{
if(event.button == 1)
return;
var _this = this;
_this.tdClick(eval(_this.TagName[1].name+nodeID));
var divElement=eval("menu");
var rightedge = document.body.clientWidth + document.documentElement.clientWidth - event.clientX ;
var bottomedge = document.body.clientHeight + document.documentElement.clientHeight - event.clientY ;
if (rightedge < divElement.offsetWidth)
{
divElement.style.left = document.body.scrollLeft + event.clientX - divElement.offsetWidth + "px";
}
else
{
divElement.style.left = document.body.scrollLeft + event.clientX + "px";
}
if (bottomedge < divElement.offsetHeight)
{
divElement.style.top = document.body.scrollTop + document.documentElement.scrollTop + event.clientY - divElement.offsetHeight + "px";
}
else
{
divElement.style.top = document.body.scrollTop + document.documentElement.scrollTop + event.clientY + "px";
}
_this.menuNodeID = nodeID;
divElement.style.visibility = "visible";
}
}
浏览页HTML的代码:
TeeView Demo HTML
<head runat="server">
<title>无标题页</title>
<script type="text/javascript" src="../js/XmlHttp.js"></script>
<script type="text/javascript" src="../js/TreeView.js"></script>
<script type="text/javascript">
function getObjById(id)
{
if (typeof(id) != "string" || id == "") return null;
if (document.getElementById) return document.getElementById(id);
if (document.all) return document.all(id);
try {return eval(id);} catch(e){ return null;}
}
String.prototype.Replace = function(oldValue,newValue)
{
return this.replace(new RegExp(oldValue,"g"), newValue);
}
var tree ;
window.onload = function()
{
tree = new Tree("tree");
tree.getXmlData(-1,tree.objTree);
}
//屏蔽系统左键
document.oncontextmenu = function () { return false; }
//鼠标点击事件
document.onmouseup = function()
{
if(event.button == 1)
{
getObjById("menu").style.visibility = 'hidden';
}
}
//菜单事件
function ObjClick(obj)
{
switch(obj.innerText)
{
case "添加" :
alert("你要添加的节点ID为:"+tree.menuNodeID);
break;
case "删除":
delteNode();
break;
}
}
//删出事件
function delteNode()
{
if(confirm('确定要删除吗?'))
{
getObjById(tree.TagName[0].name+tree.menuNodeID).removeNode(true);//删除节点
getObjById(tree.menuNodeID).removeNode(true);//删除其子节点
}
tree.selectNodeID = '';//清除选中节点值
}
function mouseOver(objNode,type)
{
tree.mouseOver(objNode,type);
}
function mouseOut(objNode,type)
{
tree.mouseOut(objNode,type);
}
</script>
</head>
<body>
<form id="form1" runat="server">
<div id="menu" style="position:absolute;visibility:hidden;width:60px;font-size: 9pt; background-color:#ACD3E2;">
<div id='divAdd' onmouseover="mouseOver(this,1)" onmouseout="mouseOut(this,1)" onclick="ObjClick(this)">添加</div>
<div style='height:2px;background-color:#fff; overflow: hidden;'></div>
<div id='divDel' onmouseover="mouseOver(this,1)" onmouseout="mouseOut(this,1)" onclick="ObjClick(this)">删除</div>
</div>
<div id="tree">
</div>
</form>
</body>
</html>
<head runat="server">
<title>无标题页</title>
<script type="text/javascript" src="../js/XmlHttp.js"></script>
<script type="text/javascript" src="../js/TreeView.js"></script>
<script type="text/javascript">
function getObjById(id)
{
if (typeof(id) != "string" || id == "") return null;
if (document.getElementById) return document.getElementById(id);
if (document.all) return document.all(id);
try {return eval(id);} catch(e){ return null;}
}
String.prototype.Replace = function(oldValue,newValue)
{
return this.replace(new RegExp(oldValue,"g"), newValue);
}
var tree ;
window.onload = function()
{
tree = new Tree("tree");
tree.getXmlData(-1,tree.objTree);
}
//屏蔽系统左键
document.oncontextmenu = function () { return false; }
//鼠标点击事件
document.onmouseup = function()
{
if(event.button == 1)
{
getObjById("menu").style.visibility = 'hidden';
}
}
//菜单事件
function ObjClick(obj)
{
switch(obj.innerText)
{
case "添加" :
alert("你要添加的节点ID为:"+tree.menuNodeID);
break;
case "删除":
delteNode();
break;
}
}
//删出事件
function delteNode()
{
if(confirm('确定要删除吗?'))
{
getObjById(tree.TagName[0].name+tree.menuNodeID).removeNode(true);//删除节点
getObjById(tree.menuNodeID).removeNode(true);//删除其子节点
}
tree.selectNodeID = '';//清除选中节点值
}
function mouseOver(objNode,type)
{
tree.mouseOver(objNode,type);
}
function mouseOut(objNode,type)
{
tree.mouseOut(objNode,type);
}
</script>
</head>
<body>
<form id="form1" runat="server">
<div id="menu" style="position:absolute;visibility:hidden;width:60px;font-size: 9pt; background-color:#ACD3E2;">
<div id='divAdd' onmouseover="mouseOver(this,1)" onmouseout="mouseOut(this,1)" onclick="ObjClick(this)">添加</div>
<div style='height:2px;background-color:#fff; overflow: hidden;'></div>
<div id='divDel' onmouseover="mouseOver(this,1)" onmouseout="mouseOut(this,1)" onclick="ObjClick(this)">删除</div>
</div>
<div id="tree">
</div>
</form>
</body>
</html>
XmlHttp.js 请见 ajax中获取xmlHttp对象方法
GetCityData.aspx返回一个XML文件,截图:
运行效果截图: 菜单截图: