PDA

View Full Version : Tree ordering



RedoX
15 Oct 2007, 12:57 PM
Hey guys,

I think I'm seeing something over its head.. So annoying.. I know the awnser must be really easy and I'm almost ashamed that I'm posting this..

Ok, so I got my tree working.. I can move around with stuff.. and it saves the right positions.. Except the order where they are in listed.. So i'm able to save the parents and stuff but the order is where I get stuck.. I know it must be really easy..

Here is some of my code..

Tree


<script type="text/javascript">

Ext.onReady(function(){
// shorthand
var Tree = Ext.tree;

var tree = new Tree.TreePanel('tree-div', {
autoScroll:true,
animate:true,
enableDD:true,
containerScroll: true,
});

// set the root node
var root = new Tree.AsyncTreeNode({
text: 'Category Structure',
draggable:false,
id:'source'
});

tree.setRootNode(root);

bildCategoryTree(root, <?php echo $node; ?>);
// render the tree

tree.addListener('beforenodedrop', categoryMove.createDelegate(this));

tree.render();
root.expand();
tree.expandAll();
});

function bildCategoryTree(parent, config){
if (!config) return null;

if (parent && config && config.length){
for (var i = 0; i < config.length; i++){
var node = new Ext.tree.TreeNode(config[i]);
parent.appendChild(node);
if(config[i].children){
bildCategoryTree(node, config[i].children);
}
}
}
}

categoryMove = function(obj){
var data = {id: obj.dropNode.id}

data.point = obj.point;
switch (obj.point) {
case 'above' :
data.pid = obj.target.parentNode.id;
if (obj.target.previousSibling) {
data.aid = obj.target.previousSibling.id;
} else {
data.aid = 0;
}
break;
case 'below' :
data.pid = obj.target.parentNode.id;
data.aid = obj.target.id;
break;
case 'append' :
data.pid = obj.target.id;
if (obj.target.lastChild) {
data.aid = obj.target.lastChild.id;
} else {
data.aid = 0;
}
break;
default :
obj.cancel = true;
return obj;
}

var success = function(o) {
try {
if(o.responseText){
alert(o.responseText);
}
}
catch(e) {

}
};
var failure = function(o) {
Ext.dump(o.statusText);
};

var pd = [];
for(var key in data) {
pd.push(encodeURIComponent(key), "=", encodeURIComponent(data[key]), "&");
}
pd.splice(pd.length-1,1);

var con = new Ext.lib.Ajax.request(
'POST',
'http://localhost/backoffice/categories/move/',
{success:success,failure:failure, scope:obj, loaderArea:'tree-div'},
pd.join(""));
}

</script>


<h1>Drag and Drop ordering in a TreePanel</h1>

<div id="tree-div" style="overflow:auto; height:300px;width:400px;border:1px solid #c3daf9;"></div>

I got a part of the CategoryMove code from a friend so I didn't write it myself..

Called by Ajax


$update = "UPDATE categories SET parent = '".$_POST['pid']."' WHERE id = '".$_POST['id']."'";
$this->Category->query($update);

$this->layout = 'ajax';

Ok, I hope you guys can lead me to the light..

I'm also experiencing some problems with IE.. It doesn't render in IE.. but it does in Safari and Firefox.. I'm stuck with that too.. I'm using the original CSS.. And another small thing.. the loading icon by the Root Node doesn't disappear.. It just stays there.. what am I doing wrong?

Thanks in advance and keep up the good work!

RedoX
The Netherlands

evant
15 Oct 2007, 1:32 PM
You could use this method http://extjs.com/deploy/ext/docs/output/Ext.tree.TreeNode.html#indexOf

Something like:


myTree.on('nodedrop', function(o)
{
alert(o.target.indexOf(o.dropNode));
}
);

RedoX
16 Oct 2007, 6:25 AM
Ah thank you very much.. I can definatly work with that.. :)

Do you have an idea what the other two errors might be?

- Loading icon at the root node..
- Can't get it to work in IE (CSS problem? I'm using the standard ext-all.css so it should work I guess (IE6x)), does work with Safari and Firefox.

Thanks in advance!

RedoX
The Netherlands

evant
16 Oct 2007, 6:27 AM
You have an extra comma:



var tree = new Tree.TreePanel('tree-div', {
autoScroll:true,
animate:true,
enableDD:true,
containerScroll: true,
});


Which will cause it to screw up in IE.

RedoX
16 Oct 2007, 6:38 AM
Ah thank you so much.. have staring blind on my code and didn't see it.. haha.. Thanks...

Still have the load icon tho.. I also noticed that it stops working when I close the Root node.. it crashes and stops working (no errors tho)

Greetings,

RedoX
The Netherlands

fangzhouxing
17 Oct 2007, 10:01 PM
hi,RedoX

So i'm able to save the parents and stuff but the order is where I get stuck.

How you done with the tree order? Maybe show some code.
Thanks in advance!

RedoX
18 Oct 2007, 6:18 AM
Hi fangzhouxing,

Here is my current code..


<script type="text/javascript">

Ext.onReady(function(){
// shorthand
var Tree = Ext.tree;

var tree = new Tree.TreePanel('tree-div', {
autoScroll:true,
animate:true,
enableDD:true,
containerScroll: true,
rootVisible: false
});

// set the root node
var root = new Tree.AsyncTreeNode({
text: 'Category Structure',
draggable:false,
id:'source'
});

tree.setRootNode(root);

bildCategoryTree(root, <?php echo $node; ?>);
// render the tree

tree.addListener('beforenodedrop', categoryMove.createDelegate(this));

tree.render();
root.expand();
tree.expandAll();

});


function bildCategoryTree(parent, config){
if (!config) return null;

if (parent && config && config.length){
for (var i = 0; i < config.length; i++){
var node = new Ext.tree.TreeNode(config[i]);
parent.appendChild(node);
if(config[i].children){
bildCategoryTree(node, config[i].children);
}
}
}
}

categoryMove = function(obj){
var data = {id: obj.dropNode.id}

data.point = obj.point;
switch (obj.point) {
case 'above' :
data.pid = obj.target.parentNode.id;
if (obj.target.previousSibling) {
data.aid = obj.target.previousSibling.id;
} else {
data.aid = 0;
}
break;
case 'below' :
data.pid = obj.target.parentNode.id;
data.aid = obj.target.id;
break;
case 'append' :
data.pid = obj.target.id;
if (obj.target.lastChild) {
data.aid = obj.target.lastChild.id;
} else {
data.aid = 0;
}
break;
default :
obj.cancel = true;
return obj;
}

var success = function(o) {
try {
if(o.responseText){
alert(o.responseText);
}
}
catch(e) {

}
};
var failure = function(o) {
Ext.dump(o.statusText);
};

var pd = [];
for(var key in data) {
pd.push(encodeURIComponent(key), "=", encodeURIComponent(data[key]), "&");
}
pd.splice(pd.length-1,1);

var con = new Ext.lib.Ajax.request(
'POST',
'http://localhost/backoffice/categories/move/',
{success:success,failure:failure, scope:obj, loaderArea:'tree-div'},
pd.join(""));
}

</script>

So, i'm able to move categories around.. but not able to save the right order where they are in. I don't know what the regular way is to save a tree but I just can't figure it out, how to save the order they are in.


myTree.on('nodedrop', function(o)
{
alert(o.target.indexOf(o.dropNode));
}
);

This doesn't work either because when I change 1 category, the index get changed for all the items in the node. So I was thinking about just saving the whole tree in XML or JSON trough ajax in every action.. But I don't know exactly how to do that. Because i'm getting alot of errors when I try to do it..

Thanks in advance!

RedoX
The Netherlands..

fangzhouxing
18 Oct 2007, 6:13 PM
hi,RedoX,thanks for reply!

I have solved the problem of tree node ordering yesterday. if you need, I can provide some detail!

In short, my solution:
1.listen to beforemove event.
2.through drag and drop, node can chang its parent and position, and at the same time, save the state of this node at server side.

I am using Ext 2.0-beta1 and java server side(DWR).

RedoX
19 Oct 2007, 6:07 AM
Hi fangzhouxing,

Could you give me some of your code? And would it work with 1.1.1 aswell or do I have to use the beta1 version?

Thanks in advance,

RedoX
The Netherlands

fangzhouxing
19 Oct 2007, 7:36 AM
The client js code is simple(but I don't know if it can be used with Ext 1.x):



tree.on('beforemove', onMoveNode);
...
function onMoveNode(tree, node, oldParent, newParent, index) {
var allowMove = true;

// prevent other events while processing this one
Ext.util.Observable.capture(tree, function() {
return false;
});

var result; //server side response
// call server side method to handle tree order:
// parameters: node.id, oldParent.id, newParent.id

if (!result.success) {
//Prompt user
allowMove = false;
}

// restore normal event handling
Ext.util.Observable.releaseCapture(tree);

return allowMove;
}


to handle tree order in server side, you can:

(1) create database table structure like this:


CREATE TABLE tree_table (
Id int NOT NULL,
Name nvarchar(255) NOT NULL,
IsLeaf nchar(1) NOT NULL, //'Y' = hasChildren
ParentId int NOT NULL, //0 = root
SortOrder int NOT NULL, // for tree order
PRIMARY KEY (Id)
)


(2) parameters: node.id, oldParent.id, newParent.id,

step 1. get the current number of sibling at new position:


SELECT COUNT(*) FROM tree_table WHERE ParentId = newParent.id

if number of sibling is 0, then A = 0, goto step 3.

step 2. get the current max SortOrder in sibling at new position:


SELECT MAX(SortOrder) FROM tree_table WHERE ParentId = newParent.id

A = select result.

step 3. set the SortOrder of current node:


UPDATE tree_table SET SortOrder = A+1 WHERE Id = node.id

step 4. update parentId:


UPDATE tree_table SET ParentId = newParentId WHERE Id = node.id

step 5. update field value of IsLeaf


SELECT COUNT(*) FROM tree_table WHERE ParentId = oldParent.id
UPDATE tree_table SET IsLeaf = [above result=0?'Y','N'] WHERE Id = oldParent.id

SELECT COUNT(*) FROM tree_table WHERE ParentId = newParent.id
UPDATE tree_table SET IsLeaf = [above result=0?'Y','N'] WHERE Id = newParent.id

(3) use async tree load, get all children of specified parent node:


SELECT * FROM tree_table WHERE ParentId = parentNode.id ORDER BY SortOrder,Id


sorry for my poor English, wish you can understand my description and I can help.

RedoX
19 Oct 2007, 12:11 PM
Hi fangzhouxing,

It's not that MySQL / php part that is my problem. The Javascript part is. How do I load those functions correctly in the tree? So if you could share some of your javascript code of your tree.. how to transfer the data from the tree into the function.. I'm getting like alot of javascripts error when I try.. and debugging is hell in Javascript..

Thanks in advance,

RedoX
The Netherlands

tryanDLS
19 Oct 2007, 12:27 PM
Why is debugging 'hell'? Unless you're still debugging using alert().
Use firebug or MS ScriptDebugger for IE or VisualStudio.

fangzhouxing
19 Oct 2007, 5:09 PM
hi, RedoX,I use DWRTreeLoader from:

http://extjs.com/forum/showthread.php?t=6217&page=3

RedoX
19 Oct 2007, 9:22 PM
Why is debugging 'hell'? Unless you're still debugging using alert().
Use firebug or MS ScriptDebugger for IE or VisualStudio.

Ah ofcourse.. totally forgot about that..

Thanks fangzhouxing, I will have a look at it..