Monday 27 May 2013

Expandable Treeview in HTML (without images).

      A treeview presents a hierarchical view of information. Each item can have a number of subitems. An item can be expanded to reveal the subitems, and collapsed to hide them. The following figure gives an idea of what it actually looks like :



      This kind of a treeview can be used in HTML reports to hierarchically categorize information in the way shown above. Most solutions for this, however, use external images for the plus/minus icons. This may not acceptable if the report has to be portable (as it would require that the icon file also be sent with the HTML report). So here we generate the above tree-view without using any extra image files, with the help of plain HTML elements, JavaScript and CSS.

      The source code of the HTML document containing the treeview is shown below. An explanation of how this was achieved follows.


<html>
 <head>
  <style>
   .invisible
   {
    background-color: #E6E6E6;
    border: none;
    padding-bottom: 5;
   }
   li,ul
   {
    list-style-type: none;
   }
  </style>
  <script type="text/javascript">
   function toggle(id,v){
    if(v.value=="+")
     v.value="-";
    else
     v.value="+";
    var e=document.getElementById(id);
    if(e.style.display=='')
     e.style.display='none';
    else
     e.style.display='';
   }
  </script>
 </head>
 <body>
  <ul>
   <li><!- (+ item)->
    <input id="item1" class="invisible" type="button" onclick="toggle('content1',this)" value="+" style="width:20px;height:20px;"/>
    <label for"item1"> item 1 (nested item)</label>
    <div id="content1" style="display:none">
    <ul>
     <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;item 1.1</li>
     <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;item 1.2</li>
     <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;item 1.3</li>
     <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;item 1.4</li>
     <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;item 1.5</li>
     <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;item 1.6</li>
     <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;item 1.7</li>
     <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;item 1.8</li>
    </ul>
    </div>
   </li>
   <li><!- (normal item) ->
         
    item 2 (nomal item)
    
   </li>
   <li><!- (+ item)->
    <input id="item3" class="invisible" type="button" onclick="toggle('content3',this)" value="+" style="width:20px;height:20px;"/>
    <label for"item3"> item 3</label>
    <div id="content3" style="display:none">
    <ul>
     <li>     item 3.1</li>
     <li>
      <input id="item3.2" class="invisible" type="button" onclick="toggle('content3.2',this)" value="+" style="width:20px;height:20px;"/>
      <label for"item3.2">item 3.2</label>
      <div id="content3.2" style="display:none">
      <ul>
       <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;item 3.2.1</li>
       <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;item 3.2.2</li>
       <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;item 3.2.3</li>
       <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;item 3.2.4</li>
       <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;item 3.2.5</li>
       <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;item 3.2.6</li> 
      </ul>
     </li>
     <li>
      <input id="item3.3" class="invisible" type="button" onclick="toggle('content3.3',this)" value="+" style="width:20px;height:20px;"/>
      <label for"item3.3">item 3.3</label>
      <div id="content3.3" style="display:none">
      <ul>
       <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;item 3.3.1</li>
       <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;item 3.3.2</li>
       <li>
        <input id="item3.3.3" class="invisible" type="button" onclick="toggle('content3.3.3',this)" value="+" style="width:20px;height:20px;"/>
        <label for"item3.3.3">item 3.3.3</label>
        <div id="content3.3.3" style="display:none">
        <ul>
         <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;item 3.3.3.1</li>
         <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;item 3.3.3.2</li>
         <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;item 3.3.3.3</li> 
        </ul>
       </li>
       <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;item 3.3.6</li> 
      </ul>
     </li>
     <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;item 3.3</li>
    </div>
   </li>
   <li><!- (+ item)->
    <input id="item4" class="invisible" type="button" onclick="toggle('content4',this)" value="+" style="width:20px;height:20px;"/>
    <label for"item4"> item 4</label>
    <div id="content4" style="display:none">
    <ul>
     <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;item 4.1</li>
     <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;item 4.2</li>
     <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;item 4.3</li>
     <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;item 4.4</li>
    </ul>
    </div>
   </li>
  </ul>
 </body>
</html>

Explanation :

The List :
We can visualize each subtree as a separate list. We can thus use the HTML list <ul> to display the subtree. This <ul> will contain all the items in this subtree as list iems <li>. If any of the list items itself is a subtree we can include another <ul> inside the <li> elements. To hide the bullets that accompany the list we use the CSS property "list-style-type: none".

The Icons :
For the expandable icon, since we cannot use external image file for the icons, we shall make use of HTML elements. We use a Button in this case. For making it look less like a button and more like an expandable icon, we remove the border and change the background color of the button. We also set the text of the button to a '+' to make it look like an expandable icon. On clicking the button the text will change to '-' and the subtree will become visible.

The hidden <div> tags : 
To display/hide the subtree we can use div tags with their style set to "display:none". On clicking the '+' icon we shall change this style attribute to the default(i.e. empty), which will make it visible once again.

The Javascript :
We shall use Javascript to hide/display the subtree. The following javascript function will take care of this. The function takes two arguments, the contained div tag and the button itself. In the function we check the text of the button from a '+' to a '-' for expanding and vice-versa for hiding the contents. Also we change the style attribute of the div tags from 'none' to empty (i.e. ' ') and for making it visible or vice-versa for hiding it.


function toggle(id,v){
    if(v.value=="+")
        v.value="-";
    else
        v.value="+";
    var e=document.getElementById(id);
    if(e.style.display=='')
        e.style.display='none';
    else
 e.style.display='';
}

1 comment:

  1. Thank you for writing this code. When I put it into a new page on blogger, I get a "Your HTML cannot be accepted: Tag is not closed: DIV" error message. Can you help?

    ReplyDelete