JSFiddle - React, Tailwind, and code Playground

by der_robert

HTML

<table>
  <thead>
    <tr>
      <th colspan="2">Row Change</th>
      <th>Feld</th>
      <th>vorher</th>
      <th>nachher</th>
      <th>Datum</th>
      <th>Nutzer</th>
      <th>Aktionen</th> <!-- Neue Spalte -->
    </tr>
  </thead>

  <tbody>
    <tr>
      <td colspan="5">User Action XYZ</td>
      <td>01.01.2000</td>
      <td>Admin</td>
      <td class="actions">
        <button id="show-level-1">L1</button>
        <button id="show-level-2">L2</button>
        <button id="show-level-3">L3</button>
      </td>
    </tr>
  </tbody>

  <tbody class="hidden" data-hide-level="1">
    <tr>
      <td rowspan="8">Aktualisiert 1</td>
      <td rowspan="8">Buchungsoption</td>
      <td></td>
      <td></td>
      <td></td>
      <td rowspan="8"></td>
      <td rowspan="8"></td>
      <td rowspan="8"></td>
    </tr>
    <tr class="hidden" data-hide-level="3">
      <td>Feld 1</td>
      <td>vorher 1</td>
      <td>nachher 1</td>
      <td colspan="2"></td>
    </tr>
    <tr class="hidden" data-hide-level="3">
      <td>Feld 2</td>
      <td>vorher 2</td>
      <td>nachher 2</td>
      <td colspan="2"></td>
    </tr>
    <tr class="hidden" data-hide-level="3">
      <td>Feld 3</td>
      <td>vorher 3</td>
      <td>nachher 3</td>
      <td colspan="2"></td>
    </tr>
    <tr class="hidden" data-hide-level="3">
      <td>Feld 4</td>
      <td>vorher 4</td>
      <td>nachher 4</td>
      <td colspan="2"></td>
    </tr>
    <tr class="hidden" data-hide-level="3">
      <td>Feld 5</td>
      <td>vorher 5</td>
      <td>nachher 5</td>
      <td colspan="2"></td>
    </tr>
    <tr class="hidden" data-hide-level="3">
      <td>Feld 6</td>
      <td>vorher 6</td>
      <td>nachher 6</td>
      <td colspan="2"></td>
    </tr>
    <tr class="hidden" data-hide-level="2">
      <td><strong>Offener Posten</strong></td>
      <td><strong>vorher 1</strong></td>
      <td><strong>nachher 1</strong></td>
...

CSS

.hidden{
  display: none;
}

JavaScript

function toggleTbodyByLevel(level, visible) {
  document.querySelectorAll(`tbody[data-hide-level="${level}"]`).forEach(tbody => {
    tbody.classList.toggle('hidden', !visible);
    const headerTr = [...tbody.querySelectorAll('tr')].find(tr =>
      tr.querySelector('td')?.hasAttribute('rowspan')
    );
    if (headerTr) headerTr.classList.toggle('hidden', !visible);
  });
}

function toggleTrByLevel(level, visible) {
  const trs = document.querySelectorAll(`tr[data-hide-level="${level}"]`);
  trs.forEach(tr => tr.classList.toggle('hidden', !visible));

  const tbodySet = new Set([...trs].map(tr => tr.closest('tbody')));
  tbodySet.forEach(tbody => {
    const anyVisible = [...tbody.querySelectorAll(`tr[data-hide-level="${level}"]`)]
      .some(tr => !tr.classList.contains('hidden'));
    const headerTr = [...tbody.querySelectorAll('tr')].find(tr =>
      tr.querySelector('td')?.hasAttribute('rowspan')
    );
    if (headerTr) headerTr.classList.toggle('hidden', !anyVisible);
  });
}

function isVisible(level) {
  const selector = level === 1 ? `tbody[data-hide-level="1"]` : `tr[data-hide-level="${level}"]`;
  return [...document.querySelectorAll(selector)].some(el => !el.classList.contains('hidden'));
}

document.getElementById('show-level-1').addEventListener('click', () => {
  const l1 = isVisible(1);
  const l2 = isVisible(2);
  const l3 = isVisible(3);

  if (l1 && !l2 && !l3) {
    // Nur L1 sichtbar → alles ausblenden
    toggleTbodyByLevel(1, false);
  } else {
    // Sonst → nur L1 sichtbar
    toggleTbodyByLevel(1, true);
    toggleTrByLevel(2, false);
    toggleTrByLevel(3, false);
  }
});

document.getElementById('show-level-2').addEventListener('click', () => {
  const l1 = isVisible(1);
  const l2 = isVisible(2);
  const l3 = isVisible(3);

  if (l1 && l2 && !l3) {
    // L1 + L2 sichtbar → alles ausblenden
    toggleTbodyByLevel(1, false);
    toggleTrByLevel(2, false);
  } else {
    //...