我们看到在数码艺术网的首页上,四个主要栏目版块中的列表是折叠式的。如下图:
当鼠标经过第二个标题时,第一个列表项折叠,第二个展开。大家想到了Ajax技术,不过这里的摘要信息并没有异步更新,而是提早加载好的。所以折叠列表虽然具有Ajax技术的动作特点,却不是Ajax。我只是通过javascript控制<div>的隐藏和显示。
折叠列表的主要思路是,用规范的 javascript DOM 编程来切换<div>的CSS类。ListSummary为显示,ListSummaryHidden为隐藏。(我把CSS的id和class名都用大写字母开头,以区别javascript脚本程序里小写开头的习惯用法。)
首先,把第一个版块的HTML编写好,大致如下:
<div id="NewDesignInfo">
<div class="PanelHead1">
<div><a href="#"><img _fcksavedurl=""#"><img" _fcksavedurl=""#"><img" src="Icon_Title/PanelNameDeisgnNews.jpg" /></a></div>
</div>
<div class="PanelBody1">
<ul class="List">
<li class="ListItem">
<div><span class="ListCateLog">[<a href="#">子栏目一</a>] </span><span class="ListTitle"><a href="#">标题javascript折叠式列表的制作</a></span><span class="ListDate">2005-05-12</span></div>
<div class="ListSummaryHidden"><img src="TempImages/ThumbImg.jpg" class="ListThumb" />我们看到在数码艺术网(http://www.hutda.cn)的首页上,四个主要栏目版块中的列表是折叠式的。如下图,当鼠标经过第二个标题,第一个列表项折叠,第二个...</div>
</li>
<li class="ListItem">
<div><span class="ListCateLog">[<a href="#">子栏目二</a>] </span><span class="ListTitle"><a href="#">标题javascript折叠式列表的制作</a></span><span class="ListDate">2005-05-12</span></div>
<div class="ListSummaryHidden"><img src="TempImages/ThumbImg.jpg" class="ListThumb" />我们看到在数码艺术网(http://www.hutda.cn)的首页上,四个主要栏目版块中的列表是折叠式的。如下图,当鼠标经过第二个标题,第一个列表项折叠,第二个...</div>
</li>
<li class="ListItem">(这里同上)</li>
<li class="ListItem">(这里同上)</li>
<li class="ListItem">(这里同上)</li>
</ul>
</div>
</div>
(这里我不对HTML做过多解释,想必大多数读者能轻松的阅读。)
注意加粗的部分。
NewDesignInfo 是第一个版块“设计资讯”的ID编号,这个很重要,关系到后面javascript函数的使用。既然是ID,我们便要给每个版块建立一个ID名。如果版块不是固定的,可以起名panel1,panel2,panel3……,以便javascript的循环语句来调用。
缩略图和摘要所在的<div>的class是ListSummaryHidden,初始即为隐藏状态,后面我们再通过javascript让它切换成ListSummary。把类和ID的名称起的直观易读以便你的合作者和一年后的你都能轻松明白它的意思。还要注意,这个<div>是<li>中的第二个<div>。
然后,我们编写CSS。这应该由你自己去创意,关键在于下面两个类选择符的display属性:
.ListSummary {display:block;}
.ListSummaryHidden {display:none;}
好了,现在可以开始编写javascript,我会逐行解释。先看完整的:
function puckerList(element_id) { //遍历element_id中的<li>与<div>
var list_item = document.getElementById(element_id).getElementsByTagName("li");
var list_div = document.getElementById(element_id).getElementsByTagName("div");
list_item[0].getElementsByTagName("div")[1].className = "ListSummary";
for (var i=0; i<list_item.length; i++){
list_item[i].onmouseover = function(){
//查找已展开的<div>并将其隐藏
for (var j=0; j<list_div.length; j++){
if (list_div[j].className == "ListSummary") {
list_div[j].className = "ListSummaryHidden";
}
}
//展开<div>
var list_summary = this.getElementsByTagName("div");
if (!list_summary[1].className){
list_summary[1].className = "ListSummary";
}
}
}
}
第1行,function puckerList(element_id) 是构造一个自定义函数,名为puckerList 。element_id是参数,即是函数内部要用到的变量,后面就能知道它到底有什么用途。
function puckerList(element_id) {
......
}
第2行、第3行我们要遍历“设计资讯”版块里的所有<li>与<div>。
什么是遍历?就是找到所有的<li>和<div>并编号。注意,编号是从0开始的。怎么遍历呢?拿第2行解释。
var list_item = document.getElementById(element_id).getElementsByTagName("li");
document.文档中的,也就是这个页面中的。“点”就是“的”的意思。
getElementById(element_id).按ID名查找,获取名为element_id的<div>。element_id是一个变量,在“设计资讯”版块里,即是NewDesignInfo
getElementsByTagName("li");这是按照元素名称(HTML标签名)查找,获取设计资讯里的所有<li>,那肯定有好几个,所以这里是Elements复数。上一个是单数,因为ID肯定独一无二。这一行结束,还要记得分号。
<li>遍历好了,就把结果赋予给list_item ,它是一个数组变量。
那么,在前面的HTML中,一共有5个<li>,编号0,1,2,3,4。<div>有很多个,不去算它了,等会要用时也不用管它具体几个。
第4行用来让列表中的第一个条新闻显示出摘要信息。
list_item[0].getElementsByTagName("div")[1].className = "ListSummary";
第一条便是编号为0的<li>,表示为list_item[0]。
之前我们提过,摘要所在的<div>是第二个,getElementsByTagName("div")遍历了第一个<li>里的所有<div>。getElementsByTagName("div")[1]直接表示其中的第二个<div>。为什么之前我们用list_item和list_div数组变量来存储遍历结果,现在却不存储了?当然,我也可以这样做,那么第4行将变成两行:
var list_li_div = list_item[0].getElementsByTagName("div");
list_li_div[1]].className = "ListSummary";
由于getElementsByTagName("div")我们只用这一次,这样做就繁琐了一点。list_item和list_div在后面不止用一次,最好用变量存储起来,也为了代码简洁易读。
className = "ListSummary";也就是把<div class="ListSummaryHidden">改为<div class="ListSummary">。
解释到这里,你对getElementById , getElementsByTagName 以及如何改变所调用的类应该明白很多了。这也就是规范的DOM(文档对象模型)方法。
第5行是一个循环语句,里面有两个动作。
for (var i=0; i<list_item.length; i++){
......
}
第一个是把已展开的摘要信息关闭,那我怎么知道当前哪一条摘要是展开的呢?别管它,再用一个循环语句,把只要是打开的门全关上,就算是我眼前这扇门。那么这个循环就用上list_div这个数组,把“设计资讯”里的所有的class="ListSummary"改成class="ListSummaryHidden"。
for (var j=0; j<list_div.length; j++){
if (list_div[j].className == "ListSummary") {
list_div[j].className = "ListSummaryHidden";
}
}
第二个动作把当前鼠标经过的这条新闻的摘要信息展开。第一个动作把所有门关上了,我再主动把眼前这扇门打开。
这时还要再遍历一次,来查找<li>中的所有<div>。之前好像我们做过一次了,没错,是好像做过,在第4行,但不完全一样。之前是遍历第一条新闻,现在是在循环语句里,每条新闻都做一次。遍历之后结果存在list_summary中。
var list_summary = this.getElementsByTagName("div");
随后做了一个判断,判断我眼前是门还是窗户。if (!list_summary[1].className)用来判断第二个<div>是否有class值,感叹号表示“非”,也就是“如果class值非空”则执行下一行。
if (!list_summary[1].className){
list_summary[1].className = "ListSummary";
}
这两个动作通过一个命令来执行,也就是onmouseover(当鼠标经过时)。
list_item[i].onmouseover = function(){
......
}
这里最好用一个临时函数,才能执行两个动作。list_item[i]又是什么?在第4行我们用到的是list_item[0],表示第一个<li>。这里的 i 是第5行的循环语句里的变量。第一次循环i=0,第二次i=1,依此类推。i最大不超过<li>的总数量list_item.length。
到这里,我们的puckerList函数已经编写完,接下来要让设计资讯这个版块能够执行这个函数。代码如下:
window.onload = function(){
puckerList('NewDesignInfo');
puckerList('NewResource');
puckerList('NewJob');
}
window.onload 意为当整个窗口(页面)加载完毕。
window.onload = function()构造一个临时函数,就可以执行三个命令了。三个命令分别让“设计咨询”、“最新资源”和“招聘信息”三个版块都执行了puckerList函数。这时候明白element_id这个参数的用意了吧?前面提到,如果版块不固定,起名panel1,panel2,panel3……,就要在这里写循环语句来用,这就让你自己思考去。
还没完,javascript文件已经编写完整了,并命名为PuckerList.js ,但还没把它和网页绑定呢。
回到HTML的页面,在<head></head>之间插入下面代码:
<script type="text/javascript" src="PuckerList.js"></script>
最后提一个要点,你是否发现,HTML页面里没有任何的javascript代码。就像我们不把CSS属性写在HTML一样,javascript也要尽量分离开。一个纯HTML文件(结构),一个纯javascript文件(行为)和一个纯CSS文件(表现),只通过<script>,<style>,id和class来相互沟通。
我写过教程不多,用问题欢迎指正,有意见请踊跃提出,谢谢您的阅读。