sunlei 发表于 2005 年 12 月 19 日 19:44:13

[转]js练习“树”,读取xml数据(无层次,结构简单),兼容ie&mf

最近看到大家都练习写树,偶也学习学习写了一个,大家多多批评,我好进步,呵呵
不过我看了一些树的xml文档都是在xml中就已经有了树的结构,所以我写了一个xml文档不用分层,来生成树的,不过要给每个节点定义编号和父编号

写得有点糙,大家不要笑话,以后逐渐学习在改进

演示地址: www.lapuasi.com/javascript/xmltree

使用方法:
var tree = new xmlTree('tree'); //生成对象
tree.mode = 1; //设置初始模式,默认全部关闭。0全部关闭,1全部展开
tree.createTree(); //输出树

Javascript代码:
/*
xmlTree v1.1
=================================

Infomation
----------------------
Author   : Lapuasi
E-Mail   : lapuasi@gmail.com
WebSite: http://www.lapuasi.com/javascript
DateTime : 2005-12-14


Example
----------------------
var tree = new xmlTree('tree'); //生成对象
tree.mode = 1; //设置初始模式,默认全部关闭。0全部关闭,1全部展开
tree.createTree(); //输出树


for Internet Explorer, Mozilla Firefox
*/


function xmlTree(name) {
 this.name     = name;       //实例名称
 this.xmlFile    = 'xmltree.xml';    //默认xml文件
 this.iconPath     = 'images/'       //默认图标路径
 this.iconFolder   = 'tree_icon_folder.gif'; //默认文件夹图标
 this.iconFile     = 'tree_icon_file.gif';   //默认文件图标
 this.iconOpen     = 'tree_arrow_open.gif';//默认箭头展开图标
 this.iconOver     = 'tree_arrow_over.gif';//默认箭头活动图标
 this.iconClose  = 'tree_arrow_close.gif'; //默认箭头关闭图标
 this.mode     = 0;        //初始模式,默认全部关闭。0全部关闭,1全部展开
 this.html     = '';         //最终输出html代码
 this.prevTip    = null;       //上一次被显示的tip的时间编号 (内部使用)
 this.prevSelected = null;       //上一次被选中的节点的自动编号 (内部使用)
}

xmlTree.prototype.createXMLDOM = function() { //生成XMLDOM对象
 var xmldom;
 if (window.ActiveXObject){
     var xmldom = new ActiveXObject("Microsoft.XMLDOM");
 } 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;
}

xmlTree.prototype.createTree = function() { //生成并打印
 var xmldom = this.createXMLDOM();
 document.write('<div id="tree">Loading...<\/div>'); // 树所用层
 document.write('<div id="treeTip"><\/div>'); //提示所用层
 document.getElementById('treeTip').style.visibility = 'visible';
 document.getElementById('treeTip').style.display = 'none';
 if (xmldom.load(this.xmlFile)) {
     this.createNodes(xmldom);
 } else {
     this.html = 'Load XML Error';
 }
 document.getElementById('tree').innerHTML = this.html;
 return;
}

xmlTree.prototype.getFirstChildData = function(obj, name) { //取得指定名称节点的第一个子节点的数据
 var result = '';
 if (typeof(obj) == 'object' && name != null && name != '') {
     var node = obj.getElementsByTagName(name);
     if (node != null && node.length > 0) {
     result = node.firstChild.data;
     }
 }
 return result;
}

xmlTree.prototype.checkChildNodes = function(obj, id) { //检测是否有分支
 var result = false;
 var nodes = obj.getElementsByTagName('node');
 if (nodes != null && nodes.length > 0) {
     var pid;
     for (var i = 0; i < nodes.length; i++) {
     pid = parseInt(nodes.getAttribute('parentid'));
     if (isNaN(pid)) pid = 0;
     if (!isNaN(pid) && pid == id) {
     result = true;
     break;
     }
     }
 }
 return result;
}

xmlTree.prototype.createNodes = function(obj, id) { //生成指定编号节点的树
 if (typeof(id) == 'undefined' || isNaN(parseInt(id))) id = 0;
 var nodes = obj.getElementsByTagName('node');
 if (nodes != null && nodes.length > 0) {
     var modeClass, modeSrc, iconClass, iconSrc;
     var nid, npid, nname, nicon, nlink, nexplain, hasChildNodes;
     
     //判断模式类型,并应用样式
     modeClass = 'close';
     modeSrc = this.iconPath + this.iconClose;
     if (this.mode == 1) {
     modeSrc = this.iconPath + this.iconOpen;
     modeClass = 'open';
     }
     if (parseInt(id) == 0) modeClass = 'open';
     this.html += '<ul id="tree_' + id + '_c" class="' + modeClass + '">';

     for (var i = 0; i < nodes.length; i++) {
     npid = parseInt(nodes.getAttribute('parentid'));
     if (isNaN(npid)) npid = 0;
     if (npid == id) {
     //初始化
     modeClass = 'close'; iconClass = 'icon-file'; iconSrc = this.iconPath + this.iconFile;

     //取得节点编号并检测
     nid = parseInt(nodes.getAttribute('id'));
     if (isNaN(nid)) break;
     this.html += '<li id="tree_' + nid + '"><span onclick="' + this.name + '.action(this,event);" onmouseover="' + this.name + '.action(this,event);" onmouseout="' + this.name + '.action(this,event);">';
     
     //取得节点自定义图标
     //判断是否含有子节点,并确定箭头和图标的图片及样式
     nicon = this.getFirstChildData(nodes, 'icon');
     hasChildNodes = this.checkChildNodes(obj, nid);
     if (hasChildNodes) {
         iconClass = '';
         iconSrc = this.iconPath + this.iconFolder;
         this.html += '<img id="tree_' + nid + '_a" src="' + modeSrc + '" class="arrow" \/>'; //箭头
     }
     if (nicon != '') iconSrc = nicon;
     this.html += '<img id="tree_' + nid + '_i" src="' + iconSrc + '" class="' + iconClass + '" \/>'; //图标

     //取得节点名称,连接,说明
     nname = this.getFirstChildData(nodes, 'name');
     nlink = this.getFirstChildData(nodes, 'link');
     nexplain = this.getFirstChildData(nodes, 'explain');
     if (nexplain != '') {
         nexplain = '\'' + nexplain + '\'';
         nexplain = 'onmouseover="' + this.name + '.treeTips(' + nexplain + ');window.status = \'\';return true;" onmouseout="' + this.name + '.treeTips();"'
     }
     this.html += '<a id="tree_' + nid + '_l" href="#" onclick="' + this.name + '.action(this,event);" ' + nexplain + '>' + nname + '<\/a><\/span>';

     //obj.documentElement.removeChild(nodes);
     if (hasChildNodes) this.createNodes(obj, nid); //迭代子节点

     this.html += '<\/li>';
     }
     }
     this.html += '<\/ul>';
 }
 return;
}

xmlTree.prototype.action = function(obj, e) { //节点操作
 e = e ? e : (window.event ? window.event : null); //获取操作类型
 e = e.type;
 if (obj.tagName == 'A') {
     try { this.prevSelected.className = '';}
     catch(e) {}
     this.prevSelected = obj;
     obj.className = 'selected';
 }
 if (obj.tagName == 'SPAN') {
     var arrow = obj.firstChild; //取得箭头对象
     var borther = obj;
     while (borther.tagName != 'UL') { //取得分支对象
     borther = borther.nextSibling;
     if (borther == null) break;
     }
     if (borther != null) {
     switch (e) { //检测操作类型并执行相应代码
     case 'click':
         if (borther.className == 'open') {
         borther.className = 'close';
         arrow.src = this.iconPath + this.iconClose;
         } else {
         borther.className = 'open';
         arrow.src = this.iconPath + this.iconOpen;
         }
         break;
     case 'mouseover':
         if (arrow.tagName == 'IMG' && borther.className == 'close') {
         arrow.src = this.iconPath + this.iconOver;
         }
         break;
     case 'mouseout':
         if (arrow.tagName == 'IMG' && borther.className == 'close') {
         arrow.src = this.iconPath + this.iconClose;
         }
         break;
     }
     }
 }
 return;
}

xmlTree.prototype.treeTips = function(msg) { //提示栏
 if (this.prevTip != null) clearTimeout(this.prevTip);
 var obj = document.getElementById('treeTip');
 if (obj != null) {
     if (this.treeTips.arguments.length < 1) { // hide
     obj.style.display = 'none';
     } else { // show
     obj.innerHTML = msg;
     this.prevTip = setTimeout('document.getElementById("treeTip").style.display = "block"',300);
     document.onmousemove = this.moveToMouseLoc;
     }
 }
 return;
}

xmlTree.prototype.moveToMouseLoc = function(e) { //移动到鼠标所在位置
 var obj = document.getElementById('treeTip');
 if (obj != null) {
     var offsetX = -10, offsetY = 20;
     var x = 0, y = 0;
     if (window.event) {
     x = event.x + document.body.scrollLeft;
     y = event.y + document.body.scrollTop;
     } else {
     x = e.pageX;
     y = e.pageY;
     }
     obj.style.left = x + offsetX + 'px';
     obj.style.top = y + offsetY + 'px';
 }
 return;
}

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

<!--
CODE BY Lapuasi.com

Explain:
===================================================
node 为树的一个节点,具有以下属性和内容
 属性
     id: 编号,如果不唯一,只取第一个,其余被忽略 (必须)
     parentid: 父编号,没有则为父节点 (可选)
 内容
     name: 名称 (必须)
     link: 连接 (可选)
     icon: 图标 (可选)
     explain: 说明 (可选)
-->

<root>
 <node id="1">
     <name>我的电脑</name>
     <icon>images/tree_icon_computer.gif</icon>
     <explain>显示连接到此计算机的驱动器和硬件</explain>
 </node>
 <node id="2" parentid="1">
     <name>硬盘驱动器 (C:)</name>
     <icon>images/tree_icon_driver.gif</icon>
 </node>
 <node id="3">
     <name>网上邻居</name>
     <icon>images/tree_icon_net.gif</icon>
     <explain>显示到网站,网络计算机和FTP站点的快捷方式</explain>
 </node>
 <node id="4" parentid="1">
     <name>硬盘驱动器 (D:)</name>
     <icon>images/tree_icon_driver.gif</icon>
 </node>
 <node id="5" parentid="2">
     <name>Windows</name>
 </node>
 <node id="6" parentid="3">
     <name>menu6</name>
 </node>
 <node id="7" parentid="3">
     <name>menu7</name>
 </node>
 <node id="8" parentid="3">
     <name>menu8</name>
 </node>
 <node id="9" parentid="7">
     <name>menu9</name>
 </node>
 <node id="10">
     <name>回收站</name>
     <icon>images/tree_icon_recycler.gif</icon>
     <explain>包含您已经删除的文件和文件夹</explain>
 </node>
 <node id="11" parentid="5">
     <name>system32</name>
 </node>
 <node id="12" parentid="11">
     <name>system.dll</name>
 </node>
 <node id="13" parentid="7">
     <name>menu13</name>
 </node>
 <node id="14" parentid="1">
     <name>DVD 驱动器</name>
     <icon>images/tree_icon_cdrom.gif</icon>
 </node>
</root>

esnak 发表于 2005 年 12 月 20 日 00:42:39

记得以前有个asp.net的树很牛X,据说能几千层

winsock 发表于 2005 年 12 月 20 日 13:51:13

OMG.......................

xchange 发表于 2005 年 12 月 20 日 15:19:30

我想要能解析RSS的

sunlei 发表于 2005 年 12 月 19 日 19:44:13

[转]js练习“树”,读取xml数据(无层次,结构简单),兼容ie&mf

最近看到大家都练习写树,偶也学习学习写了一个,大家多多批评,我好进步,呵呵
不过我看了一些树的xml文档都是在xml中就已经有了树的结构,所以我写了一个xml文档不用分层,来生成树的,不过要给每个节点定义编号和父编号

写得有点糙,大家不要笑话,以后逐渐学习在改进

演示地址: www.lapuasi.com/javascript/xmltree

使用方法:
var tree = new xmlTree('tree'); //生成对象
tree.mode = 1; //设置初始模式,默认全部关闭。0全部关闭,1全部展开
tree.createTree(); //输出树

Javascript代码:
/*
xmlTree v1.1
=================================

Infomation
----------------------
Author   : Lapuasi
E-Mail   : lapuasi@gmail.com
WebSite: http://www.lapuasi.com/javascript
DateTime : 2005-12-14


Example
----------------------
var tree = new xmlTree('tree'); //生成对象
tree.mode = 1; //设置初始模式,默认全部关闭。0全部关闭,1全部展开
tree.createTree(); //输出树


for Internet Explorer, Mozilla Firefox
*/


function xmlTree(name) {
 this.name     = name;       //实例名称
 this.xmlFile    = 'xmltree.xml';    //默认xml文件
 this.iconPath     = 'images/'       //默认图标路径
 this.iconFolder   = 'tree_icon_folder.gif'; //默认文件夹图标
 this.iconFile     = 'tree_icon_file.gif';   //默认文件图标
 this.iconOpen     = 'tree_arrow_open.gif';//默认箭头展开图标
 this.iconOver     = 'tree_arrow_over.gif';//默认箭头活动图标
 this.iconClose  = 'tree_arrow_close.gif'; //默认箭头关闭图标
 this.mode     = 0;        //初始模式,默认全部关闭。0全部关闭,1全部展开
 this.html     = '';         //最终输出html代码
 this.prevTip    = null;       //上一次被显示的tip的时间编号 (内部使用)
 this.prevSelected = null;       //上一次被选中的节点的自动编号 (内部使用)
}

xmlTree.prototype.createXMLDOM = function() { //生成XMLDOM对象
 var xmldom;
 if (window.ActiveXObject){
     var xmldom = new ActiveXObject("Microsoft.XMLDOM");
 } 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;
}

xmlTree.prototype.createTree = function() { //生成并打印
 var xmldom = this.createXMLDOM();
 document.write('<div id="tree">Loading...<\/div>'); // 树所用层
 document.write('<div id="treeTip"><\/div>'); //提示所用层
 document.getElementById('treeTip').style.visibility = 'visible';
 document.getElementById('treeTip').style.display = 'none';
 if (xmldom.load(this.xmlFile)) {
     this.createNodes(xmldom);
 } else {
     this.html = 'Load XML Error';
 }
 document.getElementById('tree').innerHTML = this.html;
 return;
}

xmlTree.prototype.getFirstChildData = function(obj, name) { //取得指定名称节点的第一个子节点的数据
 var result = '';
 if (typeof(obj) == 'object' && name != null && name != '') {
     var node = obj.getElementsByTagName(name);
     if (node != null && node.length > 0) {
     result = node.firstChild.data;
     }
 }
 return result;
}

xmlTree.prototype.checkChildNodes = function(obj, id) { //检测是否有分支
 var result = false;
 var nodes = obj.getElementsByTagName('node');
 if (nodes != null && nodes.length > 0) {
     var pid;
     for (var i = 0; i < nodes.length; i++) {
     pid = parseInt(nodes.getAttribute('parentid'));
     if (isNaN(pid)) pid = 0;
     if (!isNaN(pid) && pid == id) {
     result = true;
     break;
     }
     }
 }
 return result;
}

xmlTree.prototype.createNodes = function(obj, id) { //生成指定编号节点的树
 if (typeof(id) == 'undefined' || isNaN(parseInt(id))) id = 0;
 var nodes = obj.getElementsByTagName('node');
 if (nodes != null && nodes.length > 0) {
     var modeClass, modeSrc, iconClass, iconSrc;
     var nid, npid, nname, nicon, nlink, nexplain, hasChildNodes;
     
     //判断模式类型,并应用样式
     modeClass = 'close';
     modeSrc = this.iconPath + this.iconClose;
     if (this.mode == 1) {
     modeSrc = this.iconPath + this.iconOpen;
     modeClass = 'open';
     }
     if (parseInt(id) == 0) modeClass = 'open';
     this.html += '<ul id="tree_' + id + '_c" class="' + modeClass + '">';

     for (var i = 0; i < nodes.length; i++) {
     npid = parseInt(nodes.getAttribute('parentid'));
     if (isNaN(npid)) npid = 0;
     if (npid == id) {
     //初始化
     modeClass = 'close'; iconClass = 'icon-file'; iconSrc = this.iconPath + this.iconFile;

     //取得节点编号并检测
     nid = parseInt(nodes.getAttribute('id'));
     if (isNaN(nid)) break;
     this.html += '<li id="tree_' + nid + '"><span onclick="' + this.name + '.action(this,event);" onmouseover="' + this.name + '.action(this,event);" onmouseout="' + this.name + '.action(this,event);">';
     
     //取得节点自定义图标
     //判断是否含有子节点,并确定箭头和图标的图片及样式
     nicon = this.getFirstChildData(nodes, 'icon');
     hasChildNodes = this.checkChildNodes(obj, nid);
     if (hasChildNodes) {
         iconClass = '';
         iconSrc = this.iconPath + this.iconFolder;
         this.html += '<img id="tree_' + nid + '_a" src="' + modeSrc + '" class="arrow" \/>'; //箭头
     }
     if (nicon != '') iconSrc = nicon;
     this.html += '<img id="tree_' + nid + '_i" src="' + iconSrc + '" class="' + iconClass + '" \/>'; //图标

     //取得节点名称,连接,说明
     nname = this.getFirstChildData(nodes, 'name');
     nlink = this.getFirstChildData(nodes, 'link');
     nexplain = this.getFirstChildData(nodes, 'explain');
     if (nexplain != '') {
         nexplain = '\'' + nexplain + '\'';
         nexplain = 'onmouseover="' + this.name + '.treeTips(' + nexplain + ');window.status = \'\';return true;" onmouseout="' + this.name + '.treeTips();"'
     }
     this.html += '<a id="tree_' + nid + '_l" href="#" onclick="' + this.name + '.action(this,event);" ' + nexplain + '>' + nname + '<\/a><\/span>';

     //obj.documentElement.removeChild(nodes);
     if (hasChildNodes) this.createNodes(obj, nid); //迭代子节点

     this.html += '<\/li>';
     }
     }
     this.html += '<\/ul>';
 }
 return;
}

xmlTree.prototype.action = function(obj, e) { //节点操作
 e = e ? e : (window.event ? window.event : null); //获取操作类型
 e = e.type;
 if (obj.tagName == 'A') {
     try { this.prevSelected.className = '';}
     catch(e) {}
     this.prevSelected = obj;
     obj.className = 'selected';
 }
 if (obj.tagName == 'SPAN') {
     var arrow = obj.firstChild; //取得箭头对象
     var borther = obj;
     while (borther.tagName != 'UL') { //取得分支对象
     borther = borther.nextSibling;
     if (borther == null) break;
     }
     if (borther != null) {
     switch (e) { //检测操作类型并执行相应代码
     case 'click':
         if (borther.className == 'open') {
         borther.className = 'close';
         arrow.src = this.iconPath + this.iconClose;
         } else {
         borther.className = 'open';
         arrow.src = this.iconPath + this.iconOpen;
         }
         break;
     case 'mouseover':
         if (arrow.tagName == 'IMG' && borther.className == 'close') {
         arrow.src = this.iconPath + this.iconOver;
         }
         break;
     case 'mouseout':
         if (arrow.tagName == 'IMG' && borther.className == 'close') {
         arrow.src = this.iconPath + this.iconClose;
         }
         break;
     }
     }
 }
 return;
}

xmlTree.prototype.treeTips = function(msg) { //提示栏
 if (this.prevTip != null) clearTimeout(this.prevTip);
 var obj = document.getElementById('treeTip');
 if (obj != null) {
     if (this.treeTips.arguments.length < 1) { // hide
     obj.style.display = 'none';
     } else { // show
     obj.innerHTML = msg;
     this.prevTip = setTimeout('document.getElementById("treeTip").style.display = "block"',300);
     document.onmousemove = this.moveToMouseLoc;
     }
 }
 return;
}

xmlTree.prototype.moveToMouseLoc = function(e) { //移动到鼠标所在位置
 var obj = document.getElementById('treeTip');
 if (obj != null) {
     var offsetX = -10, offsetY = 20;
     var x = 0, y = 0;
     if (window.event) {
     x = event.x + document.body.scrollLeft;
     y = event.y + document.body.scrollTop;
     } else {
     x = e.pageX;
     y = e.pageY;
     }
     obj.style.left = x + offsetX + 'px';
     obj.style.top = y + offsetY + 'px';
 }
 return;
}

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

<!--
CODE BY Lapuasi.com

Explain:
===================================================
node 为树的一个节点,具有以下属性和内容
 属性
     id: 编号,如果不唯一,只取第一个,其余被忽略 (必须)
     parentid: 父编号,没有则为父节点 (可选)
 内容
     name: 名称 (必须)
     link: 连接 (可选)
     icon: 图标 (可选)
     explain: 说明 (可选)
-->

<root>
 <node id="1">
     <name>我的电脑</name>
     <icon>images/tree_icon_computer.gif</icon>
     <explain>显示连接到此计算机的驱动器和硬件</explain>
 </node>
 <node id="2" parentid="1">
     <name>硬盘驱动器 (C:)</name>
     <icon>images/tree_icon_driver.gif</icon>
 </node>
 <node id="3">
     <name>网上邻居</name>
     <icon>images/tree_icon_net.gif</icon>
     <explain>显示到网站,网络计算机和FTP站点的快捷方式</explain>
 </node>
 <node id="4" parentid="1">
     <name>硬盘驱动器 (D:)</name>
     <icon>images/tree_icon_driver.gif</icon>
 </node>
 <node id="5" parentid="2">
     <name>Windows</name>
 </node>
 <node id="6" parentid="3">
     <name>menu6</name>
 </node>
 <node id="7" parentid="3">
     <name>menu7</name>
 </node>
 <node id="8" parentid="3">
     <name>menu8</name>
 </node>
 <node id="9" parentid="7">
     <name>menu9</name>
 </node>
 <node id="10">
     <name>回收站</name>
     <icon>images/tree_icon_recycler.gif</icon>
     <explain>包含您已经删除的文件和文件夹</explain>
 </node>
 <node id="11" parentid="5">
     <name>system32</name>
 </node>
 <node id="12" parentid="11">
     <name>system.dll</name>
 </node>
 <node id="13" parentid="7">
     <name>menu13</name>
 </node>
 <node id="14" parentid="1">
     <name>DVD 驱动器</name>
     <icon>images/tree_icon_cdrom.gif</icon>
 </node>
</root>
页: [1]
查看完整版本: [转]js练习“树”,读取xml数据(无层次,结构简单),兼容ie&mf