JavaScript實現樹形菜單

 隨便做瞭一個例子如下圖

   
[html] 
1,用之前需要組織一個這種結構的XML 
2,業務類別和功能在數據庫中配置一下就好瞭   
      比如:"學生管理"配置的在數據庫中的狀態時001 
      那麼 他的孩子節點  "添加學生信息" 對應數據庫配置應該是001的孩子節點, 
      這個隨你怎麼配  ,隻要能表示是001的孩子節點就可以瞭、 
      可以配置為001001,001002,001003後面的三位數代表孩子節點的順序,前面三位代表。 
3,"/student/student.jsp"  功能所對應的JSP也需要在數據庫中配置 
4,不同的角色有不同的權限,這個自己想配吧。 
 js代碼
[html] 
function Folder(folderDescription, hreference) //constructor  
{  
  //constant data  
  this.desc = folderDescription  
  this.hreference = hreference  
  this.id = -1    
  this.navObj = 0   
  this.iconImg = 0   
  this.nodeImg = 0   
  this.isLastNode = 0  
  
  //dynamic data  
  this.isOpen = true  
  this.iconSrc = "ftv2folderopen.gif"    
  this.children = new Array  
  this.nChildren = 0  
  
  //methods  
  this.initialize = initializeFolder  
  this.setState = setStateFolder  
  this.addChild = addChild  
  this.createIndex = createEntryIndex  
  this.hide = hideFolder  
  this.display = display  
  this.renderOb = drawFolder  
  this.totalHeight = totalHeight  
  this.subEntries = folderSubEntries  
  this.outputLink = outputFolderLink  
}  
  
function setStateFolder(isOpen)  
{  
  var subEntries  
  var totalHeight  
  var fIt = 0  
  var i=0  
  
  if (isOpen == this.isOpen)  
    return  
  
  if (browserVersion == 2)   
  {  
    totalHeight = 0  
    for (i=0; i < this.nChildren; i++)  
      totalHeight = totalHeight + this.children[i].navObj.clip.height  
      subEntries = this.subEntries()  
    if (this.isOpen)  
      totalHeight = 0 – totalHeight  
    for (fIt = this.id + subEntries + 1; fIt < nEntries; fIt++)  
      indexOfEntries[fIt].navObj.moveBy(0, totalHeight)  
  }   
  this.isOpen = isOpen  
  propagateChangesInState(this)  
}  
  
function propagateChangesInState(folder)  
{    
  var i=0  
  
  if (folder.isOpen)  
  {  
    if (folder.nodeImg)  
      if (folder.isLastNode)  
        folder.nodeImg.src = "ftv2mlastnode.gif"  
      else  
      folder.nodeImg.src = "ftv2mnode.gif"  
    folder.iconImg.src = "ftv2folderopen.gif"  
    for (i=0; i<folder.nChildren; i++)  
      folder.children[i].display()  
  }  
  else  
  {  
    if (folder.nodeImg)  
      if (folder.isLastNode)  
        folder.nodeImg.src = "ftv2plastnode.gif"  
      else  
      folder.nodeImg.src = "ftv2pnode.gif"  
    folder.iconImg.src = "ftv2folderclosed.gif"  
    for (i=0; i<folder.nChildren; i++)  
      folder.children[i].hide()  
  }   
}  
  
function hideFolder()  
{  
  if (browserVersion == 1) {  
    if (this.navObj.style.display == "none")  
      return  
    this.navObj.style.display = "none"  
  } else {  
    if (this.navObj.visibility == "hiden")  
      return  
    this.navObj.visibility = "hiden"  
  }  
    
  this.setState(0)  
}  
  
function initializeFolder(level, lastNode, leftSide)  
{  
var j=0  
var i=0  
var numberOfFolders  
var numberOfDocs  
var nc  
       
  nc = this.nChildren  
    
  this.createIndex()  
  
  var auxEv = ""  
  
  if (browserVersion > 0)  
    auxEv = "<a href='javascript:clickOnNode("+this.id+")'>"  
  else  
    auxEv = "<a>"  
  
  if (level>0)  
    if (lastNode) //the last 'brother' in the children array  
    {  
      this.renderOb(leftSide + auxEv + "<img name='nodeIcon" + this.id + "' src='ftv2mlastnode.gif' width=16 height=22 border=0></a>")  
      leftSide = leftSide + "<img src='ftv2blank.gif' width=16 height=22>"   
      this.isLastNode = 1  
    }  
    else  
    {  
      this.renderOb(leftSide + auxEv + "<img name='nodeIcon" + this.id + "' src='ftv2mnode.gif' width=16 height=22 border=0></a>")  
      leftSide = leftSide + "<img src='ftv2vertline.gif' width=16 height=22>"  
      this.isLastNode = 0  
    }  
  else  
    this.renderOb("")  
    
  if (nc > 0)  
  {  
    level = level + 1  
    for (i=0 ; i < this.nChildren; i++)   
    {  
      if (i == this.nChildren-1)  
        this.children[i].initialize(level, 1, leftSide)  
      else  
        this.children[i].initialize(level, 0, leftSide)  
      }  
  }  
}  
function drawFolder(leftSide)  
{  
  if (browserVersion == 2) {  
    if (!doc.yPos)  
      doc.yPos=8  
    doc.write("<layer id='folder" + this.id + "' top=" + doc.yPos + " visibility=hiden>")  
  }  
    
  doc.write("<table ")  
  if (browserVersion == 1)  
    doc.write(" id='folder" + this.id + "' style='position:block;' ")  
  doc.write(" border=0 cellspacing=0 cellpadding=0>")  
  doc.write("<tr><td>")  
  doc.write(leftSide)  
  this.outputLink()  
  doc.write("<img name='folderIcon" + this.id + "' ")  
  doc.write("src='" + this.iconSrc+"' border=0></a>")  
  doc.write("</td><td valign=middle nowrap>")  
  if (USETEXTLINKS)  
  {  
    this.outputLink()  
    doc.write(this.desc + "</a>")  
  }  
  else  
    doc.write(this.desc)  
  doc.write("</td>")   
  doc.write("</table>")  
    
  if (browserVersion == 2) {  
    doc.write("</layer>")  
  }  
  
  if (browserVersion == 1) {  
    this.navObj = doc.all["folder"+this.id]  
    this.iconImg = doc.all["folderIcon"+this.id]  
    this.nodeImg = doc.all["nodeIcon"+this.id]  
  } else if (browserVersion == 2) {  
    this.navObj = doc.layers["folder"+this.id]  
    this.iconImg = this.navObj.document.images["folderIcon"+this.id]  
    this.nodeImg = this.navObj.document.images["nodeIcon"+this.id]  
    doc.yPos=doc.yPos+this.navObj.clip.height  
  }  
}  
  
function outputFolderLink()  
{  
  if (this.hreference)  
  {  
    doc.write("<a href='" + this.hreference + "' TARGET=main ")  
    if (browserVersion > 0)  
      doc.write("onClick='javascript:clickOnFolder("+this.id+")'")  
    doc.write(">")  
  }  
  else  
    doc.write("<a>")  
//  doc.write("<a href='javascript:clickOnFolder("+this.id+")'>")    
}  
  
function addChild(childNode)  
{  
  this.children[this.nChildren] = childNode  
  this.nChildren++  
  return childNode  
}  
  
function folderSubEntries()  
{  
  var i = 0  
  var se = this.nChildren  
  
  for (i=0; i < this.nChildren; i++){  
    if (this.children[i].children) //is a folder  
      se = se + this.children[i].subEntries()  
  }  
  
  return se  
}  
  
  
// Definition of class Item (a document or link inside a Folder)  
// *************************************************************  
  
function Item(itemDescription, itemLink) // Constructor  
{  
  // constant data  
  this.desc = itemDescription  
  this.link = itemLink  
  this.id = -1 //initialized in initalize()  
  this.navObj = 0 //initialized in render()  
  this.iconImg = 0 //initialized in render()  
  this.iconSrc = "ftv2doc.gif"  
  
  // methods  
  this.initialize = initializeItem  
  this.createIndex = createEntryIndex  
  this.hide = hideItem  
  this.display = display  
  this.renderOb = drawItem  
  this.totalHeight = totalHeight  
}  
  
function hideItem()  
{  
  if (browserVersion == 1) {  
    if (this.navObj.style.display == "none")  
      return  
    this.navObj.style.display = "none"  
  } else {  
    if (this.navObj.visibility == "hiden")  
      return  
    this.navObj.visibility = "hiden"  
  }      
}  
  
function initializeItem(level, lastNode, leftSide)  
{   
  this.createIndex()  
  
  if (level>0)  
    if (lastNode) //the last 'brother' in the children array  
    {  
      this.renderOb(leftSide + "<img src='ftv2lastnode.gif' width=16 height=22>")  
      leftSide = leftSide + "<img src='ftv2blank.gif' width=16 height=22>"   
    }  
    else  
    {  
      this.renderOb(leftSide + "<img src='ftv2node.gif' width=16 height=22>")  
      leftSide = leftSide + "<img src='ftv2vertline.gif' width=16 height=22>"  
    }  
  else  
    this.renderOb("")    
}  
  
function drawItem(leftSide)  
{  
  if (browserVersion == 2)  
    doc.write("<layer id='item" + this.id + "' top=" + doc.yPos + " visibility=hiden>")  
      
  doc.write("<table ")  
  if (browserVersion == 1)  
    doc.write(" id='item" + this.id + "' style='position:block;' ")  
  doc.write(" border=0 cellspacing=0 cellpadding=0>")  
  doc.write("<tr><td>")  
  doc.write(leftSide)  
  doc.write("<a href='"+ this.link + "' target=main>")  
  doc.write("<img id='itemIcon"+this.id+"' ")  
  doc.write("src='"+this.iconSrc+"' border=0>")  
  doc.write("</a>")  
  doc.write("</td><td valign=middle nowrap>")  
  if (USETEXTLINKS)  
    doc.write("<a href='"+ this.link + "' target=main>" + this.desc + "</a>")  
  else  
    doc.write(this.desc)  
  doc.write("</table>")  
    
  if (browserVersion == 2)  
    doc.write("</layer>")  
  
  if (browserVersion == 1) {  
    this.navObj = doc.all["item"+this.id]  
    this.iconImg = doc.all["itemIcon"+this.id]  
  } else if (browserVersion == 2) {  
    this.navObj = doc.layers["item"+this.id]  
    this.iconImg = this.navObj.document.images["itemIcon"+this.id]  
    doc.yPos=doc.yPos+this.navObj.clip.height  
  }  
}  
  
  
// Methods common to both objects (pseudo-inheritance)  
// ********************************************************  
  
function display()  
{  
  if (browserVersion == 1)  
    this.navObj.style.display = "block"  
  else  
    this.navObj.visibility = "show"  
}  
  
function createEntryIndex()  
{  
  this.id = nEntries  
  indexOfEntries[nEntries] = this  
  nEntries++  
}  
  
// total height of subEntries open  
function totalHeight() //used with browserVersion == 2  
{  
  var h = this.navObj.clip.height  
  var i = 0  
    
  if (this.isOpen) //is a folder and _is_ open  
    for (i=0 ; i < this.nChildren; i++)   
      h = h + this.children[i].totalHeight()  
  
  return h  
}  
  
  
// Events  
// *********************************************************  
  
function clickOnFolder(folderId)  
{  
  var clicked = indexOfEntries[folderId]  
  
  if (!clicked.isOpen)  
    clickOnNode(folderId)  
  
  return   
  
  if (clicked.isSelected)  
    return  
}  
  
function clickOnNode(folderId)  
{  
  var clickedFolder = 0  
  var state = 0  
  
  clickedFolder = indexOfEntries[folderId]  
  state = clickedFolder.isOpen  
  
  clickedFolder.setState(!state) //open<->close   
}  
  
function initializeDocument()  
{  
  if (doc.all)  
    browserVersion = 1 //IE4    
  else  
    if (doc.layers)  
      browserVersion = 2 //NS4  
    else  
      browserVersion = 0 //other  
  
  foldersTree.initialize(0, 1, "")  
  foldersTree.display() 
   
  if (browserVersion > 0)  
  {  
    doc.write("<layer top="+indexOfEntries[nEntries-1].navObj.top+"> </layer>")  
  
    // close the whole tree  
    clickOnNode(0)  
    // open the root folder  
    clickOnNode(0)  
  }  
}  
  
// Auxiliary Functions for Folder-Treee backward compatibility  
// *********************************************************  
  
function gFld(description, hreference)  
{  
  description="<font style=font-size:9pt; font-color: #00ff00;background-color:#ccff99>" + description 
  folder = new Folder(description, hreference)  
  return folder  
}  
  
function gLnk(target, description, linkData)  
{  
  description="<font style=font-size:9pt; font-color: #0000ff;background-color:#ccff99>" + description 
  fullLink = ""  
  
  if (target==0)  
  {  
    fullLink = "'"+linkData+"' target=main"  
  }  
  else  
  {  
    if (target==1)  
       fullLink = "'http://"+linkData+"' target=_top"  
    else  
       fullLink = "'http://"+linkData+"' target=main"  
  }  
  
  linkItem = new Item(description, fullLink)    
  return linkItem  
}  
  
function insFld(parentFolder, childFolder)  
{  
  return parentFolder.addChild(childFolder)  
}  
  
function insDoc(parentFolder, document)  
{  
  parentFolder.addChild(document)  
}  
  
// Global variables  
// ****************  
  
USETEXTLINKS = 1  
indexOfEntries = new Array  
nEntries = 0  
doc = document  
browserVersion = 0  
selectedFolder=0 

 
jsp代碼
[html] 
<%@ page language="java" import="java.util.*" pageEncoding="gbk"%> 
<% 
String path = request.getContextPath(); 
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; 
%> 
 
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> 
<html> 
  <head> 
    <base href="<%=basePath%>"> 
     
    <title>My JSP 'tree.jsp' starting page</title> 
     
    <meta http-equiv="pragma" content="no-cache"> 
    <meta http-equiv="cache-control" content="no-cache"> 
    <meta http-equiv="expires" content="0">     
    <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> 
    <meta http-equiv="description" content="This is my page"> 
    <style type="text/css"> 
        .navtree {  background-color: #FFFFFF ; font-family: Arial, Helvetica, sans-serif; border-right: 1px solid black; margin-top: 5px; scrollbar-face-color:#CCCCCC; scrollbar-shadow-color:#FFFFFF; scrollbar-highlight-color:#FFFFFF; scrollbar-3dlight-color:#6B7A92; scrollbar-darkshadow-color:#6B7A92; scrollbar-track-color:#E2E2E2; scrollbar-arrow-color:#6B7A92 } 
    </style>   
    <script type="text/javascript" src="tree.js"></script> 
    <script type="text/javascript" > 
    function parseXml2Tree(str_xml) 
    { 
        var xmlDoc = new ActiveXObject("Microsoft.XMLDOM");  
        xmlDoc.async = false;  
        xmlDoc.loadXML(str_xml);     
        node=xmlDoc.documentElement;//根節點  
        var i=0;//用來記數父節點數 
        var h=0;//用來查找父節點 
        var fp_array=new Array();//用來存放父目錄 
        foldersTree =gFld(node.nodeName);//根目錄 
        fp=foldersTree;   //父目錄 
        var f1; //子目錄 
        fp_array[i]=fp;     //第一個父目錄為根目錄     
        var rootname=node.nodeName; //根節點的名字       
        getAllNode(node);   //執行遞歸查找節點,生成目錄樹     
        initializeDocument(); 
        function getAllNode(currNode) 
        //首先查找根節點,先找其第一個孩子,如果第一個孩子存在及其兄弟,插入目錄樹,並記錄父目錄, 
        //然後把第一個節點看作當前根節點,繼續查找其第一個孩子。 
        { 
                //第一個孩子 
            childNode=currNode.firstChild;               
            if(childNode!=null ) 
            { 
                if(childNode.firstChild!=null) 
                { 
                    f1=gFld(childNode.getAttribute("name"),childNode.getAttribute("link")); 
                    insFld(fp,f1); 
 
                    fp=f1;                       
                    fp_array[++i]=fp;                        
                    h++;                     
                }else{ 
                    item1= new Item("<font style=font-size:9pt; font-color: #0000ff;background-color:#ccff99>"+childNode.getAttribute("name"),childNode.getAttribute("link")); 
                    insDoc(fp,item1); 
                 
                } 
                //遞歸查找孩子 
                getAllNode(childNode); 
                 
            } 
            else 
            //如果沒有孩子,即葉子 
            //葉子的兄弟 
            if(currNode.nodeName==rootname) 
            //如果為根節點返回。 
            {                                
                return; 
            } 
            nextBrother=currNode.nextSibling;                
            if(nextBrother==null ) 
            {                    
                currNode=currNode.parentNode;                          
                if(currNode.nodeName==rootname)  
                {                
                    return; 
                } 
                fp=fp_array[–h];                    
            } 
            else 
            { 
                 
                currNode=nextBrother;            
                if(currNode.firstChild!=null) 
                { 
                    f1=gFld(currNode.getAttribute("name"),currNode.getAttribute("link")); 
                    insFld(fp,f1); 
 
                    fp=f1;                       
                    fp_array[++i]=fp;                        
                    h++;                     
                } 
                else 
                { 
                    item1= new Item("<font style=font-size:9pt; font-color: #0000ff;background-color:#ccff99>"+currNode.getAttribute("name"),currNode.getAttribute("link")); 
                    insDoc(fp,item1); 
                }                    
                getAllNode(currNode);    
            } 
        }        
    }  
 
</script> 
  </head> 
   
  <body class="navtree"> 
      <% 
         String str_dom =   "<?xml version=\"1.0\" encoding=\"GB2312\"?>"+    
                            "<功能列表>"+ 
                            "<業務類別 link=\"\" name=\"學生管理\">"+ 
                            "<功能 link=\"/student/student.jsp\" name=\"添加學生信息\"/>"+ 
                            "<功能 link=\"/student/student.jsp\" name=\"更改學生信息\"/>"+ 
                            "<功能 link=\"/student/student.jsp\" name=\"查看學生信息\"/>"+ 
                            "<功能 link=\"/student/student.jsp\" name=\"刪除學生信息\"/>"+ 
                            "<功能 link=\"/student/student.jsp\" name=\"下載學生列表\"/>"+ 
                            "</業務類別>"+ 
                            "<業務類別 link=\"\" name=\"成績管理\">"+ 
                            "<功能 link=\"/student/student.jsp\" name=\"成績查詢\"/>"+ 
                            "<功能 link=\"/student/student.jsp\" name=\"成績排名\"/>"+ 
                            "<功能 link=\"/student/student.jsp\" name=\"成績匯總\"/>"+ 
                            "<功能 link=\"/student/student.jsp\" name=\"打印成績\"/>"+ 
                            "</業務類別>"+ 
                            "<業務類別 link=\"\" name=\"繳費管理\">"+ 
                            "<功能 link=\"/student/student.jsp\" name=\"已經交費\"/>"+ 
                            "<功能 link=\"/student/student.jsp\" name=\"繳費查詢\"/>"+ 
                            "<功能 link=\"/student/student.jsp\" name=\"繳費匯總\"/>"+ 
                            "</業務類別>"+ 
                            "<業務類別 link=\"\" name=\"選課管理\">"+ 
                            "<功能 link=\"/student/student.jsp\" name=\"語文\"/>"+ 
                            "<功能 link=\"/student/student.jsp\" name=\"數學\"/>"+ 
                            "<功能 link=\"/student/student.jsp\" name=\"英語\"/>"+ 
                            "<功能 link=\"/student/student.jsp\" name=\"物理\"/>"+ 
                            "<功能 link=\"/student/student.jsp\" name=\"化學\"/>"+ 
                            "<功能 link=\"/student/student.jsp\" name=\"生物\"/>"+ 
                            "</業務類別>"+ 
                            "<業務類別 link=\"\" name=\"系統設置\">"+ 
                            "<功能 link=\"/student/student.jsp\" name=\"修改密碼\"/>"+ 
                            "<功能 link=\"/student/student.jsp\" name=\"用戶註冊\"/>"+ 
                            "<功能 link=\"/student/student.jsp\" name=\"用戶註銷\"/>"+ 
                            "</業務類別>"+ 
                            "</功能列表>"; 
                            str_dom=str_dom.replace('"','\''); 
                            int begin_index=str_dom.indexOf("<");     
                            str_dom=str_dom.substring(begin_index+1); 
                            begin_index=str_dom.indexOf("<"); 
                            str_dom=str_dom.substring(begin_index); 
                                      
      %> 
      <script type="text/javascript"> 
        parseXml2Tree("<%=str_dom%>"); 
      </script> 
  </body> 
</html> 

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *