Collapsible Tables with Javascript

A lot of people have asked me lately how to create collapsable tables (or div’s, or anything else for that matter) and I thought I’d do a little informal writeup on how I do it.

So what really goes on to collapse something? Well, all we do is call upon Javascript to toggle the display property of an object. So just about any object can be collapsed, or more technically, “hidden”.

Note that the display property is different from the visibility property. When display is set to none, the object is “removed” from the page, thus taking up no space. When visibility is set to hidden, the object is simply hidden and still takes up space on the page. For example, if I simply apply visibility:hidden to an image that is 33×33, then everything (text, other images, etc) will still “flow” around that 33×33 space as if it were still there. But if I apply display:none to that image, everything else will “collapse” onto it as if it were never there.

Let’s start out with the actual table HTML:
[code lang="xml"]

Toggle
Test row1
Test row2
Test row3
Test row4
Test row5

[/code]

The first thing you have to understand is that Javascript treats each element on a page as it’s own object. So we must locate the object so we can do the effects we want on it. In this case, we want to access it’s style and change the value of the display property. To find the object we want, we give it a unique id. In the example above, I’ve used myTbody.

Now that we’ve assigned an id to the object we want, we let Javascript grab it using a custom function. Since browsers use different DOM’s, we have to try and get the object a number of different ways. Here’s the getItem function:

[code lang="javascript"]function getItem(id)
{
var itm = false;
if(document.getElementById)
itm = document.getElementById(id);
else if(document.all)
itm = document.all[id];
else if(document.layers)
itm = document.layers[id];

return itm;
}[/code]

We pass this function the id of the object we want and it attempts to return it (or false on failure). For example, if we wanted to work with the myTbody object we would do something like myTbody = getItem('myTbody').

Now for the good bits ;-) We know how to get the object, now time to talk about the onclick we have attached to the “Toggle” link above. We create another custom function to toggle the display property from none (which is the “collapsed” state) and its default. To do this, we grab the object with the getItem function and test to see if it’s already set to none, if it is then we want to toggle it back on (thus resetting it to the default value) and if it’s not, then we want to toggle it off (thus setting it to none). Here’s the code for the toggleItem function. We pass it the id of the object we want to toggle.

[code lang="javascript"]function toggleItem(id)
{
itm = getItem(id);

if(!itm)
return false;

if(itm.style.display == ‘none’)
itm.style.display = ”;
else
itm.style.display = ‘none’;

return false;
}[/code]

All in all, it’s pretty simple. Give your object an id, and attach the toggleItem to any event you want (can be onclick, onblur etc) to toggle it on and off. Here’s a fully working example:

[code lang="xml"]



Toggle 1
Test row1
Test row2
Test row3
Test row4
Test row5


[/code]

Later, I’ll show how to use cookies to remember which things you have collapsed so on the next page view, they are still collapsed. Useful for things like “Icon Legends” where you want your users to be able to keep it collapsed if they don’t need it at all.

13 Responses to “Collapsible Tables with Javascript”

  1. K Bouton Says:

    This is just what I was looking for. Thanks. I’ve added images for collapse/expand.
    But I want to add the possibility via onlick to collapse or expand ALL of the ids. How do I do this? I know there is a loop involved, but I’ve tried - and no luck.
    K

  2. Chris Says:

    The easiest way would to attach a certain class name to each of them and loop through all of the tbody’s (or whatever tag your using), and collapse/expand each of the objects with that class name.

    <html>
    <head>
        <title>My Doc</title>
        <script language="javascript">
        function getItem(id)
        {
            var itm = false;
            if(document.getElementById)
                itm = document.getElementById(id);
            else if(document.all)
                itm = document.all[id];
            else if(document.layers)
                itm = document.layers[id];

            return itm;
        }

        function toggleAll(dowhat)
        {
            var tags = document.getElementsByTagName(’tbody’);
            if(!tags)
                return false;

            for(var i = 0; i < tags.length; i++)
            {
                if(tags[i].className == ’collapse_obj’)
                {
                    if(dowhat == ’collapse’)
                        tags[i].style.display = ’none’;
                    else
                        tags[i].style.display = ”;
                }
            }

            return false;
        }

        function toggleItem(id)
        {
            itm = getItem(id);

            if(!itm)
                return false;

            if(itm.style.display == ’none’)
                itm.style.display = ”;
            else
                itm.style.display = ’none’;

            return false;
        }
        </script>
    </head>
    <body>

    <a href=”#” onclick=”return toggleAll(’collapse’)”>Collapse All</a>
    <a href=”#” onclick=”return toggleAll(’expand’)”>Expand All</a>

    <table width=”400″>
        <tbody>
            <tr><td style=”background-color: #CCC”><a href=”#” onclick=”return toggleItem(’collapse_myTbody1′)”>Toggle 1</a></td></tr>
        </tbody>

        <tbody class=”collapse_obj” id=”collapse_myTbody1″>
            <tr><td>Test row1</td></tr>
            <tr><td>Test row2</td></tr>
            <tr><td>Test row3</td></tr>
            <tr><td>Test row4</td></tr>
            <tr><td>Test row5</td></tr>
        </tbody>
    </table>

    <table width=”400″>
        <tbody>
            <tr><td style=”background-color: #CCC”><a href=”#” onclick=”return toggleItem(’collapse_myTbody2′)”>Toggle 1</a></td></tr>
        </tbody>

        <tbody class=”collapse_obj” id=”collapse_myTbody2″>
            <tr><td>Test row1</td></tr>
            <tr><td>Test row2</td></tr>
            <tr><td>Test row3</td></tr>
            <tr><td>Test row4</td></tr>
            <tr><td>Test row5</td></tr>
        </tbody>
    </table>

    <table width=”400″>
        <tbody>
            <tr><td style=”background-color: #CCC”><a href=”#” onclick=”return toggleItem(’collapse_myTbody3′)”>Toggle 1</a></td></tr>
        </tbody>

        <tbody class=”collapse_obj” id=”collapse_myTbody3″>
            <tr><td>Test row1</td></tr>
            <tr><td>Test row2</td></tr>
            <tr><td>Test row3</td></tr>
            <tr><td>Test row4</td></tr>
            <tr><td>Test row5</td></tr>
        </tbody>
    </table>

    </body>
    </html>

  3. K Bouton Says:

    Excellent. Works great. Thanks for your quick response which, of course, brings up another question - how do I add the “collapsed all”/”expanded all” to the cookies so upon return to page it remains in state whether partially expanded or all expanded etc?

    Someone on another forum was looking on how to add images to toggle - so I attach my edited version of your function which makes a rollover effect on the toggle images.

    function rollOvers(image, new_width, new_height) {
    document.getElementById(image).setAttribute(’width’, new_width);
    document.getElementById(image).setAttribute(’height’, new_height);
    }

    and the relevant part of your edited function

    function toggleItem(id,image)
    {
    itm = getItem(id);
    if(!itm)
    return false;
    if(itm.style.display == ‘none’) // if hidden
    {
    itm.style.display = ”; // show
    document.getElementById(image).src=”collapse.gif”;
    document.getElementById(image).alt=”Click to collapse ” + id;
    document.getElementById(image).setAttribute(’width’, 15);
    document.getElementById(image).setAttribute(’height’, 15);
    } else {
    itm.style.display = ‘none’; // hide
    document.getElementById(image).src=”expand.gif”;
    document.getElementById(image).alt=”Click to expand ” + id;
    document.getElementById(image).setAttribute(’width’, 15);
    document.getElementById(image).setAttribute(’height’, 15);
    }

    used like:
    click to collapseInformation

    K

    PS - you wouldn’t have any ideas on hiding/showing table columns would you? (grin)

  4. K Bouton Says:

    example didn’t come out above cause it was in html. I try again with out tags

    img src=”collapse.gif” alt=”click to collapse” width=”15″ height=”15″ align=”absmiddle” id=”information_image” onClick=”toggleItem(’information’,'information_image’)” onMouseOver=”rollOvers(’information_image’,'18′,’18′)” onMouseOut=”rollOvers(’information_image’,'15′,’15′) “>Information

  5. K Bouton Says:

    Again - any ideas how I could add the “collapsed all”/”expanded all” to the cookies so upon return to page it remains in state whether partially expanded or all expanded etc?

  6. Michelle Says:

    Using the example above, I’m getting the default as expanded with the toggle collapsing. Is there a way to reverse this so that the default is collapsed and toggling expands? Thanks!

  7. djnicholi Says:

    because default is open place an onLoad call in the like:

  8. djnicholi Says:

    BODY bgColor=#EFEFEF onLoad=”toggleItem(’tblMenu1′, ‘tblMenu1_img’);toggleItem(’tblMenu2′, ‘tblMenu2_img’);toggleItem(’tblMenu2_1′, ‘tblMenu2_1_img’);toggleItem(’tblMenu3′, ‘tblMenu3_img’);toggleItem(’tblMenu3_1′, ‘tblMenu3_1_img’)”>

  9. Jason Says:

    I’m interested in this as well

    –Michelle wrote:
    Using the example above, I’m getting the default as expanded with the toggle collapsing. Is there a way to reverse this so that the default is collapsed and toggling expands? Thanks!

  10. Chroder.com » Blog Archive » Remembered Collapsible Objects with PHP and Javascript Says:

    [...] This is kind of a part two to my quite popular (well, popular according to the search engines) post Collapsible Tables with Javascript. [...]

  11. Lunch Says:

    Have spent hours searching and manipulating codelines hungry codes that actually never worked well.
    I just registered to say a huge thanks : a very kiss code !

  12. Frapster Says:

    To have your rows ‘collapsed’ by default and ‘expand’ upon toggle - set the ’style’ of each of your tags to ‘display:none’.

    Like so:

    This will achieve that goal.

  13. mht7 Says:

    I’m attempting to write some custom javascript for collapsing the tables and fit it in an existing application already provided. I found this code and it works great. In this example there are 3 fixed set of tables with 3 fixed/hardcoded “id”.
    I tried to fit this code into a FOR loop so it becomes dynamic and it would work for any number and not just 3 tables.

    FOR (f, f>0, f++)
    Toggle 1

    But it is not working.
    Has anyone done this before. Can anyone share some ideas or pointers?

    Regards,
    MHT
    NY City.

Leave a Reply