The problem:
I have XML data populating 'treechildren' in a XUL window and would like to allow the user the option to sort that data. Firefox's treecols are clickable but offer no native sorting options unless you use rdf templates.
The solution:
The first thing I had to do was import the XML data into an array. At first I had it dumped right into the tree and thought about trying to sort that, but javascript has a basic array sorting feature, not a node sorting feature. To do this, I use code like this:
var nodes = document.evaluate(".//node1/node2", document.root, null, XPathResult.ANY_TYPE, null);
var treeArray = new Array();
for(i=0; i < nodes.length; i++){
var count = treeArray.length
treeArray[count] = new Array();
treeArray[count]['info1'] = nodes[i].getAttribute("info1");
treeArray[count]['info2'] = nodes[i].getAttribute("info2");
treeArray[count]['info3'] = nodes[i].getAttribute("info3");
}Now that you have the data you need, you can can populate your tree with this data. I will leave this up to you. It's pretty self explanatory if you know basic XML formatting. You add treeitem nodes, treerow nodes and treecell nodes using the info1, info2 and info3 information gathered in your array.
Let's say, for the sake of argument that you call that function populateTree().
Now comes the sorting.
In your treecol nodes within your XUL document, you'll want to add onClick events. For example:
<treecol label="Info1 Column" onClick="sortArray(sortByInfo1);" />
<treecol label="Info2 Column" onClick="sortArray(sortByInfo2);" />
<treecol label="Info3 Column" onClick="sortArray(sortByInfo3);" />
Back to your javascript, you will create not only a sortArray function, but also functions to match sortByInfo1, sortByInfo2 and sortByInfo3.
These will look like this:
// This is a callbackfunction. It's called from within array.sort(). This will take each item within the array and return back whether it comes before or after in either alphabetical or numeric order.
sortByInfo1: function(a,b){
return a['info1'] - b['info1'];
},
sortByInfo2: function(a,b){
return a['info2'] - b['info2'];
},
sortByInfo3: function(a,b){
return a['info3'] - b['info3'];
},
// The 'method' is what calls sortByInfo1 - 3. Store this into an object variable so that if sorted a second time, we can determine if the column should just be reversed or sorted.
sortArray: function(method){
if( this.method != method ){
this.method = method;
.treeArray.sort(method);
}
else {
treeArray.reverse();
}
// Populate the tree again, be sure to remove all child nodes first so that you don't have double the info each time.
populateTree();
}
Now, any time you click on a tree column, it will sort the array to the column that you clicked on, and then populate the tree once again. It's important to remember to remove all child nodes for that tree each time or else you will just be adding information on top of what's already in there.
It will also store the column you sorted by and if you sort by the same column a second time, it will simply reverse the array, giving the user the illusion that it's just been sorted again in the opposite direction.
I find it very odd that Firefox wouldn't have a very easy way to do this, since the tree columns are clickable anyhow and once the data is in there, it's basically a spreadsheet of nodes. It would seem to me that it would be easy for them to do.
Hopefully this helps you with sorting those trees.



My Code - Examples


