动态载入数据的无刷新TreeView控件(7)

    上一次说了一下要支持无限级的动态加载TreeView控件,服务器端数据的准备情况。不过那只是一个小小的演示实例,在实际的使用中,服务器端的数据可能会完全的不同,不过不管怎么变化,也必须要保证能形成树形数据的request/response结构。

    由于TreeView必须在加载了节点信息有才能被Show出来,所以这里我们先手动把root level的节点生成。代码示例如下:
ExpandedBlockStart.gif ContractedBlock.gif < script  Language ="javascript" > dot.gif
InBlock.gif
var tree = new Tree();    
InBlock.gif
var url = tree.m_Attributes.m_Url + '?nid=1';
InBlock.gif
var metadata = __XmlHttpPool__.GetRemoteDataEx(url);
InBlock.gif
var data = metadata.substring(metadata.indexOf('$')+1);
InBlock.gif
var aryData = eval(data);
InBlock.gif
for ( var i=0 ; i < aryData.length ; ++i )
ExpandedSubBlockStart.gifContractedSubBlock.gif
dot.gif{
InBlock.gif     
// ["1","Movie","-1","Mar 29 07:23"],
InBlock.gif
     var aryNode = aryData[i];
InBlock.gif     
var node = new TreeNode(aryNode[1]);
InBlock.gif     
if ( aryNode[0!= -1 )
ExpandedSubBlockStart.gifContractedSubBlock.gif     
dot.gif{
InBlock.gif         node.m_IsLazyLoad 
= true;
ExpandedSubBlockEnd.gif     }

InBlock.gif     node.m_ServerId 
= aryNode[4];
InBlock.gif     tree.Add(node);
ExpandedSubBlockEnd.gif}

InBlock.gif
if ( tree.m_Count > 0 )
ExpandedSubBlockStart.gifContractedSubBlock.gif
dot.gif{
InBlock.gif    tree.Show(document.getElementById('loadTree'));
ExpandedBlockEnd.gif}
 
None.gif
</ script >

    这里需要注意的是我们在此使用的是同步xmlhttp方式去获取的root level的数据,为什么这里不用异步呢?这是由我们的节点关系决定的,在 第一节里我就说过,这个TreeView的每一层,其实是一个独立的Tree,然后在节点TreeNode下挂接Tree,就形成无限级的结构了。而当我们在获取root level的数据时,还没有TreeNode这个东西。我们使用同步连接,可以保证原数据获取的顺序。当然在子节点的动态展开中,我们使用得是异步xmlhttp获取的数据。

    当我们在Expand一个TreeNode时,如果这个节点的IsLazyLoad属性是true,那么执行代码:
None.gif  TreeNode.prototype.LoadNodes  =   function ()
None.gif {
None.gif    
var  childTree  =   this .m_Element.nextSibling;
None.gif     childTree.style.display  =  'inline';
None.gif     this.m_IsChildExpanded = true;
None.gif    
this .m_Element.OpIcon.src  =  TreeStyle.OpIcon( this .GetOpIconName());
None.gif     childTree.cells(
1 ).innerHTML  =  ' < img src = " ' + TreeStyle.OpIcon('BottomLine')
None.gif         + '
"  border = " 0 "  align = " absMiddle " >< span style = " color:blue; " > loadingdot.gif </ span > ';
None.gif    
var  url  =   this .Attributes('Url')  +  ' ? NID = +   this .m_ServerId
None.gif         
+  ' & CID = +   this .m_Id  +  ' & t = +   new  Date().getTime();
None.gif     __XmlHttpPool__.GetRemoteData(url, 
this .LoadingNodes);
None.gif };

    在上面的调用中,url是类似如下的一个请求:
    http://localhost/TreeView/GetTreeNodes.aspx?NID=1&CID=__TreeObject__11&t=12349803

    NID是NodeId,CID是ClientId,t是一个时间戳(用来绕开IE的cache机制)。

    返回的数据,上次也都说过了,形如:
None.gif  __TreeObject__11$[
None.gif   ["2",    "DV作品",    "-1",    "Mar 22 10:28",    "2"],
None.gif   ["5",    "大陆",    "-1",    "Apr 2 02:01 ",    "9"],
None.gif   ["14",    "港台",    "-1",    "Apr 2 02:02 ",    "34"],
None.gif   ["63",    "欧美",    "-1",    "Apr 2 01:50 ",    "174"],
None.gif   ["80",    "日韩",    "-1",    "Apr 2 01:53 ",    "226"]]

    在我们的xmlhttp的回调函数中,我们主要做三件事情:
    1、找到本次返回数据的Parent Node,就是说这些数据是谁的子节点;
    2、根据返回的数据生成子树,然后把子树append到Parent Node上;
    3、更新Parent Node和Child Tree中的属性状态值,比如:m_ChildTree、m_ParentNode等。
    
    参考代码如下:
None.gif  TreeNode.prototype.LoadingNodes  =   function (metadata)
None.gif {
None.gif    
try
None.gif    {
None.gif         
var  clientId  =  metadata.substring( 0 , metadata.indexOf('$'));
None.gif         
var  data  =  metadata.substring(metadata.indexOf('$') + 1 );
None.gif         
var  aryData  =  eval(data);
None.gif         
var  tree  =   new  Tree();
None.gif         
for  (  var  i = 0  ; i  <  aryData.length ;  ++ i )
None.gif         {
None.gif             
//  ["1","Movie","-1","Mar 29 07:23", "1"],
None.gif
              var  aryNode  =  aryData[i];
None.gif             
var  node  =   new  TreeNode(aryNode[ 1 ]);
None.gif             
if  ( aryNode[ 0 !=   - 1  )
None.gif             {
None.gif                  node.m_IsLazyLoad 
=   true ;
None.gif             }
None.gif             node.m_ServerId 
=  aryNode[ 4 ];
None.gif             tree.Add(node);
None.gif         }
None.gif         
var  objNode  =  __GlobalTreeCache__[clientId];
None.gif         objNode.m_ChildTree 
=  tree; 
None.gif         objNode.m_Tree.ApplySingleton(); 
None.gif         objNode.m_IsLazyLoad = false;
None.gif         tree.m_ParentNode 
=  objNode;
None.gif         
var  childTree  =  objNode.m_Element.nextSibling;
None.gif         
var  childNode  =  childTree.cells( 1 );
None.gif         childNode.innerHTML 
=  '';
None.gif         childNode.appendChild(tree.Render(childTree.document));
None.gif     }
None.gif     
catch (e)
None.gif     {
None.gif         __Debug(e, metadata);
None.gif     }
None.gif };

    // 在类似这样的callback函数中,一般是不会有this出现的,因为这是的this指代的是window。

    本来步骤2是比较麻烦的,但是由于我们在获取子节点的metadata时,同时把节点的Client ID也发到了服务器端。服务器返回时又将其原样返回了,所以我们只需要用这个Client ID,并且借助TreeView的全局Cache,很容易就能得到这个节点:var objNode = __GlobalTreeCache__[clientId];。

    使用这样一个子节点的装载方式,可以非常sexy的利用异步操作同时加载多个子节点数据(只要的鼠标点击足够快emteeth.gif)。同时load多个子节点的效果如下图:

    TreeView-5.gif
    注:关于__XmlHttpPool__参看这里

    to be continued ...

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值