Sorting with hierarchical data and HTML tables
Takeaway: See what solution Phillip Perkins offered a colleague who wanted to create a folder/file hierarchy view with sorting capabilities using JavaScript.
An IT colleague recently asked me how to create a folder/file hierarchy view with sorting capabilities using a JavaScript solution. He wanted the view to look similar to the following:
item 1
item 2
item 3
folder 1
item 1
item 2
item 4
folder 2
item 1
item 2
item 5
…
Working with XML data bound tables
My recommended approach is to use nested tables bound to XML. This solution is simple, and I can use DOM methods to arrange the underlying XML, and the table will reflect the changes. (Note: This solution is designed to work in Internet Explorer 5.0+. Data binding with tables is available in IE—other browsers do not have the same functionality.) Check out the working sample here.
If you've ever worked with XML data bound tables in IE, you know that the layout of the XML is important. Every repeating child node under the root element represents a row in the table. Nested tables can be bound to nested nodes within the bound row node, and so on and so forth. Listing A contains a skeletal example of this binding.
In the XML data island xmlMain, rows are represented by row node in the first level of the hierarchy, and individual fields are represented by item nodes. In the table HTML, you create the binding by specifying the dataSrc attribute on the TABLE element. This value is the pound symbol (#) followed by the id attribute of the XML data island. The number of rows are reflected by the number of row nodes in the underlying XML of which data items are bound to items in the row node of the table row. This means that if a TR contains elements bound to fields in the parent node, that row becomes bound to the number of repeating nodes in that particular level of the underlying XML.
In this example, the first row will only display once for the one row node under the root element in the XML. However, another TR element is specified for the table. The row contains a nested table to which the rows of that table will be bound to the nested row nodes in the XML. The only difference between this table and the parent table is the dataFld attribute in the TABLE declaration.
Populating the XML data and binding the table
Now that we have a basic understanding of how the XML data is going to appear, we need to add the sorting. We don't have to worry about the table HTML since it will be bound to the XML, and the table will reflect any changes to the XML. One important detail to note is that every bound row has the nodeName row.
You should not have the client PC sort large amounts of data—this task should be left up to the original data provider, such as SQL Server. However, for small, on-the-spot sorting, a JavaScript solution should be fine.
Using DOM methods, a sorting solution is a breeze. The rows are the individual items you want to sort, and each row should contain a field that can be used as the sorting criteria. In my example, I use a date field.
First, create an unchanging array of nodes that represent the nodes you wish to sort. To do so, select the nodes you wish to sort using the selectNodes method of the parent node. The parent node for the outer sort should be the root element of the XML. (You can identify the nodes by the row node name.) Also, notice that I refer to "outer sort." This means that we'll need to be able to sort nested row nodes, so we should make a recursive function that can sort inner rows as it sorts the outer rows. This function will accept a parent node and the sorting criteria field name.
Finally, there's the sorting algorithm. With the selected array of nodes, each row node of the array is matched against every row node in the parent node by the criteria element. Every iterated row node is skipped until the criteria element of the current row node of the array is not greater than the value of the criteria element of the iterated row. At that point, the current row node of the array is inserted before the iterated row node using the insertBefore DOM method. The reason an array is created to hold the node references is that any changes to the DOM will be reflected in the order of the array of nodes returned by the selectNodes method. The order of the nodes will not change in this array as we iterate through them.
Listing B contains the sorting function. The code is pretty flexible; the biggest limiting factor in this algorithm is that the row nodes must be named row. You could add more functionality to the sorting criteria by making the criteria (sortOn) an array of element names. You could then concatenate the node values in the criteria, padding numbers to execute the greater-than condition. This could also be used to sort folders against files by giving them a sorting value (i.e., folders being 1, and files being 2).
Miss a column?
Check out the Web Development Zone archive, and catch up on the most recent editions of Phillip Perkins' column.
Print/View all Posts Comments on this article
SponsoredWhite Papers, Webcasts, and Downloads
- Next Generation Mobility Now Sprint
- Nextel Direct Connect Fact Sheet Sprint
- Case Study: Clackamas County Oregon's Outdated Fibre Channel Infrastructure Runs Out of Capacity Dell EqualLogic
- Sprint IPVoice Connect Fact Sheet Sprint
- Case Study: GHS Data Management - Improving Data Protection and Storage Reliability for Critical Databases Dell EqualLogic
Article Categories
- Security
- Security Solutions, IT Locksmith
- Networking and Communications
- E-mail Administration NetNote, Cisco Routers and Switches
- CIO and IT Management
- Project Management, CIO Issues, Strategies that Scale
- Desktops, Laptops & OS
- Windows 2000 Professional, Microsoft Word, Microsoft Excel, Microsoft Access, Windows XP,
- Data Management
- Oracle, SQL Server
- Servers
- Windows NT, Linux NetNote, Windows Server 2003
- Career Development
- Geek Trivia
- Software/Web Development
- Web Development Zone, Visual Basic, .NET

