PDA

View Full Version : [Solved] Treepanel & Folders List



amegahed
19 Aug 2009, 12:07 PM
Im trying to build a sort of hybrid Folders List in a TreePanel, but I cant seem to get it.
- Im reading the main Folders / Dir from a database (based on the logged in user), which loads fine up to this point. The code for it is:


var treeMyFiles = new Ext.tree.TreePanel({
region : 'west',
width : 350,
useArrows : true,
autoScroll : true,
animate : true,
enableDD : true,
containerScroll : true,
border : true,
split : true,
collapsible : true,
loader : new Ext.tree.TreeLoader({
dataUrl : 'php/myfiles.php',
baseParams : { action: 101}
}),
root : new Ext.tree.AsyncTreeNode({
text : 'My Folders'
}),
listeners : { click: function(node, event){
if(node.leaf){
dsMyFilesList.load({
params: {
action : 102,
folderpath : '/var/www/' + node.attributes.path
// folderpath : node.attributes.path
}
})
}
}
}
});



and its populated from the following result:


[{"text":"Movies - MyMovies","id":100,"leaf":"true","path":"users\/Adel.Megahed\/Movies\/MyMovies","cls":"folder"},{"text":"TVSeries - MySeries","id":201,"leaf":"true","path":"users\/Adel.Megahed\/TVSeries\/MySeries","cls":"folder"}]


now, what i would like to acheive is when i click any of the above two nodes, the path will be scanned for folders and added to that node. And if i click on any of those subsequent folders, that will be scanned and added under that particular node.

i have no problem in the code for scanning the folders (i.e. the php code for it), my problem lies in how to add nodes dynamically? (im sure its very simple but i cant seem to be able to put my hands on it)

thanks u all

avsomeren
19 Aug 2009, 12:14 PM
The thing you are looking for is async loading.
I am using :



dataUrl: 'php/myfiles.php',
root: new Ext.tree.AsyncTreeNode({
text: 'Folders',
expanded: true,
id: 'root'
})


This way the tree will call myfiles.php with the current node id (starting with root).
Just return the subfolders for this "id" from serverside code.

amegahed
19 Aug 2009, 12:24 PM
avsomeren: thanks for your quick help, but isn't that what im using:


.....
loader : new Ext.tree.TreeLoader({
dataUrl : 'php/myfiles.php',
baseParams : { action: 101}
}),
root : new Ext.tree.AsyncTreeNode({
text : 'My Folders'
}),
......

This loads the first nodes with no problem. My issue is after that, when i click on any of these nodes, i would like to add their children to the tree, so my problem lies in:
- identifying the node im on
- adding the children to that selected node (based on the data returned from php)

if you notice, i have a listener for when clicking on a node which triggers the loading of a grid on the same form with the files contained in the selected folder.


...
listeners : { click: function(node, event){
if(node.leaf){
dsMyFilesList.load({
params: {
action : 102,
folderpath : '/var/www/' + node.attributes.path
}
})
}
}
}
....


what im guessing regarding my first problem is that in that listener i will add a call to load the children... but how? is where im lost.

amegahed
19 Aug 2009, 12:34 PM
well, i got the node id:


....
listeners : { click: function(node, event){
if(node.leaf){
Ext.Msg.alert('Status', node.id);
dsMyFilesList.load({
params: {
action : 102,
folderpath : '/var/www/' + node.attributes.path
// folderpath : node.attributes.path
}
})
}
}
}
......

avsomeren
19 Aug 2009, 12:38 PM
var treeMyFiles = new Ext.tree.TreePanel({
region: 'west',
width: 350,
useArrows: true,
autoScroll: true,
animate: true,
enableDD: true,
containerScroll: true,
border: true,
split: true,
collapsible: true,
dataUrl: 'php/myfiles.php',
root: new Ext.tree.AsyncTreeNode({
text: 'My Folders',
expanded: true,
id: '/var/www/'
}),
listeners: {
click: function(node, event) {
event.stopEvent();
}
}
});

Just make sure you have the foldername map to the id of the node you are creating. The id will be posted by the asynctreenode once expanded. That way you can easily read it's children from your drive and return the treenodes...

Im using many trees in my applications like this, and this method never failed for me.

amegahed
19 Aug 2009, 2:36 PM
avsomeren: thanks again, but i seem to be very stupid today :) i dont quite get what you are trying to tell me, but i got a bit further in my search and this is what reached until now:

in the listener i added:


..........
listeners : { click: function(node, event){
if(node.leaf){
dsMyFilesList.load({
params: {
action : 102,
folderpath : '/var/www/' + node.attributes.path
}
});
// node.appendChild(new Ext.tree.TreeNode({text: 'Course Catalog', leaf:false, cls:'folder'}))
Ext.Ajax.request({
url : 'php/myfiles.php',
method : 'POST',
timeout : 120000,
params : {
action : '103',
folderpath : '/var/www/' + node.attributes.path,
nodeid : node.id
},
success: function(f,a){
Ext.MessageBox.hide();
},
scope: this
});
}
}
}
...........


now the AJAX request returns to me the following:


[{"text":"\/var\/www\/users\/TVSeries\/MySeries\/3rd.Rock.From.The.Sun","id":215,"leaf":"true","path":"\/var\/www\/users\/TVSeries\/MySeries\/3rd.Rock.From.The.Sun","cls":"folder"}]


now my quest is to loop through the returned json response and add / append the nodes with something like:


node.appendChild(new Ext.tree.TreeNode({text: 'Course Catalog', leaf:false, cls:'folder'}))


Is there a way to load the returned array directly into the appendChild?

amegahed
19 Aug 2009, 3:28 PM
I think i got this:


....
listeners : { click: function(node, event){
//clears all the children from the node
while(node.firstChild) {
node.removeChild(node.firstChild);
}

// this loads the files into a grid
if(node.leaf){
dsMyFilesList.load({
params: {
action : 102,
folderpath : '/var/www/' + node.attributes.path
}
});

// this loads my folders as children to that node
Ext.Ajax.request({
url : 'php/myfiles.php',
method : 'POST',
timeout : 120000,
params : {
action : '103',
folderpath : '/var/www/' + node.attributes.path,
nodeid : node.id
},
success: function(response, request){
Ext.each(Ext.decode(response.responseText), function(a){
node.appendChild(new Ext.tree.TreeNode(a.text));
}
);
// Ext.MessageBox.alert('', Ext.decode(response.responseText));
},
scope: this
});
}
}
}

....

amegahed
19 Aug 2009, 3:46 PM
final code:


....
listeners : { click: function(node, event){
while(node.firstChild) {
node.removeChild(node.firstChild);
}

// if(node.leaf){
dsMyFilesList.load({
params: {
action : 102,
folderpath : '/var/www/' + node.attributes.path
}
});
Ext.Ajax.request({
url : 'php/myfiles.php',
method : 'POST',
timeout : 120000,
params : {
action : '103',
folderpath : '/var/www/' + node.attributes.path,
nodeid : node.id
},
success: function(response, request){
Ext.each(Ext.decode(response.responseText), function(a){
node.appendChild(new Ext.tree.TreeNode({text: a.text, id: a.id, leaf: a.leaf, path: a.path, cls: a.cls}));
}
);
},
scope: this
});
node.expand(true);
// }
}
}

....

amegahed
19 Aug 2009, 3:49 PM
this is the php function (just incase anyone is looking for same thing):


//func: listFolders
function listFolders($dir_handle, $path, $n) {
global $myArray;
while (false !== ($file = readdir($dir_handle))) {
$dir =$path.'/'.$file;
if(is_dir($dir) && $file != '.' && $file !='..' )
{
$n++;
$dir = str_replace('/var/www/', '', $dir);
$myArray[] = array("text" => str_replace('.', ' ', $file) , "id" => $n, "leaf" => "true", "path" => $dir, "cls" => "folder");
}
}
closedir($dir_handle);
sort($myArray);
return $myArray;
}



and im calling it from a case / switch:


....
case 103:
$path = $_POST['folderpath'];
$n = $_POST['nodeid'];
$dir_handle = @opendir($path) or die("Unable to open $path");
$myArray = listFolders($dir_handle, $path, $n);
echo json_encode($myArray);
break;
....