前两天想把无限联动改成颗树,好选择嘛,所以就写了点东西。
所需数据sortArr.js,每项最后一位表示是组还是元素:
var arrSorts = new Array(35);
arrSorts[0] = [1, "主类别一1", "0","0"];
arrSorts[1] = [2, "主类别二2", "0","0"];
arrSorts[2] = [3, "主类别三3", "0","1"];
arrSorts[3] = [4, "小类一4", "1","0"];
arrSorts[4] = [5, "小类二5", "1","0"];
arrSorts[5] = [6, "小类三6", "1","1"];
arrSorts[6] = [7, "细类一7", "4","0"];
arrSorts[7] = [8, "细类二8", "4","0"];
arrSorts[8] = [9, "细类三9", "4","1"];
arrSorts[9] = [10, "小类四10", "2","1"];
arrSorts[10] = [11, "小类五11", "2","1"];
arrSorts[11] = [12, "小类六12", "2","1"];
arrSorts[12] = [13, "细类四13", "5","1"];
arrSorts[13] = [14, "细类五14", "5","1"];
arrSorts[14] = [15, "末类一15", "7","0"];
arrSorts[15] = [16, "末类二16", "7","0"];
arrSorts[16] = [17, "末类三17", "7","0"];
arrSorts[17] = [18, "终极类一18", "15","1"];
arrSorts[18] = [19, "终极类二19", "15","1"];
arrSorts[19] = [20, "终极类三20", "15","1"];
arrSorts[20] = [21, "终极类四21", "16","1"];
arrSorts[21] = [22, "终极类五22", "16","1"];
arrSorts[22] = [23, "终极类六23", "16","1"];
arrSorts[23] = [24, "末类四24", "8","0"];
arrSorts[24] = [25, "末类五25", "8","1"];
arrSorts[25] = [26, "末类六26", "8","1"];
arrSorts[26] = [27, "末类七27", "9","0"];
arrSorts[27] = [28, "末类八28", "9","0"];
arrSorts[28] = [29, "末类九29", "9","0"];
arrSorts[29] = [30, "终极类七30", "17","1"];
arrSorts[30] = [31, "终极类八31", "17","1"];
arrSorts[31] = [32, "终极类九32", "17","1"];
arrSorts[32] = [33, "终极类十33", "24","1"];
arrSorts[33] = [34, "终极类十一34", "24","1"];
arrSorts[34] = [35, "终极类十二35", "24","1"];
arrSorts[35] = [36, "终极类十三36", "24","1"];
主要类tree.js:
/**
* 无限树形选择菜单类
* _containerName:显示该菜单的容器元素名称
* _dataArr:显示菜单所需的数组,格式如下
* 节点类型用于判断该节点是组还是成员
* arrSorts[0] = ["类别ID1", "类别一", "父类ID1","节点类型1"];
* arrSorts[1] = ["类别ID2", "类别二", "父类ID2","节点类型2"];
* 数组元素的第一项类别ID的数据类型与数据库中的一样,若为数字,则不加引号
* @author zxub 2005-10-09
*/
function tree(_containerName,_dataArr)
{
//加入样式
document.write('<style type="text/css">');
document.write('.treeCheckBox{height:11px; 11px;vertical-align:middle}');
document.write('.treeImg{cursor:hand;vertical-align:text-bottom;margin-right:2px}');
document.write('</style>');
//定义图标显示用数组
this.icon=new Array();
this.icon["member"]='img/member.gif';
this.icon["open"]='img/open.gif';
this.icon["close"]='img/close.gif';
/*this.icon["jointop"]='img/jointop.gif';
this.icon["joinmiddle"]='img/joinmiddle.gif';
this.icon["joinbottom"]='img/L.gif';
this.icon["plustop"]='img/plustop.gif';
this.icon["plusmiddle"]='img/plusmiddle.gif';
this.icon["plusbottom"]='img/plusbottom.gif';
this.icon["minustop"]='img/minustop.gif';
this.icon["minusmiddle"]='img/minusmiddle.gif';
this.icon["minusbottom"]='img/minusbottom.gif';
this.icon["line"]='img/line.gif';*/
//获取树结构所需父容器和数据
this.container=document.getElementById(_containerName);
this.dataArr=_dataArr;
//定义区分组和成员所用的值
this.groupValue=0;
this.memberValue=1;
/**
* 根据所取节点ID和子级所存放容器,生成该节点的下级选项
* _parentId:所取节点ID,对于子级选项来说,它是parentID。
* _container:用来存放子级选项的容器。
*/
this.setNode=function(_parentId,_container)
{
var length=this.dataArr.length;
//设置一个标记,若为false,说明没子级,则要删除自己容器。
var getChild=false;
//子级容器,所有子级选项都放一个容器中。
_nodeContainer=document.createElement("div");
_nodeContainer.id="_container"+_parentId;
//子级容器放入选项存放容器
_container.insertAdjacentElement("beforeEnd",_nodeContainer);
//遍历数组,获取子级
for (var i=0;i<length;i++)
{
if (this.dataArr[i][2] == _parentId)
{
getChild=true;
_node=document.createElement("div");
_node.style.cssText="padding-bottom:5px";
_node.innerHTML="";
//若所取为组
if (this.dataArr[i][3]==this.groupValue)
{
_node.innerHTML+='<input onFocus="this.blur()" onclick="setChildrenChecked(this);setParentChecked(this)" type="checkbox" class="treeCheckBox" name="group" id="'+this.dataArr[i][0]+'">';
//_node.innerHTML+='<img style="cursor:hand" src="'+this.icon["plusmiddle"]+'"/>';
_node.innerHTML+='<img class="treeImg" src="'+this.icon["close"]+'" onclick="changeShowStatus(this,this.parentNode.lastChild);"/>';
_node.innerHTML+='<span style="cursor:hand" onclick="this.previousSibling.click();">'+this.dataArr[i][1]+'</span>';
}
//否则若所取为成员
else if (this.dataArr[i][3]==this.memberValue)
{
_node.innerHTML+='<input onFocus="this.blur()" onclick="setParentChecked(this);" type="checkbox" class="treeCheckBox" name="member" id="'+this.dataArr[i][0]+'">';
//_node.innerHTML+='<img style="cursor:hand" src="'+this.icon["plusmiddle"]+'"/>';
_node.innerHTML+='<img class="treeImg" src="'+this.icon["member"]+'"/>';
_node.innerHTML+='<span style="cursor:hand" onclick="this.parentNode.firstChild.click();">'+this.dataArr[i][1]+'</span>';
}
//节点加入子级容器
_nodeContainer.insertAdjacentElement("beforeEnd",_node);
}
}
if (_parentId==this.dataArr[0][2])
{
_nodeContainer.style.cssText="margin-top:5px";
}
else
{
_nodeContainer.style.cssText="display:none;margin-left:18px;margin-top:5px";
}
//若没有子级,则删除子级容器
if (getChild==false)
{
_container.removeChild(_nodeContainer);
}
}
/**
* 获取一个容器中的所有子级对象(只是子级)
* _container:容器对象
*/
this.getChildren=function(_container)
{
var _children=_container.children;
return _children;
}
/**
* 根据容器中的选项,生成树结构
* _container:所取容器对象
*/
this.setTree=function(_container)
{
//获取容器中所有对象
var _root=this.getChildren(_container);
var length=_root.length;
//遍历容器中的对象
for (var i=0;i<length;i++)
{
//生成子级选项
this.setNode(_root[i].firstChild.id,_root[i]);
//递归完成整颗树
this.setTree(_root[i].lastChild);
}
}
//由于数组中数据的规则,第一个节点的父级节点必是其它节点的父级节点
//数组规则不再缀述,可参考无限分类所用数组介绍
//下面二句把整颗完整的树构造出来
this.setNode(this.dataArr[0][2],this.container);
this.setTree(this.container.firstChild);
}
/**
* 单击复选框后,图片变换处理
* obj复选框对象
*/
function changePic(obj)
{
obj.checked=(obj.checked==true?false:true);
//复选框的下一个兄弟对象则是图片
obj.nextSibling.src=(obj.checked==true?"img/open.gif":"img/close.gif");
//设置下级复选框的选择情况
setChildChecked(obj);
}
/**
* 改变下级选项的显示/隐藏,同时,改变图片的显示
* _pic:要改变的图片对象
* _div:要改变的选项容器对象
*/
function changeShowStatus(_pic,_div)
{
if (_div.tagName=="DIV")
{
_div.style.display=(_div.style.display=="none")?"":"none";
_pic.src=(_div.style.display=="none")?"img/close.gif":"img/open.gif";
}
}
/**
* 设置下级选项复选框的选择情况
* _obj:上级选项对应的复选框对象
*/
function setChildrenChecked(_obj)
{
var _checked=_obj.checked;
var _siblingDiv=_obj.parentNode.lastChild;
if (_siblingDiv.tagName=="DIV")
{
var _children=_siblingDiv.children;
var length=_children.length;
for (var i=0;i<length;i++)
{
_children[i].firstChild.checked=_checked;
setChildrenChecked(_children[i].firstChild);
}
}
}
/**
* 设置上级选项的选择情况
* _obj:选项所对应的复选框对象
*/
function setParentChecked(_obj)
{
//只有取消复选框选择时,父级选项的选择才要取消
if (_obj.checked==false)
{
//获取父级选项对应的复选框
var _parentCheckBox=_obj.parentNode.parentNode.parentNode.firstChild;
if (_parentCheckBox && _parentCheckBox.tagName=="INPUT" && _parentCheckBox.type=="checkbox")
{
_parentCheckBox.checked=false;
setParentChecked(_parentCheckBox);
}
}
}
/**
* childId和parentId对应的对象是否存在父子关系
* arr:所用数组
* 由于数组的特殊结构,做为子级的选项的id必然要大于父级选项的id
*/
function checkChild(childId,parentId,arr)
{
var returnValue=false;
var length=arr.length;
var pid=0;
for (i=0;i<length;i++)
{
if (arr[i][0]==childId)
{
pid=arr[i][2];
break;
}
else if (arr[i][0]>childId)
{
break;
}
}
//父级可能与parentId对应对象存在父子关系,故递归判断
if (pid>parentId)
{
returnValue=checkChild(pid,parentId,arr);
}
else if (pid==parentId)
{
returnValue=true;
}
return returnValue;
}
/**
* 获取页面一组Name一样的复选框选中项的值集合
* _groupName:组对象的名称
*/
function getGroupChoosed(_groupName)
{
var chooseValue=new Array;
var member=document.getElementsByName(_groupName);
var length=member.length;
for (var i=0;i<length;i++)
{
if (member[i].checked==true)
{
chooseValue.push(member[i].id);
}
}
return chooseValue;
}
测试页面test.htm:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
<HEAD>
<TITLE> New Document </TITLE>
<META NAME="Generator" CONTENT="EditPlus">
<META NAME="Author" CONTENT="">
<META NAME="Keywords" CONTENT="">
<META NAME="Description" CONTENT="">
<script language="javascript" src="sortArr.js"></script>
<script language="javascript" src="tree.js"></script>
<style type="text/css">
<!--
body { font-size: 12px;}
-->
</style>
<!--div { border: 1px solid black; padding: 5px}-->
</HEAD>
<BODY>
<P id=selBox></P>
<script language="javascript">
var b=new tree("selBox",arrSorts);
</script>
<INPUT TYPE="button" value="测试父子关系" onclick="alert(checkChild(23,1,arrSorts))">
<input id="tt" size="100">
<INPUT TYPE="button" value="获取选择成员" onclick="tt.value=getGroupChoosed('member')">
</BODY>
</HTML>
效果类似windows资源管理器,多了复选框。
今天就写到这里了,还有些东西太大了,代码太多,下次有空再贴上来吧。