Javascript Tree View Sample

This is the code for the page that is actually called.  This code calls a separate Javascript file (treeview.js) which is listed below.

The upper section of this source code is all you really need to understand in order to use this module, but the javascript file is also listed out for those who would like to see in greater detail how it works.


<html>
<head>
<title>Javascript Tree View Example</title>
<script type='text/javascript' src='treeview.js'></script>
</head>
<body bgcolor="#FFFF99">
<script>
// The syntax for treeAdd is
//  treeAdd(Level,Text to Display,URL to open when clicked)
treeAdd(1,'<span style="font-size:1.3em;font-weight:bold;">Application Development Group</span>','');
treeAdd(2,'Search Engines','');
treeAdd(3,'Google','http://www.google.com');
treeAdd(3,'Yahoo','http://www.yahoo.com');
treeAdd(3,'MSN','http://www.msn.com');
treeAdd(2,'Development Sites','');
treeAdd(3,'General','');
treeAdd(4,'Experts Exchange','http://www.experts-exchange.com');
treeAdd(4,'Developer Shed','http://www.devshed.com');
treeAdd(3,'Web Development','');
treeAdd(4,'World Wide Web Consortium','http://www.w3c.org');
treeAdd(4,'W3 Schools','http://www.w3schools.com');
treeAdd(4,'4 Guys from Rolla','http://www.4guysfromrolla.com');
treeAdd(2,'Level 2','');
treeAdd(3,'Level 3','');
treeAdd(4,'Level 4','');
treeAdd(5,'Level 5','');
treeAdd(6,'Level 6','');
makeTree()
</script>
</body>
</html>

 

treeview.js


/*
TreeView version 1.2
by Neal Schafer

This Code is generated mainly to develop programming skills.
There are many Tree View applications readily available, many most likely more advanced
than the one here. If you wish to use this code, please feel free.
No warranty of any kind is made as to its functionality or useability.
You might want to remove these comments if you are going to use this code for production as
the amount of built in documentation could affect the load speed of your page slightly.

The code is fairly well documented to make it a better learning tool.

How to call this application
============================
1. Save the treeview.js file in your web directory (If you place it in a subdirectory
   you will need to modify the src in the next step to match the subdirectory)
2. Include the following line within the <head> </head> section of your web page:
   <script language=javascript src='treeview.js'></script>
3. Save the Image files and set the image path described in the global variables below.
4. Call the treeAdd function from within your web page. You must call it once for each
   row of the tree.
   You may include link information or not for each row.
   If you do not include link information, be sure to include an empty string.
   example: 
   treeAdd(1,'Level A text','www.applicationgroup.com/tutorials/')
   treeAdd(2,'Level 2 text','')
   treeAdd(3,'Level 3 text','')
   treeAdd(2,'Level 2 text','')
5. When you have added all of the rows you wish to to the tree call the treeMake() function:

// Simple Example Web page Code
// ----------------------------
<html>
<head>
<title>Tree View Example </title>
<script language=javascript src='treeview.js'></script>
</head>
</body>
<script language=javascript>
treeAdd(1,'Level 1 Text','')
treeAdd(2,'Level 2 Text','')
treeAdd(3,'Level 3 Text','')
treeAdd(4,'Level 4 Text','')
treeAdd(2,'Level 2 Text','')
treeAdd(3,'Level 3 Text','')
treeMake()
</script>
</body>
</html>
*/

 
// Define Global Variables
// The treeData array stores all of the information before the tree is displayed
var treeData = new Array()
var imagePath = './images/tvimages/'       // Stores the path to image files used
var mn = imagePath + 'tvMinusNode.gif'     // The Minus Node image file
var ml = imagePath + 'tvMinusLastNode.gif' // The Minus Last Node image file
var pn = imagePath + 'tvPlusNode.gif'      // The Plus Node Image file
var pl = imagePath + 'tvPlusLastNode.gif'  // The Plus Last Node image file
var no = imagePath + 'tvNode.gif'          // The Node image file (no plus or minus)
var ln = imagePath + 'tvLastNode.gif'      // The Last Node image file (no plus or minus)
var vl = imagePath + 'tvVertLine.gif'      // The Vertical Line image file
var bl = imagePath + 'tvBlank.gif'         // The blank image file
var tl = imagePath + 'tvTopLevel.gif'      // The Top Level Image file (Used for Level A nodes)
var of = imagePath + 'tvOpenFolder.gif'    // The Open Folder image file
var cf = imagePath + 'tvClosedFolder.gif'  // The Closed Folder image file
var dc = imagePath + 'tvPage.gif'          // the Document image file
 

// function tree(level,txt,link)
// This function actually creates the object of which treeData is an array.  
// The parameters of this object are:
//  Level   (integer) 1 being top level
//  txt     The text to be displayed in the tree view
//  link    The page that clicking on the text will link you to
//  show    determines if the node is visible 1 = yes; 0 = no
//  hasChild   
//  hasLowerSibling
//  nextSibling
//--------------------------------------------------------------------------------------------------------
function tree(level,txt,link) {
   this.level = level;
   this.txt = txt;
   this.link = link;
   this.show = 1;
   this.hasChild = false;
   this.hasLowerSibling = false;
   this.nextSibling = 0;
}

 
//function treeAdd(level,txt,link)
// This function is used to actually create the array element
// containing the tree object defined above. 
// There is one array entry for each row in the tree.
//------------------------------------------------------------------------------------ 
function treeAdd(level,txt,link) {
  x = treeData.length
  treeData[x] = new tree(level,txt,link)
}
 
// function makeTree()
// This function actually creates and fills in the table in the web browser using the data from the treeData array.
// This function should be called only after treeAdd() has been called for each node in the tree.
// --------------------------------------------------------------------------------------------------------
function makeTree() {
  var levelSet = 0;
  var link = '';
  var txt = '';
  // Set the Child and Sibling Flags for Each Row
  for (i=0;i<treeData.length;i++)	{
    hasSibling(i);
    if (i+1 < treeData.length) {
      if (treeData[i+1].level > treeData[i].level) treeData[i].hasChild = true;
      else treeData[i].hasChild = false;
    }
  }
  levelSibling = new Array();
  for (i=0;i<treeData.length;i++)	{
    sLevel = treeData[i].level;
    levelSibling.length = sLevel+1;
    levelSibling[sLevel] = treeData[i].hasLowerSibling;
    txt = treeData[i].txt;
    var img = setImg(i);
    // Create a div to hold the node.  
    if (sLevel > 2) {  // If the node level is higher than 2 then start with it hidden.
      var sRow = "<div id='row" + i + "' style='height:20px;overflow:hidden;display:none;width:100%;'>";
      treeData[i].show = 0;  // mark the node as hidden
    }
    else {
      var sRow = "<div id='Div1' style='height:20px;overflow:hidden;width:100%;'>";
    }
    for (zz=1;zz<sLevel;zz++) {// display vertical lines or spaces as required to line up the node properly.
      // if the node has a sibling then display a vertial line
      if (levelSibling[zz]) sRow += "<img src='" + vl + "' alt='' style='float:left;' />";  
      // otherwise display a vertical line (if the node level is > 1)
      else if(zz > 1) sRow += "<img src='" + bl + "' alt='' style='float:left;' />"; 
    }
    sRow += "<div style='float:left;'>" + img + "</div%gt;" ;  // display the images for the node
    sRow += "<div style='margin-top:2px;' ><span id='tvText" +i + "' onclick='clickRow(" + i + ");'>" + treeData[i].txt + "</span></div>";
    sRow += "</div>"
    document.write(sRow);
   
  }
}
 
// hasSibling(rec)
// Determine if the specified node has siblings (members at the same level under the same parent)
function hasSibling(rec) {
  var hasSibling = false;
  // loop through the array of tree objects.
  for (z=rec+1;z<treeData.length;z++) {  
    // if we reach a tree object with a lower level number then we are no longer under
    // the same parent, set the nextSibling to be the next node and break out of the loop.
    if (treeData[z].level < treeData[rec].level) {
        treeData[rec].nextSibling = z;
        break;
    }
    // if we find a node at the same level as the current node
    // set the nextSibling value to that node and set the hasLowerSibling
    // value to true, then break out of the loop.
    if (treeData[z].level == treeData[rec].level) {
      treeData[rec].hasLowerSibling = true;
      treeData[rec].nextSibling = z;
      break;
    }
  }
  // if the nextSibling value is 0 then set the nextSibling value to the last Node.
  if (treeData[rec].nextSibling == 0) treeData[rec].nextSibling = treeData.length;
}  

// setImg(nRow)
// This function determines what image files are required for each row in the tree and stores
// that information in the treeData array.
// ---------------------------------------------------------------------------------------------------------
function setImg(nRow) {
  // if the node has a child then
  if (treeData[nRow].hasChild ) {
    // and the node has a sibling then imagea = plusnode
    if (treeData[nRow].hasLowerSibling) imagea = pn;
    // else imagea = plusLastNode
    else imagea = pl;
    // imageb = closed Folder
    imageb = cf;
  }
  // if the node does not have a child 
  else {
    // if the node has a sibling then imagea = node image
    if (treeData[nRow].hasLowerSibling) imagea = no;
    // else imagea = LastNode
    else imagea = ln;
    // imageb = document
    imageb = dc; 
  }
	var img = "<img id='imagea" + nRow + "' src='" + imagea + "' border=0 onclick='treeHide(" + nRow + ");' alt='' />";
  img += "<img id='imageb" + nRow + "' src='" + imageb + "' border=0 onclick='clickRow(" + nRow + ");' alt='' />";
  // if the node level is 1 then show the treeLevel image
  if (parseInt(treeData[nRow].level) == 1) var img = "<img id='Img1' src='" + tl + "' border=0 onclick='clickRow(" + nRow + ");' alt='' />";
  return img
}

 

// function treeHide(nRow)
// Hides or shows the children of a given row
// ------------------------------------------------------------------------------------------------------
function treeHide(nRow) {
	if (treeData[nRow+1].show ==0) {      	// Show hidden rows We use nRow+1 because we don't actually want to hide the row that was clicked
    for (i=nRow+1;i<treeData[nRow].nextSibling;i++) {
      if (parseInt(treeData[i].level) == parseInt(treeData[nRow].level)+1) {
        document.getElementById('row' + i).style.display = 'block';
        treeData[i].show = 1;
      }
    }
    if(treeData[nRow].hasLowerSibling) document.getElementById('imagea' + nRow).src = mn;
    else document.getElementById('imagea' + nRow).src = ml;
    document.getElementById('imageb' + nRow).src = of;
  }
	else {	// Hide Rows
    for (i=nRow+1;i<treeData[nRow].nextSibling;i++) {
      document.getElementById('row' + i).style.display = 'none';
      treeData[i].show = 0;
      if (treeData[i].hasChild) {
        document.getElementById('imagea' + i).src = pl;
        document.getElementById('imageb' + i).src = cf;   
      }
    }
    if(treeData[nRow].hasLowerSibling) document.getElementById('imagea' + nRow).src = pn;
    else document.getElementById('imagea' + nRow).src = pl;
    document.getElementById('imageb' + nRow).src = cf;
  }
}
 

// function clickRow(nRow) - Event to occur when a user clicks a row
// ---------------------------------------------------------------------------------
function clickRow(nRow) {
  currentRow = nRow;
  // unhighlight all rows
  for (i=0;i<treeData.length;i++) {
    document.getElementById('tvText'+i).style.color = "#000000";
    document.getElementById('tvText'+i).style.backgroundColor = "transparent";
    document.getElementById('tvText'+i).style.fontWeight = "normal";
  }
  // highlight clicked row
  document.getElementById('tvText'+nRow).style.color = "#ffffff";
  document.getElementById('tvText'+nRow).style.backgroundColor = "#0000cc";
  document.getElementById('tvText'+nRow).style.fontWeight = "bold";
  // perform the row's link command
  // Note changing the next line will change what happens when the user clicks a node
  if (treeData[nRow].link != "") window.location = (treeData[nRow].link); 
}