荔园在线
荔园之美,在春之萌芽,在夏之绽放,在秋之收获,在冬之沉淀
[回到开始]
[上一篇][下一篇]
发信人: sephiroth (birds of paradise), 信区: Internet
标 题: 在下拉列表中动态显示树形选项
发信站: 荔园晨风BBS站 (Tue Jun 18 11:10:52 2002), 转信
----------------------------------------------------------------
----★ 警 告 ★----
该文系原创作品。版权没有,盗版不究。欢迎复制传播,但是请保持
文章的完整性、注明作者及出处,且不得以盈利为目的。
(C)2002 Lounge Workroom
作者:边城浪子
-----------------------------------------------------------------
在WEB页面上使用SELECT标签提供一组选项供济览者选择是一种很普遍的做法,但
通常来说为一系列固定的选项。本人在制作某一网页时需要提供一组以树形结构存
储的非固定的选项供用户选择,经过大量试验后,我使用一个下拉列表成功地实现
了。
具体方案就是:首先,在列表框中显示一组主选项(也可能会是从一个非主选项开
始,后面介绍),当用户从中选择一项后,JavaScript代码测试所选的选项是否有
子项,若有子项则在该列表框中显示,用户可以作进一步的选择,选项中还提供返
回上一级列表的选项,以便用户错选后有机会进行反悔。在这里,用户如想选择一
个深层次的选项,可能要连续进行好几次的选择才能实现,好像有点麻烦。但对于
一个以树形结构存放的数据来说这也是最直观的了。对于一个有大量选项的选择来
说,这也是一种好的组织方法。
下面通过一个例子来谈谈具体的实现。这是一个论坛发表文章的页面的ASP代码的
一部分,在标题为文章分类的下拉列表中,显示一驵以树形结构存放在数据库中的
文章分类信息。在这里你不必一定选择最里层的选项,你可以在任何一个选项上停
止做进一步的选择,这是允许的。因为,假如你只是发表一篇对编程进行概括性描
述,而不涉及任何一种语言的文章,你只需选择程序设计这一选项就行了,尽管其
下还有Visual Studio系列、Borland系列、OpenGL技术、DirectX技术等子项。相
关代码段如下:
<%
...
Response.Write "内容分类:<select id=""classlist""
onchange=""changelist();"">"
'Add this place:the luntan's class field
Response.Write "</select>" & vbCrLf
%>
<script language="javascript">
<!--
<%
dim aTree(),root,i,strS,s
s=1
root=CInt(bbsid)
if root=0 then root=-1
Call GetClassTree("list_lt",aTree)
call showClass(aTree,root,s,0)
strS= "var s=new Array("
for i=1 to s
strS=strS & "s" & i & ","
next
If right(strS,1)="," Then strS=Left(strS,Len(strS)-1)
strS=strS & ");"
Response.Write strS
%>
//set the select's item
start();
function start(){
//-------------------------
removeall();
addselect(s[0]);
//return false;
//----------=-==-=---------
}
function changelist(){
var p=document.all.classlist;
var id=p.selectedIndex
var m=p.options(id).value;
if(m<0)m=-m;
document.all.type.value=p.options[id].text;
if(id==0||m==0) return false;
removeall();
addselect(s[m-1]);
p.blur();
return false;
}
function removeall(){
var o1=document.all.classlist;
for(;o1.options(0)!==null;){
o1.options.remove(0);
}
}
function addselect(a){
var o2;
var o1=document.all.classlist;
for(var i=0;i<a.length;i+=3)
{
o2=document.createElement("option");
o2.value=a[i];
o2.text=a[i+2];
if (a[i]==0)
{
o2.style.color='#000060';
}
else if(a[i]>0)
{
o2.style.color='#ff0000';
}
else
{
o2.style.color='#0000ff';
}
if(i==0)
{
o2.style.backgroundColor='#ffffa0';
o2.style.color='#a06020';
}
o1.options.add(o2);
}
document.all.type.value=a[2];
}
//-->
</script>
...
下面对程序进行一些解释:
代码开始的不相关部分我己省去。
程序首先用ASP输出一个下拉列表的HTML代码,ID为“classlist”。
ASP代码其后就是JavaScript代码。在JavaScript代码的开始部分又嵌入了一段
ASP代码。这里的ASP代码是用来生成列表选项的数据,并成为JavaScript代码的一
个二维数组定义语句。在这段ASP代码中,使用了两个函数,GetClassTree()函数
的功能是从数据库中读取所有的相关记录,并用来填充一个参数数组来返回数据。
该函数的第一个参数是表句,第二个参数就是用来返回数据的可变数组。该函数定
义如下:
<%
Function GetClassTree(byVal TableName,aData)
'从数据库中读取数据
strSQL="SELECT * FROM " & TableName & " WHERE true ORDER BY id"
oRs.Open strSQL,oConn,1,1
'将数据转入一个数组中
ReDim aData(oRs.RecordCount-1,4)
For i=0 to oRs.RecordCount-1
aData(i,0)=oRs("id") '记录索引号
aData(i,1)=oRs("name") '记录名称
aData(i,2)=oRs("parent") '父记录索引号
aData(i,3)=oRs("show") '记录的说明
aData(i,4)=oRs("place") '记录的参数,用它来决定记录的操作权
限
oRs.MoveNext
next
oRs.Close
GetClassTree=true
End Function
%>
在这个函数中,strSQL是一个全局变量,用来设定SQL语句;oRs和oConn是全局的
Recordest和Conncent对象。该函数应根据你所用的数据库不同而自己进行定义。
函数ShowClass()其实是对己读入的数据进行变换,输出JavaScript语句。它有四
个参数,第一个是数据数组,通过上面那个函数获得第二个是记录索引号,表示需
要输出该记录及其子项;第三个是一个数字。规定当前输出的JavaSciprt语句的序
号,给出该参数是因为该函数是递归的。函数返回时它就是最后一个JavaScript语
句的编号;第四个参数也是一个递归参数,调用该函数时应置为0。下面给出该函
数的定义:
<%
'###################################
'#一个使用SELECT来显示分类结构 #
'###################################
'aTree 类结构数组
's 当前类的索引
'm 当前类的编号
'parent 当前类的父类的编号
'###################################
function ShowClass(aTree,s,m,parent)
dim strJava,n,strSonIndex,aSon,Son,iSon,cSon,p
p=m
n=GetArrayIndex(s,aTree)
if n<0 then
ShowClass=false
Exit Function
End If
strJava="var s" & m & "=new Array(" & m & "," & aTree(n,0) & ",'"
& replace(aTree(n,1),"'","\'") & "',"
strSonIndex=GetSon(s,aTree)
aSon=Split(strSonIndex,",")
for each Son in aSon
iSon=CInt(Son)
If GetSon(aTree(iSon,0),aTree)="" Then
cSon=0
Else
m=m+1
cSon=m
End If
strJava=strJava & cSon & "," & aTree(iSon,0) & ",'" &
replace(aTree(iSon,1),"'","\'") & "',"
If cSon<>0 Then
if not showClass(aTree,aTree(iSon,0),m,p) then
ShowClass=false
exit function
end if
End If
next
If right(strJava,1)="," then strJava=left(strJava,Len(strJava)-1)
If parent>0 then strJava=strJava & ",-" & parent & ",0,'▲..返回上一
级'"
strJava=strJava & ");" & vbcrlf
Response.Write strJava
showClass=true
end function
%>
在该函数中又用到了几个函数,它们的定义如下:
<%
'该函数用来获取给定类的所有子类,并将结果连接成一个字符串返回
'字符串中的子索引号以逗号分割
'id:给定类的索引
'aTree:数据数组
Function GetSon(id,aTree)
Dim strSon,i
strSon=""
For i=LBound(aTree) to UBound(aTree)
If aTree(i,2)=id Then
strSon=strSon & "," & i
End if
Next
If Left(strSon,1)="," Then strSon=Mid(strSon,2)
GetSon=strSon
End function
%>
<%
'该函数用来查找给定类在数组中的下标
'id:给定类的索引
'aTree:数据数组
Function GetArrayIndex(id,aTree)
Dim i
For i=LBound(aTree,1) to UBound(aTree,1)
If aTree(i,0)=id Then
GetArrayIndex=i
Exit Function
End If
Next
GetArrayIndex=-1
End Function
%>
好了,下面回到对主代码段的叙述。在调用函数ShowClass()输出了每个带有子项
的数据的JavaScript数组定义语句之后,函数返回的s值确定了一共产生了多少个
这样的数组。这些语句产生的数组定义有这样的规律:它们的名称从“s1”开始,
并并编号结束于返回的S值,尽管语句并非按该序号排列。如s返回20,则一共产生
20个数组,分别是:s1,s2,...,s19,s20。
然后的ASP代码根据s值生成一个数组定义语句,将这些数组组按顺序织成一个二维
数组s。这就是在客户端执行JavaScript代码所需要的全部数据。
再下面的JavaScript代码就是用来响应用户的操作,在下拉列表框中动态地,按我
们预先的规律显示出来。
JavaScript代码主要部分是三个函数:changelist()、removeall()、
addselect(a)。下面分别讨论一下这三个函数。
一、函数removeall()。该函数用于将下拉列表中原有的内容去除,以便显示新的
内容。代码很简单,就不再描述了。
二、函数addselect(a)。该函数用天将新的内容增加到下拉列表中,供用户作进一
步的选择。首先生成一个option对象,然后根据传入的数组中的当前选项内容来设
置该对象的标题和值,并根据选项的不同而设定它不同的样式。父选项带有浅黄的
底色,字符偏深橙;没有再下级子项的子选项为深蓝色表示该选项是终点;具有再
子级子项的子项的子先项是红色,表示当你选择该项后还可以再往下进行选择;返
回上级选项是浅蓝色。这样用户在作选择时就一目了然了。生成的选项使用
select对象的options集合的add方法将它加入select对象中。加入新选项是循环进
行的,直到数组中的所有内容都加入了为止。
三、函数changelist()。该函数是一个消息处理函数,它用来响应select对象的
onchange事件,当用户进行了选择之后,onchange消息被触发,于是便执行
changelist()函数。在该函数中,首先程序读取下拉列表的当前项索引,根据索引
取得所当前项的值。如果当前项具有下级选,则删除当前下拉列表的所有选项,并
死列出该项的子项供进一步选择。否则立刻返回。
在JavaScript代码开始处还调用了函数start(),该函数用来对下拉列表框进行初始
化。显示一组主选项。显示主选项很简单,就是用s[0]为参数来调用addlist()函
数。因为数组s[0]中存放的就是主选项。
附:从一个非主选项开始
上面讨论了实现的全过程。当然,根据个人情况的不同,程序肯定是要作一定的修
改的,这里就不在讨论了。下面说一下如何在页面装载时首先定位在某一个非主选
项上。我们需要对start()函数作一点修改。给该函数增加一个参数,也就是需要
在开始时显示的选项的索引。改后的start()函数如下:
function start(id){
//-------------------------
var i,j,pc,pr
var fpp=1;
removeall();
for(i=0;(i<s.length)&&fpp;i++)
{
var os=s[i];
for(j=0;(j<os.length/3)&&fpp;j++)
{
if(os[j*3+1]==id)
{
pc=i;
pr=j;
//fpp=0;
}
}
}
addselect(s[pc]);
document.all.classlist.selectedIndex=pr;
//return false;
//----------=-==-=---------
}
函数中使用一个二重循环在数组中进行搜索指定的id,根据结果来调用
addselect()函数,而不是使用s[0]。并在函数的末尾将下拉列表的当前选项定位
至我们需要的地方。
--
※ 来源:·荔园晨风BBS站 bbs.szu.edu.cn·[FROM: 192.168.44.43]
[回到开始]
[上一篇][下一篇]
荔园在线首页 友情链接:深圳大学 深大招生 荔园晨风BBS S-Term软件 网络书店