回首页

后一页
前一页
用ASP方式实现拥有动态伸缩层次列表的主页

济南大众日报社信息中心
王 飞

---- 微 软 公 司 推 出 的IE4.X, 使 得 按 照HTML4 标 准 制 作 的 网 页 一 时 成 为 时 尚, 这 类 网 页 在 动 态 功 能 方 面 有 了 非 常 大 的 提 高。 特 别 是 可 以 通 过 页 面 内 嵌 的Script 语 句, 使 页 面 中 的 任 意 一 段 文 字 可 以 在 需 要 时 显 示 出 来, 在 不 需 要 时 隐 藏 起 来, 利 用 这 一 特 性, 就 可 以 在 页 面 上 设 计 出 可 以 伸 缩 的 层 次 列 表 出 来。 这 种 列 表 实 际 表 现 的 是 一 种 分 层 次 的 树 状 结 构, 读 者 可 以 用 鼠 标 点 击 上 一 层 的 条 目, 而 展 开 或 收 起 它 的 下 一 层。 在 明 白 了HTML4 标 准 中DOM 的 实 现 机 制 及 对 风 格 表 单 的 定 义 之 后, 很 容 易 可 以 找 到 实 现 这 种 列 表 的 途 径。 但 是 一 般 来 说, 这 种 列 表 的 条 目 都 比 较 多, 如 果 每 次 都 用 手 工 制 作, 不 仅 非 常 烦 琐, 而 且 也 十 分 容 易 出 错, 所 以 要 真 正 应 用 到 实 际 的 页 面 制 作 当 中, 还 必 须 有 一 种 比 较 自 动 的 方 法。 本 人 通 过 实 验, 用ASP 方 式 完 成 了 一 种 比 较 通 用 的 实 现 过 程, 稍 加 变 化 就 可 以 应 用 到 各 种 主 页 的 制 作 过 程 当 中, 非 常 方 便。

---- 简 单 的 实 现

---- 要 在 网 页 上 实 现 伸 缩, 首 先 要 清 楚 如 何 使 页 面 中 的 一 段 文 字 按 需 要 隐 藏 和 显 示 出 来。 我 们 看 下 面 这 段HTML 格 式 的 片 段:


 < Div Id="test" Style="Display:none" >
要 隐 藏 的 文 字< /Div >

---- 这 是 符 合HTML4 标 准 的HTML 语 句, 夹 在< Div > 之 间 的 文 本 将 不 显 示 在 页 面 上, 因 为 它 风 格 表 单 的Display 属 性 为none。( 由 于 本 文 不 主 要 介 绍HTML4 的 风 格 表 单, 有 关 祥 情 请 读 者 查 找 相 关 资 料。) 只 要 能 动 态 地 将Display 属 性 设 为 空, 即 缺 省 值, 那 么 这 段 文 字 就 可 以 动 态 地 被 显 示 出 来。 这 需 要Script 的 支 持, 下 面 就 是 一 个 让 上 面 那 样 的 文 字 显 示 和 隐 藏 起 来 的 两 个JavaScript 函 数, 只 要 将 自 定 义 的Div 的Id 值 代 入, 对 应 的 文 字 就 显 示 或 隐 藏 起 来 了:


 < script language="JavaScript" >
function ShowDiv(DivId)
{
	document.all[DivId].style.display='';
	return 0;
}
< /script >
function HideDiv(DivId)
{
	document.all[DivId].style.display='none';
	return 0;
}
< /script >

---- 有 了 这 两 个 函 数, 就 要 考 虑 在 什 么 时 候 调 用 它 们。 熟 悉Script 编 程 的 读 者 当 然 已 经 想 到, 可 以 把 它 们 放 到 事 件 响 应 过 程 之 中 了。 大 体 的 形 式 可 能 是 这 样:


 < a href="#" onclick="return ShowDiv('test');" >显示< /a >
< a href="#" onclick="return HideDiv('test');" >隐藏< /a >

---- 将 上 面 的 片 段 组 合 到 一 个HTML 文 件 中, 也 算 是 一 个 完 整 的 例 子 了, 用IE4 试 验 一 下, 看 看 是 否 达 到 了 预 期 的 效 果。( 注 意:JavaScript 是 大 小 写 敏 感 的, 排 版 时 可 能 出 现 差 错, 实 际 应 用 中, 最 好 都 用 小 写。)

---- 有 了 以 上 的 了 解, 制 作 一 个 伸 缩 式 的 层 次 列 表, 只 是 由 简 到 繁 的 过 程, 所 以 我 也 就 不 必 做 什 么 解 释, 只 提 供 一 个 例 子 做 为 参 考, 这 个 例 子 也 是 我 们 下 一 步 要 用 程 序 来 实 现 的 一 个 结 果:


  文 件 名:LsTest.htm
< html >
< head >
< title >DyList Test< /title >
< script language="JavaScript" >
/>
	根据对象当前的属性,改变对象的显示状态
>/
function OnClickDiv(DivId)
{
	if(document.all[DivId].style.display=='none')
	  { document.all[DivId].style.display=''; }
	else
	  { document.all[DivId].style.display='none'; }
	return 0;
}
< /script >
< /head >
< body >
< h3 >List Start< /h3 >< hr >
< Div Id="dy1" Style=display: >< ul >
< li >< a href="#" onclick="return
OnClickDiv('dy2')") >国内报刊< /a >
< Div Id="dy2" Style=display:none >< ul >
< li >< a href="http://www.peopledaily.com.cn" >
人民日报< /a >
< li >< a href="http://www.gmdaily.com.cn" >
光明日报< /a >
< li >< a href="#" onclick="return
OnClickDiv('dy3')") >大众日报< /a >
< Div Id="dy3" Style=display:none >< ul >
< li >< a href="http://www.dzdaily.com.cn" >
大众日报< /a >
< li >< a href="http://www.dzdaily.com.cn/ncdz.htm" >
农村大众< /a >
< li >< a href="http://www.dzdaily.com.cn/qlwb.htm" >
齐鲁晚报< /a >
< li >< a href="http://www.dzdaily.com.cn/shrb.htm" >
生活日报< /a >
< /ul >< /div >
< /ul >< /div >
< li >< a href="#" onclick="return OnClickDiv('dy4')") >
搜索引擎< /a >
< Div Id="dy4" Style=display:none >< ul >
< li >< a href="http://gbchinese.yahoo.com" >
雅虎< /a >
< li >< a href="http://www.sohoo.com.cn" >
搜狐< /a >
< /ul >< /div >
< /ul >< /div >
< hr >< h3 >List End< /h3 >
< /body >
< /html >

---- 实 现 自 动 化

---- 上 面 的 一 大 堆 东 西, 谁 看 了 都 会 眼 花 缭 乱 的。 不 过 在IE4 上 浏 览 的 效 果, 又 确 实 酷 得 让 人 心 痒, 所 以 费 一 点 力 气, 用 程 序 将 这 一 烦 琐 的 制 作 过 程 自 动 化 一 下, 是 完 全 值 得 的。 一 个 简 单 的 思 路: 将 树 状 层 次 结 构 的 数 据 保 存 到 一 个 简 洁 的 文 件 载 体 当 中, 写 一 段 通 用 的 程 序 从 载 体 文 件 中 读 取 数 据, 生 成 我 们 所 要 的HTML 文 件。 那 么 头 一 步 是 要 选 择 什 么 样 的 载 体 啦, 数 据 库 方 式 当 然 最 值 得 考 虑, 但 这 将 牵 扯 出 一 大 堆 的 问 题, 我 想 还 是 在 另 一 个 专 题 里 来 讨 论 吧, 在 这 里 我 选 择 了Windows 平 台 上 常 用 的.ini 文 件, 这 种 文 件 很 适 合 于 保 存 树 状 的 层 次 数 据, 并 且 系 统 平 台 已 经 提 供 了 基 本 的 操 作 函 数, 可 以 大 大 省 些 力 气。

---- 我 把 这 一 过 程 制 成 了ASP(Active Server Page) 的 形 式, 这 样 拿 过 来 就 可 以 直 接 使 用 了, 当 然 有 时 还 是 需 要 静 态 的HTML 文 件, 那 么 可 以 把ASP 中 的 代 码 转 移 到VB 程 序 中, 也 并 不 困 难。 为 了 能 在ASP 中 处 理.ini 文 件, 用 到 了 我 以 前 写 的 一 个ActiveX 服 务 对 象, 这 个 服 务 对 象 将 对.ini 文 件 操 作 的 各 种 函 数 函 数 封 装 在 一 个 类(class) 中, 我 用 起 来 已 经 有 顺 手 了, 下 面 开 始 我 们 的 程 序 设 计 吧, 先 来 看 一 下 树 状 的 层 次 数 据 保 存 在.ini 文 件 中 的 形 式:


  文 件 名:LsTest.ini
[root]
a= 国 内 报 刊
b= 搜 索 引 擎

[a] a1= 人 民 日 报,http://www.peopledaily.com.cn a2= 光 明 日 报,http://www.gmdaily.com.cn a3= 大 众 日 报
[a3] a3_1= 大 众 日 报,http://www.dzdaily.com.cn/ a3_1= 农 村 大 众,http://www.dzdaily.com.cn/ncdz.htm a3_1= 齐 鲁 晚 报,http://www.dzdaily.com.cn/qlwb.htm a3_1= 生 活 日 报,http://www.dzdaily.com.cn/shrb.htm
[b] b1= 雅 虎,http://gbchinese.yahoo.com b2= 搜 狐,http://www.sohoo.com.cn

---- 文 件 中 表 现 出 的 树 状 层 次 关 系 非 常 明 显, 你 只 要 稍 微 花 点 心 思 就 一 定 能 够 明 白 了。 这 里 我 做 了 一 个 小 小 的 约 定, 就 是 每 一 个 条 目 的 等 号 后 面, 首 先 是 这 个 条 目 的“ 标 题”, 它 是 不 应 省 略 的。 之 后 是 该 条 目 的 超 级 链 接 地 址, 由 一 个 逗 号 进 行 分 隔, 如 果 没 有 地 址, 就 表 明 它 还 有 下 一 层 的 子 条 目。

---- 要 在ASP 程 序 中 使 用 自 制 的ActiveX 服 务 对 象, 首 先 要 把 该 服 务 程 序 安 装 到ASP 程 序 运 行 的 机 器 上, 然 后 在ASP 程 序 中 建 立 这 个 对 象, 我 想 这 些 大 家 一 定 也 有 些 经 验 了, 这 里 就 不 多 说 了。 那 么 列 出 一 个 主 题 中 的 所 有 子 条 目, 大 概 的 形 式 就 如 下 面 的 样 子:


Set Prof = Server.CreateObject("vbProFile.ProFile")
Prof.FileName = proPath
Buf = Prof.FirstValue(" 主 题 名")
Do While Len( Buf )  > 0
	... ...
	Buf = Prof.NextValue()
Loop

----     在 上 面 的 循 环 中,Buf 中 接 收 的 数 据 是 这 样 的 一 种 形 式:“ 条 目 名= 条 目 标 题, 链 接 地 址”, 为 了 便 于 在 程 序 中 使 用, 用InitDyItemStr 函 数 将 字 符 串 分 解 到 定 义 好 的 全 局 变 量 当 中:


 < !--#INCLUDE FILE="Str.inc"-- >
< %
gDyItemName=""		' 当 前 条 目 的 名 称
gDyItemTitle=""			' 当 前 条 目 的 标 题
gDyItemLink=""			' 当 前 条 目 的 链 接 地 址

Sub InitDyItemStr( s ) gDyItemName = StrHead(s, "=") gDyItemTitle = StrHead(s, ",") gDyItemLink = s End Sub % >

---- 这 里 调 用 了 一 个StrHead 函 数, 这 个 函 数 也 是 出 自 本 人 之 手, 在 处 理 字 符 串 时 十 分 有 用, 是 我 在 编 程 时 使 用 频 率 最 高 的 函 数 之 一。 另 外 为 了 方 更 地 在 程 序 中 输 出 引 号, 就 写 了 一 个 专 门 在 字 符 串 两 端 加 上 引 号 的 函 数, 因 为 在 编 写ASP 程 序 时 常 常 要 调 用 这 两 个 函 数, 所 以 我 单 独 把 他 们 放 在 一 个 文 件 中, 在 要 使 用 时 把 这 个 文 件 包 含 进 行 就 可 以 了, 下 面 就 是 这 个 文 件:


  文 件 名:Str.inc
< %
' 在 第 一 次 遇 参 数c 的 位 置 载 取ss
' 返 回 载 取 的 前 半 载,ss 中 保 留 后 半 载
' 当ss 中 不 包 含c 时, 相 当 于 从ss 的 最 后 载 取
Public Function StrHead(ss, c)
i = InStr(ss, c)
If i  > 0 Then
StrHead = Mid(ss, 1, i - 1)
ss = Mid(ss, i + Len(c))
Else
StrHead = ss
ss = ""
End If
End Function
' 在s 的 两 端 加 上 引 号 返 回
Public Function YH(s)
YH = Chr(34) & s & Chr(34)
End Function
% >

---- 在 响 应OnChick 事 件 时, 为 书 写 简 单, 可 以 先 写 成 一 个JavaScript 函 数, 以 备 调 用( 注 意: 这 里 的Java Script 函 数 是 在 浏 览 器 上 执 行 的, 一 定 要 与 服 务 器 端 执 行 的 代 码 区 分 开 来):


 < script language="JavaScript" >
function OnClickDiv(DivId)
{
	if(document.all[DivId].style.display=='none')
	  { document.all[DivId].style.display=''; }
	else
	  { document.all[DivId].style.display='none'; }
	return 0;
}
< /script >

---- 为 了 给 每 一 个 条 目 在 页 面 上 建 立 一 个 唯 一 的ID 值, 以 便 在 事 件 处 理 过 程 中 进 行 操 作, 所 以 定 义 了 一 个 全 局 的 计 数 器 和 一 个ID 构 造 函 数:


 < %
curDyItemIndex=0
Function DyItemId()
	DyItemId="dy" & curDyItemIndex
End Function
% >

---- 有 了 这 些 准 备 工 作, 最 后 的 输 出 就 不 难 了, 提 炼 一 下 我 们 要 完 成 的 任 务, 就 在 从LsTest.ini 文 件 中 读 取 数 据, 输 出 如LsTest.htm 文 件 中 的 格 式 数 据。 由 于 数 据 是 树 状 的, 所 以 很 自 然 地 会 使 用 上 函 数 的 递 归, 请 看 下 面 实 现 的 主 体 函 数:


Sub ListItems(proPath,ItemName,Disp)
	'建立并初始化ProFile对象
	Set ItemProf = Server.CreateObject("vbProFile.ProFile")
	ItemProf.FileName = proPath
	
	'开始一个DIV对象,包含所有的子条目在其中
	Response.Write "< Div Id=" & YH(DyItemId) & _
		" Style=display:" & Disp & " >< ul >" & vbCrLf

'开始输出每一个子条目 buf = ItemProf.FirstValue(ItemName) Do While Len(buf) > 0 InitDyItemStr buf If Len(gDyItemLink) > 0 then Response.Write "< li >< a href= " & YH(gDyItemLink) & " >" & _ gDyItemTitle & "< /a >" & vbCrLf Else '如果链接地址为空,则开始下一层的列表 curDyItemIndex = curDyItemIndex + 1 Response.Write "< li > < a href=" & YH("#") & _ " onclick=" & YH("return OnClickDiv ('" & DyItemId & "')") & _ ") >" & gDyItemTitle & "< /a >" & vbCrLf ListItems proPath,gDyItemName,"none" '使用递归 End If
buf=ItemProf.NextValue() Loop
'结束定义的DIV对象 Response.Write "< /ul >< /div >" & vbCrLf End Sub   最后为了调用方便,再定义一个对外的接口函数: Public Sub DyList(proName,rootItem) '将逻辑路径映射成物理路径 proPath=Server.mappath(proName) curDyItemIndex = curDyItemIndex + 1 ListItems proPath,rootItem,"" End Sub

----     把 上 面 这 些 片 段 保 存 到 一 个 文 件 中, 文 件 名 就 叫dyList.inc 吧, 我 们 就 算 大 功 告 成 了, 你 是 不 是 想 马 上 看 看 效 果 呢 ? 用 下 面 这 个ASP 文 件 来 做 一 下 实 验, 瞧 瞧 你 是 否 满 意 ?


  文 件 名:LsTest.asp
< html >
< head >
< title >DyList Test< /title >
< !--#INCLUDE FILE=" dyList.inc"-- >
< /head >
< body >
< h3 >List Start< /h3 >< hr >
< %
	DyList "lsTest.ini","root"
% >
< hr >< h3 >List End< /h3 >
< /body >
< /html >

---- 走 向 完 善

---- 功 能 是 实 现 了, 但 在 美 观 程 度 上 还 不 能 尽 人 意, 不 过 这 是 让 每 个 人 施 展 各 自 绝 活 的 时 候, 我 可 就 不 便 包 办 了。 这 里 我 只 提 出 几 个 我 想 到 的 改 进 方 式, 供 大 家 参 考:

---- 通 过 响 应onmouseover 和onmouseout 两 个 事 件, 可 以 做 到 当 鼠 标 移 到 某 一 个 条 目 上 时, 令 其 变 成 与 众 不 同 的 颜 色, 这 功 能 实 现 起 来 不 难, 确 很 有 效 果, 何 乐 而 不 为 呢 ? 只 要 在 条 目 输 出 时, 象 下 面 的 样 子 加 上 点 内 容, 想 要 的 效 果 就 有 了:


 < a ... onmouseover="this.style.color=COLOR1"
onmouseout="this.style.color=COLOR2" ...  >

---- 再 有 一 点, 在 列 表 中, 我 们 使 用 的 是

后一页
前一页

回首页