Build a List, Get a
Tree
How to create an
outlined tree from <ul> and <li> tags, CSS and JavaScript
Cláudio Alexandre da Costa Dias«
Hierarchical data can
be fairly represented using <ul> and <li> HTML tags. For instance,
in order to represent a company?s organization chart, we could write:

Viewing it in a browser:

With some CSS
statements, we can give this list a much better aspect.
In this tutorial,
we?ll learn how to convert this list into an outlined tree control, using an
elaborated CSS and some JavaScript code.
The tree control, or
tree, shows you the relationships among nodes and provides items
expand/collapse control.

Let?s build our tree
from Megaputz company organization chart, displayed below:
|
Division |
Department |
Employee |
|
CEO |
|
|
|
Industry |
Engineering |
Axel Lissmann |
|
Claudia Kuhlmann |
||
|
Ronald Lorenz |
||
|
Thorsten Goeckeler |
||
|
Manufacturing |
Hardy Mums |
|
|
Mike O'Phone |
||
|
Peter Piper |
||
|
Administrative |
Finance |
Donna Hood |
|
Fanny Farmer |
||
|
Rob Banks |
||
|
Human Resources |
Carrie Mehome |
|
|
Ella Mentary |
||
|
Jerry Atrix |
||
|
Support |
Customer Service |
Mahatma Coate |
|
Moe Bilhome |
In order to build tree.htm
page, let?s use the following HTML code:
![]() |
To build the list, we
will use <div>, <h3>, <ul>, <li> and <span> tags.
Thus, from organization chart, we get:

We shall place this code on page tree.htm
inside <body> tag.
Some explanations:
2.
The <div
class="tree">...</div> tag shall exist in order to group the
tree and it?s root in the same block
3.
The
<span>...</span> tag was used inside <li>...</li> tags.
It shall group all item content (images, links, texts)
4.
If we want to
define a collapsed item, we shall define the <li> class as collapsed
Our HTML page is done!
Viewing it in a browser:

To keep our source
code simple, and as long as we cannot use CSS 2 to render our tree ? remember
that IE does not correctly implement this CSS version ? we shall use some
JavaScript code.
In addition, we must
code sub-trees expand/collapse functionality.
First, we create tree.js
file, add to our page a calling to this file and also call getTrees()
function:

Inside tree.js file,
we write getTrees() function to find all <div> tags having class tree.
For each <div>
found, this function will point onclick event to treeAction()
function and will retrieve all <ul> tags. Also, it will call another
function ? ul2tree() ? that converts each <ul> found to a tree.
![Text Box: function getTrees() {
// retrieve all <div>
var treeObjs = document.getElementsByTagName('DIV');
for (var i=0;i<treeObjs.length;i++)
// class = 'tree' ?
if (treeObjs[i].className == 'tree') {
// point onclick event to treeAction() function
treeObjs[i].onclick = treeAction;
// loop over all <div> children using childNodes[] array
for (j=0;j<treeObjs[i].childNodes.length;j++)
if (treeObjs[i].childNodes[j].tagName == 'UL') {
// if <ul>, call ul2tree()
ul2tree(treeObjs[i].childNodes[j]);
}
}
}](http://www.easycfm.com/tutorials/BuildAListGetATree_files/image011.gif)
Going on tree.js,
we?ll create now ul2tree(ulObj) function. As seen before, this function
is called by getTrees() function.
An <ul> element
is passed as argument to ul2tree(ulObj). For each <li> inside this
<ul>, we check the existence of internal <ul>. If so, we set
<li> class attribute to folder, we create a link to
expand/collapse this item?s sub-tree, and we call, recursively, ul2tree(ulObj)
function with the new <ul> as argument.
![Text Box: function ul2tree(ulObj) {
var liObj;
var liCollapsed;
// loop over all <ul> children using childNodes[] array
for (var i=0;i<ulObj.childNodes.length;i++)
// child tag = <li> ?
if (ulObj.childNodes[i].tagName == 'LI') {
liObj = ulObj.childNodes[i];
// retrieve all <ul> inside <li>
var ulObjs = liObj.getElementsByTagName('UL');
// is there any <ul>?
if (ulObjs.length) {
liCollapsed = (liObj.className == 'collapsed');
// set <li> class to 'folder'
liObj.className = 'folder';
// add a link to expand/collapse <li> sub-tree
liObj.insertBefore(newExpandLink('[*]',liCollapsed),liObj.firstChild);
// if <li> class = collapsed, hide internal <ul>
if (liCollapsed) ulObjs[0].style.display = 'none';
// call recursevely internal <ul>
ul2tree(ulObjs[0]);
}
}
// set last <li> class to 'last'
if (liObj.className == '') liObj.className = 'last'
else liObj.className += ' last';
}](http://www.easycfm.com/tutorials/BuildAListGetATree_files/image012.gif)
Further, we create two other functions:


The link to
expand/collapse items? sub-tree is just created. Now, we need to give it
functionality through treeAction() function, which is called by onclick
event at <div> class=tree.
This function
recognizes which <a> element was clicked, modifying its class from minus
to plus (or vice-versa), and hiding (or showing) the item?s sub-tree
(<ul>).
![Text Box: function treeAction(obj) {
// retrieve clicked element
if (document.all) obj = event.srcElement // IE
else obj = obj.target;
// if the element is not na <a>, return
if (obj.tagName == 'SPAN') obj = obj.parentNode;
if (obj.tagName != 'A') return;
// change class
if (obj.className == 'plus') obj.className = 'minus';
else obj.className = 'plus';
// get associated <li>
var liObj = obj.parentNode;
var ulObjs = liObj.getElementsByTagName('UL');
// if there is no internal <ul>, return
if (!ulObjs.length) return;
// hide/show internal <ul>
if ( ulObjs[0].style.display == 'none' ) ulObjs[0].style.display = 'block'
else ulObjs[0].style.display = 'none' ;
}](http://www.easycfm.com/tutorials/BuildAListGetATree_files/image015.gif)
If we save tree.js
file and refresh tree.htm page on browser, we should have:

Note that Administrative
item is collapsed (as expected). Clicking on [*], we expand/collapse sub‑trees.
Our tree is able to
expand/collapse sub-trees and tree items have appropriate classes.
We have, now, to show
it as proposed in the beginning of this tutorial.
First, we will create tree.css
file and call it from our page
As we write CSS rules,
it will be shown how tree.htm page would look like on browser.
Codes that should be
processed only by IE are preceded by ?//?.

All rules will refer
to <div> class=tree as part of theirs selectors..
Inside tree.css
file, we create two selectors: one for all elements (*) and another for
all <ul>. Rules inside * selector define font properties and non-wrapping
for internal text. Inside ul selector, the only rule hides list bullets.
|
CSS |
IE |
Firefox |
|
div.tree
* { font-family : "MS sans serif"; font-size : 11px; margin : 0; padding : 0; white-space: nowrap; } div.tree
ul { list-style : none; } |
|
|
|
|
We shall add another
rule to ul selector and create a new selector to match all <li>
elements. The new ul rule defines indentation (20px) and distance
between an item and its sub-tree (2px). li rules define the box size
around each item.
|
CSS |
IE & Firefox |
|
div.tree
ul { list-style : none; padding : 2px 0 0 20px; } div.tree
li { padding : 2px 0 2px 9px; line-height : 12px; } |
|