Collapsible table

Hi, I have a table consisting of header rows and associated regular rows. I’d like to create this table such that the regular rows are initialy hidden, but when you click the “+”(expand) next to a header row the associated rows will show. I’m not sure if you even need javascript to do this. I am open to using jquery but it is not my first preference unless it is easy to read and code(I have 0 experience with jquery and minimal experience with javascript as I am a backend developer). If someone could post example code I would be grateful. Thanks!

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">

<head>
  <title></title>
<script type="text/javascript">

function Open(id,sz){
 document.getElementById(id).style.height=sz+'px';
}

</script>

</head>

<body>
<input type="button" name="" value="Open" onmouseup="Open('tst',true);"/>
<input type="button" name="" value="Close" onmouseup="Open('tst',false);"/>
<input type="button" name="" value="Toggle" onmouseup="Open('tst');"/>
<TABLE id="tst" border="1" >
  <THEAD>
    <TR>
      <TH >Character</TH>
      <TH>Entity</TH>
      <TH >Decimal</TH>
      <TH >Hex</TH>
      <TH >Rendering in Your Browser</TH>
    </TR>
  </THEAD>
  <TBODY>
    <TR>
      <TD SCOPE=row>non-breaking space</TD>
      <TD>&amp;nbsp;</TD>
      <TD>&amp;#160;</TD>
      <TD>&amp;#xA0;</TD>
      <TD>&nbsp;</TD>
    </TR>
    <TR>
      <TD SCOPE=row>non-breaking space</TD>
      <TD>&amp;nbsp;</TD>
      <TD>&amp;#160;</TD>
      <TD>&amp;#xA0;</TD>
      <TD>&#xA0;</TD>
    </TR>
  </TBODY>
</TABLE>

<script type="text/javascript">

function Open(id,ud){
 var o=Open['zxc'+id];obj=document.getElementById(id),tbdy=obj.getElementsByTagName('TBODY')[0];
 if (obj){
  if (!o){
   o=Open['zxc'+id]={
    tbdy:tbdy,
    ud:false
   }
  }
  if (o&&o.tbdy){
   o.ud=typeof(ud)=='boolean'?ud:o.ud;
   if (!o.ud&&tbdy){
    obj.removeChild(o.tbdy);
    o.ud=true;
  }
   else if (o.ud&&!tbdy){
    obj.appendChild(o.tbdy);
    o.ud=false;
   }
  }
 }
}

Open('tst',false);

</script>

</body>

</html>

Thanks for the response, but the thing is there are at least 25 table headers, each with anywhere from 10-200 associated regular rows. The table expanded looks something like this:
TABLE HEADER 1
Row associated with TABLE HEADER 1(1st one)

Row associated with TABLE HEADER 1(60th one)
TABLE HEADER 2
Row associated with TABLE HEADER 2(1st one)

Row associated with TABLE HEADER 2(30th one)
TABLE HEADER 3
Row associated with TABLE HEADER 3(1st one)

Row associated with TABLE HEADER 3(185th one)

I was hoping to code it such that initially only the headers show, and then when you click on the “+” next to the header it will expand its associated rows. Can anybody please post some example code I can follow? Thanks.

What about using something like an Accordion style UI element (http://jqueryui.com/accordion/) … could probably work relatively well for you.

To build something like this without the massive overhead of jQuery UI it would be relatively trivial, you just need to follow some basic markup and CSS

Firstly, we’ll start with our markup.


<!-- this is the element we'll apply CSS / scripting to -->
<div class="collapser"> 

    <!-- The table headings can be a HTML heading element -->
    <h3>Table heading</h3>  

    <!-- these headings are followed by a content area, we'll hide/show this content with JavaScript -->
    <div class="content">  

         <!-- Any content can go here -->

    </div>

    <h3>Table heading</h3>
    <div class="content"> 

        <!-- Any content can go here -->

    </div>

    <!-- etc, add more headings/content -->
</div>

Now on to our relevant CSS, what we need is a little indicator next to the heading when it is active and when it is not to indicate the state.

.collapser h3 {
    position: relative;
}

.collapser h3::before {
    content: " > ";
    font-size:20px;
    font-weight: bold;
    position: absolute;
    left:-20px;
    top:0px;
}

.collapser h3.active::before {
    content: " v ";
}

I’ve opted for a “>” and “v” to indicate the open and closed state, you could of course use a background image and create a “+” / “-” symbol (or whatever you fancy).

Ok, so finally, our JavaScript, it’s going to be relatively short and sweet, we don’t actually need this to do too much.


$(document).ready(function(){

    //firstly we'll collapse all the content areas so only the headings are visible
    $(".collapser .content").hide();

    //now we'll set a click handler on the headings so that we can show/hide the content as required
    $(".collapser").on("click", "> h3", function(e) {

        var el = $(this);
        
        el.toggleClass("active"); //toggle the active class on the heading
        
        el.next(".content").slideToggle(400); // find the next content element and toggle showing it depending on the current state.

    });

});

There you have it, simplicity itself.

A full working example is on JS Fiddle: http://jsfiddle.net/GeekyJohn/VKeS3/

Thanks, the example page in your link is what I was looking for. However, I could not get this to work when I did it on my computer, here it is:

[highlight=HTML AND JS]
<html>
<head>
<link rel=“stylesheet” type=“text/css” href=“TableStyle.css”>
</head>

<script>
$(document).ready(function(){
$(“.collapser .content”).hide();
$(“.collapser”).on(“click”, “> h3”, function(e) {
var el = $(this);
el.toggleClass(“active”);
el.next(“.content”).slideToggle(400);
});
});
</script>
<div id=“content”>
<div class=“collapser”>
<h3>Table heading</h3>
<div class=“content”>
<table class=“some-table”>
<thead>
<tr>
<th>Index</th>
<th>Name</th>
<th>Location</th>
</tr>
</thead>
<tbody>
<tr>
<td class=“index”>1</td>
<td class=“name”>John Smith</td>
<td class=“location”>Sydney</td>
</tr>
<tr>
<td class=“index”>2</td>
<td class=“name”>Jane Doe</td>
<td class=“location”>London</td>
</tr>
<tr>
<td class=“index”>3</td>
<td class=“name”>Samuel L. Jackson</td>
<td class=“location”>Hollywood</td>
</tr>
</tbody>
</table>
</div>
<h3>2nd Table Heading</h3>
<div class=“content”>
<table class=“some-table”>
<thead>
<tr>
<th>Index</th>
<th>Name</th>
<th>Location</th>
</tr>
</thead>
<tbody>
<tr>
<td class=“index”>1</td>
<td class=“name”>John Smith</td>
<td class=“location”>Sydney</td>
</tr>
<tr>
<td class=“index”>2</td>
<td class=“name”>Jane Doe</td>
<td class=“location”>London</td>
</tr>
<tr>
<td class=“index”>3</td>
<td class=“name”>Samuel L. Jackson</td>
<td class=“location”>Hollywood</td>
</tr>
</tbody>
</table>
</div>

        &lt;h3&gt;3rd Table heading&lt;/h3&gt;
        &lt;div class="content"&gt;
            &lt;table class="some-table"&gt;
                &lt;thead&gt;
                    &lt;tr&gt;
                        &lt;th&gt;Index&lt;/th&gt;
                        &lt;th&gt;Name&lt;/th&gt;
                        &lt;th&gt;Location&lt;/th&gt;
                    &lt;/tr&gt;
                &lt;/thead&gt;
                &lt;tbody&gt;
                    &lt;tr&gt;
                        &lt;td class="index"&gt;1&lt;/td&gt;
                        &lt;td class="name"&gt;John Smith&lt;/td&gt;
                        &lt;td class="location"&gt;Sydney&lt;/td&gt;
                    &lt;/tr&gt;
                    &lt;tr&gt;
                        &lt;td class="index"&gt;2&lt;/td&gt;
                        &lt;td class="name"&gt;Jane Doe&lt;/td&gt;
                        &lt;td class="location"&gt;London&lt;/td&gt;
                    &lt;/tr&gt;
                    &lt;tr&gt;
                        &lt;td class="index"&gt;3&lt;/td&gt;
                        &lt;td class="name"&gt;Samuel L. Jackson&lt;/td&gt;
                        &lt;td class="location"&gt;Hollywood&lt;/td&gt;
                    &lt;/tr&gt;
                &lt;/tbody&gt;
            &lt;/table&gt;
        &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;

</head>
</html>



The css is exactly the same as yours in a separate file entitled TableStyle.css.

Ah, it looks like you’re not including the jQuery library. My mistake, probably should have mentioned that.

Just put this line right above the current JavaScript in the page:


	<script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>

Thanks, it works now! 3 little discrepancies I see though that probably have to do with the css:

  1. The expand/collapse arrows don’t appear.
  2. The table cells don’t have right padding(the next column starts almost immediately after the previous one).
  3. The table doesn’t have visible borders, which is strange because you specified a border width of 1 pixel.

Here is the code:
[Highlight=recent html and js]
<html>
<head>
<link rel=“stylesheet” type=“text/css” href=“TableStyle.css”>
</head>

<script type=“text/javascript” src=“http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js”></script>
<script>
$(document).ready(function(){
$(“.collapser .content”).hide();
$(“.collapser”).on(“click”, “> h3”, function(e) {
var el = $(this);
el.toggleClass(“active”);
el.next(“.content”).slideToggle(400);
});
});
</script>
<div id=“content”>
<div class=“collapser”>
<h3>Table heading</h3>
<div class=“content”>
<table class=“some-table”>
<thead>
<tr>
<th>Index</th>
<th>Name</th>
<th>Location</th>
</tr>
</thead>
<tbody>
<tr>
<td class=“index”>1</td>
<td class=“name”>John Smith</td>
<td class=“location”>Sydney</td>
</tr>
<tr>
<td class=“index”>2</td>
<td class=“name”>Jane Doe</td>
<td class=“location”>London</td>
</tr>
<tr>
<td class=“index”>3</td>
<td class=“name”>Samuel L. Jackson</td>
<td class=“location”>Hollywood</td>
</tr>
</tbody>
</table>
</div>
<h3>2nd Table Heading</h3>
<div class=“content”>
<table class=“some-table”>
<thead>
<tr>
<th>Index</th>
<th>Name</th>
<th>Location</th>
</tr>
</thead>
<tbody>
<tr>
<td class=“index”>1</td>
<td class=“name”>John Smith</td>
<td class=“location”>Sydney</td>
</tr>
<tr>
<td class=“index”>2</td>
<td class=“name”>Jane Doe</td>
<td class=“location”>London</td>
</tr>
<tr>
<td class=“index”>3</td>
<td class=“name”>Samuel L. Jackson</td>
<td class=“location”>Hollywood</td>
</tr>
</tbody>
</table>
</div>

        &lt;h3&gt;3rd Table heading&lt;/h3&gt;
        &lt;div class="content"&gt;
            &lt;table class="some-table"&gt;
                &lt;thead&gt;
                    &lt;tr&gt;
                        &lt;th&gt;Index&lt;/th&gt;
                        &lt;th&gt;Name&lt;/th&gt;
                        &lt;th&gt;Location&lt;/th&gt;
                    &lt;/tr&gt;
                &lt;/thead&gt;
                &lt;tbody&gt;
                    &lt;tr&gt;
                        &lt;td class="index"&gt;1&lt;/td&gt;
                        &lt;td class="name"&gt;John Smith&lt;/td&gt;
                        &lt;td class="location"&gt;Sydney&lt;/td&gt;
                    &lt;/tr&gt;
                    &lt;tr&gt;
                        &lt;td class="index"&gt;2&lt;/td&gt;
                        &lt;td class="name"&gt;Jane Doe&lt;/td&gt;
                        &lt;td class="location"&gt;London&lt;/td&gt;
                    &lt;/tr&gt;
                    &lt;tr&gt;
                        &lt;td class="index"&gt;3&lt;/td&gt;
                        &lt;td class="name"&gt;Samuel L. Jackson&lt;/td&gt;
                        &lt;td class="location"&gt;Hollywood&lt;/td&gt;
                    &lt;/tr&gt;
                &lt;/tbody&gt;
            &lt;/table&gt;
        &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;

</head>
</html>


Again, the external stylesheet "TableStyle.css" is identical to what you posted.

I'm using Firefox 16.0.1 and Internet Explorer 9.

Please ignore that post I had the wrong extension for my css file.