现在的位置: 首页 > 综合 > 正文

无限树形选择菜单类【原创】

2013年02月04日 ⁄ 综合 ⁄ 共 8261字 ⁄ 字号 评论关闭

  前两天想把无限联动改成颗树,好选择嘛,所以就写了点东西。
  所需数据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; width: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资源管理器,多了复选框。
  今天就写到这里了,还有些东西太大了,代码太多,下次有空再贴上来吧。

抱歉!评论已关闭.