JSFiddle - React, Tailwind, and code Playground

by 2Yootz

HTML

<table border="0">
  <tr>
      <th>Header 1</th>
      <th>Header 2</th>
  </tr>
  <tr>
    <td class='group1'>Group 1</td>
    <td>data 2</td>
  </tr>
  <tr class='group1'>
    <td>data 3</td>
    <td>data 4</td>
  </tr>
  <tr>
    <td class='group2'>Group 2</td>
    <td>data 2</td>
  </tr>
  <tr class='group2'>
    <td>data 3</td>
    <td>data 4</td>
  </tr>
  <tr class='group2'>
    <td class='sub_group1'>Sub Group 1</td>
    <td>data 6</td>
  </tr>
  <tr class='group2 sub_group1'>
    <td>data 7</td>
    <td>data 8</td>
  </tr>
  <tr class='group2 sub_group1'>
    <td>data 9</td>
    <td>data 10</td>
  </tr>
  <tr class='group2 sub_group1'>
    <td class='sub_sub_group1'>Sub Sub Group 1</td>
    <td>data 11</td>
  </tr>
  <tr class='group2 sub_group1 sub_sub_group1'>
    <td>data 12</td>
    <td>data 13</td>
  </tr>
  <tr class='group2 sub_group1 sub_sub_group1'>
    <td>data 14</td>
    <td>data 15</td>
  <tr class='group2'>
    <td class='sub_group2'>Sub Group 2</td>
    <td>data 11</td>
  </tr>
  <tr class='group2 sub_group2'>
    <td>data 12</td>
    <td>data 13</td>
  </tr>
  <tr class='group2 sub_group2'>
    <td>data 14</td>
    <td>data 15</td>
  </tr>
</table>

CSS

table, tr, td, th
{
    border: 1px solid black;
    border-collapse:collapse;
}

img.button_open{
  content:url('http://code.stephenmorley.org/javascript/collapsible-lists/button-open.png');
  cursor:pointer;
}

img.button_closed{
  content: url('http://code.stephenmorley.org/javascript/collapsible-lists/button-closed.png');
  cursor:pointer;
}

JavaScript

function CreateGroup(group_name)
{
    // Create Button(Image)
    $('td.' + group_name).prepend("<img class='" + group_name + " button_closed'> ");
    // Add Padding to Data
    $('tr.' + group_name).each(function () {
        var first_td = $(this).children('td').first();
        var padding_left = parseInt($(first_td).css('padding-left'));
        $(first_td).css('padding-left', String(padding_left + 25) + 'px');
    });
    RestoreGroup(group_name);
    
    // Tie toggle function to the button
    $('img.' + group_name).click(function(){
        ToggleGroup(group_name);
    });
}

function ToggleGroup(group_name)
{
    ToggleButton($('img.' + group_name));
    RestoreGroup(group_name);
}

function RestoreGroup(group_name)
{
    if ($('img.' + group_name).hasClass('button_open'))
    {
        // Open everything
        $('tr.' + group_name).show();
        
        // Close subgroups that been closed
        $('tr.' + group_name).find('img.button_closed').each(function () {
            sub_group_name = $(this).attr('class').split(/\s+/)[0];
            //console.log(sub_group_name);
            RestoreGroup(sub_group_name);
        });
    }
    
    if ($('img.' + group_name).hasClass('button_closed'))
    {
        // Close everything
        $('tr.' + group_name).hide();
    }
}

function ToggleButton(button)
{
    $(button).toggleClass('button_open');
    $(button).toggleClass('button_closed');
}

CreateGroup('group1');
CreateGroup('group2');
CreateGroup('sub_group1');
CreateGroup('sub_group2');
CreateGroup('sub_sub_group1');