Skip to main content
Email Password   helpLost your password?

Sample with specific colors in Internet Explorer

Figure 1. Sample with specific colors rendered with VML in Internet Explorer.

Sample with specific colors in Firefox

Figure 2. Sample with specific colors rendered with canvas in Firefox.

Sample showing collapsed and selected nodes

Figure 3. Sample showing collapsed and selected nodes rendered with VML in Internet Explorer.

Contents

Introduction

This article presents a JavaScript component which renders a tree on the screen using VML (Vector Markup Language) in Internet Explorer 6+ or the <canvas> element in Firefox 1.5+.

There are plenty of JavaScript trees out there, and most of them have a better cross-browser compatibility than this, are faster and better optimized. The goal of this code is to present a client-side implementation of the Walker's layout algorithm (see References), leaving off code optimizations. In short, the component has born after the algorithm, as I think that a living sample would be better than an abstract source-code level implementation.

One of the classic treeview JavaScript components I use sometimes is Geir Landr�'s DTree: outstanding and simple. Some time ago, an article appeared here at CodeProject that presents a horizontal JavaScript tree, based upon DTree, which uses HTML tables to render the tree in a horizontal manner. I want to mention those here as they inspired me to publish this article. Moreover, much of the functionalities of this version mimic that on those scripts.

I hope this component will fill the gap in projects when a tree layout is needed, but without server-side code. Of course, any comments, corrections, suggestions, etc... are very welcome.

Features

The best way to get an idea of what could be accomplished by using this component is to download the sources and play with the sample included. The API reference below could give you a more precise idea of what could be done. But, as a briefing, features include:

I would like to say that this is a work in progress. In particular, the code is structured to allow different rendering technologies and I must definitively work harder on this topic.

Background

The Walker's algorithm expands on the previous works of Reingold, Tilford, Shannon et al. providing a solution where a tree drawing occupies as little space as possible while satisfying the following aesthetic rules:

  1. Nodes of the same level are aligned, and the axis of all levels are parallel.
  2. A parent should be centered over its children.
  3. A tree and the same tree defined in reverse order, should produce layouts that are reflections of one another. The same subtree must be rendered the same way no matter where it appears in the tree.

The Walker's algorithm goal over its predecessors was to provide a solution to fully satisfy the third rule, by means of spacing out evenly smaller subtrees in the interior of adjacent larger subtrees.

The difference of the apportion routine in Walker's algorithm

Figure 4. Samples showing the difference of the apportion routine in Walker's algorithm..

The main concepts of the algorithm are:

The algorithm works in two passes. The first pass (firstWalk) is a postorder traversal. The different subtrees are processed recursively from bottom to top and left to right positioning the rigid units that form each subtree until no one touch each other. As the traversal goes, smaller subtrees are combined forming larger subtrees until we reach the root. During the process, the apportion routine space out evenly the inner smaller subtrees that could float between two adjacent larger subtrees (to satisfy the symmetry of the 3rd rule). The second pass (secondWalk) is a preorder traversal which calculates the final node position by adding all the ancestors modifiers to the preliminary coordinate of each node.

Gao Chaowei (see References) proposed an optimization to the firstWalk routine which consists in an incremental version of the Walker's algorithm. This version avoids to recalculate the node preliminary coordinate and modifier when changes made to the tree structure don't imply modifications to their values. This optimization is not yet implemented in this component.

The algorithm also adjust the calculations if the layout is to be made in a different direction (i.e. bottom to top). Different uses may require different views. In occident, traditionally a top disposition means power, like in organizational hierarchies; a bottom layout means evolution or growth, like in biology; whereas left and right layouts could mean time evolution. (But this is a particular consideration).

Just a word to mention that, an uniform layout algorithm like this one is adequate for relative small trees. Trees with a large number of nodes may require other layout and visualization techniques, like the ability to zoom, pan and focus, collapse some but not all the children of a node, adding interactive searching. There are a number of other solutions to achieve the same objectives including, but not limited to, hyperbolic trees, treemaps, Degree of interest calculations, ... The curious reader could find a lot of information on the net.

Using the code

Quick & dirty guide to get things up and working

Let's build an example, (all samples are included in the download) to understand how to draw a simple tree. After that, with the API reference and looking at the advanced samples code you could fully understand how to use this component.

First of all, you must include the component script and link the style-sheet in the <head> section of your HTML page (remember to set the paths upon your installation):

<head>
    <!-- Content goes here... -->
    <script type="text/javascript" src="ECOTree.js"></script>
    <link type="text/css" rel="style-sheet" href="ECOTree.css" />
    <!-- Content goes here... -->
</head>

Besides, if you plan to user Internet Explorer you must add the next lines to the <head> section of your HTML page for VML to render correctly:

<head>
    <!-- Content goes here... -->
    <xml:namespace ns="urn:schemas-microsoft-com:vml" prefix="v"/>
    <style>v\:*{ behavior:url(#default#VML);}</style>         
    <!-- Content goes here... -->
</head>

In your HTML page you must place a block container for the tree, like a <div> with an ID that you must supply to the tree constructor. Then you must include a <script> block to create the tree itself, add some nodes -probably from a database in real projects- and then draw the tree. Let's look at an example:

<div id="myTreeContainer"></div>
var myTree = new ECOTree("myTree","myTreeContainer");
myTree.add(0,-1,"Apex Node");
myTree.add(1,0,"Left Child");
myTree.add(2,0,"Right Child");
myTree.UpdateTree();

The result will be:

Quick example 1

Figure 5. Quick example 1.

You must ensure that the script block gets executed once the page is loaded, or at least when the container is loaded. So you could choose to insert the script after the container or to create the tree inside a function that gets called when the OnLoad event occurs for the document or body, as usual.

Note that the component has default values for almost everything, causing that those five lines of code could create a tree that you can collapse or expand at will, and you can select/unselect multiple nodes by simply clicking them. Also, every node has a hyperlink Javascript:void(0); by default. Almost every time, you will want to change the look and feel and the behavior of the tree to better fit your needs. This can be done with the config instance member of the tree. Let's modify the previous example by adding some lines:

var myTree = new ECOTree("myTree","myTreeContainer");    
myTree.config.linkType = 'B';
myTree.config.iRootOrientation = ECOTree.RO_BOTTOM;                        
myTree.config.topYAdjustment = -160;
myTree.config.linkColor = "black";
myTree.config.nodeColor = "#FFAAAA";
myTree.config.nodeBorderColor = "black";
myTree.config.useTarget = false;
myTree.config.selectMode = ECOTree.SL_SINGLE;
myTree.add(0,-1,"Apex Node");
myTree.add(1,0,"Left Child");
myTree.add(2,0,"Right Child");
myTree.UpdateTree();

With these minor changes, the tree now will look like this:

Quick example 2

Figure 6. Quick example 2.

This time, the nodes don't have a hyperlink (useTarget = false) and you can select only one node at a time (selectMode = ECOTree.SL_SINGLE).

OK, now that the basics had been covered, let's go on to discover all the possibilities.

API Reference

ECOTree configuration

Here are the config parameters with their default values:

this.config = {
    iMaxDepth : 100,
    iLevelSeparation : 40,
    iSiblingSeparation : 40,
    iSubtreeSeparation : 80,
    iRootOrientation : ECOTree.RO_TOP,
    iNodeJustification : ECOTree.NJ_TOP,
    topXAdjustment : 0,
    topYAdjustment : 0,
    render : "AUTO",
    linkType : "M",
    linkColor : "blue",
    nodeColor : "#CCCCFF",
    nodeFill : ECOTree.NF_GRADIENT,
    nodeBorderColor : "blue",
    nodeSelColor : "#FFFFCC",
    levelColors : ["#5555FF","#8888FF","#AAAAFF","#CCCCFF"],
    levelBorderColors : ["#5555FF","#8888FF","#AAAAFF","#CCCCFF"],
    colorStyle : ECOTree.CS_NODE,
    useTarget : true,
    searchMode : ECOTree.SM_DSC,
    selectMode : ECOTree.SL_MULTIPLE,
    defaultNodeWidth : 80,
    defaultNodeHeight : 40,
    defaultTarget : 'Javascript:void(0);',
    expandedImage : './img/less.gif',
    collapsedImage : './img/plus.gif',
    transImage : './img/trans.gif'
}

ECOTree public methods

Samples Included

In the download you can find several simple examples you can play with. All the images in this article are made with the code on the examples. There is an advanced example which will let you play with almost all the options in the component. The data in the samples has been obtained in the Wikipedia.

References

Future Enhancements

History

You must Sign In to use this message board.
 
 
Per page   
 FirstPrevNext
GeneralIdea for Family Tree Pin
u329
19:26 26 Aug '09  
GeneralAlign to center Pin
Antonio_Lopez
0:26 12 Aug '09  
GeneralThank you! Pin
Reza Nazemi
20:53 30 Jul '09  
Generaltree not working with ie8 Pin
Praveensoli
0:13 14 Jul '09  
GeneralRe: tree not working with ie8 Pin
axadmin
8:52 4 Sep '09  
GeneralRe: tree not working with ie8 Pin
Praveensoli
0:47 29 Sep '09  
QuestionVML:Group element scrollbars Pin
Eisenfuss
5:11 7 Jul '09  
Generalproblem with collapse node Pin
Sabitha P
20:27 4 Jun '09  
Generalproblem with IE8!!! please help! Pin
Member 3913151
4:54 3 Jun '09  
GeneralRe: problem with IE8!!! please help! Pin
fr33j6ck
11:15 30 Jun '09  
GeneralRe: problem with IE8!!! please help! Pin
Praveensoli
0:51 13 Jul '09  
Questionproblem with the print [modified] Pin
Member 3911851
4:49 13 May '09  
Questionlong time to expand all when tree is big(many level nodes) [modified] Pin
Member 3911851
4:31 13 May '09  
Questionhow to include many persons with a hyperlink in a single node Pin
Sabitha P
21:42 12 May '09  
Generalhow to implement horizontal line between two node?? Pin
regey
23:11 29 Apr '09  
NewsProblem with target: try this solution Pin
falcon79
7:05 23 Apr '09  
GeneralRe: Problem with target: try this solution Pin
passionjavaj2ee
3:37 8 Jul '09  
GeneralThank you for your script!!! Pin
funkypunkydrunky
2:05 19 Apr '09  
General"Title" feature when the mouse over the node. [modified] Pin
tonyyeung
22:38 25 Mar '09  
Generalgreat script, I've incorporated this into an icefaces iphone app. Pin
cwg1
2:26 16 Mar '09  
Generalhi i need help Pin
tareqwz
5:02 2 Feb '09  
QuestionDrawing in FF3 Pin
ipaliych
21:01 25 Jan '09  
QuestionWon't display root oriented at bottom or right Pin
AshleyKitson
8:22 10 Nov '08  
AnswerRe: Won't display root oriented at bottom or right Pin
AshleyKitson
9:06 10 Nov '08  
GeneralDon't need expand/collapse [modified] Pin
jimmygyuma
3:56 9 Nov '08  


Last Updated 28 Nov 2006 | Advertise | Privacy | Terms of Use | Copyright © CodeProject, 1999-2009