页面效果
js树状目录.png
js
//定义树节点
function Node(id,pid,name,icon,iconOpen,open){
this.id = id; //该节点的id
this.pid = pid; //该节点的父id
this.name = name; //该节点显示的名字
this.icon = icon; //该节点未展开时的图标
this.iconOpen = iconOpen; //该节点展开时的图标
this.co = open || false; //该节点是否展开(close/open),默认是false
this.last = false; //该节点是否是同级节点中最后一个,用来判断返回递归的上一层
this.hc = false; //该节点是否含有孩子节点(hasChild)
this.index = 0; //该节点在全局数组中的下标
this.parent; //该节点的父节点
}
//定义树对象
function Tree(objName){
//配置
this.config={
useIcons: false, //文件夹图标
useLines: false, //缩进线
checkbox: false, //复选框
checkName: objName //复选框的name,默认是对象名
};
//图标
this.icon = {
root: 'img/base.gif',
floder: 'img/folder.gif',
floderOpen:'img/folderopen.gif',
node: 'img/page.gif',
line: 'img/line.gif',
empty: 'img/empty.gif',
nlMinus:'img/nolines_minus.gif', //无线的-号
nlPlus: 'img/nolines_plus.gif', //无线的+号
minusBottom:'img/minusbottom.gif',
plusBottom: 'img/plusbottom.gif',
minus: 'img/minus.gif',
plus: 'img/plus.gif',
join: 'img/join.gif',
joinBottom: 'img/joinbottom.gif'
}
this.obj = objName; //当前对象名字,通过这个名字生成id
this.nodes = new Array(); //保存树节点的数组
this.root = new Node(-1); //根节点
this.indent = new Array(); //缩进的个数
}
//添加一个节点对象
Tree.prototype.add = function(id,pid,name,icon,iconOpen,open){
//把节点存入数组中
this.nodes[this.nodes.length] = new Node(id,pid,name,icon,iconOpen,open);
}
//当执行document.write(Tree的对象)语句时会执行toString函数
Tree.prototype.toString = function(){
var str = '<div class="dtree">\n';
str += this.addNode(this.root);
str += '</div>';
return str;
}
//添加一个节点
Tree.prototype.addNode = function(pNode){
var str = ''; //拼接html的字符串
var n = 0; //下标
for(n;n<this.nodes.length;n++){
if(this.nodes[n].pid == pNode.id){ //找到当前节点的子节点进行处理
var cn = this.nodes[n]; //把找到的子节点赋给cn(childNode)
cn.parent = pNode; //设置该节点的父节点
cn.index = n; //设置该节点的数组下标
this.setHc(cn); //设置该节点是否含有子节点
str += this.node(cn,n); //拼接树
if(cn.last){ //如果当前节点是最后一个节点,则返回上一层递归
break;
}
}
}
return str;
}
//查看当前节点是否含有子节点
Tree.prototype.setHc = function(node){
var lastId;
for(var n=0;n<this.nodes.length;n++){
if(node.id == this.nodes[n].pid){ //如果有子节点,设置成true
node.hc = true;
}
if(node.pid == this.nodes[n].pid){ //
lastId = this.nodes[n].id;
}
}
if(node.id == lastId){ //当前节点是否是同级节点中最后一个节点
node.last = true;
}
}
//
Tree.prototype.node = function(node,n){
var str = '<div class="dtreeNode">' + this.getIndent(node,n); //第一次getIndent是空的,用空白图片占位来缩进
if(this.config.useIcons){
if(!node.icon){ //没展开时图标
node.icon = (node.hc) ? this.icon.floder : this.icon.node;
}
if(!node.iconOpen){ //展开时图标
node.iconOpen = (node.hc) ? this.icon.floderOpen : this.icon.node;
}
if(node.pid == this.root.id){ //根节点的图标
node.icon = this.icon.floder;
node.iconOpen = this.icon.floder;
}
//判断根据node.cn的设置来使用图标
str += '<img id="i'+ this.obj + n +'" src="'+((node.co) ? node.iconOpen : node.icon)+'" alt="" />';
}
if(this.config.checkbox){ //是否有复选框
str += '<input type="checkbox" id="c'+this.obj + node.id +'" value="'+node.id+'" name="'+this.config.checkName+'" onclick="'+this.obj+'.clickCheckbox('+node.id+','+node.pid+');" style="vertical-align:middle"/>';
}
str += node.name; //节点的名字
str += '</div>';
//判断有没有子节点,如果有则递归调用addNode,把一个节点的所有子节点处理完再处理其他节点
if(node.hc){
str += '<div id="d'+ this.obj + n +'" class="clip" style="display:'+((this.root.id == node.pid || node.co)?'block':'none')+'">';
str += this.addNode(node);
str += '</div>';
}
this.indent.pop(); //返回一层,删除一个数组元素
return str;
}
//节点的缩进
Tree.prototype.getIndent = function(node,nodeId){
var str = '';
if(this.root.id != node.pid){ //判断当前节点的是否是根节点的子节点,如果是,则没有缩进
for(var n=0;n<this.indent.length;n++){
str += '<img src="'+((this.indent[n] == 1 && this.config.useLines) ? this.icon.line : this.icon.empty)+'"/>'
}
(node.last) ? this.indent.push(0) : this.indent.push(1); //递归一层,添加一个数组元素,用来识别使用几个缩进
if(node.hc){ //是否有子节点
str += '<a href="javascript:'+ this.obj +'.toggle('+ nodeId +');"><img id="j'+ this.obj + nodeId +'" src="';
if(!this.config.useLines){
str += (node.co) ? this.icon.nlMinus : this.icon.nlPlus;
}else{
str += ((node.co) ? ((node.last) ? this.icon.minusBottom : this.icon.minus) : ((node.last) ? this.icon.plusBottom : this.icon.plus));
}
str += '" alt="" /></a>';
}else{
str += '<img src="' + ((this.config.useLines) ? ((node.last) ? this.icon.joinBottom : this.icon.join) : this.icon.empty) + '" alt="" />';
}
}
return str;
}
//展开或关闭节点
Tree.prototype.toggle = function(id){
var cn = this.nodes[id];
this.nodeStatus(!cn.co,id,cn.last);
cn.co = !cn.co; //修改co的状态
}
//修改展开和关闭状态的图标
Tree.prototype.nodeStatus = function(co,id,last) {
var eDiv = document.getElementById("d" + this.obj + id); //一个节点div对象
var eJion = document.getElementById("j" + this.obj + id); //加减号img对象
if(this.config.useIcons){
eIcon = document.getElementById('i' + this.obj + id); //文件夹图标img对象
eIcon.src = (co) ? this.nodes[id].iconOpen : this.nodes[id].icon;
}
//先判断用不用线,要是用线的话,并且是同级最后一个节点,则没有下边的线
eJion.src = (this.config.useLines) ?
((co)?((last)?this.icon.minusBottom:this.icon.minus):((last)?this.icon.plusBottom:this.icon.plus)) :
((co)?this.icon.nlMinus:this.icon.nlPlus);
eDiv.style.display = (co) ? 'block' : 'none'; //节点的div标签显示或关闭
}
//点击复选框事件
Tree.prototype.clickCheckbox = function(id,pid){
var bo = document.getElementById("c"+this.obj+id); //多选框对象
for(var i=0;i<this.nodes.length;i++){
if(this.nodes[i].pid == id){ //把当前节点的子节点选中或取消
document.getElementById("c"+this.obj+this.nodes[i].id).checked = bo.checked;
this.clickCheckbox(this.nodes[i].id,this.nodes[i].pid); //递归调用
}
}
}
html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>js树状目录</title>
<link type="text/css" rel="stylesheet" href="dtree.css"/>
<script type="text/javascript" src="shztree.js"></script>
</head>
<body>
<h2>树</h2>
<input type="button" id="btn" value="提交"/>
<script>
var tree = new Tree("tree");
tree.add(0,-1,'My root tree');
tree.add(1,0,'Node 1');
tree.add(2,0,'Node 2');
tree.add(3,1,'Node 1.1');
tree.add(4,3,'Node 1.1.1');
tree.add(5,2,'Node 2.1');
tree.add(6,2,'Node 2.2');
tree.add(7,0,'Node 3');
tree.add(8,7,'Node 3.1');
tree.add(9,3,'Node 1.1.2');
/* for(var i=0;i<array.length;i++){ //从后台传过来一个array
tree.add(array[i].id,array[i].pid,array[i].name);
} */
tree.config.useLines = true;
tree.config.checkbox = true;
tree.config.useIcons = true;
document.write(tree);
document.getElementById("btn").onclick = function(){
var check = document.getElementsByName("tree");
var idsTmp = '';
for(var i=0;i<check.length;i++){
if(check[i].checked == true){
idsTmp = idsTmp + check[i].value +",";
}
}
var ids = idsTmp.substr(0,idsTmp.length-1);
alert(ids);
}
</script>
</body>
</html>
css
.dtree {
font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;
font-size: 11px;
color: #666;
white-space: nowrap;
}
.dtree img {
border: 0px;
vertical-align: middle;
}
.dtree a {
color: #333;
text-decoration: none;
}
.dtree a.node, .dtree a.nodeSel {
white-space: nowrap;
padding: 1px 2px 1px 2px;
}
.dtree a.node:hover, .dtree a.nodeSel:hover {
color: #333;
text-decoration: underline;
}
.dtree a.nodeSel {
background-color: #c0d2ec;
}
.dtree .clip {
overflow: hidden;
}
网友评论