DeepTree在多表中的应用

今天,我们说说使用Deeptree的一个心得技巧。可能还有不知道Deeptree是什么的兄弟,deeptree是微软最早使用在msdn里作为导航树的,在ajax大行其道之前已经以优秀的设计及出众的性能(不是一次性加载数据,而是使用的时候再加载,套句术语就是属于“lazy loading”)为广大开发者争相采用。

下面,简单介绍下deeptree的组成,它主要包括以下几个文件:

deeptree.htc:负责处理数据加载,用户事件
deeptree.xsl:负责将xml数据格式化为html,展现给用户
deeptree.css:负责树的显示风格
server.asp:负责从服务器获取数据

Deeptree一般是使用单表作为数据源的,表结构一般是类似这样:

栏目表
列名列类型
栏目ID自增数字型
栏目名称

字符型

父栏目ID

数字型

deeptree在生成树的过程中,一般流程如下:

  1. htc里定义了server.asp和deeptree.xsl文件
    var  Config = {
        loading:
    " 正在加载,请稍候... " , // 加载时显示信息
        unavaible: " 加载失败,请检查... " , // 加载失败时显示信息
        Service: " getAreaByType.asp " , // 节点数据文件
        SyncXSLsrc: " deeptree_area.xsl " , // 一次加载时xsl文件
        isExpandOne: true   // 同一级别是否只允许打开一个节点
    }
  2. htc里调用Init()方法初始化数据
    function  Init(){
        GetXml(element,
    0 )
    }
  3. GetXml(objContainer,id)方法从服务器获取数据(XMLHTTP),格式如下:
    <? xml version="1.0" encoding="gb2312" ?>
    < xml >
    < TreeNode  id ="1" >
    < NodeText > 旅游 </ NodeText >
    < title ></ title >
    < NodeUrl > searchform.php?fdIcoId=1 </ NodeUrl >
    < child > 2 </ child >
    < target > showresult </ target >
    </ TreeNode >
    < TreeNode  id ="4" >
    < NodeText > 房产 </ NodeText >
    < title ></ title >
    < NodeUrl > searchform.php?fdIcoId=4 </ NodeUrl >
    < child > 5 </ child >
    < target > showresult </ target >
    </ TreeNode >
    </ xml >
  4. xml数据+deeptree.xsl文件处理,生成html并显示
  5. 当用户点击节点的时候,调用htc里的ExpandNode(objNode)方法加载数据(GetXml)

下面,是一个deeptree处理多表的问题,这里是一个地区数据,分为国、省、市三级,这三级的数据分别存在三张表里,如下:

国家
列名列类型
国家ID自增数字型
国家名称字符型

省份
列名列类型
省份ID自增数字型
省份名称字符型
国家ID数字型,外键

地市
列名列类型
地/市ID自增数字型
地/市名称字符型
省份ID数字型,外键

问题来了,如何在用户点击节点的时候,判断用户当前点击的是国家、省份还是地市呢?

我的处理方法是这样的:

  1. 修改GetXml方法,添加一个areaType参数:
    function  GetXml(objContainer,id,areaType){
        
    var  XmlHttp = new  ActiveXObject( " Microsoft.XMLHTTP " )
        objContainer.innerHTML
    = StateXML(Config.loading)
        objContainer.send
    = " true "
        XmlHttp.onreadystatechange
    = function (){
            
    if (XmlHttp.readyState == 4 ){
                
    if (XmlHttp.status == 200 ){
                
    var  Xmldoc = XmlHttp.responseXML
                    
    if (Xmldoc.documentElement.hasChildNodes())
                    objContainer.innerHTML
    = Xmldoc.transformNode(xsldoc)
                    
    else
                    objContainer.innerHTML
    = StateXML(Config.loading)
                }
                
    else
                objContainer.innerHTML
    = StateXML(Config.unavaible)
            }
        }
        
    var  url = Config.Service + ' ?id= ' + id + ' &areaType= ' + areaType + ' &tem ' + Math.random()
        
    // alert(url)
        XmlHttp.open( " get " ,url, true )
        XmlHttp.send()
    }
  2. 初始化的时候,areaType默认设为country
    function  Init(){
        GetXml(element,
    0 , " country " )
    }
  3. 修改ExpandNode方法
    function  ExpandNode(objNode){
        
    var  oImg = GetElement(objNode, " img " )
        
    var  oNode = GetElement(objNode, " span " )
        
    var  oChild = objNode.nextSibling
        oImg.src
    = icon.open.src
        oChild.style.display
    = ""
        objNode.open
    = " true "
        
    // alert(objNode.areaType)
         if (oChild.send == " false " )GetXml(oChild,objNode.uid,objNode.areaType)
        
    if (Config.isExpandOne){
            
    var  oContainer = objNode.parentElement
            
    var  oChildren = oContainer.children
            
    for (i = 0 ;i < oChildren.length;i ++ )
            
    if (oChildren[i].open == " true " && oChildren[i] != objNode)CollapseNode(oChildren[i])        
        }
    }
     
  4. 修改XML数据格式,添加areaType属性:
    <? xml version="1.0" encoding="gb2312" ?>  
    < xml >
    < TreeNode  id ="1"  areaType ="province" >
    < NodeText > 安哥拉 </ NodeText >
    < title ></ title >
    < NodeUrl > DD_Area_Form.asp?id=1 &amp; title=安哥拉 &amp; type=country </ NodeUrl >
    < child > 0 </ child >
    < target > mainFrame </ target >
    </ TreeNode >
    </ xml >
  5. 修改deeptree.xsl文件,为生成的树节点(div)增加areaType属性,使用xpath从xml数据中获取areaType的值:
    < xsl:attribute  name ="areaType" >< xsl:value-of  select ="@areaType" /></ xsl:attribute >
  6. 修改数据读取程序,其中有个问题,如何判断用户当前点击的是国家、省份还是地市?我们从代码的角度进行分析下,从第二步可以看到,初始化的时候:id=0,areaType=country,系统初始化以后会首先取得国家表的数据,那么当我们点击节点,希望取得的是某个国家内的省份数据,处理方式为:
    1. 判断id是否为0,若为0则设置xml数据的areaType属性值为province(省)
    2. 点击节点的时候激活ExpandNode方法,通过GetXml访问如下Xml:
      http:/getAreaByType.asp?id=37&areaType=province
      取得如下xml数据:
      <? xml version="1.0" encoding="gb2312" ?>  
      < xml >
      < TreeNode  id ="1"  areaType ="city" >
      < NodeText > 北京市 </ NodeText >
      < title ></ title >
      < NodeUrl > DD_Area_Form.asp?id=1 &amp; title=北京市 &amp; type=province </ NodeUrl >
      < child > 1 </ child >
      < target > mainFrame </ target >
      </ TreeNode >< TreeNode  id ="2"  areaType ="city" >
      < NodeText > 天津市 </ NodeText >
      < title ></ title >
      < NodeUrl > DD_Area_Form.asp?id=2 &amp; title=天津市 &amp; type=province </ NodeUrl >
      < child > 1 </ child >
      < target > mainFrame </ target >
      </ TreeNode >
      </ xml >
    3. 此时就会显示某国家的省份数据,此时id不等于0,那么我们可指定areaType=city,那么当用户单击省份的时候就会获取城市的数据:
      <? xml version="1.0" encoding="gb2312" ?>  
      < xml >
      < TreeNode  id ="134"  areaType ="city" >
      < NodeText > 南昌市 </ NodeText >
      < title ></ title >
      < NodeUrl > DD_Area_Form.asp?id=134 &amp; title=南昌市 &amp; type=city </ NodeUrl >
      < child > 0 </ child >
      < target > mainFrame </ target >
      </ TreeNode >< TreeNode  id ="135"  areaType ="city" >
      < NodeText > 景德镇市 </ NodeText >
      < title ></ title >
      < NodeUrl > DD_Area_Form.asp?id=135 &amp; title=景德镇市 &amp; type=city </ NodeUrl >
      < child > 0 </ child >
      < target > mainFrame </ target >
      </ TreeNode >
      </ xml >
  7. 总结下,这里的问题关键是以下几个方面:
    1. 为xml数据增加areaType属性;
    2. 修改deeptree.xsl文件,添加areaType属性;
    3. 修改deeptree.htc文件,添加areaType参数;
    4. 根据id来判断地区类型。
  8. 附:getAreaType.asp源代码:
    < %@LANGUAGE = " VBSCRIPT "  CODEPAGE = " 936 " % >
    < ! -- #include file = " ../System/Conn.asp "   -->
    < %
    ' 项目类型
    dim  id,areaType,target
    id 
    =  request.QueryString( " id " )
    areaType 
    =  request.QueryString( " areaType " )
    target 
    =   " mainFrame "
    if  areaType  =   ""   then
        areaType 
    =   " country "
    end   if
    ' 项目类型数据集
    dim  rs
    ' 查询项目类型sql字符串
    dim  sql,areaId,areaName

    if  areaType  =   " province "   then
        sql 
    =   " select province_id,province_name from d_Province where country_id= " &  id  & "  order by province_id "
        areaId 
    =   " province_id "
        areaName 
    =   " province_name "
    elseif  areaType  =   " city "   then
        sql 
    =   " select city_id,city_name from d_City where province_id= " &  id  & "  order by city_id "
        areaId 
    =   " city_id "
        areaName 
    =   " city_name "
    elseif  areaType  =   " country "   then
        sql 
    =   " select Country_id,Country_Chinese_Name from D_Country order by Country_id "
        areaId 
    =   " Country_id "
        areaName 
    =   " Country_Chinese_Name "
    end   if

    ' 打开数据集
    set  rs = Conn.execute(sql)
    ' 定义xml字符串变量
    dim  xml
    xml 
    =   " <?xml version=""1.0"" encoding=""gb2312""?>  "   &  vbcrlf
    xml 
    =  xml  &   " <xml> "   &  vbcrlf
    ' 循环xml文件数据体
    while  ( not  rs.eof)
        xml 
    =  xml  &   " <TreeNode id="" " &  rs(areaId)  & " "" areaType="" " &  getAreaType(id)  & " ""> "   &  vbcrlf
        xml 
    =  xml  &   " <NodeText> "   &  rs(areaName)  &   " </NodeText> "   &  vbcrlf
        xml 
    =  xml  &   " <title></title> "   &  vbcrlf
        xml 
    =  xml  &   " <NodeUrl> "   &  getUrl(rs(areaId),areaType,rs(areaName))  &   " </NodeUrl> "   &  vbcrlf
        xml 
    =  xml  &   " <child> "   &  getChildNum(rs(areaId),areaType)  &   " </child> "   &  vbcrlf
        xml 
    =  xml  &   " <target> "   &  target  &   " </target> "   &  vbcrlf
        xml 
    =  xml  &   " </TreeNode> "
        rs.movenext()
    wend
    xml 
    =  xml  &   " </xml> "   &  vbcrlf

    ' 关掉连接释放资源
    rs.close()
    conn.close()
    set  rs  =   nothing
    set  conn  =   nothing

    function  getUrl(areaId,areaType,areaName)
        
    dim  url
        
    if  areaType  =   " country "   then
            url 
    =   " DD_Area_Form.asp?id= " &  areaId  &   " &amp;title= "   &  areaName  &   " &amp;type=country "
        
    elseif  areaType  =   " province "   then
            url 
    =   " DD_Area_Form.asp?id= " &  areaId  &   " &amp;title= "   &  areaName  &   " &amp;type=province "
        
    elseif  areaType  =   " city "   then
            url 
    =   " DD_Area_Form.asp?id= " &  areaId  &   " &amp;title= "   &  areaName  &   " &amp;type=city "
        
    end   if
        getUrl 
    =  url
    end function

    function  getChildNum(areaId,areaType)
        
    dim  iCount
        
    if  areaType  =   " country "   then
            sql2 
    =   " select count(1) as iCount from D_Province where Country_Id= " &  areaId
        
    elseif  areaType  =   " province "   then
            sql2 
    =   " select count(1) as iCount from D_City where Province_Id= " &  areaId
        
    elseif  areaType  =   " city "   then
            getChildNum 
    =   " 0 "
            
    exit   function
        
    end   if
        
    set  rsCount1  =  conn.execute(sql2)
        iCount 
    =  rsCount1( " iCount " )
        rsCount1.close
        
    set  rsCount1  =   nothing
        getChildNum 
    =  iCount
    end function

    function  getAreaType(areaId)
        
    if  areaId  =   " 0 "   then
            getAreaType 
    =   " province "
        
    elseif  areaId <> ""   and  areaId <> " 0 "   then
            getAreaType 
    =   " city "
        
    end   if
    end function

    ' 输出xml文件
    response.ContentType = " text/xml "
    response.Charset
    = " gb2312 "
    response.Write(xml)
    %
    >
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值