MozillaZine

Sorting Trees

From MozillaZine Knowledge Base

(Difference between revisions)
Revision as of 20:54, 17 April 2005
GeorgeNava (Talk | contribs)

<-- Previous diff
Revision as of 22:21, 17 April 2005
Asqueella (Talk | contribs)
(wikify)
Next diff -->
Line 1: Line 1:
==Sorting Trees== ==Sorting Trees==
-<p>The following example explains how to use tables as datasources for trees and how to sort columns based on header clicks.</p>+The following example explains how to use tables as datasources for trees and how to sort columns based on header clicks.
-<p>This example applies to trees in tabular form with custom views.<br/>+ 
-It uses a small table with a few records, but it has been tested with tens of thousands of records, sorting them in a split second.</p>+This example applies to trees in tabular form with custom views. It uses a small table with a few records, but it has been tested with tens of thousands of records, sorting them in a split second.
-<p>First the [http://kb.mozillazine.org/Sorting_Trees#treesort.xul XUL] code, nothing fancy just a simple tree with four columns.<br/>+ 
-No items will be defined here, they will be attached to the tree in [http://kb.mozillazine.org/Sorting_Trees#treesort.js JS] code.<br/>+First the [[#treesort.xul|XUL code]], nothing fancy just a simple tree with four columns. No items will be defined here, they will be attached to the tree in [[#treesort.js|JS code]].
-The only thing to note is the binding of the click event of the columns to the sort method:<br/>+The only thing to note is the binding of the click event of the columns to the sort method: <code>onclick="sortcolumn(this);"</code>
-<code>onclick="sortcolumn(this);"</code>+ 
-</p>+Now, to the javascript magic. We will use a 2D array as our table. Custom tree views can use 2D arrays easily:
-<p>Now, to the javascript magic:<br/>+ 
-We will use a 2D array as our table. Custom tree views can use 2D arrays easily:<br/>+''Note: You could use the [[XMLHttpRequest]] object to ask your server for data tables.''
-<i>Note: You could use the [http://kb.mozillazine.org/XMLHttpRequest XMLHttpRequest] object to ask your server for data tables.</i>+ 
-</p>+
<pre> <pre>
// A table is a 2D array // A table is a 2D array
Line 24: Line 23:
]; ];
</pre> </pre>
-<p>Now, for our convenience, we will define the columns in another array where we can keep track of their sort order and their type whether numeric or string:</p>+ 
 +Now, for our convenience, we will define the columns in another array where we can keep track of their sort order and their type whether numeric or string:
 + 
<pre> <pre>
// colName:[index, order, isnumber] // colName:[index, order, isnumber]
var datacols = {col0:[0,0,1],col1:[1,0,0],col2:[2,0,1],col3:[3,0,0]}; var datacols = {col0:[0,0,1],col1:[1,0,0],col2:[2,0,1],col3:[3,0,0]};
</pre> </pre>
-<p>Finally, we will put everything together and bind the table to our custom treeview and to the tree.</p>+ 
 +Finally, we will put everything together and bind the table to our custom treeview and to the tree.
 + 
<pre> <pre>
var tree = document.getElementById('treedata'); var tree = document.getElementById('treedata');
tree.view = new treeView(datatable,datacols,rowcount); tree.view = new treeView(datatable,datacols,rowcount);
</pre> </pre>
-<p>+ 
-For more in-depth analisys please refer to:<br/>+For more in-depth analisys please refer to:
-- The sort method explained. (TODO: link)<br/>+* The sort method explained. (TODO: link)
-- The treeview interface explained. (TODO: link)+* The treeview interface explained. (TODO: link)
-</p>+
==Source Code== ==Source Code==
Line 162: Line 164:
==Appendix== ==Appendix==
-[[Category:Example code|Sorting Trees]]+[[Category:Example code]]

Revision as of 22:21, 17 April 2005

Contents

Sorting Trees

The following example explains how to use tables as datasources for trees and how to sort columns based on header clicks.

This example applies to trees in tabular form with custom views. It uses a small table with a few records, but it has been tested with tens of thousands of records, sorting them in a split second.

First the XUL code, nothing fancy just a simple tree with four columns. No items will be defined here, they will be attached to the tree in JS code. The only thing to note is the binding of the click event of the columns to the sort method: onclick="sortcolumn(this);"

Now, to the javascript magic. We will use a 2D array as our table. Custom tree views can use 2D arrays easily:

Note: You could use the XMLHttpRequest object to ask your server for data tables.

// A table is a 2D array
var datatable = [
    [1, 'Britney'  , 22, '1983/04/11'],
    [2, 'Jenna'    , 35, '1970/03/24'],
    [3, 'Avril'    , 21, '1984/01/31'],
    [4, 'Christina', 19, '1986/02/10'],
    [5, 'Beyonce'  , 26, '1979/02/11'],
    [6, 'Jennifer' , 28, '1977/04/01'],
    [7, 'Jessica'  , 26, '1979/03/22']
];

Now, for our convenience, we will define the columns in another array where we can keep track of their sort order and their type whether numeric or string:

// colName:[index, order, isnumber]
var datacols = {col0:[0,0,1],col1:[1,0,0],col2:[2,0,1],col3:[3,0,0]};

Finally, we will put everything together and bind the table to our custom treeview and to the tree.

var tree  = document.getElementById('treedata');
tree.view = new treeView(datatable,datacols,rowcount);

For more in-depth analisys please refer to:

  • The sort method explained. (TODO: link)
  • The treeview interface explained. (TODO: link)

Source Code

treesort.xul

<?xml version="1.0"?>
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>

<window 
    title ="TreeSort" 
    height="440px" 
    width ="540px" 
    onload="init();"
    xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">

    <script src="treesort.js" />

    <tree id="treedata" flex="1" seltype="single">
        <treecols>
            <treecol id="col0" flex="1" label="#"        onclick="sortcolumn(this);" />
            <treecol id="col1" flex="3" label="Name"     onclick="sortcolumn(this);" />
            <treecol id="col2" flex="1" label="Age"      onclick="sortcolumn(this);" />
            <treecol id="col3" flex="2" label="Birthday" onclick="sortcolumn(this);" />
        </treecols>
        <treechildren id="treeitems">
            <!-- datatable -->
        </treechildren>
    </tree>
</window>

treesort.js

// A table is a 2D array
var datatable = [
    [1, 'Britney'  , 22, '1983/04/11'],
    [2, 'Jenna'    , 35, '1970/03/24'],
    [3, 'Avril'    , 21, '1984/01/31'],
    [4, 'Christina', 19, '1986/02/10'],
    [5, 'Beyonce'  , 26, '1979/02/11'],
    [6, 'Jennifer' , 28, '1977/04/01'],
    [7, 'Jessica'  , 26, '1979/03/22']
];

// colName:[index, order, isnumber]
var datacols = {col0:[0,0,1],col1:[1,0,0],col2:[2,0,1],col3:[3,0,0]};
var rowcount = 7;

// Window OnLoad
function init()
{
    loaddata();
}

// Assign our custom treeview
function loaddata()
{
    var tree  = document.getElementById('treedata');
    tree.view = new treeView(datatable,datacols,rowcount);
}

// This function will be called everytime we click on a column header
function sortcolumn(column)
{
    var tree  = document.getElementById("treedata");
    var name  = column.getAttribute("id");
    var index = datacols[name][0];
    var order = datacols[name][1];
    var isnum = datacols[name][2];

    datacols[name][1] = (order==0)?1:0; // switch order flag
	
    tableSort(datatable,index,order,isnum);  // sort the table
    tree.view = new treeView(datatable,datacols,rowcount);  // bind to tree
}

// This is the actual sorting method, extending the array.sort() method
function tableSort(table,col,order,isnum)
{
    if(isnum){ /* use numeric comparison */
        if(order==0){ /* ascending */
            function columnSort(a,b){ return (a[col]-b[col]); }
        }
        else{ /* descending */
            function columnSort(a,b){ return (b[col]-a[col]); }
        }
    }
    else{ /* use string comparison */
        if(order==0){ /* ascending */
            function columnSort(a,b){
                return (a[col]<b[col])?-1:(a[col]>b[col])?1:0; }
        }
        else{ /* descending */
            function columnSort(a,b){
                return (a[col]>b[col])?-1:(a[col]<b[col])?1:0; }
        }
    }
    // use array.sort(comparer) method
    table.sort(columnSort);
}

// This is our custom view, based on the treeview interface
function treeView(table,columns,rowcount)
{
    this.table               = table;    // our table
    this.columns             = columns;  // our cols
    this.rowCount            = rowcount; // our counter

    this.getCellText         = function(row,column){ return this.table[row][this.columns[column][0]]; };
    this.setTree             = function(treebox){ this.treebox=treebox; };
    this.isContainer         = function(row){ return false; };
    this.isSeparator         = function(row){ return false; };
    this.isSorted            = function(row){ return false; };
    this.getLevel            = function(row){ return 0; };
    this.getImageSrc         = function(row,col){ return null; };
    this.getRowProperties    = function(row,props){};
    this.getCellProperties   = function(row,col,props){};
    this.getColumnProperties = function(colid,col,props){};
}

Appendix