<!doctype html>
<title>树 by 司徒正美</title>
<meta charset="utf-8"/>
<meta name="keywords" content="树 by 司徒正美" />
<meta name="description" content="树 by 司徒正美" />
<h2>树 by 司徒正美</h2>
<script type="text/javascript">
Tree = function(){
this.path = "http://images.cnblogs.com/cnblogs_com/rubylouvre/205314/o_";
this.name = "tree";
this.id = + new Date + parseInt(Math.random()*100000);
this.initialize.apply(this, arguments);
}
Tree.prototype = {
constructor : Tree,
initialize : function(config){
var me = this, renderTo = config.renderTo;
me.tree = config.data;
me.container = ((typeof renderTo === "string") ?
document.getElementById(renderTo) : renderTo) || document.body;
me.panel = document.createElement("div");
me.panel.setAttribute("id","tree" + me.id)
me.container.insertBefore(me.panel,null);
var id = "#"+me.panel.id;
var sheet = document.createElement('style');
sheet.type = 'text/css';
document.getElementsByTagName('head')[0].appendChild(sheet);
var bg = "background:transparent url("+me.path;
var cssCode = id +" {font-size:12px;}\n" +
id+" img {border:0;vertical-align: middle;}\n" +
id+" span {vertical-align: bottom;}\n"+
id+" .line {padding-left:18px;"+bg+"line.gif) repeat-y 0 0;}\n"+
id+" .blank {margin-left:18px;}\n"+
id+" img.collapse {padding-right:18px;"+bg+"folder.gif) no-repeat right center;}\n"+//控制枝节点的装饰图标(闭合)
id+" img.unfold {padding-right:18px;"+bg+"folderopen.gif) no-repeat right center;}\n"+//控制枝节点的装饰图标(展开)
id+" img.root {padding-right:18px;"+bg+"root.gif) no-repeat right center;}\n"+ //控制根节点的装饰图标
id+" img.leaf {padding-right:18px;"+bg+"leaf.gif) no-repeat right center;}\n" //控制叶节点的装饰图标
if(!+"\v1"){
sheet.styleSheet.cssText = cssCode
}else if(/a/[-1]=='a'){
sheet.innerHTML = cssCode
}else{
sheet.appendChild(document.createTextNode(cssCode));
}
//添加根节点
var icon = me.makeImage("nolines_plus","collapse root")
var checkbox0 = me.makeImage("checkbox_0","checkbox_0");
me.panel.innerHTML = me.makeTree(me.tree[0][0],"b",0,icon+checkbox0, me.tree[0][2]);
me.childs = [];
me.checks = [];//由来装载点击数
me.panel.onclick = function(e){
e = e || window.event;
var node = e.srcElement ? e.srcElement : e.target;
var current = node.parentNode;
var currentIndex = current.getAttribute("index");
var currentPrefix = current.getAttribute("prefix");
var currentLevel = current.getAttribute("level");
var subtree = me.getSubtree(currentIndex);
var children = current.children[3];
//添加子树集合
//存在子树并且没有添加时才添加
if(subtree && !children){
children = document.createElement("div");
var childs = [];
for(var i=0,length = subtree.length;i<length;i++){
var isLimb = me.hasSubtree(subtree[i][0]);
var isLast = (i == subtree.length - 1);
var prefix = isLast ? "blank" : "line";
icon = isLast ? "plusbottom" : "plus";
if(isLimb){
icon = me.makeImage(icon,"collapse limb");//枝节点前面的装饰图标
}else{
icon = icon.replace(/plus/, "join");//叶子节点前面的连线图标
icon = me.makeImage(icon,"leaf");//叶子节点前面的装饰图标
}
childs.push(subtree[i][0])
children.innerHTML += me.makeTree(subtree[i][0],prefix,+currentLevel+1,icon+checkbox0,subtree[i][2])
}
me.childs[currentIndex] = childs;
children.className = (currentPrefix == "line") ? "line": "blank";
current.insertBefore(children,null);
}
if(/collapse/.test(node.className)){//如果点击是加号或减号图标
node.src = node.src.replace(/plus/,"minus");//改变连线图标
node.className = node.className.replace("collapse","unfold");//改变装饰图标
children &&(children.style.display = "block");
}else if(/unfold/.test(node.className)){
node.src = node.src.replace(/minus/,"plus");//改变连线图标
node.className = node.className.replace("unfold","collapse");//改变装饰图标
children &&(children.style.display = "none");
}
if(/checkbox/.test(node.className)){//如果单击的是checkbox图标
var checked = me.isChecked(node);//如果是true则--,如果是false则++
me.setPriorCheckbox(current,checked);//一开始肯定是checkbox,返回false
me.setJuniorCheckbox(current,checked)
}
}
},
setJuniorCheckbox : function(node,/*Boolean*/checked){
var checkbox = node.children[1];
var replaceCheckbox = checked ? "checkbox_0" :"checkbox_1";
checkbox.src = checkbox.src.replace(/checkbox_\d/,replaceCheckbox);
checkbox.className = replaceCheckbox;
var index = node.getAttribute("index");
if(!!this.childs[index]){
var length = this.childs[index].length;
this.checks[index] = checked ? length : 0;
if(length > 0){
var children = node.children[3].children;
while(--length >= 0){
this.setJuniorCheckbox(children[length],checked)
}
}
}
},
setPriorCheckbox :function(node,/*Boolean*/checked){//设置上一级树的checkbox
var index = node.getAttribute("index");
var prior = node.parentNode.parentNode;
var priorIndex = this.tree[index][1];
var priorCheckbox = prior.children[1];
var priorLevel = prior.getAttribute("level");
var priorCount = this.checks[priorIndex] || 0;
checked ? priorCount-- : priorCount++;
(priorCount < 0) && (priorCount = 0)
this.checks[priorIndex] = priorCount;
if(!!priorCheckbox){
//当priorIndex等于-1时,
//priorCheckbox不存在
//me.childs[priorIndex]为undefined,不存在长度
checked = (priorCount == this.childs[priorIndex].length);
var replaceCheckbox = checked ? "checkbox_1" : "checkbox_2";
//checkbox_1为全选,checkbox_2为非全选
//全选,则让上级++,即让checked为false
priorCheckbox.src = priorCheckbox.src.replace(/checkbox_\d/,replaceCheckbox);//????????
priorCheckbox.className = replaceCheckbox;
}
if(priorLevel > 0){ //根节点没有priorCheckbox,且priorLevel等于-1
this.setPriorCheckbox(prior,checked);
}
},
isChecked : function(node){//如果是checkbox_0返回false,checkbox_1与checkbox_2返回true
return node.src.slice(-5,-4) > 0;
},
makeImage : function(image){
var status ="";
if(arguments[1] != null){
status = "class='" + arguments[1] +"'";
}
return "<img src='"+this.path+image+".gif' "+status+" />"
},
makeTree : function(index,prefix,level,images,text){
var builder = [];
builder.push("<div index='");
builder.push(index);
builder.push("' prefix='")
builder.push(prefix);
builder.push("' level='")
builder.push(level);
builder.push("'>");
builder.push(images);
builder.push("<span>");
builder.push(text);
builder.push("</span></div>")
return builder.join('');
},
hasSubtree : function (p){
var tree = this.tree;
for(var i = 0,length = tree.length;i < length; i++){
if(this.tree[i][1] == p){
return true;
};
};
return false;
},
getSubtree : function (p){
var subtree = [],tree = this.tree;
for(var i = 0,length = tree.length;i < length; i++){
if(tree[i][1] == p){
subtree.push(tree[i]);
};
};
return subtree
}
}
var data = [
[0,-1,"前台技术"],
[1,0,"表现层"],
[2,1,"CSS"],
[3,2,"CSS资源"],
[4,2,"CSS3前瞻"],
[5,1,"web标准知识"],
[6,1,"图形"],
[7,6,"SVG"],
[8,6,"VML"],
[9,6,"canvas"],
[10,0,"结构层"],
[11,10,"HTML"],
[12,10,"微格式"],
[13,10,"XML"],
[14,13,"XPath"],
[15,0,"行为层"],
[16,15,"core"],
[17,16,"变量与参数"],
[18,16,"对象与继承"],
[19,16,"函数与闭包"],
[20,16,"算法"],
[21,16,"高级技术"],
[22,21,"跨域请求"],
[23,21,"提速技术"],
[24,21,"本地存储"],
[25,21,"函数劫持"],
[26,16,"框架设计"],
[27,26,"Ext"],
[28,26,"dojo"],
[29,26,"mootools"],
[30,15,"Ajax"],
[31,15,"DOM"],
[32,15,"BOM"]
]
window.onload = function(){
var tree = new Tree({renderTo:"test",data:data});
}
</script>
<div id="test"></div>