65.9K
CodeProject is changing. Read more.
Home

Easy DHTML treeview

starIconstarIcon
emptyStarIcon
starIcon
emptyStarIconemptyStarIcon

2.22/5 (2 votes)

May 22, 2012

CPOL

2 min read

viewsIcon

12986

This is an alternative for "Easy DHTML treeview"

Introduction

This code is an HTML/JavaScript tree based on the Easy DHTML treeview.

Take a look at the original first to get an idea of what the code is doing and how the tree is organized: there

It uses div instead of tables in order to simplify the HTML code and make it a bit more readable. The downside is that the JavaScript is slightly more convoluted as the tree hierarchy is a bit more complex: at each level, the parent div contains two or more children the first one for the title bar and image, the second for the first sub-item and so on. The event is triggered by clicking on the title bar.

CSS styles are used to set the appearance of the tree elements at every level.  

 

Using the code

The code can be pasted into a stand-alone HTML file. 

Create a subfolder named "images" to store the images from the original version. 

<script type="text/javascript">

	//Expands/collapses a node's children and sets appropriate image
    function Toggle(node)
    {
	//paths to images used in tree
        var IMG_MINUS = "images/minus.gif";
        var IMG_PLUS = "images/plus.gif";
        var IMG_LEAF = "images/leaf.gif";
        
	//find the elements to modify or test relatively to node clicked
	//image to modify
        var img = node.children.item(0).children.item(0);
	//parent of items to show or hide
        var parent = node.parentNode;
	//first item to hide is second child of parent - first child is the node clicked
        var firstItem =  parent.children.item(1);
	//is this first item to hide/show an empty div?
        var bHasChildren = parent.children.item(1).childElementCount > 0;
        // Unfold the branch if it isn't visible
        if (firstItem.style.display == 'none')
        {
	    //if this level has children the image shown in a minus sign, otherwise leaf image
            img.src = bHasChildren ? IMG_MINUS : IMG_LEAF;
			//show all the children
            for(i=1;i<parent.children.length;i++)
            {
                parent.children.item(i).style.display = '';
            }
        }
        // Collapse the branch if it IS visible
        else
        {
            // Change the image to a plus sign if this level has children otherwise leaf image
            img.src = bHasChildren ? IMG_PLUS : IMG_LEAF;
			//hide all the children
            for(i=1;i<parent.children.length;i++)
            {
                parent.children.item(i).style.display = 'none';
            }
        }
    }
</script>
<style>
#tree
{
	height:500px;
	width: 200px;
	border:1px solid black;
	padding-left:2px;
	padding-right:2px;
	padding-top:1px;
	padding-bottom:1px;
}
.tl1, .tl2, .tl3
{
	border:1px solid blue;
	background-color:yellow;
	width: 100%;
	height:20px;
	position:relative;
	margin-bottom:1px;
}
.tl1_, .tl2_, .tl3_
{
	position:relative;
	text-align:left;
	-moz-user-select: none;
	-webkit-user-select: none;
}
.tl1
{
	height:20px;
	left:-1px;
}
.tl2
{
	left:-1px;
}
.tl3
{
	left:-1px;
}
.tl1_
{
	left:10px;
	font-size:14pt;
}
.tl2_
{
	left:20px;
	font-size:12pt;
}
.tl3_
{
	left:30px;
	font-size:10pt;
}
.imgNode
{
	margin-right:5px;
}

</style> 
<div id="tree">
    <div id="lvl1_1">
        <div onClick="Toggle(this)"  class="tl1" >
            <div class="tl1_" onselectstart="return false;"><img 
              class="imgNode" src="leaf.gif" />Level 1</div>
        </div>
        
        <div id="lvl2_1">
            <div onClick="Toggle(this)" class="tl2" >
                <div  class="tl2_" onselectstart="return false;"><img 
                  class="imgNode" src="leaf.gif" />Level 2</div>
            </div>
            <div id="lvl3_1">
                <div onClick="Toggle(this)" class="tl3" >
                    <div class="tl3_" onselectstart="return false;"><img 
                      class="imgNode" src="leaf.gif" />Level 3</div>
                </div>
                <div></div>
                <!--dummy subitem-->
            </div> <!--level 3-->
            
            <div id="lvl3_2">
                <div onClick="Toggle(this)" class="tl3" >
                    <div class="tl3_" onselectstart="return false;"><img 
                      class="imgNode" src="leaf.gif" />Level 3</div>
                </div>
                <div></div>
                <!--dummy subitem-->
            </div> <!--level 3-->
            
        </div> <!--level 2-->
        
        <div id="lvl2_2">
            <div onClick="Toggle(this)" class="tl2" >
                <div  class="tl2_" onselectstart="return false;"><img 
                  class="imgNode" src="leaf.gif" />Level 2</div>
            </div>
            <div id="lvl3_3">
                <div onClick="Toggle(this)" class="tl3" >
                    <div class="tl3_" onselectstart="return false;"><img 
                      class="imgNode" src="leaf.gif" />Level 3</div>
                </div>
                <div></div>
                <!--dummy subitem-->
            </div> <!--level 3-->
            
            <div id="lvl3_4">
                <div onClick="Toggle(this)" class="tl3" >
                    <div class="tl3_" 
                      onselectstart="return false;"><img class="imgNode" 
                      src="leaf.gif" />Level 3</div>
                </div>
                <div></div>
                <!--dummy subitem-->
            </div> <!--level 3-->
            
        </div> <!--level 2-->
    
    </div> <!--lvl 1-->
</div><!--tree--> 

Code description 

Here is a description of the div structure for each level:

<div id="lvlX_N">
	<div onClick="Toggle(this)" class="tlX" >
		<div class="tlX_" onselectstart="return false;">
			<img class="imgNode" src="leaf.gif" />
			Level X
		</div>
	</div>
	
	<div ...> <!--firstItem: div containing a child or empty-->
	</div>
	
	<div ...> <!--another child...-->
	</div>
	
	...
	
</div> <!--level X--> 

The main div for each level as an id like lvlX_N - where X is the level (1,2,3) and N is sequential so that IDs are unique.

The second div supports the OnClick calling the Toggle function and is the node sent to the function.

From this node the code goes up one level to find the parent:

var parent = node.parentNode; 

And we dig down to find the image:

var img = node.children.item(0).children.item(0);  

This second div also supports the style showing the "title bar", the styles tl1, tl2, tl3 in my css. Finally it contains another div with the image and text, with the text style defined by the styles tl1_, tl2_, tl3_.

From the parent node we can go down to the second div which contains the first child. If this level does not have children then this firstChild is an empty div. Additional divs may define other children: 

var firstItem =  parent.children.item(1);
var bHasChildren = firstItem.childElementCount > 0; 

The rest of the code sets the image and shows or hides the children by setting the display property of the divs which shows or hides all of their content. 

Points of Interest  

The code for switching the images does not work in IE8. This is not a problem since my HTML code will be dynamically generated by script and set to a div tree inner HTML with the proper images set on each click. However I would be interested in finding a solution for making this work properly in IE8. I tested on chrome 15 and Firefox 3.6.