Accordion Rows – Expand/Collapse Long Content in Any Table

This script adds simple expand/collapse accordion functionality to any Tadabase data table — perfect for rows with long text fields like Descriptions, Notes, or Comments.

When applied, each row displays a small “Expand / Collapse” button (with Font Awesome icons) that toggles visibility of longer text.
You can also use “Expand All” / “Collapse All” buttons at the top of the table.


:white_check_mark: What It Does

This solution:

  • Works on any Tadabase page

  • Requires no HTML edits

  • Uses Font Awesome icons already included in Tadabase

  • Automatically re-initializes after pagination or filtering

  • Uses simple, page-specific configuration

  • Can be modified to target all columns automatically


:sparkles: Features

  • :small_blue_diamond: Collapses long text for cleaner tables

  • :small_blue_diamond: Adds expand/collapse buttons in each row

  • :small_blue_diamond: Adds global “Expand All / Collapse All” controls

  • :small_blue_diamond: Compatible with pagination, filtering, and dynamic table reloads

  • :small_blue_diamond: 100% client-side — just paste CSS + JS

  • :small_blue_diamond: Works with Font Awesome 5+ already built into Tadabase

2025-10-04_22-05-41


:puzzle_piece: Step-by-Step Setup

:one: Add CSS

Go to your Page → CSS section and paste:

/* ===== Tadabase Accordion Table (clean) ===== */

#x_element_page_620_6 .data-table tbody td {
  position: relative;
  vertical-align: top !important;
}

/* Clamp long content (collapsed) */
#x_element_page_620_6 .data-table tbody tr:not(.row-expanded)
  .component_6_field_1563 span,
#x_element_page_620_6 .data-table tbody tr:not(.row-expanded)
  .component_6_field_1564 span,
#x_element_page_620_6 .data-table tbody tr:not(.row-expanded)
  .component_6_field_1565 span,
#x_element_page_620_6 .data-table tbody tr:not(.row-expanded)
  .component_6_field_1566 span {
  display: block;
  max-height: 60px;
  overflow: hidden;
  position: relative;
}

/* Soft fade at bottom when clamped */
#x_element_page_620_6 .data-table tbody tr:not(.row-expanded)
  .component_6_field_1563 span::after,
#x_element_page_620_6 .data-table tbody tr:not(.row-expanded)
  .component_6_field_1564 span::after,
#x_element_page_620_6 .data-table tbody tr:not(.row-expanded)
  .component_6_field_1565 span::after,
#x_element_page_620_6 .data-table tbody tr:not(.row-expanded)
  .component_6_field_1566 span::after {
  content: '';
  position: absolute;
  left: 0; right: 0; bottom: 0;
  height: 25px;
  background: linear-gradient(to bottom, rgba(255,255,255,0), rgba(255,255,255,0.95));
  pointer-events: none;
}

/* Expanded rows show full content */
#x_element_page_620_6 .data-table tbody tr.row-expanded
  .component_6_field_1563 span,
#x_element_page_620_6 .data-table tbody tr.row-expanded
  .component_6_field_1564 span,
#x_element_page_620_6 .data-table tbody tr.row-expanded
  .component_6_field_1565 span,
#x_element_page_620_6 .data-table tbody tr.row-expanded
  .component_6_field_1566 span {
  max-height: none !important;
  overflow: visible !important;
}

/* Row highlight when expanded */
#x_element_page_620_6 .data-table tbody tr.row-expanded {
  background-color: #f8f9fa !important;
}

/* Expand/Collapse button */
.tada-expand-btn {
  display: inline-block;
  margin-left: 10px;
  padding: 3px 8px;
  background: #007bff;
  color: #fff;
  border-radius: 3px;
  font-size: 11px;
  cursor: pointer;
  transition: background 0.2s;
  vertical-align: middle;
  user-select: none;
}
.tada-expand-btn:hover { background: #0056b3; }
.tada-expand-btn i { margin-right: 4px; }

/* Global controls */
.tada-global-controls { display: inline-block; margin-left: 15px; }
.tada-global-controls .btn { margin-right: 6px; }

/* Smooth expand/collapse transition */
#x_element_page_620_6 .data-table tbody td span {
  transition: max-height 0.25s ease-in-out;
}

:two: Add JavaScript

Paste the following into your Page → JavaScript section.

// ===== Tadabase Accordion Table (clean) =====
(function () {
  'use strict';

  const TABLE_ID = 'x_element_page_620_6';
  const TABLE_SEL = `#${TABLE_ID} .data-table`;
  const CONTENT_COLS = [
    'component_6_field_1563',
    'component_6_field_1564',
    'component_6_field_1565',
    'component_6_field_1566'
  ];

  const MIN_TEXT_LEN = 150;
  const RETRIES = 12;
  const RETRY_DELAY = 400;

  let attempts = 0;
  init();

  function init() {
    const table = document.querySelector(TABLE_SEL);
    if (!table) {
      if (attempts++ < RETRIES) return setTimeout(init, RETRY_DELAY);
      return;
    }
    if (table.dataset.accordionInit === 'true') return;
    table.dataset.accordionInit = 'true';

    processAllRows();
    addGlobalControls();
    observeTable();
  }

  function processAllRows() {
    document
      .querySelectorAll(`${TABLE_SEL} tbody tr.t-table-row`)
      .forEach(processRowIfNeeded);
  }

  function processRowIfNeeded(row) {
    if (row.dataset.tadaProcessed === '1') return;

    if (!needsAccordion(row)) {
      row.dataset.tadaProcessed = '1';
      return;
    }

    const firstCell =
      row.querySelector('.component_6_field_1560') ||
      row.querySelector('.component_6_field_1560 .af-data-table-field') ||
      row.querySelector('td.af-data-table-field') ||
      row.querySelector('td');

    if (!firstCell) return;

    if (!firstCell.querySelector('.tada-expand-btn')) {
      const btn = document.createElement('span');
      btn.className = 'tada-expand-btn';
      btn.innerHTML = '<i class="far fa-angle-double-down"></i> Expand';
      btn.setAttribute('role', 'button');
      btn.setAttribute('aria-expanded', 'false');
      btn.addEventListener('click', (e) => {
        e.stopPropagation();
        toggleRow(row, btn);
      });
      firstCell.appendChild(btn);
    }

    row.dataset.tadaProcessed = '1';
  }

  function needsAccordion(row) {
    for (const cls of CONTENT_COLS) {
      const cell = row.querySelector(`.${cls}`);
      if (!cell) continue;
      const len = (cell.textContent || '').trim().length;
      if (len > MIN_TEXT_LEN) return true;
    }
    return false;
  }

  function toggleRow(row, btn) {
    const expanded = row.classList.toggle('row-expanded');
    btn.innerHTML = expanded
      ? '<i class="far fa-angle-double-up"></i> Collapse'
      : '<i class="far fa-angle-double-down"></i> Expand';
    btn.setAttribute('aria-expanded', expanded ? 'true' : 'false');
  }

  function addGlobalControls() {
    const actions = document.querySelector(`#${TABLE_ID} .table-actions .pull-left`);
    if (!actions || actions.querySelector('.tada-global-controls')) return;

    const wrap = document.createElement('div');
    wrap.className = 'tada-global-controls';

    const expandBtn = document.createElement('button');
    expandBtn.type = 'button';
    expandBtn.className = 'btn btn-sm btn-default';
    expandBtn.innerHTML = '<i class="far fa-angle-double-down"></i> Expand All';
    expandBtn.addEventListener('click', () => setAll(true));

    const collapseBtn = document.createElement('button');
    collapseBtn.type = 'button';
    collapseBtn.className = 'btn btn-sm btn-default';
    collapseBtn.innerHTML = '<i class="far fa-angle-double-up"></i> Collapse All';
    collapseBtn.addEventListener('click', () => setAll(false));

    wrap.appendChild(expandBtn);
    wrap.appendChild(collapseBtn);
    actions.appendChild(wrap);
  }

  function setAll(expand) {
    document
      .querySelectorAll(`${TABLE_SEL} tbody tr.t-table-row`)
      .forEach((row) => {
        row.classList.toggle('row-expanded', expand);
        const btn = row.querySelector('.tada-expand-btn');
        if (btn) {
          btn.innerHTML = expand
            ? '<i class="far fa-angle-double-up"></i> Collapse'
            : '<i class="far fa-angle-double-down"></i> Expand';
          btn.setAttribute('aria-expanded', expand ? 'true' : 'false');
        }
      });
  }

  function observeTable() {
    const tbody = document.querySelector(`${TABLE_SEL} tbody`);
    if (!tbody) return;

    const observer = new MutationObserver((mutations) => {
      let changed = false;
      for (const m of mutations) {
        if (m.type === 'childList' && (m.addedNodes.length || m.removedNodes.length)) {
          changed = true;
          break;
        }
      }
      if (changed) {
        document
          .querySelectorAll(`${TABLE_SEL} tbody tr.t-table-row`)
          .forEach(processRowIfNeeded);
      }
    });

    observer.observe(tbody, { childList: true, subtree: true });
  }
})();

:gear: Configuration Notes

  • TABLE_ID:
    Replace 'x_element_page_620_6' with the ID of your Tadabase Table Component (you can find it by inspecting the element).

  • CONTENT_COLS:

    • List the columns that may contain long text (e.g., component_6_field_1563, component_6_field_1564, etc.).

    • Or, modify the script slightly to target all columns by looping through row.querySelectorAll('td').

  • MIN_TEXT_LEN:
    Controls how much text must exist before showing an Expand button (default 150).

  • Expand Button Placement:
    The expand/collapse button is appended to the first data cell (component_6_field_1560 in the example).


:light_bulb: Tips

  • Perfect for Notes, Comments, or Long Text Log tables.

  • You can have multiple accordion tables per page by duplicating the script and updating the TABLE_ID.

  • Adjust the CSS max-height to change how much text is visible when collapsed.


:brick: Example Result

  • Long text rows are neatly collapsed with a fade overlay.

  • A small blue “Expand” button appears beside the first column.

  • “Expand All” and “Collapse All” buttons at the top let users toggle everything easily.

1 Like