html表冻结列与纯JavaScript,小CSS

时间:2018-02-03 02:34:33

标签: javascript html css datatable html-table

我试图实现制作一个html水平滚动表的左三列“冻结”#39;或者'固定'。我已经全面了解了网络上的所有解决方案,但我有很多要求,无法找到解决方案:

  1. 尽可能少地更改CSS,因为此表已经应用了很多CSS。此表与jQuery DataTables具有许多相同的功能,因此还有很多功能。
  2. 我愿意根据需要做尽可能多的Javascript,但它需要纯粹是JS,没有其他像jQuery。
  3. 无法复制表格(我已经看过将表格的一个副本放在另一个表格之上的解决方案)。
  4. 桌子必须保持完全白色,我不能为冷冻柱指定背景颜色作为“修复”。在冻结列滚动时隐藏其他列。
  5. 你们对如何使用Javascript实现该功能有任何建议吗?似乎大多数适用于现有表的实现(并且不包括表中的此功能)依赖于更改大量CSS。即使只是关于如何在javascript中开始使用它的一些建议也会有所帮助。如果我使用滚动方面,我认为应该有一种方法,但我不确定。

1 个答案:

答案 0 :(得分:0)

我使用了fixed-table.js库来实现没有jquery的解决方案。试试下面的代码段。



var fixedTable = fixTable(document.getElementById('fixed-table-container-demo'));

function fixTable(container) {
  // Store references to table elements
  var thead = container.querySelector('thead');
  var tbody = container.querySelector('tbody');

  // Style container
  container.style.overflow = 'auto';
  container.style.position = 'relative';

  // Add inline styles to fix the header row and leftmost column
  function relayout() {
    var ths = [].slice.call(thead.querySelectorAll('th'));
    var tbodyTrs = [].slice.call(tbody.querySelectorAll('tr'));

    /**
     * Remove inline styles so we resort to the default table layout algorithm
     * For thead, th, and td elements, don't remove the 'transform' styles applied
     * by the scroll event listener
     */
    tbody.setAttribute('style', '');
    thead.style.width = '';
    thead.style.position = '';
    thead.style.top = '';
    thead.style.left = '';
    thead.style.zIndex = '';
    ths.forEach(function(th) {
      th.style.display = '';
      th.style.width = '';
      th.style.position = '';
      th.style.top = '';
      th.style.left = '';
    });
    tbodyTrs.forEach(function(tr) {
      tr.setAttribute('style', '');
    });
    [].slice.call(tbody.querySelectorAll('td'))
      .forEach(function(td) {
        td.style.width = '';
        td.style.position = '';
        td.style.left = '';
      });

    /**
     * Store width and height of each th
     * getBoundingClientRect()'s dimensions include paddings and borders
     */
    var thStyles = ths.map(function(th) {
      var rect = th.getBoundingClientRect();
      var style = document.defaultView.getComputedStyle(th, '');
      return {
        boundingWidth: rect.width,
        boundingHeight: rect.height,
        width: parseInt(style.width, 10),
        paddingLeft: parseInt(style.paddingLeft, 10)
      };
    });

    // Set widths of thead and tbody
    var totalWidth = thStyles.reduce(function(sum, cur) {
      return sum + cur.boundingWidth;
    }, 0);
    tbody.style.display = 'block';
    tbody.style.width = totalWidth + 'px';
    thead.style.width = totalWidth - thStyles[0].boundingWidth + 'px';

    // Position thead
    thead.style.position = 'absolute';
    thead.style.top = '0';
    thead.style.left = thStyles[0].boundingWidth + 'px';
    thead.style.zIndex = 10;

    // Set widths of the th elements in thead. For the fixed th, set its position
    ths.forEach(function(th, i) {
      th.style.width = thStyles[i].width + 'px';
      if (i === 0) {
        th.style.position = 'absolute';
        th.style.top = '0';
        th.style.left = -thStyles[0].boundingWidth + 'px';
      }
    });

    // Set margin-top for tbody - the fixed header is displayed in this margin
    tbody.style.marginTop = thStyles[0].boundingHeight + 'px';

    // Set widths of the td elements in tbody. For the fixed td, set its position
    tbodyTrs.forEach(function(tr, i) {
      tr.style.display = 'block';
      tr.style.paddingLeft = thStyles[0].boundingWidth + 'px';
      [].slice.call(tr.querySelectorAll('td'))
        .forEach(function(td, j) {
          td.style.width = thStyles[j].width + 'px';
          if (j === 0) {
            td.style.position = 'absolute';
            td.style.left = '0';
          }
        });
    });
  }

  // Initialize table styles
  relayout();

  // Update table cell dimensions on resize
  window.addEventListener('resize', resizeThrottler, false);
  var resizeTimeout;

  function resizeThrottler() {
    if (!resizeTimeout) {
      resizeTimeout = setTimeout(function() {
        resizeTimeout = null;
        relayout();
      }, 500);
    }
  }

  // Fix thead and first column on scroll
  container.addEventListener('scroll', function() {
    thead.style.transform = 'translate3d(0,' + this.scrollTop + 'px,0)';
    var hTransform = 'translate3d(' + this.scrollLeft + 'px,0,0)';
    thead.querySelector('th').style.transform = hTransform;
    [].slice.call(tbody.querySelectorAll('tr > td:first-child'))
      .forEach(function(td, i) {
        td.style.transform = hTransform;
      });
  });

  /**
   * Return an object that exposes the relayout function so that we can
   * update the table when the number of columns or the content inside columns changes
   */
  return {
    relayout: relayout
  };
}

.fixed-table-container {
  height: 300px;
  box-sizing: border-box;
  border: 1px solid #ccc;
  margin-bottom: 40px;
}

.fixed-table-container table {
  border-collapse: collapse;
  width: 100%;
}

.fixed-table-container th,
.fixed-table-container td {
  border-right: 1px solid #ccc;
  border-bottom: 1px solid #ccc;
  padding: 8px;
  text-align: left;
  vertical-align: top;
  /**
    * Current implementation doesn't work when
    * cells in a row have different heights
    */
  white-space: nowrap !important;
}

.fixed-table-container th {
  background: #fff;
  font-size: 12px;
  line-height: 16px;
  padding-top: 10px;
  padding-bottom: 10px;
}

.fixed-table-container td:first-child {
  background: #fff;
}

.fixed-table-container tr:last-child td {
  border-bottom: 0;
}

.fixed-table-container th:last-child,
.fixed-table-container td:last-child {
  border-right: 0;
}

<div id="fixed-table-container-demo" class="fixed-table-container">
  <table>
    <thead>
      <tr>
        <th>Name</th>
        <th>Status</th>
        <th>Description</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <td>Lorem</td>
        <td>Lorem ipsum</td>
        <td>Lorem</td>
      </tr>
      <tr>
        <td>Lorem ipsum dolor sit amet</td>
        <td>Lorem</td>
        <td>Dolor</td>
      </tr>
      <tr>
        <td>Lorem ipsum dolor</td>
        <td>sit</td>
        <td>Lorem ipsum dolor sit amet ipsum dolor sit amet</td>
      </tr>
      <tr>
        <td>Lorem</td>
        <td>Lorem ipsum</td>
        <td>Lorem ipsum dolor sit amet</td>
      </tr>
      <tr>
        <td>Dolor sit amet</td>
        <td>Dolor sit amet</td>
        <td>Lorem</td>
      </tr>
      <tr>
        <td>Lorem ipsum dolor</td>
        <td>Lorem ipsum dolor sit amet ipsum dolor sit amet</td>
        <td>Sit amet</td>
      </tr>
      <tr>
        <td>Lorem</td>
        <td>Lorem ipsum</td>
        <td>Lorem</td>
      </tr>
      <tr>
        <td>Lorem ipsum dolor sit amet</td>
        <td>Lorem</td>
        <td>Dolor</td>
      </tr>
      <tr>
        <td>Lorem ipsum dolor</td>
        <td>sit</td>
        <td>Lorem ipsum dolor sit amet</td>
      </tr>
      <tr>
        <td>Lorem</td>
        <td>Lorem ipsum</td>
        <td>Lorem dolor sit amet</td>
      </tr>
      <tr>
        <td>Dolor sit amet</td>
        <td>Dolor sit amet</td>
        <td>Lorem</td>
      </tr>
      <tr>
        <td>Lorem ipsum dolor</td>
        <td>Lorem ipsum dolor sit</td>
        <td>Sit amet lorem</td>
      </tr>
    </tbody>
  </table>
</div>
&#13;
&#13;
&#13;