Folding Tables Reference/Tutorial

The first thing you might want to know is what is a folding table? To see some in action have a look at the sample. The tables can be expanded and collapsed by using the handles. In addition all rows at a specific level can be expanded or collapsed at the same time using the Expand/Collapse and Show/Hide buttons. This document explains how to create folding tables . . .

Prerequisites

This tutorial assumes you understand how to create html tables by hand and use styles and classes. It will be showing examples of html code and stylesheets. You will need to understand things like use css to apply a style to DOM Elements by id and tag.

Libraries, Requirements, and Initialization

To create folding tables you will need to include prototype.js in your html page. Then include foldingTables.js. You'll need to put these lines inside the head section of your html document. There is an embedded version of the prototype library used by foldingTables which you can reference from the same directory. If you are already using prototype and it is located somewhere else you should use that version instead. Multiple calls to multiple prototype libraries is probably a bad thing.

You will also need to include the css file for foldingTables in the head section of your page.

Your tables must conform to a specific layout in order to fold them. To activate the folding on a table you will need to pass it to the foldTable function. This could be done in the onload routine of the body of the document.

Table Layout

The table folding requires that tables have certain classes assigned to the tr tags. Think of the table as an outline. This code requires that each row of the table have a class assigned to designate the level in the outline. The levels always start at 1. A table that has levels that go below 1 is invalid. The next level down in the outline is 2. Each row with level 1 might have children which would be at level 2. Each row at level 2 might have children at level 3. Levels should not skip numbers. A level 4 without a level 3 above or below it in the table is unsupported and probably will not work. A child level should always be 1 greater than the parent level.

Ordering

The table can be layed out with the levels ascending or descending. The descending parameter of the foldTable function tells the code which direction to walk the table. If the levels are ascending (increasing) as we walk the table from top to bottom we expect to find the child rows below the parent row. It will seem as though the children fold in and out of the bottom of the parent. If the levels are descending (decreasing) as we walk the table from top to bottom we expect to find the parents below the children. It will seem that children fold out from above the parents. Look at the sample again. The first table has the children below the parents so the levels are ascending as we walk the table. The second table has descending levels.

Let's look at some examples of code

Example 1 - ascending Example 2 - descending

In example 1 the children are below the parents. Notice that level 2 comes after level 1. If a level 3 existed it would come after level 2. In example 2 the children are above the parents so level 1 comes after level 2.

Classes to define levels

As you may have noticed, the format for the class name to assign to each tr tag is level1, level2, etc. So your table definition will look something like this

thead, tfoot, tbody

Folding uses the thead, tbody, and tfoot sections. tfoot is optional but the other two are required in your table for proper operation.

Working Examples

Let's take our code examples and turn them into working examples

Example 1 - ascending without folding
Label
A total
A.1 subtotal
A.2 subtotal
B total
B.1 subtotal
B.2 subtotal
Example 1- ascending with folding
Label
A total
A.1 subtotal
A.2 subtotal
B total
B.1 subtotal
B.2 subtotal
Show code >>

Example 2 - descending without folding
Label
A.1 subtotal
A.2 subtotal
A total
B.1 subtotal
B.2 subtotal
B total
Example 2 - descending with folding
Label
A.1 subtotal
A.2 subtotal
A total
B.1 subtotal
B.2 subtotal
B total
Show code >>

Collapse and expand the tables on the right to see the detail that is visible on the left. The raw code is also available with the Show Code links.

foldTable Parameters

Any table on your page that should be folded must be sent to the foldTable function. A typical call to foldTable will look like the examples below (note the parameter types are listed in the first line).

The calls for the two example tables above are:

In addition, there is a version of the folding routine that acts on all tables found with the given class name.

return value

The foldTable function returns true unless there is an error. In that case it will return false. So you can check when you call the routine.

parameter: table

The first parameter to the foldTable function is the table to work on. The easiest way to get a reference to the table is to assign an id to it and use document.getElementById() or the prototype equivalent $().

parameter: descending

This paramter indicates whether children of the current row are above the current row. If true the levels are descending as we walk the table from top to bottom. See ordering for more information.

parameter: handleLocation

The handles that are added to the table are optional. If you do not want handles set this paramter to 0. If set to 1 the handles will be added inside the first cell found in each row. If set to 2 a new column will be added to the beginning of each row and the handle will be placed inside of it. Option 2 does not work well in IE.

The default handles are a plus and a minus for expanding and collapsing a row. If you turn the handles off you will not be able to expand or collapse the rows individually unless you also turn on the click or dblclick option.

You can set custom handles to be anything you want.

parameter: rowClick

Use this paramter to assign an event handler to each row to toggle it. The parameter can be set to '' to turn off this feature. Use 'click' to add a single click handler or 'dblclick' to add a double click handler. Note: If the the rowClick is set to '' and the handles are turned off (0) the user will not be able to expand or collapse the rows individually.

parameter: Initial Visible Level

This parameter sets the default levels that will be viewable. It must be 1 or greater since levels cannot be less than 1. In our previous examples the parameter was set to 1 and only level 1 was visible by default. Let's try an example where we show levels 1, 2, and 3 by setting the parameter to 3.
Label
A total
A.1 subtotal
A.1.a
A.1.b
A.2 subtotal
A.2.a
A.2.b
B total
B.1 subtotal
B.1.a
B.1.b
B.2 subtotal
B.2.a
B.2.b

expand/collapse by Level

On the sample page you might notice the buttons surrounding a select field. These buttons call some functions: collapseLevel() and expandLevel(). You can create this form yourself or a form can be created by using generateExpandingForm(), generateHidingForm(), and generateFoldingSpans().

function: generateExpandingForm

This function will return a string. That string is an html snippet containing the form used to manipulate the table by level. It requires that you pass the id of a table or the table itself. CSS can be used to syle the output. The form will look like this

Notice the css class foldingTables is assigned to as many controls as possible to allow for css styles like:

function: generateHidingForm

This function is a special case of generateExpandingForm(). The difference is in terminology used for the buttons on the form. This function uses Hide/Show instead of Expand/Collapse.

function: generateFoldingSpans

This function will return a string. That string is an html snippet containing the controls used to manipulate the table by level. It requires that you pass the id of a table or the table itself. CSS can be used to syle the output. The output will look like this

In this case the select field needs a unique id on the page because it is not on a form. Even if it were the controls that the user will click are not seen on forms so there would be no grouping the select field with the controls as a normal form would do. The id is generated automatically by the code. It calls document.getElementById to access the select field.

Notice the css classes that are used: foldingTables, foldingTablesShow, foldingTablesHide, foldingTablesText. This arrangement of classes is subject to change as a more optimal naming is developed. As of now the foldingTables class is assigned to as many controls as possible to allow for css styles like:

function: collapseLevel

This function is called from the forms that are generated by generateExpandingForm, generateHidingForm, and generateFoldingSpans but it can also be called directly from your code. When called, the function will walk the given table and collapse all levels equal to or greater than the given level.

function: expandLevel

This function is called from the forms that are generated by generateFoldingForm and generateFoldingSpans but it can also be called directly from your code. When called the function will walk the given table and expand all levels equal to the given level. Higher Levels will be left as they were when they were originally hidden.

Classes and Styles

You may have already seen some of the classes that are built into the forms for expanding/collapsing by level but the tables use a few styles as well. The foldingTables library makes a minimal use of classes and styles. You can modify some classes to create a particular layout and look for your pages.

foldingTableHidden - internal class

BE VERY CAREFUL if you want to change this. It is used to set the display on table rows and other items on the page. In fact, I'd reccommend against changing it.

.levelX

This style is applied to all rows in tbody to designate the level for that row. X is an integer representing the level. You can style your rows with css by simply defining .level1, .level2, etc. This is the style that is applied to this page.

foldingTableCollapsed

This is to describe the table row which has been collapsed. In general that row is visible but it's children are not. Use this class to set styles for a row that is collapsed. You may need to set the default styles for all rows in the table also by setting styles on tr tags.

foldingTableLeaf

This class is applied to all rows that do not have children. If you would like to style the leaf nodes in the outline/tree structure use this class.

Example to style the leaf nodes in table with id leaf to be smaller text and have a blue background:
level Text
1 one
2 two
3 leaf

foldingTableMarker

This style is applied to the column that holds the handles to toggle rows. If handles are turned off then that column is not used.

Example to set the column width for a table with id childrenAbove:

level Text
1 one
2 two
3 leaf

Tips and Tricks

Avoiding parsing preformatted tables

If your systems are spitting out html tables that are preformatted and you don't want to hack them apart you might be able to use some builtin functions to markup the tables with the proper classes. First you will need to select a field in your table (SQL query, etc.) to be the level for that row and give it the label 'level'. Then you will need to call a function and give it the table to work on.

function: extractLevelsByHeader

This function requires that you give it the table to manipulate. First, set a field in the table header to be level. Use the thead section of the table and put a th in it with the string level as the contents. The code can find and use this column as it walks the table. WARNING. td tags will be ignored while looking for this field in thead. (i'd like to change that but it's a pain. Feel free to comment or submit patches.)

The code will mark column 1 as the level column so each row will parse out the text from the first td and use it as the level.

parameter: classes

This allows for styling a column differently based on the level of the row. Normally, styling would apply to all rows the same for a given column. For example if you set the background to be blue with a css entry all rows will have the same blue background for that column. This array will cause the code to add the levelX class to any td found with one of the given class names. So using the newly assigned classes you could set all level1 td cells to have a yellow background.

A better example might be: will yeild

Note that you must use classes on your td tags to specify the columns to style. So in the above case we had a column with the class 'name'. We then sent 'name' to the function as a class to style so the resulting tds have two classes: 'name levelX'.

function: extractLevelsByRow

Each row should have a td with a class named 'level' assigned to it. The code will walk each tr and examine each td until it finds one with the class named level.

Custom Handles

You can customize the plus/minus symbols used for handles on the rows. The contents of the handles are specified in a global var called FOLDINGHANDLES.

This content is going to be wrapped in spans with the onclick handlers for expanding and collapsing assigned to them. As long as you don't add any onclick handling to the contents everything will work normally. I'm not yet sure how bubbling and capturing are going to work if you do add handlers. I'll have to think about it.

Custom Languages

To set the strings used for Hide, Show, Expand, and Collapse in the forms you can override a global variable.

CROSS BROWSER SUPPORT

My goal is to have the library work in all major browsers.

LICENSE

Authors: JT Moree, moreejt AT xperienceinc.com, Craig Buchek

Copyright (c) 2006 JT Moree, Craig Buchek

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

ATTRIBUTION IS GIVEN TO THE ORIGINAL AUTHORS AS COMMENT OR CODE.