纸上来得终觉浅,绝知此事要躬行,我不知道读者在看完在Xslt中用递归做无限级分类三部曲之初级篇有没有自己尝试去改进一下呢,如果没有,我建议你先自己对之进行扩展再来看这篇。如果你还没有看的话,那你应该先去看基础篇,因为只有在第一篇的基础之上,才理解本篇,
虽然在上一篇我们实现了无限级分类,但我们对实现的结果还是不满意,因为实现的树居然不能收缩,这是无法容忍的。所以在这一节,我们将要攻克这个难关,实现可以收缩的树。
应该是怎么收缩呢?收缩有两种方式,一种是点击当节点,就收缩或扩展当前子节点,我把它称之为单一收缩;另一种是点击当前节点,如果当前节点是收缩状态,则扩展当前节点并且收缩其它同级节点,反之则收缩当前节点,我将之称之为联动收缩。两种方式各有优劣,根据不同的情况与不同人的爱好也会有不同的需求,怎么办呢?我想在xml中加一个开关,在xslt根据此开关,来判断是否收缩其它同级节点。于是我在上一篇规划的xml中的根节点的Items中增加一个这样的属性AutoShrink,是否自动收缩,用yes|y|1表示自动收缩同级节点,用no|n|0表示不自动收缩。
如何实现收缩呢?我记得我以前在做一个项目的时候,也有一个无限级分类的树,当时是用ASP做的,我当时用的方法就是为每一个标签命名,在事件处理时将相关的标签作为参数传递,这种做法有两个缺点,其一是每个标签都要有ID,占用太多的资源;其二是无法实现联动收缩。
到了这里,我认为我有必要对一些命名进行约定,以便于接下来的描述,我把用鼠标点击并引发事件的节点叫
点击节点,如图1你的鼠标点击在索引节点1上,那么索引节点1就是
点击节点;把在Javascript中作循环的时候循环到某个节点叫
当前循环节点;把拥子节点的节点称之为
节点子集,如图1中的红色部分被称之为索引节点1的节点子集,蓝色部分被称之为索引节点1.2的节点了集;把拥有节点子集的节点称之为索引节点;把没有节点子集的节点称之为
标题节点。
(图1)
如何实现联动收缩呢?我们主要用DOM的三个属性来实现,这三个属性分别是nextSibling、parentNode、childNodes,nextSibling用于获取当前节点的下一个兄弟节点,parentNode用于获取当前节点的父级节点,childNodes用于获取所有子节点。
让我们来实现最简单的一步,我们可以根据点击节点的className属性于判断需要扩展还是收缩节点子集(实际就是把style.display设置为none),在这里,我们需要用到DOM的nextSibling属性来获取下一个兄弟节点(索引节点的下一个兄弟节点一定是节点子集),也就是点击节点的节点子集。
我们想要实现联动收缩,就需要对当前节点的所有兄弟节点进行操作,如何获得当前节点的兄弟节点呢?DOM并没有提供这个方法,但我们可以先获取当前节点的父级节点(parentNode),再获取父级节点的所有子节点,这样就取得了包括当前节点在内的所有兄弟节点了。现在我们可以对子节点进行循环处理,便可以实现联动收缩了。在这里我们需要注意一点,对于已经收缩的的节点、节点子集、标题节点以及点击节点,我们可以跳过,因为这些节点不需要进行处理。
图2 Javascript处理流程
说了这么多,我们应该来看看Javascript了,在Javascript中已经有备注,我就不再作描述了:
// JavaScript Document
function ExtendTree(oCur, sShrink)
{
var className = oCur.className;
//这个属性很重要,在DOM中,nextSibling表示下一个兄弟节点
var subNode = oCur.nextSibling;
subNode.style.display = ("minus" == className) ? "none" : "block";
oCur.className = ("minus" == className) ? "plus" : "minus";
//如果当前节点是扩展,同需要扩展其它同级节点
if ("plus" == className &&
("y" == sShrink ||
"yes" == sShrink ||
"1" == sShrink
)) ShrinkAll(oCur);
}
function ShrinkAll(oCur)
{
//取当前的父节点
var parent = oCur.parentNode;
//取当前父节点的所有子节点
var childs = parent.childNodes;
for(var i = 0; i < childs.length; i++)
{
var child = childs[i];
var className = child.className;
/*
如果节点的class样式是title,则表示没有子节点;
如果样式是plus,则表示已经收缩;
如果节点==oCur,则表示当前循环的节点是点击的节点
如果节点样式等于SubTree,则表示是一个子节集,不需要直接处理
对于这几类节点都不需要处理,可以直接跳过
*/
if ("title" == className ||
"plus" == className ||
"SubTree" == className ||
child == oCur
) continue;
//取得同级兄弟节点
var subNode = child.nextSibling;
subNode.style.display = "none";
child.className = "plus";
}
}
Xslt中仅增加了Class样式及根据是否有子节点来判断是否增加点击事件,读者可以下载源码,限于篇幅,我不再赘述。是不是认为这棵树已经够好了呢?不,它还有改进的余地,还可以变得更加功能强大,让我们追求更加完美的树。
欲知后事如何,且听下回分解
在Xslt中用递归做无限级分类三部曲之终极篇
效果预览
(因为Firefox对xslt的解析机制不同,故仅支持IE)
注意:本文为我的独立博客镜像博客,自发表不再更新,原文可能随时被更新,敬请访问原文。同时,请大家不要在此评论,如果有什么看法,请点击这里:http://iove.net/1705/
本文来自http://iove.net,欢迎转载,转载敬请保留相关链接,否则视为侵权,原文链接:http://iove.net/1705/