*项目名称:AJAX打造4级联动菜单
*作者:草履虫
*联系:caolvchong@gmail.com
*时间:2007-10-3
*起因:
应一位网友的请求
*开发平台:Windows2003 IIS6.0 Access数据库
*工具:Emeditor,Access2003(数据库)
*测试平台:Firefox2.0,Opera9.2,IE6.0,IE7.0
*演示地址:http://finish.3322.org/4_select/index.asp(短期有效,在本机上,可能访问不顺畅)
*原文地址:http://cceer.xmu.edu.cn/blog/view.asp?id=83
*:文件结构:
数据库结构:四级联动,用四张表存各级的数据(加个conn.asp连接数据库)
对于数据库结构,其实这4个表可以放到一个表中,而不必要四个表.只要添加一个字段表名等级即可.数据库结构去附件中看看吧,加了注释了.
function.asp:数据处理文件
deal.asp:ajax后台处理文件
ajax.js:ajax交互文件核心
index.asp:表现页面
*和之前写的3级联动区别:
区别是蛮大的,采用了新的算法,代码重用性也高了,一定程度上分离了业务逻辑和表现逻辑等等.这些看代码自己体会吧
如果你要加以改造,或者实现任意级的联动,修改起来应该不难,因为这次实现联动菜单的算法已经考虑到这种情况.
或者:http://finish.3322.org/4_select.rar
index.asp代码:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>四级联动菜单</title>
<script type="text/javascript" src="ajax.js"></script>
<!--#include file="function.asp"-->
</head>
<body>
<select name="xiaoqu" onchange="ajax_change(this.value,'yuanxi',$('yuanxi'));">
<option value="-1">-----请选择校区----</option>
<%
xiaoqu=read_xiaoqu()
if IsArray(xiaoqu) then
for i=lbound(xiaoqu) to ubound(xiaoqu)
response.write "<option value="&xiaoqu(i)(0)&">"&(i+1)&"├"&xiaoqu(i)(1)&"</option>"
next
end if
%>
</select>
<span id="yuanxi">
<select>
<option value="-1">-----请选择院系-----</option>
</select>
</span>
<span id="zhuanye">
<select>
<option value="-1">-----请选择专业-----</option>
</select>
</span>
<span id="banji">
<select>
<option value="-1">-----请选择班级-----</option>
</select>
</span>
</body>
</html>
<!--#include file="conn.asp"-->
<%
'--->函数:read_xiaoqu()
' 功能:返回所有的校区
' 参数:无
' 返回值:
' 返回一个数组,格式为((校区id,校区名称),(校区id,校区名称),....)
' 调用:
' xiaoqu=read_xiaoqu() 这里,xiaoqu是变量名,可以任意取
' 使用:
' xiaoqu(0)(0)----对应第一个记录的id
' xiaoqu(0)(1)----对应第一个记录的name,依此类推
function read_xiaoqu()
sql="select id,name from xiaoqu"
set rs=server.createobject("adodb.recordset")
on error resume next
rs.open sql,conn,1,1
if err<>0 then
read_xiaoqu=-1
else
dim xiaoqu_array()
dim i:i=0
while not rs.eof
redim preserve xiaoqu_array(i)
xiaoqu_id=rs("id")
xiaoqu_name=rs("name")
xiaoqu_array(i)=array(xiaoqu_id,xiaoqu_name)
i=i+1
rs.movenext
wend
read_xiaoqu=xiaoqu_array
end if
end function
'--->函数:read_table_data(id,table_name)
' 功能:返回对应表的数据
' 参数:
' id,对应的父亲id
' table_name:对应的表名
' 比如:选择了校区的id=2,table_name选择院系yuanxi.因为要从表院系中读取对应pid为2的数据
' 返回值:
' 返回一个数组,格式为((id,name),(id,name),....)
' 调用:
' data=read_table_data(id,table_name) 这里,data是变量名,可以任意取
' 使用:
' data(0)(0)----对应第一个记录的id
' data(0)(1)----对应第一个记录的name,依此类推
function read_table_data(id,table_name)
sql="select id,name from "&table_name&" where pid="&id
set rs=server.createobject("adodb.recordset")
on error resume next
rs.open sql,conn,1,1
if err<>0 then
read_table_data=-1
else
dim data_array()
dim i:i=0
while not rs.eof
redim preserve data_array(i)
id=rs("id")
name=rs("name")
data_array(i)=array(id,name)
i=i+1
rs.movenext
wend
read_table_data=data_array
end if
end function
'--->函数:option_default(table_name)
' 功能:返回选择框的头部
' 参数:
' table_name:对应的表名
' 返回值:
' 返回一个字符串
' 调用:
' str=option_default(table_name) 这里,str是变量名,可以任意取
function option_default(table_name)
select case table_name
case "yuanxi":
str="请选择院系"
case "zhuanye":
str="请选择专业"
case "banji":
str="请选择班级"
case else
str="出错了"
end select
option_default=str
end function
'--->函数:set_next_node(table_name)
' 功能:返回当前生成节点的下一个节点的名字
' 参数:
' table_name:对应的表名
' 返回值:
' 返回一个字符串
' 调用:
' next_node=set_next_node(table_name) 这里,next_node是变量名,可以任意取
function set_next_node(table_name)
select case table_name
case "yuanxiao":
node="yuanxi"
case "yuanxi":
node="zhuanye"
case "zhuanye":
node="banji"
end select
set_next_node=node
end function
%>
var $=function(tagId){
return document.getElementById(tagId);
}
//------------------------------------------------------------
//id:接收的id值(用来提供搜索条件)
//type:接收的类型(用来提供表名)
//node:接收的节点(用来反馈数据插入),通常是指定后面一个select
function ajax_change(id,type,node){
var xmlhttp;
try{
xmlhttp=new XMLHttpRequest();
}catch(e){
xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
}
xmlhttp.onreadystatechange=function(){
if (xmlhttp.readyState==4){
if (xmlhttp.status==200){
var data=xmlhttp.responseText;
node.innerHTML=data;
}else{
node.innerHTML="<select><option>-----您未进行上一级选择-----</option></select>";
}
}
}
xmlhttp.open("post","deal.asp", true);
xmlhttp.setRequestHeader('Content-type','application/x-www-form-urlencoded');
xmlhttp.send("id="+escape(id)+"&type="+escape(type));
}
<%@LANGUAGE="VBSCRIPT" CODEPAGE="65001"%>
<!--#include file="function.asp"-->
<%
id=request.form("id")
table_name=request.form("type")
next_node=set_next_node(table_name)
if table_name <> "banji" then
response.write "<select name="""&table_name&""" onchange=""ajax_change(this.value,'"&next_node&"',$('"&next_node&"'));"">"
else
response.write "<select name="""&table_name&""">"
end if
str=option_default(table_name)
response.write "<option value=""-1"" selected>---请选择"&str&"---</option>"
data=read_table_data(id,table_name)
if IsArray(data) then
for i=lbound(data) to ubound(data)
response.write "<option value="&data(i)(0)&">"&(i+1)&"├"&data(i)(1)&"</option>"
next
end if
response.write "</select>"
%>
============================================================ 今天补充下昨天晚上最先写的代码.更简洁,思路也清晰符合思维,但是IE不支持(就是option无法innerHTML到select中去) index.asp(注意,前一个select和后一个select必须连在一起,即 select>< select ...>这种格式,否则取不到nextSibling)
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>四级联动菜单</title>
<script type="text/javascript" src="ajax.js"></script>
<!--#include file="function.asp"-->
</head>
<body>
<select name="xiaoqu" onchange="ajax_change(this.value,this.nextSibling);">
<option value="-1">-----请选择校区----</option>
<%
xiaoqu=read_xiaoqu()
if IsArray(xiaoqu) then
for i=lbound(xiaoqu) to ubound(xiaoqu)
response.write "<option value="&xiaoqu(i)(0)&">"&(i+1)&"├"&xiaoqu(i)(1)&"</option>"
next
end if
%>
</select><select name="yuanxi" id="yuanxi" onchange="ajax_change(this.value,this.nextSibling);">
<option value="-1">-----请选择院系-----</option>
</select><select name="zhuanye" id="zhuanye" onchange="ajax_change(this.value,this.nextSibling);">
<option value="-1">-----请选择专业-----</option>
</select><select name="banji" id="banji">
<option value="-1">-----请选择班级-----</option>
</select>
</body>
</html>
//------------------------------------------------------------
//id:接收的id值(用来提供搜索条件)
//node:接收的节点(用来反馈数据插入),通常是指定后面一个select
function ajax_change(id,node){
var xmlhttp;
try{
xmlhttp=new XMLHttpRequest();
}catch(e){
xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
}
xmlhttp.onreadystatechange=function(){
if (xmlhttp.readyState==4){
if (xmlhttp.status==200){
var data=xmlhttp.responseText;
alert(data)
node.innerHTML=data;
}else{
node.innerHTML="出现错误";
}
}
}
xmlhttp.open("post","deal.asp", true);
xmlhttp.setRequestHeader('Content-type','application/x-www-form-urlencoded');
xmlhttp.send("id="+escape(id)+"&type="+escape(node.name));
}
<%@LANGUAGE="VBSCRIPT" CODEPAGE="65001"%>
<!--#include file="function.asp"-->
<%
id=request.form("id")
table_name=request.form("type")
str=option_default(table_name)
response.write "<option value=""-1"" selected>-----请选择"&str&"-----</option>"
data=read_table_data(id,table_name)
if IsArray(data) then
for i=lbound(data) to ubound(data)
response.write "<option value="&data(i)(0)&">"&(i+1)&"├"&data(i)(1)&"</option>"
next
end if
%>
<!--#include file="../conn.asp"-->
<%
'--->函数:read_xiaoqu()
' 功能:返回所有的校区
' 参数:无
' 返回值:
' 返回一个数组,格式为((校区id,校区名称),(校区id,校区名称),....)
' 调用:
' xiaoqu=read_xiaoqu() 这里,xiaoqu是变量名,可以任意取
' 使用:
' xiaoqu(0)(0)----对应第一个记录的id
' xiaoqu(0)(1)----对应第一个记录的name,依此类推
function read_xiaoqu()
sql="select id,name from xiaoqu"
set rs=server.createobject("adodb.recordset")
on error resume next
rs.open sql,conn,1,1
if err<>0 then
read_xiaoqu=-1
else
dim xiaoqu_array()
dim i:i=0
while not rs.eof
redim preserve xiaoqu_array(i)
xiaoqu_id=rs("id")
xiaoqu_name=rs("name")
xiaoqu_array(i)=array(xiaoqu_id,xiaoqu_name)
i=i+1
rs.movenext
wend
read_xiaoqu=xiaoqu_array
end if
end function
'--->函数:read_table_data(id,table_name)
' 功能:返回对应表的数据
' 参数:
' id,对应的父亲id
' table_name:对应的表名
' 比如:选择了校区的id=2,table_name选择院系yuanxi.因为要从表院系中读取对应pid为2的数据
' 返回值:
' 返回一个数组,格式为((id,name),(id,name),....)
' 调用:
' data=read_table_data(id,table_name) 这里,data是变量名,可以任意取
' 使用:
' data(0)(0)----对应第一个记录的id
' data(0)(1)----对应第一个记录的name,依此类推
function read_table_data(id,table_name)
sql="select id,name from "&table_name&" where pid="&id
set rs=server.createobject("adodb.recordset")
on error resume next
rs.open sql,conn,1,1
if err<>0 then
read_table_data=-1
else
dim data_array()
dim i:i=0
while not rs.eof
redim preserve data_array(i)
id=rs("id")
name=rs("name")
data_array(i)=array(id,name)
i=i+1
rs.movenext
wend
read_table_data=data_array
end if
end function
'--->函数:option_default(table_name)
' 功能:返回选择框的头部
' 参数:
' table_name:对应的表名
' 返回值:
' 返回一个字符串
' 调用:
' str=option_default(table_name) 这里,str是变量名,可以任意取
function option_default(table_name)
select case table_name
case "yuanxi":
str="院系"
case "zhuanye":
str="专业"
case "banji":
str="班级"
case else
str="出错了"
end select
option_default=str
end function
%>