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>