用UL列表实现树目录(带连接线)

zhaolidong 2009-03-29 09:06:56
网上找到的用UL列表做的树,都没有连接线。如果把虚线作为ul的的背景,就可以做成有连线的ul树,显示效果和梅花雪的树一样。效果在这:http://mz.host.dxsidc.com/

下面是我做的树,定义树的结构用xml文件,动态增加节点也用xml。
和梅花雪的对比了一下,初始化的速度慢了好多。xmldom的速度慢是个大原因,但除了这一部分,运行的时间还是比梅花雪的要多(我的也是参考梅花雪的异步显示,第一次只显示第一级节点,其他的点击展开时再生成html)。
看来还是有差距。哪位高手给指点指点,再提高一下速度。

//mytree.js
function MyTree(treename)
{
if(typeof(treename) != "string" || treename == "") throw(new Error(-1, '没有定义树的名字!'));
this.link = "#";
this.target = "_self";
this.imgpath = "image/";
this.xmlfile = "xmltree.xml";
this.name = treename;
this.current = "";
this.node = {};
this.node["root"] = {"childnodes":[]};
this.sty='<style>.MyTree {font-size:12px;} .MyTree ul {padding-left:0px!important; padding-left:0px; margin-left:0px!important; margin-left:0px; background-image:url("'+this.imgpath+'back.gif"); background-repeat: repeat-y;} .MyTree ul.nobg {background-position:-10px;} .MyTree ul li {list-style:none; padding-left:20px;}.MyTree ul li.first{padding-left:0px;} .MyTree A {outline: none; PADDING-RIGHT: 3px; PADDING-LEFT: 3px; PADDING-TOP: 3px; PADDING-BOTTOM: 1px; color: #000060; TEXT-DECORATION: none} .MyTree A:hover {background: #7386ba; color: #fff; TEXT-DECORATION: none}</style>';

this.createXMLDOM = function()
{
var xmldom;
if (window.ActiveXObject)
{ var ActiveX = new Array("MSXML2.DOMDocument.5.0","MSXML2.DOMDocument.4.0","MSXML2.DOMDocument.3.0","MSXML2.DOMDocument","Microsoft.XMLDOM","MSXML.DOMDocument");
for(var i=0;i<ActiveX.length;i++)
{ try{ xmldom = new ActiveXObject(ActiveX[i]);break;}catch(e){} }
}
else
{ if (document.implementation && document.implementation.createDocument)
{ var xmldom = document.implementation.createDocument("","doc",null);}
}
xmldom.async = false;
xmldom.resolveExternals = false;
xmldom.validateOnParse = false;
xmldom.preserveWhiteSpace = true;
return xmldom;
};

this.loadXML = function(xml)
{
var ie = (window.ActiveXObject)?true:false, flag=false;
var obj = this.createXMLDOM();
if(xml==null || xml=='') flag=obj.load(this.xmlfile); else { //没有参数,就从文件读xml
if(ie) flag=obj.loadXML(xml); else {
var oParser=new DOMParser();
var obj=oParser.parseFromString(xml,"text/xml");
flag=true;
}}

if (flag)
{ var nodes=obj.getElementsByTagName('node');
if (nodes != null && nodes.length > 0)
{ var id='',pid='';
for(var i=0;i<nodes.length;i++)
{ id=nodes[i].getAttribute('id');
pid=nodes[i].getAttribute('pid');
if(typeof(this.node[pid])=="undefined") continue;//xml中如果子节点出现在母节点前,这个子节点将被忽略
this.node[id]=
{ "id":id,
"pid":pid,
"name":nodes[i].getAttribute('name'),
"isload":false
//"childnodes":[]
};
if(nodes[i].getAttribute('link')!=null) this.node[id].link=nodes[i].getAttribute('link');
if(nodes[i].getAttribute('target')!=null) this.node[id].target=nodes[i].getAttribute('target');
if(nodes[i].getAttribute('icon')!=null) this.node[id].icon=nodes[i].getAttribute('icon');
if(nodes[i].getAttribute('method')!=null) this.node[id].method=nodes[i].getAttribute('method');
if(typeof(this.node[pid].childnodes)=="undefined") this.node[pid].childnodes=[];
this.node[pid].childnodes[this.node[pid].childnodes.length]=this.node[id];
}
} else alert('No Valid treeNode!');
} else alert('XML Data Load Error!');
obj=null;
};

this.buildchild = function(id,end)
{
var ohtml='',icon1='',icon2='';
var classname=(end==true)?' class="nobg"':'';
if(typeof(this.node[id].childnodes)=="undefined") return ohtml;

var cn=this.node[id].childnodes;
if(cn.length>0)
{
ohtml='<SPAN style="display:none;"><UL'+ classname +'>';
for(var i=0;i<cn.length;i++)
{ if(typeof(cn[i].childnodes)=="undefined") {icon1=((i==cn.length-1)?'l2.gif':'l1.gif');icon2=(typeof(cn[i].icon)=="undefined")?'file.gif':cn[i].icon;} else {icon1=((i==cn.length-1)?'p2.gif':'p1.gif');icon2='folder.gif';}
ohtml+='<LI id="mytree_' + cn[i].id + '"><SPAN onclick="'+ this.name +'.clickhandle('+ cn[i].id +',event);"><IMG align=absmiddle src="'+ this.imgpath + icon1 +'"><IMG align=absmiddle src="'+ this.imgpath + icon2 +'"><A hidefocus onfocus="'+ this.name +'.focusid('+ cn[i].id +')" href="'+ ((typeof(cn[i].link)=="undefined")?this.link:cn[i].link) +'" target="'+ ((typeof(cn[i].target)=="undefined")?this.target:cn[i].target) +'">'+ cn[i].name +'</a></SPAN></LI>';
}
ohtml+='</UL></SPAN>';
this.node[id].isload=true;
}
return ohtml;
};

this.tostring = function(dynamic)
{
if(dynamic!=true) this.loadXML();
var ohtml='',icon1='',icon2='';
var cn=this.node["root"].childnodes;
if(cn.length>0)
{ ohtml='<SPAN onclick="'+ this.name +'.clickhandle('+cn[0].id+',event);"><IMG align=absmiddle src="'+ this.imgpath + ((typeof(cn[0].icon)=="undefined")?'root.gif':cn[0].icon)+ '"><A style="color:#ffffff; background:#0A246A;" hidefocus onfocus="'+ this.name +'.focusid('+ cn[0].id +')" href="'+ ((cn[0].link==null)?this.link:cn[0].link) +'" target="'+ ((cn[0].target==null)?this.target:cn[0].target) +'">'+ cn[0].name +'</A></SPAN><SPAN><UL class="nobg" style="margin-top:0px;">';//顶层节点,只取第一个
this.current=cn[0].id;

if(typeof(cn[0].childnodes)!="undefined")
{ cn[0].isload=true;
cn=cn[0].childnodes;
for(var i=0;i<cn.length;i++)
{ if(typeof(cn[i].childnodes)=="undefined") {icon1=((i==cn.length-1)?'l2.gif':'l1.gif');icon2=(typeof(cn[i].icon)=="undefined")?'file.gif':cn[i].icon;} else {icon1=((i==cn.length-1)?'p2.gif':'p1.gif');icon2='folder.gif';}
ohtml+='<LI class="first" id="mytree_' + cn[i].id + '"><SPAN onclick="'+ this.name +'.clickhandle('+ cn[i].id +',event);"><IMG align=absmiddle src="'+ this.imgpath + icon1 +'"><IMG align=absmiddle src="'+ this.imgpath + icon2 +'"><A hidefocus onfocus="'+ this.name +'.focusid('+ cn[i].id +')" href="'+ ((typeof(cn[i].link)=="undefined")?this.link:cn[i].link) +'" target="'+ ((typeof(cn[i].target)=="undefined")?this.target:cn[i].target) +'">'+ cn[i].name +'</a></SPAN></LI>';
}
}
ohtml+='</UL></SPAN>';
}

if(dynamic==true) return ohtml;
return '<DIV class="MyTree" id="mytree_'+this.node['root'].childnodes[0].id+'">'+ohtml+'</DIV>'+this.sty;
};
...全文
520 6 打赏 收藏 转发到动态 举报
写回复
用AI写文章
6 条回复
切换为时间正序
请发表友善的回复…
发表回复
sjboss 2010-07-29
  • 打赏
  • 举报
回复
手机博士 来顶一下
  • 打赏
  • 举报
回复
不错
zhaolidong 2009-03-30
  • 打赏
  • 举报
回复
谢谢,我试试看
zhaolidong 2009-03-29
  • 打赏
  • 举报
回复

//xmltree.xml

<?xml version="1.0" encoding="utf-8"?>

<!--
node 为树的一个节点,具有以下属性
id: 编号 (必须)
name: 名称 (必须)
link: 连接 (可选)
target: 目标 (可选)
icon: 图标 (可选)
-->
<nodes>
<node id="1" pid="root" name="孟州市" link="javascript:void(0);" method="alert('this maybe do other things');"/>
<node id="2" pid="1" name="大定办事处" link="javascript:void(0);"/>
<node id="3" pid="1" name="会昌办事处" link="javascript:void(0);"/>
<node id="4" pid="1" name="河雍办事处" link="javascript:void(0);"/>
<node id="5" pid="1" name="河阳办事处" link="javascript:void(0);"/>
<node id="6" pid="1" name="化工镇" link="javascript:void(0);"/>
<node id="7" pid="1" name="南庄镇" link="javascript:void(0);"/>
<node id="8" pid="1" name="城伯镇" link="javascript:void(0);"/>
<node id="9" pid="1" name="谷旦镇" link="javascript:void(0);"/>
<node id="10" pid="1" name="赵和镇" link="javascript:void(0);"/>
<node id="11" pid="1" name="槐树乡" link="javascript:void(0);"/>
<node id="12" pid="1" name="西虢镇" link="javascript:void(0);"/>
<node id="201" pid="2" name="北街" link="#?id=1" target="_blank"/>
<node id="202" pid="2" name="北开义" link="#?id=2" target="_blank"/>
<node id="203" pid="2" name="陈湾" link="#?id=3" target="_blank"/>
<node id="204" pid="2" name="东关" link="#?id=4" target="_blank"/>
<node id="205" pid="2" name="东韩" link="#?id=5" target="_blank"/>
<node id="206" pid="2" name="东街" link="#?id=6" target="_blank"/>
<node id="301" pid="3" name="北韩庄" link="#?id=20" target="_blank"/>
<node id="302" pid="3" name="大宋庄" link="#?id=21" target="_blank"/>
<node id="319" pid="3" name="张厚" link="#?id=38" target="_blank"/>
<node id="320" pid="3" name="中曹" link="#?id=39" target="_blank"/>
<node id="321" pid="3" name="竹园" link="#?id=40" target="_blank"/>
<node id="401" pid="4" name="陈庄" link="#?id=41" target="_blank"/>
<node id="402" pid="4" name="东田丈" link="#?id=42" target="_blank"/>
<node id="403" pid="4" name="富村" link="#?id=43" target="_blank"/>
<node id="404" pid="4" name="关耿唐" link="#?id=44" target="_blank"/>
<node id="405" pid="4" name="兰窑" link="#?id=45" target="_blank"/>
<node id="515" pid="5" name="西葛" link="#?id=69" target="_blank"/>
<node id="516" pid="5" name="中龙" link="#?id=70" target="_blank"/>
<node id="517" pid="5" name="中逯" link="#?id=71" target="_blank"/>
<node id="601" pid="6" name="晁庄" link="#?id=72" target="_blank"/>
<node id="602" pid="6" name="东光" link="#?id=73" target="_blank"/>
<node id="603" pid="6" name="东孟" link="#?id=74" target="_blank"/>
<node id="604" pid="6" name="杜庄" link="#?id=75" target="_blank"/>
<node id="605" pid="6" name="段庄" link="#?id=76" target="_blank"/>
</nodes>



//treeTest.htm

<html>
<haed>
<META http-equiv=Content-Type content="text/html; charset=utf-8">
<script language="JavaScript" src="mytree.js"></script>
</head>
<body bgcolor=#e1e1e1>

<p><input type=button onclick="dy_add();" value="动态加入"><input type=button onclick="alert(document.getElementById('t').innerHTML);" value="html"><p>
<div id="t"></div>

<SCRIPT language="JavaScript">
//var dat1= new Date();

var tree = new MyTree("tree");
document.getElementById("t").innerHTML=tree.tostring();//使用比较简单,定义树的名字,调用tostring就行了


//var dat2= new Date();
//alert(dat2.getTime()-dat1.getTime());
//速度不是很理想,比梅花雪的慢了快一个数量级。除下xmldom慢的部分,运行时间还是比梅花雪的多。看来还需要改进

function dy_add()
{
var xmlurl='http://localhost/testxml.xml';
tree.dynamicaddchild(xmlurl,'206');
}
</SCRIPT>
</body>
</html>
zhaolidong 2009-03-29
  • 打赏
  • 举报
回复
操,帖子内容太长?


this.clickhandle = function(id,e)
{ e = window.event || e; e = e.srcElement || e.target;
if(e.tagName=="A") {if(typeof(this.node[id].method)!="undefined") eval(this.node[id].method);}
else this.expand(id);
};

this.expand = function(id)
{ var pid=this.node[id].pid,span;
if(document.getElementById("mytree_"+id)==null) this.expand(pid); else
{ while(pid!='root')
{ span=document.getElementById("mytree_"+pid).childNodes;
span=span[span.length-1];
if(span.style.display=="none") {this.expand(pid);}
pid=this.node[pid].pid;
}
}
if(typeof(this.node[id].childnodes)!="undefined" && this.node[id].childnodes.length>0) //有子节点
{ if(!this.node[id].isload)//如果还没有生成子节点
{ var tmp=this.node[this.node[id].pid].childnodes;
var flag=(tmp[tmp.length-1]==this.node[id]);
document.getElementById("mytree_"+id).innerHTML+=this.buildchild(id,flag);
}
}
span=document.getElementById("mytree_"+id).childNodes;
var a=span[0].childNodes; a=a[a.length-1]; if(a) a.focus();
if(typeof(span[1])!="undefined" && span[1].nodeType==1)
{ var s1='',s2='';
if((span[1].style.display=="")) {span[1].style.display="none";s1='p';s2='folder.gif';} else {span[1].style.display="";s1='m';s2='folderopen.gif';}
if(id!=this.node['root'].childnodes[0].id) {var img=span[0].childNodes[0].src;img=s1+img.substr(img.indexOf('.gif')-1,5);span[0].childNodes[0].src=this.imgpath+img;span[0].childNodes[1].src=this.imgpath+s2;}
}
};

this.focusid = function(id)
{ if(id==this.current) return;
var a=document.getElementById("mytree_"+id).childNodes[0].childNodes; a=a[a.length-1];
with(a.style){color = "#ffffff"; backgroundColor = "#0A246A";}
a=document.getElementById("mytree_"+this.current).childNodes[0].childNodes; a=a[a.length-1];
with(a.style){color = "#000060"; backgroundColor = "";}
this.current = id;
};

this.dynamicaddchild = function(url,id) //动态增加子节点,url地址返回包含子节点信息的xml文件,id是母节点
{ this.expand(id);
if(this.node[id].isload){var tmp=document.getElementById("mytree_"+id).childNodes[1];tmp.parentNode.removeChild(tmp);}
var tmp=this.node[this.node[id].pid].childnodes;
var flag=(tmp[tmp.length-1]==this.node[id]);
var span=document.getElementById("mytree_"+id).childNodes;
span[0].childNodes[0].src=this.imgpath+((flag)?'P2':'P1')+'.gif';
span[0].childNodes[1].src=this.imgpath+'loading.gif';

var TREE=this.name;

try{
if(window.ActiveXObject){
for(var i=5; i; i--){
try{if(i==2){ xmlhttp_req = new ActiveXObject("Microsoft.XMLHTTP");}
else{
xmlhttp_req = new ActiveXObject( "Msxml2.XMLHTTP." + i + ".0" );
xmlhttp_req.setRequestHeader("Content-Type","text/html");
xmlhttp_req.setRequestHeader("Charset","utf-8");
} break;
} catch(e){xmlhttp_req = false;}
}
} else if(window.XMLHttpRequest){
xmlhttp_req = new XMLHttpRequest();
if(xmlhttp_req.overrideMimeType) {xmlhttp_req.overrideMimeType('text/html');}
}
} catch(e){alert("cann't build xmlhttp!");return;}

xmlhttp_req.open('GET', url, true);
xmlhttp_req.setRequestHeader('If-Modified-Since', '0');
xmlhttp_req.setRequestHeader('CONTENT-TYPE','application/x-www-form-urlencoded');
xmlhttp_req.send(null);
xmlhttp_req.onreadystatechange = function()
{ if (xmlhttp_req.readyState == 4 && xmlhttp_req.status==200)
{ alert(xmlhttp_req.responseText);
if(eval(TREE).node[id].isload) eval(TREE).clearchildload(id);
eval(TREE).loadXML(xmlhttp_req.responseText);
if(eval(TREE).node[id].pid=='root'){document.getElementById("mytree_"+id).innerHTML=eval(TREE).tostring(true);}
else
{ document.getElementById("mytree_"+id).innerHTML+=eval(TREE).buildchild(id,flag);
eval(TREE).expand(id);
}
}
}
};

this.clearchildload = function(id)
{ if(typeof(this.node[id].childnodes)!="undefined")
{ var i,tmp=this.node[id].childnodes;
for(var i=0;i<tmp.length;i++)if(tmp[i].isload){this.clearchildload(tmp[i].id);tmp[i].isload=false;}
}
};

}
离子漂浮物 2009-03-29
  • 打赏
  • 举报
回复
建议一下,

尽量避免大量使用innerHTML+=,用appendChild,window.document.createElement之类的东西创建你的HTML对象
查查document.createDocumentFragment()的用法。

以上会让你的代码快上一点吧。嗯,我认为应该是的。

87,901

社区成员

发帖
与我相关
我的任务
社区描述
Web 开发 JavaScript
社区管理员
  • JavaScript
  • 无·法
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧