Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

JavaScript

Proper solution to toggleable tables ?

So imagine.

You have a table with certain data. You are display the data and you have a hidden table rows which you wont to show when clicked on a specific table row.

tr
td - DATA1
tr
td  - hidden data
td  - hidden data
tr
td DATA2
 tr
td -hidden data
td - hidden data
tr
td -DATA3
tr
td -hidden data
td - hidden data

so when you click on DATA1 you want to display only the hidden data which are associated with it.

2 Answers

Well, here is the Pure JS version for you, my friend :)

<!DOCTYPE html>
<html>
    <head>
        <title>TestPage</title>
        <style>
            #testTable, #testTable td {
                border: 1px solid #000;
            }
            #testTable td {
                cursor: pointer;
            }
            #testTable tr:nth-child(2n) {
                display: none;
            }
        </style>
    </head>
    <body>
        <table id="testTable">
            <tr><td>Click anywhere on this row to hide or expose the next row</td><td>More data</td></tr>
            <tr><td>Sample Data1</td><td>Sample Data1</td></tr>
            <tr><td>Click anywhere on this row to hide or expose the next row</td><td>More data</td></tr>
            <tr><td>Sample Data2</td><td>Sample Data2</td></tr>
            <tr><td>Click anywhere on this row to hide or expose the next row</td><td>More data</td></tr>
            <tr><td>Sample Data3</td><td>Sample Data3</td></tr>
        </table>
        <script>
            var tr = document.getElementById("testTable").getElementsByTagName("tr");
            for (var i = 0; i < tr.length; i++) {
                if (i % 2 === 0) {
                    tr[i].className = "hiderController";
                }
            }
            var hiderCont = document.getElementsByClassName("hiderController");
            for (var i = 0; i < hiderCont.length; i++) {
             hiderCont[i].addEventListener("click", function ()  {
                var el = this.nextElementSibling;
                if (el.style.display === "" || el.style.display === "none"){
                  el.style.display = "table-row";
                }
                else {
                  el.style.display = "none";
                }
              }, false);
            }
        </script>
    </body>
</html>

Many thanks :-) I still did not have a time to look at it and adapt it to my thing. But thanks again for the effort!

If you want to go ahead and select a best answer, that would show many thanks for my work. :)

I think I must have misread what you wanted to do, because now I see you want the first table cell to hide/unhide the rest of the table cells in the current row. I'll re-adapt this to fit that need.

Hey Marcus,

I think your original understanding of it was correct. I wouldn't go any further with this unless you hear otherwise from Mike S.

I added a code block to the original question to maintain the formatting that Mike had put in. My understanding is that the odd rows toggle the even rows and your code seems to handle that case.

Ah, thanks, Jason! I appreciate the formatting, as I'm sure Mike will. Cheers!

Hey Mike,

It's really easy to do something like this. What this code does is when an odd row is clicked, it will reveal the row below it (an even row), or hide that row if the row is visible. The initial part of the code gets all of the tr elements that belong to a particular table, in this case with the id of "testTable". It then cycles through all of them adding the "hiderController" class to each odd element. It looks as though this would apply to every even one because of the modulus statement, but because the indices start at 0, it actually applies opposite to what you would think. And then, we just add a click handler that gets the current element that called the function, wrapping it within $() so that it's an object, then getting the next sibling element, and calling the toggle() function, which shows/hides depending on the respective current state.

Notice in the CSS that I'm utilizing the "nth-child" pseudo element which will target n number of elements within another element. Here, I'm targeting every 2nd row, and setting their display to none that way they are hidden at first and then toggled back and forth between being shown/hidden:

<!DOCTYPE html>
<html>
    <head>
        <title>TestPage</title>
        <style>
            #testTable, #testTable td {
                border: 1px solid #000;
            }
            #testTable td {
                cursor: pointer;
            }
            #testTable tr:nth-child(2n) {
                display: none;
            }
        </style>
    </head>
    <body>
        <table id="testTable">
            <tr><td>Click me to hide or expose the next row</td><td>More data</td></tr>
            <tr><td>Sample Data</td><td>Sample Data</td></tr>
            <tr><td>Click me to hide or expose the next row</td><td>More data</td></tr>
            <tr><td>Sample Data</td><td>Sample Data</td></tr>
            <tr><td>Click me to hide or expose the next row</td><td>More data</td></tr>
            <tr><td>Sample Data</td><td>Sample Data</td></tr>
        </table>
        <script type="text/javascript" src="http://code.jquery.com/jquery-2.1.3.min.js"></script>
        <script>
            var tr = document.getElementById("testTable").getElementsByTagName("tr");
            for (var i = 0; i < tr.length; i++) {
                if (i % 2 === 0) {
                    tr[i].className = "hiderController";
                }
            }
            $(".hiderController").click(function ()  {
                $(this).next().toggle();
            });
        </script>
    </body>
</html>

Hey Marcus,

I might be misunderstanding your code and maybe even the original problem but I think you would want to set a click handler on the odd rows only.

It seems to me that you could click on the 1st row which would show the hidden 2nd row, but then you could click on that 2nd row which would hide the 3rd row which is meant to be the toggle for the 4th row containing hidden data.

Quite a good catch, and I've patched the fix into the code above. :)

Thanks a lot Marcus. I'll need to review it thoroughly when i have a time and i also am going to reimplement the jquery used in this in pure JS :-)