Informatika Mihelac
July 28 2005 dhtml | javascript | usability

HTML Treetable

HTML Treetable javascript allows creating a components capable of expanding and contracting rows as well as showing multiple columns of data. It can be useful in presenting hierarchical tabular data.

Let’s look at some examples first:

Example 2 – icon that shows expanded / collaped row state is added, as well as some style to table.

How HTML Treetable works

Every table row has an id attribute set and the id is assebled of table id, eventual parent rows indexes and current row index in parent row delimitated with underscore (). If we give id to the table in examples table1, the first row would have id of table1_0, it’s child record would have id of table1_0_0, second row table1_0_1 and so on. Anchor that would expande or collapse specific row would call javascript function treetable_toggleRow(row_id);, where row_id is id of specific row.

Functions treetable_collapseAll(tableId) and treetable_expandAll(tableId) allows all rows in table to be expanded or collapsed.

Callback javascript function that would be called every time row is collapsed or expanded can be defined by setting value of treetable_callbacks['eventRowStateChanged'] to callback function name.

Additional info

HTML table is meant to be created from server side script. If there is interest for a PHP script that would create HTML code for the table from an array please drop a comment.

Script has been tested on WIN XP with Firefox 1.06, IE6 and Opera 8.

Download

Download the script and examples

comments feed

42 comments

  1. # On August 09, 2005 at 08:08 AM, Zed said:
    That's interesting idea. I wonder if it is possible and how many work would be to implement HTML Treetable using AJAX for loading data from server asynchronously.
  2. # On August 13, 2005 at 03:08 AM, Jeff said:
    Any ideas on how to sort the column data?
  3. # On August 16, 2005 at 06:08 AM, Bojan Mihela?� said:
    Sorting can be acomplished, but table should be sorted by ROW id first. As ROW id's are composed as paths of element position in tree (0, 0_0, 0_1, 0_1_0 etc) sorting them and thus upgrading some existing script for table sorting should not be a big deal.
  4. # On August 29, 2005 at 10:08 AM, Brad said:
    Is there a way to set the treetable to default, to a collapsed state? I.E. -> Upon visiting the page, I would prefer to have level 0, and level 1 visible in the heirarchy, and have the level 2 and lower children defaulted to a hidden state. As I see the script now, the script always starts out in a fully expanded state. Thoughts?
  5. # On September 20, 2005 at 09:09 AM, wiser said:
    How can the treetable be set to a collapsed state on default? Excellent javascript utility!
  6. # On September 21, 2005 at 09:09 AM, Bojan Mihela?� said:
    Wiser, treetable can be set to collapsed state on many ways, some are: - put treetable_collapseAll('table1'); in body onload method - write additional javascript function that would open and close table to the specific level
  7. # On September 21, 2005 at 09:09 AM, Bojan Mihela?� said:
    Set style on desired rows to style="display:none;" is problematic as that does not describe row state entirely (imagine when you click on collapse all on root record, all children records are still expanded even if they are not displayed). Specific row's states are saved in treetable_rowstate global variable.
  8. # On September 21, 2005 at 09:09 AM, wiser said:
    Bojan, thanks for the response. I have tried a couple of alternatives: 1). calliing js function to initialize all rows to collapsed. This is fairly slow, since I have roughly a thousand rows that may or may not have children. 2) I have set the "display:none" when creating a row, but as you stated below, the rowstate is held in the treetable_rowstate global variable, as expanded, so it takes mulitple clicks to visually expand. I am still working on the default collapse, and will respond with a solution when have a chance. Thanks, wiser
  9. # On October 19, 2005 at 08:10 AM, Ron Savage said:
    See also CGI::Explorer at http://search.cpan.org/~rsavage/CGI-Explorer-2.05/
  10. # On February 06, 2006 at 02:02 AM, Mats said:
    Nice widget! Have you tought of how to combine this with a paging utility? Mats
  11. # On February 10, 2006 at 07:02 AM, Yusuf said:
    Great utility.. hmm i wonder if anyone has any ideas on how i can modify this so that i can re-order rows. So that i can give the user the option of selecting a row and then pressing a up or down icon to move the row up or down
  12. # On February 10, 2006 at 09:02 AM, Krishnendra said:
    How do we add sorting capabilities on the columns?
  13. # On February 11, 2006 at 09:02 AM, Bojan Mihelac said:
    Krishnendra: If you generate table on server then it would be very easy to sort table.
  14. # On February 18, 2006 at 05:02 AM, Carlos Rivero said:
    hey ... thanks for this tree table, Any clues on how to collapse by default with onload event or using display none ??? I have implemented a part to hide colums but is slow very big tables.
    function togglecol(colIndex,colIndexEnd) {
    
    for (colIndex; colIndex <= colIndexEnd; colIndex++)
    {
    var table = document.all ? document.all.table1 :
    
    document.getElementById('table1');
    for (var r = 0; r < table.rows.length; r++){
    if(table.rows[r].cells[colIndex].style.display == \"none\")
    {
    table.rows[r].cells[colIndex].style.display = \'\';
    //treetable_fireEventColStateChanged(colId, \'1\');
    }
    else
    {
    table.rows[r].cells[colIndex].style.display = \'none\';
    // treetable_fireEventColStateChanged(colId, \'0\');
    }
    } } }
    
    to call the function use starting and ending column to hide
  15. # On April 04, 2006 at 03:04 AM, Jignesh said:
    Hi Bojan, its good to help me. But i have question my many clients using NetScape 4.7 can u tell me How it will work in NetScape 4.7 ? please reply asap. thanks & Regards -Jignesh
  16. # On April 04, 2006 at 11:04 AM, Bojan said:
    Jingesh, this script would not work in Netscape 4.7 at least because it uses getElementById() which Netscape 4.7 does not support.
  17. # On April 05, 2006 at 10:04 AM, mlad said:
    Hi Bojan. I have interest for server side script which generate html code for the table. Any ideas? Thanks
  18. # On April 05, 2006 at 11:04 AM, Bojan said:
    mlad, generating HTML with server side shouldn't be any problem. Just follow naming scheme for rows ID's and it would work.
  19. # On April 13, 2006 at 06:04 AM, Alexander landpro said:
    Very useful! Thank you very much!
  20. # On June 22, 2006 at 17:06 PM, Donna said:
    Hi Bojan, It is indeed a great utility. I would really appreciate if you could let me know how we can add paging support for the treetable?
  21. # On July 11, 2006 at 15:07 PM, greg@gregdressel.com said:
    bojan, thanks for the great/smart script. i just had a question about using multiple on/off images to initiate the script. currently it's based on using just 1 'folder' icon, but what if you had a couple tab-images on a page, each able to collapse/expand a tree table, BUT, they are 2 different images, both with their own on and off state? any ideas?
  22. # On July 12, 2006 at 03:07 AM, Bojan said:
    Greg, you can change treetable_eventRowChanged(rowId, state) function so you can use more icons if you need. For example, you can add "_open" or "_closed" to existing img.src and this way can use as many images you want.
  23. # On August 08, 2006 at 00:08 AM, rathina@indigotx.com said:
    Tree javascript is very usefull , i used in my project , thanks a lot
  24. # On August 10, 2006 at 21:08 PM, http://malacma.cjb.net/malacma@gmail.com said:
    Oh! I wonder too if were implemented a AJAX call that populate nodes! Anybody knows where to find it? malacma@gmail.com
  25. # On August 29, 2006 at 07:08 AM, nik said:
    the only problem I've got is a VERY slow collapse/expand feature with a number of records more than 1000...is there a way to increase a speed?
  26. # On September 30, 2006 at 06:09 AM, Nilesh Dhote said:
    Hello, We have started a new venture www.scripts-directory.net and would request you to submit your scripts. Submission of scripts is absolutely FREE and Without Registration. Please visit www.scripts-directory.net Regards Nilesh Dhote Business development, Scripts-Directory.net
  27. # On November 01, 2006 at 04:11 AM, Ajith v said:
    Hello, The script has helped me. Thank you. regards Ajith
  28. # On November 09, 2006 at 10:11 AM, Sara said:
    Thank you so much for your script. It has helped me a lot. I also had a question. How would I be able to keep the state that the rows are on, when the page is refreshed by either a row added or deleted? Some rows are expanded and some collapsed - how would I keep each of their states, so that it doesn't default to all expanded or all collapsed? Thanks!
  29. # On November 09, 2006 at 10:11 AM, Sara said:
    Thank you so much for your script. It has helped me a lot. I also had a question. How would I be able to keep the state that the rows are on, when the page is refreshed by either a row added or deleted? Some rows are expanded and some collapsed - how would I keep each of their states, so that it doesn't default to all expanded or all collapsed? Thanks!
  30. # On November 09, 2006 at 16:11 PM, Joe said:
    The last row border is not displaying when I collapse the last parent/child. I know it has something to do with the tr tag. Any ideas? Thank you.
  31. # On November 13, 2006 at 14:11 PM, Bojan said:
    Sara, you could keep states by calling URL in background on open/closing nodes which would set these data in session or database. These URL could look something like remember?id=table1_0_0_0&state=true
  32. # On November 13, 2006 at 14:11 PM, Bojan said:
    malacma, check "RadiantCMS":http://radiantcms.org, I think they have some implementation of tree table and are loading nodes with AJAX.
  33. # On February 16, 2007 at 13:02 PM, frnx said:
    Very good work! I'm very interesting to have a look of the PHP which could provide an automatic generation of the tree from an array. Can you send it to me please at this adress : franck@frnx.com. Bye
  34. # On April 12, 2007 at 10:04 AM, nullVoid said:
    I am interested in the PHP script you mentioned... would you be able to provide that?
  35. # On April 16, 2007 at 17:04 PM, Nilesh(its_nilesh@hotmail.com) said:
    Hi, I tried the same script that you have given in example2 but it not works. Intialy when the page loads it doesnt work for the first click. It starts working only from the second Click. Wondering y? Also i have got certain data to display in the rows now when i click any cell which has data the page reloads and already hidden row expand. please help me. here is my code. <table cellspacing="1" class="collapsible" bordercolor="#111111" border="0" id="table1" height="100%" cellpadding="1"> <tr id="table1_0"> <td bgcolor="#E6EDF7" class="header" height="23" valign="middle" align="left" width="100%" colspan="11">  <bean:message key=" width="9">  <bean:message bundle="AbisResources" key="facial.face" /></td> </tr> <!-- render images --> <tr id="table1_0_0"> <%thumbnailsBgColor = "#E4ECF5";%> <logic:iterate name="xmlRpcEnrollForm" indexid="indx" property="thumbnails" type="com.identix.abis.control.forms.DisplayedToken" id="thumbnail" length="1" offset="0"> <%String val = thumbnail.getValue(); String code = thumbnail.getCode(); String updatedValue = thumbnail.getValue(); if (true == val.startsWith("/abis/user/content?")) { val += "&width=400"; updatedValue += "&width=59"; } else { // MOZILLA_FIX if (isMozilla) { if (!val.endsWith(".jpg") && !val.endsWith(".jpeg") && !val.endsWith(".gif")) { if (indx.intValue() == 0) updatedValue = "/abis/images/noimage-w300.jpg"; else if (code.startsWith("0")) updatedValue = "/abis/images/fp-noimage-x-400.jpg"; else updatedValue = "/abis/images/iris-noimage-x-400.jpg"; } } else { if (!val.endsWith(".bmp") && !val.endsWith(".jpg") && !val.endsWith(".jpeg") && !val.endsWith(".gif")) { if (indx.intValue() == 0) updatedValue = "/abis/images/noimage-w300.jpg"; else if (code.startsWith("0")) updatedValue = "/abis/images/fp-noimage-x-400.jpg"; else updatedValue = "/abis/images/iris-noimage-x-400.jpg"; } } if (isMozilla && updatedValue.startsWith("/abis/images") == false) updatedValue = "file://" + updatedValue; } if ((thmbOffset + indx.intValue()) == xmlRpcEnrollForm .getSelectedThumbnailID()) thumbnailsBgColor = "#C4D2E8"; %> <td bgcolor="<%=thumbnailsBgColor%>" class="contents" id="cell.thumbnail.<%=(thmbOffset + indx.intValue())%>" valign="top" align="center" width="59" colspan="1"> <bean:message key='<%=thumbnail.getDesc()%>' bundle='AbisResources'/> </td> <% thumbnailsBgColor = "#E4ECF5"; %> </logic:iterate> </tr> <!-- render labels --> <tr id="table1_0_1"> <% thumbnailsBgColor = "#E4ECF5"; classString = "contents_9px"; %> <logic:iterate name="xmlRpcEnrollForm" indexid="indx" property="thumbnails" type="com.identix.abis.control.forms.DisplayedToken" id="thumbnail" length="1" offset="0"> <% if ((thmbOffset + indx.intValue()) == xmlRpcEnrollForm .getSelectedThumbnailID()) { thumbnailsBgColor = "#C4D2E8"; classString = "contents_9px_bold"; } %> <td bgcolor="<%=thumbnailsBgColor%>" class="<%=classString%>" id="cell.label.<%=(thmbOffset + indx.intValue())%>" height="20" valign="top" align="center" width="59" colspan="1"> <input id="label.<%=(thmbOffset + indx.intValue())%>" value="<bean:message key="<%=thumbnail.getDesc()%>" bundle="AbisResources"/>" onfocus="document.forms[0].dummy.focus();" style="border: none <%=thumbnailsBgColor%>;padding:0px;text-align:center;background:<%=thumbnailsBgColor%>;border=0px;width:59px;font-size:9px;align=center;"> </td> <% thumbnailsBgColor = "#E4ECF5"; classString = "contents_9px"; %> </logic:iterate> </tr> <tr id="table1_2"> <td bgcolor="#E6EDF7" class="header" height="23" valign="middle" align="left" width="100%" colspan="11">  <bean:message key=" width="9">  <bean:message bundle="AbisResources" key="fingerprint.fingerprint" /></td> </tr> <!-- render images --> <!-- row one --> <tr id="table1_2_0"> <% thumbnailsBgColor = "#E4ECF5"; %> <logic:iterate name="xmlRpcEnrollForm" indexid="indx" property="thumbnails" type="com.identix.abis.control.forms.DisplayedToken" id="thumbnail" length="11" offset="1"> <% String val = thumbnail.getValue(); String code = thumbnail.getCode(); String updatedValue = thumbnail.getValue(); if (true == val.startsWith("/abis/user/content?")) { val += "&width=400"; updatedValue += "&width=59"; } else { // MOZILLA_FIX if (isMozilla) { if (!val.endsWith(".jpg") && !val.endsWith(".jpeg") && !val.endsWith(".gif")) { if (indx.intValue() == 0) updatedValue = "/abis/images/noimage-w300.jpg"; else if (code.startsWith("0")) updatedValue = "/abis/images/fp-noimage-x-400.jpg"; else updatedValue = "/abis/images/iris-noimage-x-400.jpg"; } } else { if (!val.endsWith(".bmp") && !val.endsWith(".jpg") && !val.endsWith(".jpeg") && !val.endsWith(".gif")) { if (indx.intValue() == 0) updatedValue = "/abis/images/noimage-w300.jpg"; else if (code.startsWith("0")) updatedValue = "/abis/images/fp-noimage-x-400.jpg"; else updatedValue = "/abis/images/iris-noimage-x-400.jpg"; } } if (isMozilla && updatedValue.startsWith("/abis/images") == false) updatedValue = "file://" + updatedValue; } if ((thmbOffset + indx.intValue()) == xmlRpcEnrollForm .getSelectedThumbnailID()) thumbnailsBgColor = "#C4D2E8"; %> <td bgcolor="<%=thumbnailsBgColor%>" class="contents" id="cell.thumbnail.<%=(thmbOffset + indx.intValue())%>" valign="top" align="center" width="59" colspan="1"> <bean:message key='<%=thumbnail.getDesc()%>' bundle='AbisResources'/> </td> <% thumbnailsBgColor = "#E4ECF5"; %> </logic:iterate> </tr> <!-- render labels --> <tr id="table1_2_1"> <% thumbnailsBgColor = "#E4ECF5"; classString = "contents_9px"; %> <logic:iterate name="xmlRpcEnrollForm" indexid="indx" property="thumbnails" type="com.identix.abis.control.forms.DisplayedToken" id="thumbnail" length="11" offset="1"> <% if ((thmbOffset + indx.intValue()) == xmlRpcEnrollForm .getSelectedThumbnailID()) { thumbnailsBgColor = "#C4D2E8"; classString = "contents_9px_bold"; } %> <td bgcolor="<%=thumbnailsBgColor%>" class="<%=classString%>" id="cell.label.<%=(thmbOffset + indx.intValue())%>" height="20" valign="top" align="center" width="59" colspan="1"> <input id="label.<%=(thmbOffset + indx.intValue())%>" value="<bean:message key="<%=thumbnail.getDesc()%>" bundle="AbisResources"/>" onfocus="document.forms[0].dummy.focus();" style="border: none <%=thumbnailsBgColor%>;padding:0px;text-align:center;background:<%=thumbnailsBgColor%>;border=0px;width:59px;font-size:9px;align=center;"> </td> <% thumbnailsBgColor = "#E4ECF5"; classString = "contents_9px"; %> </logic:iterate> </tr> <!-- row two --> <tr id="table1_2_2"> <% thumbnailsBgColor = "#E4ECF5"; %> <logic:iterate name="xmlRpcEnrollForm" indexid="indx" property="thumbnails" type="com.identix.abis.control.forms.DisplayedToken" id="thumbnail" length="9" offset="12"> <% String val = thumbnail.getValue(); String code = thumbnail.getCode(); String updatedValue = thumbnail.getValue(); if (true == val.startsWith("/abis/user/content?")) { val += "&width=400"; updatedValue += "&width=59"; } else { // MOZILLA_FIX if (isMozilla) { if (!val.endsWith(".jpg") && !val.endsWith(".jpeg") && !val.endsWith(".gif")) { if (indx.intValue() == 0) updatedValue = "/abis/images/noimage-w300.jpg"; else if (code.startsWith("0")) updatedValue = "/abis/images/fp-noimage-x-400.jpg"; else updatedValue = "/abis/images/iris-noimage-x-400.jpg"; } } else { if (!val.endsWith(".bmp") && !val.endsWith(".jpg") && !val.endsWith(".jpeg") && !val.endsWith(".gif")) { if (indx.intValue() == 0) updatedValue = "/abis/images/noimage-w300.jpg"; else if (code.startsWith("0")) updatedValue = "/abis/images/fp-noimage-x-400.jpg"; else updatedValue = "/abis/images/iris-noimage-x-400.jpg"; } } if (isMozilla && updatedValue.startsWith("/abis/images") == false) updatedValue = "file://" + updatedValue; } if ((thmbOffset + indx.intValue()) == xmlRpcEnrollForm .getSelectedThumbnailID()) thumbnailsBgColor = "#C4D2E8"; %> <td bgcolor="<%=thumbnailsBgColor%>" class="contents" id="cell.thumbnail.<%=(thmbOffset + indx.intValue())%>" valign="top" align="center" width="59"> <bean:message key='<%=thumbnail.getDesc()%>' bundle='AbisResources'/> </td> <% thumbnailsBgColor = "#E4ECF5"; %> </logic:iterate> </tr> <!-- render labels --> <tr id="table1_2_3"> <% thumbnailsBgColor = "#E4ECF5"; classString = "contents_9px"; %> <logic:iterate name="xmlRpcEnrollForm" indexid="indx" property="thumbnails" type="com.identix.abis.control.forms.DisplayedToken" id="thumbnail" length="9" offset="12"> <% if ((thmbOffset + indx.intValue()) == xmlRpcEnrollForm .getSelectedThumbnailID()) { thumbnailsBgColor = "#C4D2E8"; classString = "contents_9px_bold"; } %> <td bgcolor="<%=thumbnailsBgColor%>" class="<%=classString%>" id="cell.label.<%=(thmbOffset + indx.intValue())%>" height="20" valign="top" align="center" width="59"> <input id="label.<%=(thmbOffset + indx.intValue())%>" value="<bean:message key="<%=thumbnail.getDesc()%>" bundle="AbisResources"/>" onfocus="document.forms[0].dummy.focus();" style="border: none <%=thumbnailsBgColor%>;padding:0px;text-align:center;background:<%=thumbnailsBgColor%>;border=0px;width:59px;font-size:9px;align=center;"> </td> <% thumbnailsBgColor = "#E4ECF5"; classString = "contents_9px"; %> </logic:iterate> </tr> <tr id="table1_3"> <td bgcolor="#E6EDF7" class="header" height="23" valign="middle" align="left" width="100%" colspan="11">  <bean:message key=" width="9">  <bean:message bundle="AbisResources" key="system.configuration.iris.label" /></td> </tr> <!-- render images --> <!-- row one --> <tr id="table1_3_0"> <% thumbnailsBgColor = "#E4ECF5"; %> <logic:iterate name="xmlRpcEnrollForm" indexid="indx" property="thumbnails" type="com.identix.abis.control.forms.DisplayedToken" id="thumbnail" length="2" offset="21"> <% String val = thumbnail.getValue(); String code = thumbnail.getCode(); String updatedValue = thumbnail.getValue(); if (true == val.startsWith("/abis/user/content?")) { val += "&width=400"; updatedValue += "&width=59"; } else { // MOZILLA_FIX if (isMozilla) { if (!val.endsWith(".jpg") && !val.endsWith(".jpeg") && !val.endsWith(".gif")) { if (indx.intValue() == 0) updatedValue = "/abis/images/noimage-w300.jpg"; else if (code.startsWith("0")) updatedValue = "/abis/images/fp-noimage-x-400.jpg"; else updatedValue = "/abis/images/iris-noimage-x-400.jpg"; } } else { if (!val.endsWith(".bmp") && !val.endsWith(".jpg") && !val.endsWith(".jpeg") && !val.endsWith(".gif")) { if (indx.intValue() == 0) updatedValue = "/abis/images/noimage-w300.jpg"; else if (code.startsWith("0")) updatedValue = "/abis/images/fp-noimage-x-400.jpg"; else updatedValue = "/abis/images/iris-noimage-x-400.jpg"; } } if (isMozilla && updatedValue.startsWith("/abis/images") == false) updatedValue = "file://" + updatedValue; } if ((thmbOffset + indx.intValue()) == xmlRpcEnrollForm .getSelectedThumbnailID()) thumbnailsBgColor = "#C4D2E8"; %> <td bgcolor="<%=thumbnailsBgColor%>" class="contents" id="cell.thumbnail.<%=(thmbOffset + indx.intValue())%>" valign="top" align="center" width="59"> <bean:message key='<%=thumbnail.getDesc()%>' bundle='AbisResources'/> </td> <% thumbnailsBgColor = "#E4ECF5"; %> </logic:iterate> </tr> <!-- render labels --> <tr id="table1_3_1"> <% thumbnailsBgColor = "#E4ECF5"; classString = "contents_9px"; %> <logic:iterate name="xmlRpcEnrollForm" indexid="indx" property="thumbnails" type="com.identix.abis.control.forms.DisplayedToken" id="thumbnail" length="2" offset="21"> <% if ((thmbOffset + indx.intValue()) == xmlRpcEnrollForm .getSelectedThumbnailID()) { thumbnailsBgColor = "#C4D2E8"; classString = "contents_9px_bold"; } %> <td bgcolor="<%=thumbnailsBgColor%>" class="<%=classString%>" id="cell.label.<%=(thmbOffset + indx.intValue())%>" height="20" valign="top" align="center" width="59"> <input id="label.<%=(thmbOffset + indx.intValue())%>" value="<bean:message key="<%=thumbnail.getDesc()%>" bundle="AbisResources"/>" onfocus="document.forms[0].dummy.focus();" style="border: none <%=thumbnailsBgColor%>;padding:0px;text-align:center;background:<%=thumbnailsBgColor%>;border=0px;width:59px;font-size:9px;align=center;"> </td> <% thumbnailsBgColor = "#E4ECF5"; classString = "contents_9px"; %> </logic:iterate> </tr> </table> </logic:notequal> </td> </tr>
  36. # On April 16, 2007 at 17:04 PM, Nilesh(its_nilesh@hotmail.com) said:
    I am sorry for the messy code above. I had a problem with the code you out here. It takes multiple clicks to expand or collapse intialy when the page reloads and then works fine. Can you tell me y is it so? and wat is the fix for it? Regards, Nilesh
  37. # On June 22, 2007 at 22:06 PM, dennis said:

    I am looking for a script that only shows one row at a time and if you klik on the link it will close the previous row and show only the selected one. Can you help me?

    On all scripts you have to close the previous selected row but I would like it to happen automatically so you will only see one row at a time

    regards dennis

  38. # On June 26, 2007 at 16:06 PM, Dino said:

    First of all thanks for your script. I found it very useful. Do you have some news about the ‘default visibility state’ of rows the first time they are displayed? I would appreciate your help. Thanks again!!!

  39. # On September 18, 2007 at 08:09 AM, hiutopor said:

    Hello

    Very interesting information! Thanks!

    G’night

  40. # On December 17, 2007 at 21:12 PM, Venkat said:

    Great Stuff Bojan, Can we get 4child nodes!! Present stuff showings only one level its possible to do it for 4 levels???

    Thanks, Ven

  41. # On December 18, 2007 at 07:12 AM, Bojan Mihelac said:

    Venkat, sure, you can add as many as you need.

  42. # On January 21, 2008 at 14:01 PM, Antton Rodriguez said:

    I’m quite interesting in a PHP script as well, if you can send me i’ll be so thanksfull..

    Thanks, even for the example

Speak your mind:

(Required)

(Required)


(You may use textile in your comments.)

About

I am Bojan Mihelac and this blog is dedicated to share code, thoughts, tools and advices I came up with while working in Informatika Mihelac.

Contact: bmihelac@mihelac.org

RSS feedSubscribe to RSS Feed