DataTables.net FixHeader 标题在滚动时移动的问题

问题描述 投票:0回答:1

我与 ChatGPT 4o 合作,根据客户的需求创建了一个复杂的 DataTables.net 概念证明,其中包括以下 DataTables.net 插件和功能:

  • 固定标题
  • 行分组
  • 儿童行
  • 行页脚
  • 多选和全选

在提供的示例代码/jsfiddle 中,每个都用不同的颜色突出显示,以便于识别。

一切都很完美。固定标头只有一个问题。向下和向上滚动时,固定标题完美对齐。但是,当您向上滚动并到达页面/视图的顶部时,固定标题会向左移动并与下面的列不对齐。 (参见位置栏)

您可以在这个jsfiddle中看到问题:https://jsfiddle.net/v5fs3do6/

之前(工作) enter image description here

之后(标题移动) enter image description here

我花了几个小时尝试用 chatgpt 解决这个问题,但这个例子似乎太复杂了,无法解决。我们尝试回滚某些插件来尝试查看问题在何处/何时引入,但这也失败了。

不幸的是,这些要求需要所有这些功能和插件。

我希望前端设计/编码方面的人类专家的眼睛能够帮助我解决这个问题。

jsfiddle 有一个演示所有功能和问题的工作示例,但这里也是代码。

任何帮助将不胜感激,并让我免于发疯。 谢谢!

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>DataTable with Grouping, Expanded Child Rows</title>
  <link rel="stylesheet" href="https://cdn.datatables.net/1.13.6/css/jquery.dataTables.min.css">
  <link rel="stylesheet" href="https://cdn.datatables.net/fixedheader/3.4.0/css/fixedHeader.dataTables.min.css">
  <link rel="stylesheet" href="https://cdn.datatables.net/rowgroup/1.4.0/css/rowGroup.dataTables.min.css">
  <style>
    table.dataTable thead th {
      background-color: #f4f4f4;
    }
    
    .group-header {
      font-weight: bold;
      background-color: #d8d8d8;
    }
    
    .child-row td {
      padding: 10px 0;
      border-top: none;
      text-align: left;
    }
    
    .blueTable th {
      background-color: #007bff !important;
      color: white !important;
    }
    
    .groupRow {
      background-color: #0056b3 !important;
      color: white !important;
    }
    
    .childDataRow {
      background-color: #80c1ff !important;
      color: black !important;
    }
    
    .groupFooterRow {
      background-color: #cce5ff !important;
      font-weight: bold;
      color: black !important;
    }
  </style>
</head>

<body>

  <h3>Select Grouping Column:</h3>
  <select id="group-by-column">
    <option value="none">None</option>
    <option value="office">Office</option>
    <option value="position">Position</option>
  </select>

  <table id="example" class="display nowrap table responsive-table table-vcenter table-hover" style="width:100%">
    <thead class="text-white">
      <tr class="bg-primary">
        <th><input type="checkbox" id="select-all"></th>
        <th>Name</th>
        <th>Position</th>
        <th>Age</th>
        <th>Start date</th>
        <th>Salary</th>
        <th>Department</th>
        <th>Project</th>
        <th>Experience (Years)</th>
        <th>Location</th>
        <th class="d-none">Office</th>
        <th class="d-none">Hobby</th>
        <th class="d-none">Favorite Animal</th>
      </tr>
    </thead>
    <tbody>
      <tr class="mainRecordRow table-light">
        <td></td>
        <td class="custom-cell-class">
          Tiger Nixon
          <input type="hidden" class="hobby" value="Fishing">
          <input type="hidden" class="favorite-animal" value="Tiger">
        </td>
        <td>System Architect</td>
        <td>61</td>
        <td>2011/04/25</td>
        <td>$320,800</td>
        <td>IT</td>
        <td>Project A</td>
        <td>10</td>
        <td>Scotland</td>
        <td>Edinburgh</td>
        <td>Fishing</td>
        <td>Tiger</td>
      </tr>
      <tr class="mainRecordRow table-light">
        <td></td>
        <td class="custom-cell-class">
          Garrett Winters
          <input type="hidden" class="hobby" value="Gardening">
          <input type="hidden" class="favorite-animal" value="Cat">
        </td>
        <td>Accountant</td>
        <td>63</td>
        <td>2011/07/25</td>
        <td>$170,750</td>
        <td>Finance</td>
        <td>Project B</td>
        <td>8</td>
        <td>Japan</td>
        <td>Tokyo</td>
        <td>Gardening</td>
        <td>Cat</td>
      </tr>
      <tr class="mainRecordRow table-light">
        <td></td>
        <td class="custom-cell-class">
          Ashton Cox
          <input type="hidden" class="hobby" value="Painting">
          <input type="hidden" class="favorite-animal" value="Dog">
        </td>
        <td>Junior Technical Author</td>
        <td>66</td>
        <td>2009/01/12</td>
        <td>$86,000</td>
        <td>Documentation</td>
        <td>Project C</td>
        <td>5</td>
        <td>USA</td>
        <td>San Francisco</td>
        <td>Painting</td>
        <td>Dog</td>
      </tr>
      <tr class="mainRecordRow table-light">
        <td></td>
        <td class="custom-cell-class">
          Ryan Dixon
          <input type="hidden" class="hobby" value="Fishing">
          <input type="hidden" class="favorite-animal" value="Tiger">
        </td>
        <td>System Architect</td>
        <td>61</td>
        <td>2011/04/25</td>
        <td>$320,800</td>
        <td>IT</td>
        <td>Project D</td>
        <td>15</td>
        <td>Japan</td>
        <td>Tokyo</td>
        <td>Fishing</td>
        <td>Tiger</td>
      </tr>
      <tr class="mainRecordRow table-light">
        <td></td>
        <td class="custom-cell-class">
          Brielle Williamson
          <input type="hidden" class="hobby" value="Photography">
          <input type="hidden" class="favorite-animal" value="Dolphin">
        </td>
        <td>Integration Specialist</td>
        <td>61</td>
        <td>2012/12/02</td>
        <td>$372,000</td>
        <td>Development</td>
        <td>Project E</td>
        <td>9</td>
        <td>New Zealand</td>
        <td>Wellington</td>
        <td>Photography</td>
        <td>Dolphin</td>
      </tr>
      <tr class="mainRecordRow table-light">
        <td></td>
        <td class="custom-cell-class">
          Herrod Chandler
          <input type="hidden" class="hobby" value="Hiking">
          <input type="hidden" class="favorite-animal" value="Eagle">
        </td>
        <td>Sales Assistant</td>
        <td>59</td>
        <td>2012/08/06</td>
        <td>$137,500</td>
        <td>Sales</td>
        <td>Project F</td>
        <td>12</td>
        <td>UK</td>
        <td>London</td>
        <td>Hiking</td>
        <td>Eagle</td>
      </tr>
      <tr class="mainRecordRow table-light">
        <td></td>
        <td class="custom-cell-class">
          Rhona Davidson
          <input type="hidden" class="hobby" value="Reading">
          <input type="hidden" class="favorite-animal" value="Panda">
        </td>
        <td>Senior Javascript Developer</td>
        <td>55</td>
        <td>2010/10/14</td>
        <td>$327,900</td>
        <td>Development</td>
        <td>Project G</td>
        <td>7</td>
        <td>Canada</td>
        <td>Toronto</td>
        <td>Reading</td>
        <td>Panda</td>
      </tr>
      <tr class="mainRecordRow table-light">
        <td></td>
        <td class="custom-cell-class">
          Colleen Hurst
          <input type="hidden" class="hobby" value="Cooking">
          <input type="hidden" class="favorite-animal" value="Elephant">
        </td>
        <td>Javascript Developer</td>
        <td>39</td>
        <td>2009/09/15</td>
        <td>$205,500</td>
        <td>Development</td>
        <td>Project H</td>
        <td>6</td>
        <td>Australia</td>
        <td>Sydney</td>
        <td>Cooking</td>
        <td>Elephant</td>
      </tr>
      <tr class="mainRecordRow table-light">
        <td></td>
        <td class="custom-cell-class">
          Sonya Frost
          <input type="hidden" class="hobby" value="Knitting">
          <input type="hidden" class="favorite-animal" value="Fox">
        </td>
        <td>Software Engineer</td>
        <td>23</td>
        <td>2008/12/13</td>
        <td>$103,600</td>
        <td>IT</td>
        <td>Project I</td>
        <td>4</td>
        <td>USA</td>
        <td>San Diego</td>
        <td>Knitting</td>
        <td>Fox</td>
      </tr>
      <tr class="mainRecordRow table-light">
        <td></td>
        <td class="custom-cell-class">
          Jena Gaines
          <input type="hidden" class="hobby" value="Traveling">
          <input type="hidden" class="favorite-animal" value="Whale">
        </td>
        <td>Office Manager</td>
        <td>30</td>
        <td>2008/12/19</td>
        <td>$90,560</td>
        <td>Administration</td>
        <td>Project J</td>
        <td>2</td>
        <td>USA</td>
        <td>New York</td>
        <td>Traveling</td>
        <td>Whale</td>
      </tr>
      <tr class="mainRecordRow table-light">
        <td></td>
        <td class="custom-cell-class">
          Quinn Flynn
          <input type="hidden" class="hobby" value="Swimming">
          <input type="hidden" class="favorite-animal" value="Shark">
        </td>
        <td>Support Lead</td>
        <td>22</td>
        <td>2013/03/03</td>
        <td>$342,000</td>
        <td>Support</td>
        <td>Project K</td>
        <td>1</td>
        <td>Canada</td>
        <td>Vancouver</td>
        <td>Swimming</td>
        <td>Shark</td>
      </tr>
      <tr class="mainRecordRow table-light">
        <td></td>
        <td class="custom-cell-class">
          Charde Marshall
          <input type="hidden" class="hobby" value="Writing">
          <input type="hidden" class="favorite-animal" value="Wolf">
        </td>
        <td>Regional Director</td>
        <td>36</td>
        <td>2008/10/16</td>
        <td>$470,600</td>
        <td>Management</td>
        <td>Project L</td>
        <td>11</td>
        <td>Singapore</td>
        <td>Singapore</td>
        <td>Writing</td>
        <td>Wolf</td>
      </tr>
      <tr class="mainRecordRow table-light">
        <td></td>
        <td class="custom-cell-class">
          Haley Kennedy
          <input type="hidden" class="hobby" value="Cycling">
          <input type="hidden" class="favorite-animal" value="Bear">
        </td>
        <td>Senior Marketing Designer</td>
        <td>43</td>
        <td>2012/12/18</td>
        <td>$313,500</td>
        <td>Marketing</td>
        <td>Project M</td>
        <td>8</td>
        <td>UK</td>
        <td>Manchester</td>
        <td>Cycling</td>
        <td>Bear</td>
      </tr>
      <tr class="mainRecordRow table-light">
        <td></td>
        <td class="custom-cell-class">
          Tatyana Fitzpatrick
          <input type="hidden" class="hobby" value="Dancing">
          <input type="hidden" class="favorite-animal" value="Peacock">
        </td>
        <td>Regional Director</td>
        <td>19</td>
        <td>2010/03/17</td>
        <td>$385,750</td>
        <td>Management</td>
        <td>Project N</td>
        <td>3</td>
        <td>India</td>
        <td>Mumbai</td>
        <td>Dancing</td>
        <td>Peacock</td>
      </tr>
    </tbody>
  </table>


  <script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
  <script src="https://cdn.datatables.net/1.13.6/js/jquery.dataTables.min.js"></script>
  <script src="https://cdn.datatables.net/fixedheader/3.4.0/js/dataTables.fixedHeader.min.js"></script>
  <script src="https://cdn.datatables.net/rowgroup/1.4.0/js/dataTables.rowGroup.min.js"></script>

  <script>
    $(document).ready(function() {
      var groupColumn = 10;
      var initialColumnWidths = [];

      function storeOriginalClasses() {
        $('#example tbody tr').each(function() {
          $(this).data('original-classes', $(this).attr('class'));
          $(this).find('td').each(function() {
            $(this).data('original-classes', $(this).attr('class'));
          });
        });
      }

      function reapplyOriginalClasses() {
        $('#example tbody tr').each(function() {
          var originalClasses = $(this).data('original-classes');
          if (originalClasses) {
            $(this).attr('class', originalClasses);
          }
          $(this).find('td').each(function() {
            var originalTdClasses = $(this).data('original-classes');
            if (originalTdClasses) {
              $(this).attr('class', originalTdClasses);
            }
          });
        });

        $('.groupRow').each(function() {
          var originalClasses = $(this).data('original-classes');
          if (originalClasses) {
            $(this).attr('class', originalClasses);
          }
        });
      }

      function addChildRows() {
        $('.child-row').remove();

        var colspan = $('#example thead tr th:visible').length - 1;

        table.rows().every(function(rowIdx, tableLoop, rowLoop) {
          var tr = $(this.node());
          var hobby = tr.find('.hobby').val();
          var favoriteAnimal = tr.find('.favorite-animal').val();

          var childRowHtml = `
                    <tr class="childDataRow table-light">
                        <td></td>
                        <td colspan="${colspan}">Hobby: ${hobby} | Favorite Animal: ${favoriteAnimal}</td>
                    </tr>
                `;

          tr.after(childRowHtml);
        });
      }

      function addGroupFooter() {
        $('.groupFooterRow').remove();

        var groupData = {};
        table.rows({
          page: 'current'
        }).every(function() {
          var data = this.data();
          var groupKey = data[groupColumn];
          if (!groupData[groupKey]) {
            groupData[groupKey] = {
              totalSalary: 0,
              totalYears: 0,
              rows: []
            };
          }
          groupData[groupKey].rows.push(this.node());
          groupData[groupKey].totalSalary += parseFloat(data[5].toString().replace(/[\$,]/g, ''));
          groupData[groupKey].totalYears += parseFloat(data[8]) || 0;
        });

        $.each(groupData, function(groupKey, groupInfo) {
          var lastRow = $(groupInfo.rows[groupInfo.rows.length - 1]);
          var lastChildRow = lastRow.next('.childDataRow').length ? lastRow.next('.childDataRow') : lastRow;

          var totalVisibleColumns = $('#example thead tr th:visible').length;
          var colspanBeforeSalary = 5;
          var colspanBetween = 2;
          var colspanAfterYears = totalVisibleColumns - 9;

          var formattedSalary = groupInfo.totalSalary.toFixed(2).replace(/\B(?=(\d{3})+(?!\d))/g, ',');
          var formattedYears = groupInfo.totalYears.toFixed(2);

          var groupFooterHtml = `
                    <tr class="groupFooterRow bg-primary text-white">
                        <td colspan="${colspanBeforeSalary}"></td>
                        <td>Group Total Salary: $${formattedSalary}</td>
                        <td colspan="${colspanBetween}"></td>
                        <td>Group Total Years: ${formattedYears}</td>
                        <td colspan="${colspanAfterYears}"></td>
                    </tr>
                `;

          lastChildRow.after(groupFooterHtml);
        });
      }

      // Capture initial column widths when the table is first drawn
      function captureInitialColumnWidths() {
        initialColumnWidths = [];
        $('#example thead th').each(function() {
          initialColumnWidths.push($(this).width());
        });
      }

      // Apply the captured column widths
      function applyColumnWidths() {
        $('#example thead th').each(function(index) {
          $(this).css('width', initialColumnWidths[index] + 'px');
        });

        $('#example tbody tr:first td').each(function(index) {
          $(this).css('width', initialColumnWidths[index] + 'px');
        });
      }

      storeOriginalClasses();

      var table = $('#example').DataTable({
        responsive: false,
        fixedHeader: true,
        scrollX: true,
        order: [
          [1, 'asc']
        ],
        lengthChange: true,
        lengthMenu: [10, 25, 50, 100],
        paging: true,
        rowGroup: {
          dataSrc: groupColumn,
          startRender: function(rows, group) {
            var colspan = $('#example thead tr th:visible').length;
            return $('<tr/>')
              .addClass('groupRow bg-primary-light text-white')
              .append(`<td colspan="${colspan}">Group: ${group}</td>`);
          }
        },
        columnDefs: [{
            targets: 0,
            orderable: false,
            searchable: false,
            className: 'select-checkbox',
            render: function() {
              return '<input type="checkbox" class="select-row">';
            }
          },
          {
            targets: [10, 11, 12],
            visible: false,
            searchable: true
          },
          {
            targets: 2, // The "Position" column
            width: '100px', // Set width to 100px
            createdCell: function(td, cellData, rowData, row, col) {
              $(td).css('white-space', 'normal'); // Enable word wrapping
              $(td).css('word-wrap', 'break-word'); // Ensure long words break
            }
          }
        ],
        autoWidth: false
      });

      // Add child rows and group footers initially
      addChildRows();
      addGroupFooter();

      // Capture initial column widths after the table is drawn
      table.on('draw', function() {
        if (initialColumnWidths.length === 0) {
          captureInitialColumnWidths();
        }
        addChildRows();
        addGroupFooter();
        reapplyOriginalClasses();
        adjustTable();
      });

      // Apply fixed column widths during scrolling to avoid shifting
      $('#example_wrapper .dataTables_scrollBody').on('scroll', function() {
        applyColumnWidths();
      });

      // Adjust on column order change
      table.on('order', function() {
        adjustTable();
      });

      // Handle Select All checkbox
      $('#select-all').on('click', function() {
        var rows = table.rows({
          'search': 'applied'
        }).nodes();
        $('input[type="checkbox"]', rows).prop('checked', this.checked);
      });

      // Handle grouping change based on dropdown
      $('#group-by-column').on('change', function() {
        var selectedColumn = $(this).val();
        if (selectedColumn === "none") {
          groupColumn = null;
        } else if (selectedColumn === "position") {
          groupColumn = 2;
        } else if (selectedColumn === "office") {
          groupColumn = 10;
        }

        table.rowGroup().dataSrc(groupColumn).draw();
        adjustTable();
      });

      // Function to adjust columns and fixed header alignment
      function adjustTable() {
        table.columns.adjust();
        if (table.fixedHeader) {
          table.fixedHeader.adjust();
        }
      }

      // Fix header alignment on window resize
      $(window).on('resize', function() {
        adjustTable();
      });

      // Recalculate column width on table draw events, like search or paging
      table.on('responsive-resize', function() {
        adjustTable();
      });

      // Call the adjustment function on initial load to ensure correct alignment
      adjustTable();
    });
  </script>
</body>

</html>

jquery datatables
1个回答
0
投票

只需添加以下 CSS:

.dataTables_scrollHeadInner table .text-white .bg-primary{ 
  display: flex;   
  justify-content: space-evenly;
}
.dataTables_scrollHeadInner table .text-white .bg-primary th{ 
  flex: 1;
}

像这样:

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>DataTable with Grouping, Expanded Child Rows</title>
  <link rel="stylesheet" href="https://cdn.datatables.net/1.13.6/css/jquery.dataTables.min.css">
  <link rel="stylesheet" href="https://cdn.datatables.net/fixedheader/3.4.0/css/fixedHeader.dataTables.min.css">
  <link rel="stylesheet" href="https://cdn.datatables.net/rowgroup/1.4.0/css/rowGroup.dataTables.min.css">
  <style>
    table.dataTable thead th {
      background-color: #f4f4f4;
    }
    
    .group-header {
      font-weight: bold;
      background-color: #d8d8d8;
    }
    
    .child-row td {
      padding: 10px 0;
      border-top: none;
      text-align: left;
    }
    
    .blueTable th {
      background-color: #007bff !important;
      color: white !important;
    }
    
    .groupRow {
      background-color: #0056b3 !important;
      color: white !important;
    }
    
    .childDataRow {
      background-color: #80c1ff !important;
      color: black !important;
    }
    
    .groupFooterRow {
      background-color: #cce5ff !important;
      font-weight: bold;
      color: black !important;
    }
    
    .dataTables_scrollHeadInner table .text-white .bg-primary {
      display: flex;
      justify-content: space-evenly;
    }
    
    .dataTables_scrollHeadInner table .text-white .bg-primary th {
      flex: 1;
    }
  </style>
</head>

<body>

  <h3>Select Grouping Column:</h3>
  <select id="group-by-column">
    <option value="none">None</option>
    <option value="office">Office</option>
    <option value="position">Position</option>
  </select>

  <table id="example" class="display nowrap table responsive-table table-vcenter table-hover" style="width:100%">
    <thead class="text-white">
      <tr class="bg-primary">
        <th><input type="checkbox" id="select-all"></th>
        <th>Name</th>
        <th>Position</th>
        <th>Age</th>
        <th>Start date</th>
        <th>Salary</th>
        <th>Department</th>
        <th>Project</th>
        <th>Experience (Years)</th>
        <th>Location</th>
        <th class="d-none">Office</th>
        <th class="d-none">Hobby</th>
        <th class="d-none">Favorite Animal</th>
      </tr>
    </thead>
    <tbody>
      <tr class="mainRecordRow table-light">
        <td></td>
        <td class="custom-cell-class">
          Tiger Nixon
          <input type="hidden" class="hobby" value="Fishing">
          <input type="hidden" class="favorite-animal" value="Tiger">
        </td>
        <td>System Architect</td>
        <td>61</td>
        <td>2011/04/25</td>
        <td>$320,800</td>
        <td>IT</td>
        <td>Project A</td>
        <td>10</td>
        <td>Scotland</td>
        <td>Edinburgh</td>
        <td>Fishing</td>
        <td>Tiger</td>
      </tr>
      <tr class="mainRecordRow table-light">
        <td></td>
        <td class="custom-cell-class">
          Garrett Winters
          <input type="hidden" class="hobby" value="Gardening">
          <input type="hidden" class="favorite-animal" value="Cat">
        </td>
        <td>Accountant</td>
        <td>63</td>
        <td>2011/07/25</td>
        <td>$170,750</td>
        <td>Finance</td>
        <td>Project B</td>
        <td>8</td>
        <td>Japan</td>
        <td>Tokyo</td>
        <td>Gardening</td>
        <td>Cat</td>
      </tr>
      <tr class="mainRecordRow table-light">
        <td></td>
        <td class="custom-cell-class">
          Ashton Cox
          <input type="hidden" class="hobby" value="Painting">
          <input type="hidden" class="favorite-animal" value="Dog">
        </td>
        <td>Junior Technical Author</td>
        <td>66</td>
        <td>2009/01/12</td>
        <td>$86,000</td>
        <td>Documentation</td>
        <td>Project C</td>
        <td>5</td>
        <td>USA</td>
        <td>San Francisco</td>
        <td>Painting</td>
        <td>Dog</td>
      </tr>
      <tr class="mainRecordRow table-light">
        <td></td>
        <td class="custom-cell-class">
          Ryan Dixon
          <input type="hidden" class="hobby" value="Fishing">
          <input type="hidden" class="favorite-animal" value="Tiger">
        </td>
        <td>System Architect</td>
        <td>61</td>
        <td>2011/04/25</td>
        <td>$320,800</td>
        <td>IT</td>
        <td>Project D</td>
        <td>15</td>
        <td>Japan</td>
        <td>Tokyo</td>
        <td>Fishing</td>
        <td>Tiger</td>
      </tr>
      <tr class="mainRecordRow table-light">
        <td></td>
        <td class="custom-cell-class">
          Brielle Williamson
          <input type="hidden" class="hobby" value="Photography">
          <input type="hidden" class="favorite-animal" value="Dolphin">
        </td>
        <td>Integration Specialist</td>
        <td>61</td>
        <td>2012/12/02</td>
        <td>$372,000</td>
        <td>Development</td>
        <td>Project E</td>
        <td>9</td>
        <td>New Zealand</td>
        <td>Wellington</td>
        <td>Photography</td>
        <td>Dolphin</td>
      </tr>
      <tr class="mainRecordRow table-light">
        <td></td>
        <td class="custom-cell-class">
          Herrod Chandler
          <input type="hidden" class="hobby" value="Hiking">
          <input type="hidden" class="favorite-animal" value="Eagle">
        </td>
        <td>Sales Assistant</td>
        <td>59</td>
        <td>2012/08/06</td>
        <td>$137,500</td>
        <td>Sales</td>
        <td>Project F</td>
        <td>12</td>
        <td>UK</td>
        <td>London</td>
        <td>Hiking</td>
        <td>Eagle</td>
      </tr>
      <tr class="mainRecordRow table-light">
        <td></td>
        <td class="custom-cell-class">
          Rhona Davidson
          <input type="hidden" class="hobby" value="Reading">
          <input type="hidden" class="favorite-animal" value="Panda">
        </td>
        <td>Senior Javascript Developer</td>
        <td>55</td>
        <td>2010/10/14</td>
        <td>$327,900</td>
        <td>Development</td>
        <td>Project G</td>
        <td>7</td>
        <td>Canada</td>
        <td>Toronto</td>
        <td>Reading</td>
        <td>Panda</td>
      </tr>
      <tr class="mainRecordRow table-light">
        <td></td>
        <td class="custom-cell-class">
          Colleen Hurst
          <input type="hidden" class="hobby" value="Cooking">
          <input type="hidden" class="favorite-animal" value="Elephant">
        </td>
        <td>Javascript Developer</td>
        <td>39</td>
        <td>2009/09/15</td>
        <td>$205,500</td>
        <td>Development</td>
        <td>Project H</td>
        <td>6</td>
        <td>Australia</td>
        <td>Sydney</td>
        <td>Cooking</td>
        <td>Elephant</td>
      </tr>
      <tr class="mainRecordRow table-light">
        <td></td>
        <td class="custom-cell-class">
          Sonya Frost
          <input type="hidden" class="hobby" value="Knitting">
          <input type="hidden" class="favorite-animal" value="Fox">
        </td>
        <td>Software Engineer</td>
        <td>23</td>
        <td>2008/12/13</td>
        <td>$103,600</td>
        <td>IT</td>
        <td>Project I</td>
        <td>4</td>
        <td>USA</td>
        <td>San Diego</td>
        <td>Knitting</td>
        <td>Fox</td>
      </tr>
      <tr class="mainRecordRow table-light">
        <td></td>
        <td class="custom-cell-class">
          Jena Gaines
          <input type="hidden" class="hobby" value="Traveling">
          <input type="hidden" class="favorite-animal" value="Whale">
        </td>
        <td>Office Manager</td>
        <td>30</td>
        <td>2008/12/19</td>
        <td>$90,560</td>
        <td>Administration</td>
        <td>Project J</td>
        <td>2</td>
        <td>USA</td>
        <td>New York</td>
        <td>Traveling</td>
        <td>Whale</td>
      </tr>
      <tr class="mainRecordRow table-light">
        <td></td>
        <td class="custom-cell-class">
          Quinn Flynn
          <input type="hidden" class="hobby" value="Swimming">
          <input type="hidden" class="favorite-animal" value="Shark">
        </td>
        <td>Support Lead</td>
        <td>22</td>
        <td>2013/03/03</td>
        <td>$342,000</td>
        <td>Support</td>
        <td>Project K</td>
        <td>1</td>
        <td>Canada</td>
        <td>Vancouver</td>
        <td>Swimming</td>
        <td>Shark</td>
      </tr>
      <tr class="mainRecordRow table-light">
        <td></td>
        <td class="custom-cell-class">
          Charde Marshall
          <input type="hidden" class="hobby" value="Writing">
          <input type="hidden" class="favorite-animal" value="Wolf">
        </td>
        <td>Regional Director</td>
        <td>36</td>
        <td>2008/10/16</td>
        <td>$470,600</td>
        <td>Management</td>
        <td>Project L</td>
        <td>11</td>
        <td>Singapore</td>
        <td>Singapore</td>
        <td>Writing</td>
        <td>Wolf</td>
      </tr>
      <tr class="mainRecordRow table-light">
        <td></td>
        <td class="custom-cell-class">
          Haley Kennedy
          <input type="hidden" class="hobby" value="Cycling">
          <input type="hidden" class="favorite-animal" value="Bear">
        </td>
        <td>Senior Marketing Designer</td>
        <td>43</td>
        <td>2012/12/18</td>
        <td>$313,500</td>
        <td>Marketing</td>
        <td>Project M</td>
        <td>8</td>
        <td>UK</td>
        <td>Manchester</td>
        <td>Cycling</td>
        <td>Bear</td>
      </tr>
      <tr class="mainRecordRow table-light">
        <td></td>
        <td class="custom-cell-class">
          Tatyana Fitzpatrick
          <input type="hidden" class="hobby" value="Dancing">
          <input type="hidden" class="favorite-animal" value="Peacock">
        </td>
        <td>Regional Director</td>
        <td>19</td>
        <td>2010/03/17</td>
        <td>$385,750</td>
        <td>Management</td>
        <td>Project N</td>
        <td>3</td>
        <td>India</td>
        <td>Mumbai</td>
        <td>Dancing</td>
        <td>Peacock</td>
      </tr>
    </tbody>
  </table>


  <script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
  <script src="https://cdn.datatables.net/1.13.6/js/jquery.dataTables.min.js"></script>
  <script src="https://cdn.datatables.net/fixedheader/3.4.0/js/dataTables.fixedHeader.min.js"></script>
  <script src="https://cdn.datatables.net/rowgroup/1.4.0/js/dataTables.rowGroup.min.js"></script>

  <script>
    $(document).ready(function() {
      var groupColumn = 10;
      var initialColumnWidths = [];

      function storeOriginalClasses() {
        $('#example tbody tr').each(function() {
          $(this).data('original-classes', $(this).attr('class'));
          $(this).find('td').each(function() {
            $(this).data('original-classes', $(this).attr('class'));
          });
        });
      }

      function reapplyOriginalClasses() {
        $('#example tbody tr').each(function() {
          var originalClasses = $(this).data('original-classes');
          if (originalClasses) {
            $(this).attr('class', originalClasses);
          }
          $(this).find('td').each(function() {
            var originalTdClasses = $(this).data('original-classes');
            if (originalTdClasses) {
              $(this).attr('class', originalTdClasses);
            }
          });
        });

        $('.groupRow').each(function() {
          var originalClasses = $(this).data('original-classes');
          if (originalClasses) {
            $(this).attr('class', originalClasses);
          }
        });
      }

      function addChildRows() {
        $('.child-row').remove();

        var colspan = $('#example thead tr th:visible').length - 1;

        table.rows().every(function(rowIdx, tableLoop, rowLoop) {
          var tr = $(this.node());
          var hobby = tr.find('.hobby').val();
          var favoriteAnimal = tr.find('.favorite-animal').val();

          var childRowHtml = `
                    <tr class="childDataRow table-light">
                        <td></td>
                        <td colspan="${colspan}">Hobby: ${hobby} | Favorite Animal: ${favoriteAnimal}</td>
                    </tr>
                `;

          tr.after(childRowHtml);
        });
      }

      function addGroupFooter() {
        $('.groupFooterRow').remove();

        var groupData = {};
        table.rows({
          page: 'current'
        }).every(function() {
          var data = this.data();
          var groupKey = data[groupColumn];
          if (!groupData[groupKey]) {
            groupData[groupKey] = {
              totalSalary: 0,
              totalYears: 0,
              rows: []
            };
          }
          groupData[groupKey].rows.push(this.node());
          groupData[groupKey].totalSalary += parseFloat(data[5].toString().replace(/[\$,]/g, ''));
          groupData[groupKey].totalYears += parseFloat(data[8]) || 0;
        });

        $.each(groupData, function(groupKey, groupInfo) {
          var lastRow = $(groupInfo.rows[groupInfo.rows.length - 1]);
          var lastChildRow = lastRow.next('.childDataRow').length ? lastRow.next('.childDataRow') : lastRow;

          var totalVisibleColumns = $('#example thead tr th:visible').length;
          var colspanBeforeSalary = 5;
          var colspanBetween = 2;
          var colspanAfterYears = totalVisibleColumns - 9;

          var formattedSalary = groupInfo.totalSalary.toFixed(2).replace(/\B(?=(\d{3})+(?!\d))/g, ',');
          var formattedYears = groupInfo.totalYears.toFixed(2);

          var groupFooterHtml = `
                    <tr class="groupFooterRow bg-primary text-white">
                        <td colspan="${colspanBeforeSalary}"></td>
                        <td>Group Total Salary: $${formattedSalary}</td>
                        <td colspan="${colspanBetween}"></td>
                        <td>Group Total Years: ${formattedYears}</td>
                        <td colspan="${colspanAfterYears}"></td>
                    </tr>
                `;

          lastChildRow.after(groupFooterHtml);
        });
      }

      // Capture initial column widths when the table is first drawn
      function captureInitialColumnWidths() {
        initialColumnWidths = [];
        $('#example thead th').each(function() {
          initialColumnWidths.push($(this).width());
        });
      }

      // Apply the captured column widths
      function applyColumnWidths() {
        $('#example thead th').each(function(index) {
          $(this).css('width', initialColumnWidths[index] + 'px');
        });

        $('#example tbody tr:first td').each(function(index) {
          $(this).css('width', initialColumnWidths[index] + 'px');
        });
      }

      storeOriginalClasses();

      var table = $('#example').DataTable({
        responsive: false,
        fixedHeader: true,
        scrollX: true,
        order: [
          [1, 'asc']
        ],
        lengthChange: true,
        lengthMenu: [10, 25, 50, 100],
        paging: true,
        rowGroup: {
          dataSrc: groupColumn,
          startRender: function(rows, group) {
            var colspan = $('#example thead tr th:visible').length;
            return $('<tr/>')
              .addClass('groupRow bg-primary-light text-white')
              .append(`<td colspan="${colspan}">Group: ${group}</td>`);
          }
        },
        columnDefs: [{
            targets: 0,
            orderable: false,
            searchable: false,
            className: 'select-checkbox',
            render: function() {
              return '<input type="checkbox" class="select-row">';
            }
          },
          {
            targets: [10, 11, 12],
            visible: false,
            searchable: true
          },
          {
            targets: 2, // The "Position" column
            width: '100px', // Set width to 100px
            createdCell: function(td, cellData, rowData, row, col) {
              $(td).css('white-space', 'normal'); // Enable word wrapping
              $(td).css('word-wrap', 'break-word'); // Ensure long words break
            }
          }
        ],
        autoWidth: false
      });

      // Add child rows and group footers initially
      addChildRows();
      addGroupFooter();

      // Capture initial column widths after the table is drawn
      table.on('draw', function() {
        if (initialColumnWidths.length === 0) {
          captureInitialColumnWidths();
        }
        addChildRows();
        addGroupFooter();
        reapplyOriginalClasses();
        adjustTable();
      });

      // Apply fixed column widths during scrolling to avoid shifting
      $('#example_wrapper .dataTables_scrollBody').on('scroll', function() {
        applyColumnWidths();
      });

      // Adjust on column order change
      table.on('order', function() {
        adjustTable();
      });

      // Handle Select All checkbox
      $('#select-all').on('click', function() {
        var rows = table.rows({
          'search': 'applied'
        }).nodes();
        $('input[type="checkbox"]', rows).prop('checked', this.checked);
      });

      // Handle grouping change based on dropdown
      $('#group-by-column').on('change', function() {
        var selectedColumn = $(this).val();
        if (selectedColumn === "none") {
          groupColumn = null;
        } else if (selectedColumn === "position") {
          groupColumn = 2;
        } else if (selectedColumn === "office") {
          groupColumn = 10;
        }

        table.rowGroup().dataSrc(groupColumn).draw();
        adjustTable();
      });

      // Function to adjust columns and fixed header alignment
      function adjustTable() {
        table.columns.adjust();
        if (table.fixedHeader) {
          table.fixedHeader.adjust();
        }
      }

      // Fix header alignment on window resize
      $(window).on('resize', function() {
        adjustTable();
      });

      // Recalculate column width on table draw events, like search or paging
      table.on('responsive-resize', function() {
        adjustTable();
      });

      // Call the adjustment function on initial load to ensure correct alignment
      adjustTable();
    });
  </script>
</body>

</html>

因为,一旦向后滚动,

width
属性中的
style
就会消失,因此最简单的解决方案是使用
flex
并均匀地间隔标题单元格。

© www.soinside.com 2019 - 2024. All rights reserved.