<div class="table table--light">
    <div class="table__inner">
        <table>
            <thead>
                <tr>
                    <th scope="col">Beitragssatz</th>
                    <th scope="col">Einnahmen</th>
                </tr>
            </thead>
            <tbody>
                <tr>
                    <td>14,59 Prozent</td>
                    <td>Beamtenbezüge<br/>Einnahmen aus Vermietung und Verpachtung<br/>Kapitalerträge</td>
                </tr>
                <tr>
                    <td>15,19 Prozent</td>
                    <td>Rente<br/>Pension<br/>Betriebsrente<br/>Arbeitseinkommen neben Rente oder<br/>Versorgungsbezug</td>
                </tr>
            </tbody>
        </table>
    </div>
</div>
-
  //- Prepare attr object
  attr = attr || {};
  attr.class = classList(attr.class);

  //- Alternative design?
  if (light) attr.class.push('table--light');

  //- Complex table
  if (complex) attr.class.push('table--complex');

  //- List table
  if (list) attr.class.push('table--list');

  //- Fixed table layout
  if (fixed) attr.class.push('table--fixed');

  //- BBNR filter table
  if (filter && filter.type === 'bbnr') attr.class.push('js-table-filter');

  //- Generic filter table
  if (filter && filter.type === 'generic') {
    attr.class.push('js-table-filter-generic');
    attr = Object.assign(attr, {
      'data-label': filter.label,
      'data-placeholder': filter.placeholder,
      'data-no-results-message': filter.noResultsMessage,
    });
  }

//- Render table
.table&attributes(attr): .table__inner
  //- Header
  if headline || subline
    header.table__header
      if headline
        != include('@headline--headline-2', {text: headline, level: 4, attr: {class: 'table__headline'}})

      if subline
        .table__subline #{subline}

  //- Content
  if content
    != renderPug(content)
{
  "content": "table\n  thead\n    tr\n      th(scope='col') Beitragssatz\n      th(scope='col') Einnahmen\n  tbody\n    tr\n      td 14,59 Prozent\n      td Beamtenbezüge#[br]Einnahmen aus Vermietung und Verpachtung#[br]Kapitalerträge\n    tr\n      td 15,19 Prozent\n      td Rente#[br]Pension#[br]Betriebsrente#[br]Arbeitseinkommen neben Rente oder#[br]Versorgungsbezug\n",
  "light": true
}
  • Content:
    import h from 'hyperscript';
    import randomId from '../../../javascripts/utils/random-id';
    
    const hkkCompanyNumber = '20013461';
    
    export default class TableFilter {
      constructor($el) {
        this.$el = $el;
        this.$inner = this.$el.querySelector('.table__inner');
        this.$rows = this.$el.querySelectorAll('[data-filter]');
        this.$tableHead = this.$el.querySelector('thead');
    
        this.id = randomId();
        this.NUMBER_FORMAT = /^[0-9]{8}$/;
    
        this.init();
      }
    
      init() {
        this.initInput();
        this.initRows();
        this.initEvents();
        this.initTableHead();
      }
    
      initTableHead() {
        this.$tableHead.classList.add('table__table-head--hidden');
      }
    
      initInput() {
        // Insert filter section
        this.$el.insertBefore(
          h('.table__filter',
            h('.form-group',
              h('label.label', { for: `table-filter-${this.id}` }, 'Ansprechpartner finden'),
              h('.form-group__inner',
                h('input.input.input--text', {
                  id: `table-filter-${this.id}`,
                  type: 'text',
                  placeholder: '8-stellige Betriebsnummer',
                  maxLength: 8,
                }),
              ),
            ),
          ),
    
          this.$inner,
        );
    
        // Define inputs
        this.$input = this.$el.querySelector(`#table-filter-${this.id}`);
      }
    
      initEvents() {
        this.$input.addEventListener('input', () => {
          if (this.NUMBER_FORMAT.test(this.$input.value)) {
            this.$input.setAttribute('aria-invalid', 'false');
            this.filter(this.$input.value);
          } else {
            this.$input.setAttribute('aria-invalid', 'true');
            this.reset();
          }
        });
      }
    
      initRows() {
        const $rows = [...this.$rows];
    
        $rows.forEach(($row) => {
          $row.classList.add('table__row--hidden');
        });
      }
    
      filter(number) {
        const parsedNumber = parseInt(number.slice(-3), 10);
        const $rows = [...this.$rows];
    
        $rows.forEach(($row) => {
          const rangeFrom = parseInt($row.dataset.filterFrom, 10);
          const rangeTo = parseInt($row.dataset.filterTo, 10);
    
          const rowMatches = parsedNumber >= rangeFrom && parsedNumber <= rangeTo;
    
          const fn = rowMatches ? 'remove' : 'add';
          $row.classList[fn]('table__row--hidden');
        });
    
        const message = this.$inner.querySelector('.table__message');
        if (message) {
          message.remove();
        }
    
        if (number === hkkCompanyNumber) {
          this.$message = h('p.table__message', 'Sie haben die Betriebsnummer der hkk eingegeben. Bitte geben Sie die Betriebsnummer Ihres Betriebes an.');
          this.$inner.appendChild(this.$message);
          this.$inner.querySelector('table').style.display = 'none';
        } else if (this.$el.querySelectorAll('.table__row--hidden').length === this.$rows.length) { // No results
          this.$message = h('p.table__message', 'Für diese Betriebsnummer existiert derzeit kein Ansprechpartner.');
          this.$inner.appendChild(this.$message);
          this.$tableHead.classList.add('table__table-head--hidden');
          this.$inner.querySelector('table').style.display = 'block';
        } else {
          this.$tableHead.classList.remove('table__table-head--hidden');
          this.$inner.querySelector('table').style.display = 'block';
        }
      }
    
      reset() {
        if (this.$message) this.$message.remove();
        this.initRows();
        this.initTableHead();
      }
    }
    
    // Initialize TableFilter
    document
      .querySelectorAll('.js-table-filter')
      .forEach($el => new TableFilter($el));
    
  • URL: /components/raw/table/table-filter-bbnr.js
  • Filesystem Path: src/components/atoms/table/table-filter-bbnr.js
  • Size: 3.4 KB
  • Content:
    import h from 'hyperscript';
    import randomId from '../../../javascripts/utils/random-id';
    
    const createSearchIndex = $rows => $rows.map(
      $row => $row
        .querySelectorAll('td[data-filter]')
        .map($column => $column.innerText)
        .join(' ')
    );
    
    const createFilterReducer = query => (prevMatches, rowText, rowIndex) => {
      const doesMatch = rowText.toLowerCase().includes(query.toLowerCase());
    
      if (doesMatch) {
        return [...prevMatches, rowIndex];
      }
    
      return prevMatches;
    };
    
    const createNoResultsMessage = message => h(
      'p.table__message',
      { style: { display: 'none' } },
      message
    );
    
    const createForm = ({
      id,
      label,
      placeholder,
      onChange,
    }) => {
      const $input = h('input.input.input--text', {
        id,
        type: 'text',
        placeholder,
        oninput: ({ target }) => onChange(target.value.trim() || null),
      });
    
      return h('.table__filter',
        h('.form-group',
          h('label.label', { for: id }, label),
          h('.form-group__inner', $input),
        ),
      );
    };
    
    export default class TableFilter {
      constructor($el) {
        this.$el = $el;
        this.$inner = this.$el.querySelector('.table__inner');
        this.$table = this.$el.querySelector('table');
        this.$rows = this.$el.querySelectorAll('tbody tr');
    
        this.state = {
          query: null,
          results: [],
        };
    
        this.init();
      }
    
      init() {
        const id = randomId();
        const { label, placeholder, noResultsMessage } = this.$el.dataset;
        const $form = createForm({
          id,
          label,
          placeholder,
          onChange: query => this.handleFilter(query),
        });
    
        this.searchIndex = createSearchIndex(this.$rows);
        this.$noResultsMessage = createNoResultsMessage(noResultsMessage);
    
        this.$el.insertBefore($form, this.$inner);
        this.$inner.appendChild(this.$noResultsMessage);
      }
    
      handleFilter(query) {
        const filterReducer = createFilterReducer(query);
        const results = query !== null
          ? this.searchIndex.reduce(filterReducer, [])
          : [];
    
        this.state = Object.assign(this.state, { query, results });
        this.render();
      }
    
      render() {
        const { results, query } = this.state;
        const isQueryEmpty = query === null;
        const hasResults = Boolean(results.length);
    
        this.$rows.forEach(
          ($row, index) => {
            if (isQueryEmpty || results.includes(index)) {
              $row.classList.remove('table__row--hidden');
    
              return;
            }
    
            $row.classList.add('table__row--hidden');
          },
        );
    
        if (isQueryEmpty || hasResults) {
          this.$noResultsMessage.style.display = 'none';
        } else {
          this.$noResultsMessage.style.display = null;
        }
      }
    }
    
    document
      .querySelectorAll('.js-table-filter-generic')
      .forEach($el => new TableFilter($el));
    
  • URL: /components/raw/table/table-filter-generic.js
  • Filesystem Path: src/components/atoms/table/table-filter-generic.js
  • Size: 2.7 KB
  • Content:
    .table {
      font-size: 1.5rem;
      position: relative;
    
      &::before,
      &::after {
        bottom: 0;
        content: '';
        position: absolute;
        top: 0;
        width: 2rem;
        z-index: 2;
      }
    
      table {
        border-collapse: separate;
        border-spacing: 0 1px;
        caption-side: bottom;
        margin: 1.5rem 0;
        position: relative;
        width: 100%;
      }
    
      caption {
        color: $color-steelgrey-xdark;
        font-style: italic;
        padding-top: $spacer;
        text-align: left;
      }
    
      th {
        background-color: $color-red;
        color: #fff;
        font-weight: bold;
        text-align: left;
      }
    
      td {
        background-color: $color-steelgrey-light;
      }
    
      th p,
      td p {
        margin: 0;
      }
    
      th,
      td {
        padding: 1rem;
        vertical-align: top;
      }
    }
    
    .table--light {
      table {
        border-collapse: collapse;
      }
    
      thead {
        border-bottom: 4px solid $color-steelgrey-light;
      }
    
      thead th {
        padding-top: 0;
      }
    
      tbody {
        border-top: 1px solid $color-steelgrey-light;
      }
    
      th,
      td {
        background-color: transparent;
        border-bottom: 1px solid $color-steelgrey-light;
        color: inherit;
      }
    }
    
    .table--complex {
      &::before {
        background-image: linear-gradient(to right, #fff, rgba(#fff, 0));
        left: -2rem;
      }
    
      &::after {
        background-image: linear-gradient(to right, rgba(#fff, 0), #fff);
        right: -2rem;
      }
    
      table {
        border-left: 2rem solid transparent;
        border-right: 2rem solid transparent;
      }
    
      .table__inner {
        margin: 0 -2rem $spacer;
      }
    }
    
    .table--list {
      background-color: $color-steelgrey-xlight;
    
      .table__inner {
        margin: 0;
      }
    
      .table__header {
        padding: 2rem 2rem 0;
      }
    
      .table-row--disabled {
        color: $color-steelgrey;
      }
    
      .table-row--disabled strong {
        color: $color-steelgrey-xdark;
      }
    
      thead,
      th,
      td {
        border-color: $color-steelgrey;
      }
    
      th:first-child,
      th:last-child,
      td:first-child,
      td:last-child {
        padding-left: 0;
      }
    }
    
    .table--fixed {
      table {
        table-layout: fixed;
      }
    }
    
    .table__inner {
      overflow-x: auto;
      position: relative;
      z-index: 1;
    }
    
    .table__headline {
      margin-bottom: 1rem;
    }
    
    .table__message {
      color: $color-red;
      text-align: center;
    }
    
    .table__row--hidden {
      display: none;
    }
    
    .table__table-head--hidden {
      display: none;
    }
    
    @include mq($from: m) {
      .table {
        table {
          margin-bottom: 3rem;
          margin-top: 0.5rem;
        }
    
        th,
        td {
          padding: 1.5rem;
        }
      }
    
      .table--light {
        tbody th {
          padding-left: 0;
        }
      }
    
      .table--list {
        .table__inner,
        .table__header {
          padding: 2rem;
        }
      }
    }
    
  • URL: /components/raw/table/table.scss
  • Filesystem Path: src/components/atoms/table/table.scss
  • Size: 2.6 KB

There are no notes for this item.