预览:
![1211868350-clip-4kb.png](https://i-blog.csdnimg.cn/blog_migrate/c6fed5298bdfc3a8eae13ae1a0f0dc2f.png)
Extension goal:
The main goal of the extension is to extend the Ext.tree.TreeLoader so that you can update a TreePanel by manipulating normal "data object" that you can have loaded by an ajax call or in a different way. So you do not have to create an ad-hoc data to populate a TreePanel; it also help to understand better the public interface that a TreeLoader need to implement to be intagrated in the framework. (Attachment with code and examples at the bottom.)
Development history:
************** (24 April 2008)
* Version 0.2.3 *
**************
===== Changed =====
Ext.Tree.MyTreeLoader
-Internal refactoring
===== Changed =====
****************
**************
* Version 0.2.2 *
**************
===== Added =====
Ext.tree.TreeNodeProvider class
-Added new class Ext.tree.TreeNodeProvider as a better alternative to the prevoius treeNodeProvider object
===== Added =====
===== Fixed =====
Ext.Tree.MyTreeLoader
-Fixed load event, now it is correctly fired (if loadexception is not fired and beforeload does not return false of course, following the standard TreeLoader behaviour), thanks to tford for pointing out the bug
===== Fixed =====
****************
**************
* Version 0.2.1 *
**************
===== Fixed =====
Ext.Tree.MyTreeLoader
-Fixed load function, now call node.destroy(), thanks to mykes for his/her kind help, more info here http://extjs.com/forum/showthread.php?t=14993
===== Fixed =====
****************
**************
* Version 0.2 *
************
===== Added =====
Ext.Tree.MyTreeLoader
-Added getTreeNodeProvider: function()-> get the treeNodeProvider
-Added setTreeNodeProvider: function(newTreeNodeProvider)-> set a new treeNodeProvider
===== Added =====
****************
************
* Version 0.1 *
************
Ext.Tree.MyTreeLoader
-Initial release
****************
Tutorial end previous explanations
Version 0.2.2 (examples are based on version 0.2.1)
----------------------------------------------------------------------------------
FIX: load event is correctly fired (if loadexception is not fired and beforeload does not return false of course, following the standard TreeLoader behaviour), thanks to tford for pointing out the bug
ADDED: new class Ext.tree.TreeNodeProvider as a better alternative to the prevoius treeNodeProvider object.
You need to pass to the constructor the following configuration object:
cfg = {
data: object //@optional, to preload data inside your TreeNodeProvider
getNodes: function(dataToElaborate) //@mandatory
}
![None.gif](/Images/OutliningIndicators/None.gif)
![ExpandedBlockStart.gif](/Images/OutliningIndicators/ExpandedBlockStart.gif)
var treeNodeProvider = new Ext.tree.TreeNodeProvider(
{
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
getNodes: function(dataToElaborate)
{ //Here you process your data
var nodeArray = [];//The tree structure used to refresh the TreePanel
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
for(var i = 0; i < dataToElaborate.length; i++)
{
var folder = dataToElaborate[i];
var filesInFolder = folder.files;
//Create the parent node
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
var node =
{
text: folder.name,
leaf: false,
children: []
}
//Create the children node
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
for(var j = 0; j < filesInFolder.length; j++)
{
var fileName = filesInFolder[j];
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
var childNode =
{
text: fileName,
leaf: true
}
//Set the children to the parent node
node.children.push(childNode);
}
//Add the parent node to the nodeArray
nodeArray.push(node);
}
//throw 'exception';
//return the tree structure here
return nodeArray;
}
});
![None.gif](/Images/OutliningIndicators/None.gif)
![None.gif](/Images/OutliningIndicators/None.gif)
Version 0.2.1
----------------------------------------------------------------------------------
FIX: load function now call node.destroy(), thanks to mykes for his/her kind help, more info here http://extjs.com/forum/showthread.php?t=14993
----------------------------------------------------------------------------------
Version 0.2
----------------------------------------------------------------------------------
Added getTreeNodeProvider: function()-> get the treeNodeProvider
Added setTreeNodeProvider: function(newTreeNodeProvider)-> set a new treeNodeProvider
----------------------------------------------------------------------------------
Version 0.1
-------------
-------------
The main goal of the extension is to extend the Ext.tree.TreeLoader so that you can update a TreePanel by manipulating normal "data object" that you can have loaded by an ajax call or in a different way (for example if you want to create a menu with the TreePanel, you can "hardcode" the data in your javascript and display them in the TreePanel without any server side call)
So for example, you can update a treeView manipulating an object like this one:
var treeData1 = [
{
name: "Folder1",
files:['File1', 'File2', 'File3']
},{
name: "Folder2",
files:['Picture1', 'Picture2']
}
];
![None.gif](/Images/OutliningIndicators/None.gif)
![None.gif](/Images/OutliningIndicators/None.gif)
![None.gif](/Images/OutliningIndicators/None.gif)
![None.gif](/Images/OutliningIndicators/None.gif)
![ExpandedBlockStart.gif](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![ContractedBlock.gif](/Images/OutliningIndicators/ContractedBlock.gif)
![dot.gif](/Images/dot.gif)
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![ContractedSubBlock.gif](/Images/OutliningIndicators/ContractedSubBlock.gif)
![dot.gif](/Images/dot.gif)
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![ContractedSubBlock.gif](/Images/OutliningIndicators/ContractedSubBlock.gif)
![dot.gif](/Images/dot.gif)
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![ContractedSubBlock.gif](/Images/OutliningIndicators/ContractedSubBlock.gif)
![dot.gif](/Images/dot.gif)
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
![ExpandedSubBlockEnd.gif](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![ContractedSubBlock.gif](/Images/OutliningIndicators/ContractedSubBlock.gif)
![dot.gif](/Images/dot.gif)
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![ContractedSubBlock.gif](/Images/OutliningIndicators/ContractedSubBlock.gif)
![dot.gif](/Images/dot.gif)
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
![ExpandedSubBlockEnd.gif](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
![ExpandedSubBlockEnd.gif](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
![ExpandedSubBlockEnd.gif](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
![ExpandedSubBlockEnd.gif](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![ContractedSubBlock.gif](/Images/OutliningIndicators/ContractedSubBlock.gif)
![dot.gif](/Images/dot.gif)
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
![ExpandedSubBlockEnd.gif](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
![dot.gif](/Images/dot.gif)
![ExpandedBlockEnd.gif](/Images/OutliningIndicators/ExpandedBlockEnd.gif)
![None.gif](/Images/OutliningIndicators/None.gif)
![None.gif](/Images/OutliningIndicators/None.gif)
![None.gif](/Images/OutliningIndicators/None.gif)
//Data to load in the tree
var treeData1 = [
{
name: "Folder1",
files:['File1', 'File2', 'File3']
},{
name: "Folder2",
files:['Picture1', 'Picture2']
}
];
//Data to load in the tree
var treeData2 = [
{
name: "Pictures",
files:['Doc1.txt', 'Doc2.txt']
},{
name: "Documents",
files:['xxx.txt', 'yyy.txt']
}
];
myTreeLoader.updateTreeNodeProvider(treeData1);
![None.gif](/Images/OutliningIndicators/None.gif)
var rootNode = treePanel.getRootNode();//get the root node
var loader = treePanel.getLoader();//Get the loader, note that is of type MyTreeLoader
loader.updateTreeNodeProvider(treeData2);//update the treeNodeProvider associated to the loder, but you DON't reload the TreePanel yet!!!
loader.load(rootNode);//Actually refresh the TreePanel UI
![None.gif](/Images/OutliningIndicators/None.gif)
the data can be in the format you like but in getNodes method you need to return a structure that the treePanel can udertend to render itself.
Please feel free to contact me if something is not clear and give me suggestions and feedback so I can improve the code and the example.
I have found it very usefull in my application because you can load the data in the way you want (ajax call or in other way) and then elaborate the data in getNodes.
NEW EXAMPLE 2:
Now, I have updated the extension with these two methods:
getTreeNodeProvider: function(){
return this.treeNodeProvider;
},
setTreeNodeProvider: function(newTreeNodeProvider) {
if(newTreeNodeProvider == null || (typeof newTreeNodeProvider =='undefined'))
throw 'setTreeNodeProvider, newTreeNodeProvider == null || (typeof newTreeNodeProvider == undefined)';
this.treeNodeProvider = newTreeNodeProvider;
}
So here we are, first treeNodeProvider:
![None.gif](/Images/OutliningIndicators/None.gif)
![ExpandedBlockStart.gif](/Images/OutliningIndicators/ExpandedBlockStart.gif)
var treeNodeProvider =
{
data: [],//Property in which are set the data to elaborate
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
getNodes: function()
{ //Here you process your data
var nodeArray = [];//The tree structure used to refresh the TreePanel
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
for(var i = 0; i < this.data.length; i++)
{
var folder = this.data[i];
var filesInFolder = folder.files;
//Create the parent node
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
var node =
{
text: folder.name,
leaf: false,
children: []
}
//Create the children node
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
for(var j = 0; j < filesInFolder.length; j++)
{
var fileName = filesInFolder[j];
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
var childNode =
{
text: fileName,
leaf: true
}
//Set the children to the parent node
node.children.push(childNode);
}
//Add the parent node to the nodeArray
nodeArray.push(node);
}
//return the tree structure here
return nodeArray;
},
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
setData: function(data)
{//Called internally by Ext.tree.MyTreeLoader by the method updateTreeNodeProvider
this.data = data;
},
scope: this//Could be useful to use when you elaborates data to switch the context
not used in this example and it's not required
};
![None.gif](/Images/OutliningIndicators/None.gif)
![None.gif](/Images/OutliningIndicators/None.gif)
![ExpandedBlockStart.gif](/Images/OutliningIndicators/ExpandedBlockStart.gif)
var treeNodeProvider2 =
{
data: [],//Property in which are set the data to elaborate
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
getNodes: function()
{ //Here you process your data
return Ext.decode(this.data);
},
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
setData: function(data)
{//Called internally by Ext.tree.MyTreeLoader by the method updateTreeNodeProvider
this.data = data;
},
scope: this//Could be useful to use when you elaborates data to switch the context
not used in this example and it's not required
};
![None.gif](/Images/OutliningIndicators/None.gif)
![None.gif](/Images/OutliningIndicators/None.gif)
![ExpandedBlockStart.gif](/Images/OutliningIndicators/ExpandedBlockStart.gif)
var ajaxCallGetDataForTree = function(inputParameters)
{
treePanel.body.mask("Loading data
");
setTimeout(ajaxCallbackGetDataForTree, 5000);
}
![ExpandedBlockStart.gif](/Images/OutliningIndicators/ExpandedBlockStart.gif)
var ajaxCallbackGetDataForTree = function()
{
treePanel.body.unmask();
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
treePanel.body.highlight('#c3daf9',
{block:true});
//Simulating that I have received the response that is treeData2 from the callback of the ajaxCall
var rootNode = treePanel.getRootNode();//get the rootnode
var loader = treePanel.getLoader();//Get the loader, note that is of type MyTreeLoader
loader.updateTreeNodeProvider(treeData2);
loader.load(rootNode);
}
![None.gif](/Images/OutliningIndicators/None.gif)
The response form the server is the following indeed:
![None.gif](/Images/OutliningIndicators/None.gif)
![None.gif](/Images/OutliningIndicators/None.gif)
![None.gif](/Images/OutliningIndicators/None.gif)
![None.gif](/Images/OutliningIndicators/None.gif)
![None.gif](/Images/OutliningIndicators/None.gif)
![None.gif](/Images/OutliningIndicators/None.gif)
![None.gif](/Images/OutliningIndicators/None.gif)
![ExpandedBlockStart.gif](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![ContractedBlock.gif](/Images/OutliningIndicators/ContractedBlock.gif)
![dot.gif](/Images/dot.gif)
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
![dot.gif](/Images/dot.gif)
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
![ExpandedBlockEnd.gif](/Images/OutliningIndicators/ExpandedBlockEnd.gif)
![None.gif](/Images/OutliningIndicators/None.gif)
![ExpandedBlockStart.gif](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![ContractedBlock.gif](/Images/OutliningIndicators/ContractedBlock.gif)
![dot.gif](/Images/dot.gif)
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![ContractedSubBlock.gif](/Images/OutliningIndicators/ContractedSubBlock.gif)
![dot.gif](/Images/dot.gif)
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
![ExpandedBlockEnd.gif](/Images/OutliningIndicators/ExpandedBlockEnd.gif)
![None.gif](/Images/OutliningIndicators/None.gif)
![None.gif](/Images/OutliningIndicators/None.gif)
![None.gif](/Images/OutliningIndicators/None.gif)
![None.gif](/Images/OutliningIndicators/None.gif)
![ExpandedBlockStart.gif](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![ContractedBlock.gif](/Images/OutliningIndicators/ContractedBlock.gif)
![dot.gif](/Images/dot.gif)
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![ContractedSubBlock.gif](/Images/OutliningIndicators/ContractedSubBlock.gif)
![dot.gif](/Images/dot.gif)
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
![ExpandedSubBlockEnd.gif](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
![ExpandedBlockStart.gif](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![ContractedBlock.gif](/Images/OutliningIndicators/ContractedBlock.gif)
![dot.gif](/Images/dot.gif)
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![ContractedSubBlock.gif](/Images/OutliningIndicators/ContractedSubBlock.gif)
![dot.gif](/Images/dot.gif)
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
![ExpandedSubBlockEnd.gif](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
![ExpandedBlockEnd.gif](/Images/OutliningIndicators/ExpandedBlockEnd.gif)
![None.gif](/Images/OutliningIndicators/None.gif)
![None.gif](/Images/OutliningIndicators/None.gif)
![None.gif](/Images/OutliningIndicators/None.gif)
loader.setTreeNodeProvider(treeNodeProvider2);
If you want to preolad your tree, you need to use this line of code before creating the treeLoader (as you can see in the example):
myTreeLoader.updateTreeNodeProvider(treeData1);//if you want to "preload" the TreePanel with this data
下载源码
![]() | http://cn.ziddu.com/download.php?uid=a7GemJWqarKdlZzzaaqZnJGlbKebm5g%3D7 (10.7 KB, 69 views) |