Guidance

Index tables allow you to present structured data. This is the type of data that typically comes from JSON or databases where the data structure is predictable.

This differs from the @uol-rich-text-table for use in Rich Text Areas where authors can edit the table content.

If the data can be presented with a single heading row and does not rely on column headings there is the option to present a “stacked” view for smaller screens. See Options for tables.

When to use

  • Where data is predictable and comes from a structured source such as JSON or a database

When not to use

  • Where the data is unpredictable or can be edited by a CMS editor

Developer guidance

Options

Name Type Description
tables array An array of tables.

Options for tables

Name Type Description
stackable boolean Provides a “stacked” view for smaller screens. Only use when date has a single heading row.
caption string Provides a title for the table, renders as a <h2>. Recommended unless preceded by an alternative semantic title.
headings array The table headings, includes a “label: string that provides the cell data and boolean options for ‘image_column’ ‘sortable’ and ‘numeric’ which affect layout and functionality.
rows array Each table row contains an array of ‘cells’ with the following required or optional fields:

Required: ‘content’ string.

Optional: ‘type’ that currently accepts a value of ‘numeric’.

Optional: ‘img’ object that can have a ‘src’, ‘alt’ and ‘type’ (currently accepts ‘profile’).

Optional: ‘link’ URL which acts as an active link.

Optional: ‘sortBy’ string can be added for when the data is to be sorted by a value other than the displayed content (eg. ‘content’: ‘Dr Richard Ansell’, ‘sortBy’: ‘Ansell Richard Dr’). This should also be used when the displayed content is a mixture of text and numerical data and the content is to be sorted by the numerical value (eg. ‘content’: ‘£8’, ‘sortBy’: ‘8’).
{% for table in tables %}
  {% if table.caption %}<h2 class="uol-index-table-caption">{{ table.caption }}</h2>{% endif %}
  {% if table.search_results and table.search_results.term %}
    <div class="uol-index-table--results-container">
      <h2 class="uol-index-table--results">{{ table.rows.length }} results for <strong>'{{ table.search_results.term }}'</strong></h2>
    </div>
  {% endif %}
  <table class="uol-index-table{{ ' js-uolTableStackable' if table.stackable}} {{ ' uol-index-table--search-results' if table.search_results}}">

    {# Currently unused due to Safari position: sticky bug #}
    {# {% if table.caption %}<caption>{{ table.caption }}</caption>{% endif %} #}

    {% if table.headings.length > 0 %}
      <thead>
        <tr>
          {% for heading in table.headings%}
            <th
              class="uol-index-table__th {{ 'uol-index-table__th--numeric' if heading.numeric }} {{ 'uol-index-table__th--image-column' if heading.image_column }}"
              {{ ' data-sortable=true' if heading.sortable }}>
              {{ heading.label }}
            </th>
          {% endfor %}
        </tr>
      </thead>
    {% endif %}

    {% if table.rows.length > 0%}
      <tbody>
        {% for row in table.rows %}
          <tr>
            {% for cell in row.cells %}
              <td
                class="uol-index-table__td {{ 'uol-index-table__td--type-img' if cell.img }} {{ 'uol-index-table__td--type-numeric' if cell.type=='numeric' }}"
                data-value="{{ cell.content }}"
                {% if cell.sortBy %}
                  data-sortby="{{ cell.sortBy }}"
                {% endif%}
                >
                {% if cell.link %}<a href="{{ cell.link }}">{% endif %}
                {{ cell.content }}
                {% if cell.img %}
                  <span
                    class="uol-index-table__td__img uol-index-table__td__img--profile"
                    {% if cell.img.src %}
                      role="img"
                      aria-label="{{ cell.img.alt }}"
                      style="background-image: url({{ cell.img.src }})"
                    {% endif%}
                    {% if cell.sortBy %}
                      data-sortkey="{{ cell.sortBy }}"
                    {% endif%}
                    >
                  </span>
                {% endif %}
                {% if cell.link %}</a>{% endif %}

                {% if cell.email %}
                  <a href="mailto:{{cell.email}}">{{cell.email}}</a>
                {% endif %}
              </td>
            {% endfor %}
          </tr>
        {% endfor %}
      </tbody>
    {% endif %}
  </table>
{% endfor %}
<h2 class="uol-index-table-caption">Cheeses</h2>

<table class="uol-index-table js-uolTableStackable ">

    <thead>
        <tr>

            <th class="uol-index-table__th  ">
                Name
            </th>

            <th class="uol-index-table__th  ">
                Description
            </th>

            <th class="uol-index-table__th  ">
                Country of origin
            </th>

            <th class="uol-index-table__th  ">
                Fat percentage
            </th>

        </tr>
    </thead>

    <tbody>

        <tr>

            <td class="uol-index-table__td  " data-value="Cheddar">

                Cheddar

            </td>

            <td class="uol-index-table__td  " data-value="Cheddar cheese is a relatively hard, off-white, sometimes sharp-tasting, natural cheese. Originating in the English village of Cheddar in Somerset, cheeses of this style are now produced beyond the region and in several countries around the world">

                Cheddar cheese is a relatively hard, off-white, sometimes sharp-tasting, natural cheese. Originating in the English village of Cheddar in Somerset, cheeses of this style are now produced beyond the region and in several countries around the world

            </td>

            <td class="uol-index-table__td  " data-value="UK">

                UK

            </td>

            <td class="uol-index-table__td  uol-index-table__td--type-numeric" data-value="16%">

                16%

            </td>

        </tr>

        <tr>

            <td class="uol-index-table__td  " data-value="Brie">

                Brie

            </td>

            <td class="uol-index-table__td  " data-value="Brie is a soft cow&#39;s-milk cheese named after Brie, the French region from which it originated. It is pale in color with a slight grayish tinge under a rind of white mould. The rind is typically eaten, with its flavor depending largely upon the ingredients used and its manufacturing environment">

                Brie is a soft cow&#39;s-milk cheese named after Brie, the French region from which it originated. It is pale in color with a slight grayish tinge under a rind of white mould. The rind is typically eaten, with its flavor depending largely upon the ingredients used and its manufacturing environment

            </td>

            <td class="uol-index-table__td  " data-value="France">

                France

            </td>

            <td class="uol-index-table__td  uol-index-table__td--type-numeric" data-value="2%">

                2%

            </td>

        </tr>

        <tr>

            <td class="uol-index-table__td  " data-value="Edam">

                Edam

            </td>

            <td class="uol-index-table__td  " data-value="Edam is a semi-hard cheese that originated in the Netherlands, and is named after the town of Edam in the province of North Holland. Edam is traditionally sold in rounded cylinders with a pale yellow interior and a coat, or rind, of red paraffin wax. Edam ages and travels well, and does not spoil; it only hardens">

                Edam is a semi-hard cheese that originated in the Netherlands, and is named after the town of Edam in the province of North Holland. Edam is traditionally sold in rounded cylinders with a pale yellow interior and a coat, or rind, of red paraffin wax. Edam ages and travels well, and does not spoil; it only hardens

            </td>

            <td class="uol-index-table__td  " data-value="Netherlands">

                Netherlands

            </td>

            <td class="uol-index-table__td  uol-index-table__td--type-numeric" data-value="11%">

                11%

            </td>

        </tr>

        <tr>

            <td class="uol-index-table__td  " data-value="Manchego">

                Manchego

            </td>

            <td class="uol-index-table__td  " data-value="Manchego is a cheese made in the La Mancha region of Spain from the milk of sheep of the Manchega breed. It is aged between 60 days and 2 years. Manchego has a firm and compact consistency and a buttery texture, and often contains small, unevenly distributed air pockets">

                Manchego is a cheese made in the La Mancha region of Spain from the milk of sheep of the Manchega breed. It is aged between 60 days and 2 years. Manchego has a firm and compact consistency and a buttery texture, and often contains small, unevenly distributed air pockets

            </td>

            <td class="uol-index-table__td  " data-value="Spain">

                Spain

            </td>

            <td class="uol-index-table__td  uol-index-table__td--type-numeric" data-value="25%">

                25%

            </td>

        </tr>

        <tr>

            <td class="uol-index-table__td  " data-value="Parmigiano-Reggiano">

                Parmigiano-Reggiano

            </td>

            <td class="uol-index-table__td  " data-value="Parmigiano-Reggiano or Parmesan is an Italian hard, granular cheese that is produced from cow&#39;s milk and has aged 12-36 months.">

                Parmigiano-Reggiano or Parmesan is an Italian hard, granular cheese that is produced from cow&#39;s milk and has aged 12-36 months.

            </td>

            <td class="uol-index-table__td  " data-value="Italy">

                Italy

            </td>

            <td class="uol-index-table__td  uol-index-table__td--type-numeric" data-value="29.7%">

                29.7%

            </td>

        </tr>

        <tr>

            <td class="uol-index-table__td  " data-value="Cashel Blue">

                Cashel Blue

            </td>

            <td class="uol-index-table__td  " data-value="Cashel Blue is a hand-made, semi-soft, blue veined, medium-strength blue cheese with a creamy texture. Cashel Blue was the first Irish blue cheese, named after the Rock of Cashel overlooking the pastures close to the cheese farm of the family Grubb.">

                Cashel Blue is a hand-made, semi-soft, blue veined, medium-strength blue cheese with a creamy texture. Cashel Blue was the first Irish blue cheese, named after the Rock of Cashel overlooking the pastures close to the cheese farm of the family Grubb.

            </td>

            <td class="uol-index-table__td  " data-value="Ireland">

                Ireland

            </td>

            <td class="uol-index-table__td  uol-index-table__td--type-numeric" data-value="45%">

                45%

            </td>

        </tr>

        <tr>

            <td class="uol-index-table__td  " data-value="Stilton">

                Stilton

            </td>

            <td class="uol-index-table__td  " data-value="Stilton is an English cheese, produced in two varieties: Blue, which has had Penicillium roqueforti added to generate a characteristic smell and taste, and White, which has not.">

                Stilton is an English cheese, produced in two varieties: Blue, which has had Penicillium roqueforti added to generate a characteristic smell and taste, and White, which has not.

            </td>

            <td class="uol-index-table__td  " data-value="Uk">

                Uk

            </td>

            <td class="uol-index-table__td  uol-index-table__td--type-numeric" data-value="35%">

                35%

            </td>

        </tr>

        <tr>

            <td class="uol-index-table__td  " data-value="Shropshire Blue">

                Shropshire Blue

            </td>

            <td class="uol-index-table__td  " data-value="Shropshire Blue is a cow&#39;s milk cheese made in the United Kingdon">

                Shropshire Blue is a cow&#39;s milk cheese made in the United Kingdon

            </td>

            <td class="uol-index-table__td  " data-value="Uk">

                Uk

            </td>

            <td class="uol-index-table__td  uol-index-table__td--type-numeric" data-value="48%">

                48%

            </td>

        </tr>

        <tr>

            <td class="uol-index-table__td  " data-value="Wensleydale">

                Wensleydale

            </td>

            <td class="uol-index-table__td  " data-value="Wensleydale is a style of cheese originally produced in Wensleydale, North Yorkshire, England, but now mostly made in large commercial creameries throughout the UK. The term &quot;Yorkshire Wensleydale&quot; can only be used for cheese that is made in Wensleydale">

                Wensleydale is a style of cheese originally produced in Wensleydale, North Yorkshire, England, but now mostly made in large commercial creameries throughout the UK. The term &quot;Yorkshire Wensleydale&quot; can only be used for cheese that is made in Wensleydale

            </td>

            <td class="uol-index-table__td  " data-value="Uk">

                Uk

            </td>

            <td class="uol-index-table__td  uol-index-table__td--type-numeric" data-value="32%">

                32%

            </td>

        </tr>

        <tr>

            <td class="uol-index-table__td  " data-value="Cornish Yarg">

                Cornish Yarg

            </td>

            <td class="uol-index-table__td  " data-value="Semi-hard cow&#39;s milk cheese made in Cornwall from the milk of Friesian cows. Before being left to mature, this cheese is wrapped in nettle leaves to form an edible, though mouldy, rind.">

                Semi-hard cow&#39;s milk cheese made in Cornwall from the milk of Friesian cows. Before being left to mature, this cheese is wrapped in nettle leaves to form an edible, though mouldy, rind.

            </td>

            <td class="uol-index-table__td  " data-value="Uk">

                Uk

            </td>

            <td class="uol-index-table__td  uol-index-table__td--type-numeric" data-value="30%">

                30%

            </td>

        </tr>

        <tr>

            <td class="uol-index-table__td  " data-value="Stinking Bishop">

                Stinking Bishop

            </td>

            <td class="uol-index-table__td  " data-value="Award-winning, washed-rind cheese produced since 1994 by Charles Martell and Son at Hunts Court Farm, Dymock, Gloucestershire, in the south west of England.">

                Award-winning, washed-rind cheese produced since 1994 by Charles Martell and Son at Hunts Court Farm, Dymock, Gloucestershire, in the south west of England.

            </td>

            <td class="uol-index-table__td  " data-value="Uk">

                Uk

            </td>

            <td class="uol-index-table__td  uol-index-table__td--type-numeric" data-value="48%">

                48%

            </td>

        </tr>

    </tbody>

</table>
  • Content:
    .uol-index-table-caption {
      @extend %text-size-heading-4;
    
      color: $color-font--dark;
      margin: $spacing-4 0 0;
      padding: $spacing-4;
    
      @include media("<uol-media-m") {
        border: 1px solid $color-border--light;
        border-radius: 6px 6px 0 0;
      }
    }
    
    .uol-index-table--results-container {
      padding: $spacing-4;
    
      @include media(">uol-media-m") {
        text-align: right;
      }
    }
    
    .uol-index-table--results {
      @include font-size-responsive(1rem);
    }
    
    .uol-index-table {
      @extend %text-size-paragraph--small;
    
      border-collapse: unset;
      margin-bottom: $spacing-4;
      border: 1px solid $color-border--light;
      font-variant-numeric: lining-nums;
    
      @include media(">=uol-media-m") {
        margin: $spacing-4;
        position: relative;
        border-radius: 12px;
      }
    
      // Currently unused due to Safari position: sticky bug
      // caption {
      //     font-size: 18px;
      //     font-weight: 600;
      //     color: $color-font--dark;
      // }
    
      thead {
        border-radius: 6px 6px 0 0;
    
        @include media(">=uol-media-m") {
          z-index: 2;
          border-radius: 0;
        }
      }
    
      th,
      td {
        vertical-align: top;
    
        @include media(">=uol-media-m") {
          padding: $spacing-4;
        }
      }
    
      th {
        font-weight: $font-weight-medium--sans-serif;
    
        @include media(">=uol-media-m") {
          text-align: left;
          position: sticky;
          top: 0;
          padding-bottom: 20px;
          background: $color-white;
          z-index: 2;
          // transform: translateZ(0) scaleX(1.01);
    
          &:first-of-type {
            border-radius: 12px 0 0 0;
          }
    
          &:last-of-type {
            border-radius: 0 12px 0 0;
          }
    
          .csspositionsticky & {
            &::before {
              content: "";
              display: block;
              position: absolute;
              top: 0;
              bottom: -4px;
              left: 0;
              right: 0;
              background: linear-gradient(0deg, rgba(#000, 0) 0, rgba(#000, 0.4) 4px, rgba(#000, 0) 4px);
              opacity: 0;
              transition: opacity 0.7s ease;
            }
          }
    
          &.uol-index-table__th--numeric {
            text-align: right;
          }
    
          &.uol-index-table__th--image-column {
            @include media(">=uol-media-m") {
              padding-left: 6.5rem;
            }
          }
        }
      }
    
      .thead--stuck th {
        @include media(">=uol-media-m") {
          &::before {
            opacity: 1;
          }
    
          &:first-of-type,
          &:last-of-type {
            border-radius: 0;
          }
        }
      }
    
      td {
        color: $color-font;
    
        a {
          color: $color-font;
          text-decoration: underline;
    
          &:hover,
          &:focus {
            text-decoration-color: $color-brand;
          }
        }
      }
    
      tbody {
        line-height: 1.5;
    
        @include media(">=uol-media-m") {
          z-index: 1;
        }
    
        tr {
          transition: all 0.3s ease;
    
          @include media(">=uol-media-m") {
            &:nth-child(odd) {
              background: $color-grey--faded;
            }
    
            &:last-of-type {
              td {
                &:first-of-type {
                  border-radius: 0 0 0 12px;
                }
    
                &:last-of-type {
                  border-radius: 0 0 12px 0;
                }
              }
            }
          }
        }
    
        td {
          @include media(">=uol-media-m") {
            border-bottom: 1px solid $color-border--light;
          }
        }
    
        tr:last-of-type td {
          border-bottom: none;
        }
      }
    
      .uol-index-table__td--type-numeric {
        @include media(">=uol-media-m") {
          text-align: right;
        }
      }
    
      .uol-index-table__td--type-img {
        position: relative;
        margin-top: -#{$spacing-4};
        margin-left: -#{$spacing-4};
        margin-right: -#{$spacing-4};
        padding: $spacing-4 $spacing-4 $spacing-4 6.5rem;
    
        &::before {
          content: "";
          float: left;
          overflow: hidden;
          height: $spacing-8;
          font-size: 0;
       }
      }
    
      .uol-index-table__td__img {
        position: absolute;
        top: 8px;
        left: 8px;
        display: block;
        width: 80px;
        height: 80px;
        background-color: $color-white;
        border-radius: 50%;
        overflow: hidden;
    
        @include media(">=uol-media-m") {
          width: 64px;
          height: 64px;
          top: 16px;
        }
    
        &::before,
        &::after {
          content: "";
          display: block;
          position: absolute;
          top: 0;
          right: 0;
          width: inherit;
          height: inherit;
          border-radius: inherit;
        }
    
        &::before {
          background: 50% / cover;
          background-image: inherit;
        }
    
        &::after {
          box-shadow: inset 0 2px 5px rgba($color-black, 0.16);
        }
      }
    
      .uol-index-table__td__img--profile {
        background: $color-white url("../img/avatar-missing.png");
      }
    
      .uol-index-table__sort-select {
        display: block;
        font-weight: $font-weight-bold--sans-serif;
        width: 100%;
        margin: 0;
        padding: $spacing-4;
        border-color: $color-border;
        border-radius: 0;
    
        @supports (-webkit-appearance:none) {
          -webkit-appearance: none;
          -moz-appearance: none;
          appearance: none;
          background: url("../img/sort.svg") no-repeat right $spacing-4 top 50%;
        }
    
        @media (-ms-high-contrast: active) {
          -webkit-appearance: menulist;
          -moz-appearance: menulist;
          appearance: menulist;
          background: initial;
        }
    
        @include media(">=uol-media-m") {
          display: none;
        }
      }
    
      .uol-index-table__th-inner {
        display: flex;
      }
    
      .uol-index-table__btn-sort {
        position: relative;
        width: 25px;
        height: 24px;
        background: transparent;
        border: none;
    
        @include media("<uol-media-m") {
          display: none;
        }
    
        &::before,
        &::after {
          content: "";
          display: block;
          position: absolute;
          width: 0;
          height: 0;
          left: 8px;
          border: 0.35rem solid transparent;
          border-bottom: none;
          border-top: 0.4rem solid $color-black--dark;
    
          @media (forced-colors: active) {
            border: 0.35rem solid canvas;
            border-top: 0.4rem solid $color-black--dark;
          }
    
          @media (-ms-high-contrast: active) {
            border: 0.35rem solid window;
            border-top: 0.4rem solid windowText;
          }
        }
    
        &::before {
          transform: rotate(180deg) translateY(120%);
        }
    
        &::after {
          transform: translateY(20%);
        }
    
        &.sorted--asc {
    
          &::after {
            opacity: 0;
          }
        }
    
        &.sorted--desc {
    
          &::before {
            opacity: 0;
          }
        }
      }
    }
    
    // uol-index-table--stacked class added with javascript
    .uol-index-table--stacked {
      margin: 0 0 $spacing-4;
      border-radius: 12px;
    
      @include media("<uol-media-m") {
        display: block;
        border-collapse: separate;
        border-radius: 0 0 6px 6px;
        // Currently unused due to Safari position: sticky bug
        // caption {
        //     padding: 16px;
        //     line-height: 1.333;
        //     background-color: $color-cream--dark;
        //     border-bottom: 4px solid hotpink;
        // }
    
        thead {
          position: absolute !important;
          clip: rect(1px, 1px, 1px, 1px);
          height: 1px;
          width: 1px;
          overflow: hidden;
          left: -9999px;
        }
    
        tbody {
          display: block;
    
          tr {
            display: block;
            margin-bottom: 0;
          }
    
          td {
            display: block;
            padding: $spacing-4;
            color: $color-font--dark;
    
            &:first-of-type {
              background: $color-grey--faded;
            }
    
            &:not(:first-child):not(:last-child) {
              border-bottom: 1px solid $color-border--light;
            }
          }
    
          .uol-index-table__td--type-img {
            position: relative;
            background: $color-cream--dark;
            padding: $spacing-5 $spacing-4 $spacing-5 7rem;
            margin: 0;
          }
    
          .uol-index-table__td__img {
            position: absolute;
            top: $spacing-4;
            left: $spacing-4;
            display: block;
            width: $spacing-9;
            height: $spacing-9;
            background-color: $color-white;
            border-radius: 50%;
            overflow: hidden;
    
            &::before,
            &::after {
              content: "";
              display: block;
              position: absolute;
              top: 0;
              right: 0;
              width: inherit;
              height: inherit;
              border-radius: inherit;
            }
    
            &::before {
              background: 50% / cover;
              background-image: inherit;
            }
    
            &::after {
              box-shadow: inset 0 2px 5px rgba($color-black, 0.16);
            }
    
            img {
              width: 100%;
              height: auto;
            }
          }
        }
      }
    }
    
    .uol-index-table--search-results {
    
      @include media("<uol-media-m") {
        border-radius: 6px;
    
        .uol-index-table__sort-select {
          border-radius: 6px 6px 0 0;
        }
      }
    }
    
    .uol-index-table__pseudo-th {
      display: block;
      font-weight: $font-weight-bold--sans-serif;
      color: $color-font;
      margin-bottom: $spacing-1;
    
      @include media(">=uol-media-m") {
        display: none;
      }
    }
    
  • URL: /components/raw/uol-index-table/_index-table.scss
  • Filesystem Path: src/library/02-components/index-table/_index-table.scss
  • Size: 8.8 KB
  • Content:
    // TODO: Add colspan support
    export const uolTableStackable = () => {
      // Config
      const
        stackableTableClass = '.js-uolTableStackable',
        stackableTablePseudoThClass = 'uol-index-table__pseudo-th',
        stackedTableClass = 'uol-index-table--stacked';
    
      // Get tables
      const tables = document.querySelectorAll(stackableTableClass);
    
      // Process tables
      tables.forEach( (table) => {
        const ths = table.querySelectorAll('thead th');
        const rows = table.querySelectorAll('tbody tr');
    
        rows.forEach( (row) => {
    
          const cells = row.querySelectorAll('td')
    
          cells.forEach( (cell, i) => {
            cell.innerHTML = `
              <span
                class="${stackableTablePseudoThClass}"
                aria-hidden="true">
                    ${ths.item(i).innerText}
              </span>
              ${cell.innerHTML}
          `;
          })
        })
    
        table.classList.add(stackedTableClass);
      })
    }
    
    export const uolTablesSortable = () => {
      let ascending;
      const sortRowsByIndex = (table, colNumber) => {
        const tBody = table.querySelector('tbody');
        const rows = tBody.rows;
        let newTableArray = [];
        for (let i = 0; i < (rows.length); i++) {
          newTableArray[i] = rows[i];
        }
        
        /**
         * Sort function - switches through adjacent table elements
         * Sorts in array, no swapping in DOM
         * @param {element} a - first element to compare
         * @param {element} b - second element to compare
         * @returns {number} if -ve a is sorted before b, +ve b before a, 0 no change
         */
        newTableArray.sort(function(a, b){
          let aElement = a.getElementsByTagName("TD")[colNumber];
          let bElement = b.getElementsByTagName("TD")[colNumber];
    
          let aItem = aElement.dataset.sortby ?
            aElement.dataset.sortby :
            aElement.innerText;
    
          let bItem = bElement.dataset.sortby ?
            bElement.dataset.sortby :
            bElement.innerText;
    
          /**
           * Nested ternary return statement
           * Outer checks if both values are number or not
           * Inner checks ascending boolean
           * Returns -ve, +ve or 0
           */
          return (!isNaN(parseFloat(aItem)) && !isNaN(parseFloat(bItem)) ? 
            ascending ? aItem - bItem : bItem - aItem :
            ascending ? ('' + aItem).localeCompare(bItem) : ('' + bItem).localeCompare(aItem)
          );         
        });
        
        /** after sort completed build new table body from sorted array */
        let newTBody = '';
        for (let i = 0; i < (newTableArray.length); i++) {
          newTBody += '<tr>' + newTableArray[i].innerHTML + '</tr>';
        }
        
        /** update DOM with new sorted table body content */
        tBody.innerHTML = newTBody;
      }
    
      const tables = document.querySelectorAll('.uol-index-table');
    
      tables.forEach( (table) => {
    
        const tableHeadings = table.querySelectorAll('thead th');
    
        /** Create map for mobile dropdown */
        let mobileSortableColumns = new Map();
    
        tableHeadings.forEach( (th, index) => {
    
          if (th.dataset.sortable) {
            const thValue = th.innerText;
            th.innerHTML = `<span class="uol-index-table__th-inner"><span class="uol-index-table__sortable-label">${thValue}</span></span>`
    
            // Add value to mobile dropdown map
            mobileSortableColumns.set(index, thValue);
    
            const sortButton = document.createElement('button');
            sortButton.classList.add('uol-index-table__btn-sort');
            sortButton.type = 'button';
            sortButton.setAttribute('aria-label', 'Sort column');
    
            sortButton.onclick = () => {
              const allTh = table.querySelectorAll('thead th');
              const thisBtn = allTh[index].querySelector('button');
              
             if (thisBtn.classList.contains('sorted--asc')) {
                ascending = false;
                thisBtn.classList.add('sorted');
                thisBtn.classList.add('sorted--desc');
                thisBtn.classList.remove('sorted--asc');
              } else {
                ascending = true;
                thisBtn.classList.add('sorted');
                thisBtn.classList.remove('sorted--desc');
                thisBtn.classList.add('sorted--asc');
              }
    
              // Reset all the other buttons
              allTh.forEach( (th, i) => {
                // Don't reset the button just clicked
                if (i != index) {
                  // Get the button
                  const otherBtn = th.querySelector('button');
                  // Not all th have buttons
                  if (otherBtn) {
                    otherBtn.classList.remove('sorted');
                    otherBtn.classList.remove('sorted--asc');
                    otherBtn.classList.remove('sorted--desc');
                  }
                }
              })
    
              sortRowsByIndex(table, index);
            }
            th.querySelector('.uol-index-table__th-inner').appendChild(sortButton);
          }
        })
    
        if (mobileSortableColumns.size > 0) {
    
          let selectSort = document.createElement('select');
          selectSort.classList.add('uol-index-table__sort-select');
          selectSort.setAttribute('aria-label', 'Sort table columns');
    
          let selectSortOptions = `<option value="">Sort by</option>`;
    
          mobileSortableColumns.forEach( (value, key) => {
            selectSortOptions += `
              <option data-sort_index="${key}" data-sort_dir="asc" value="${key}">${value} - ascending</option>
              <option data-sort_index="${key}" data-sort_dir="desc" value="${key}">${value} - descending</option>
            `;
          })
    
          selectSort.innerHTML = selectSortOptions;
    
          selectSort.addEventListener('change', (e) => {
            const selected = e.target.options[e.target.selectedIndex],
              selectedIndex = selected.dataset.sort_index,
              selectedDir = selected.dataset.sort_dir;
            ascending = (selectedDir == "asc") ? true: false;
            sortRowsByIndex(table, selectedIndex); 
          })
    
          // Insert select
          const thead = table.querySelector('thead');
          thead.parentNode.insertBefore(selectSort, thead);
        }
      })
    }
    
    export const uolTableSticky = () => {
      require('intersection-observer');
    
      const tHeads = document.querySelectorAll('.uol-index-table thead')
    
      tHeads.forEach( (thead) => {
    
        (new IntersectionObserver(function(e,options){
          if(e[0].intersectionRatio>0){
            thead.classList.remove('thead--stuck');
          } else {
            thead.classList.add('thead--stuck');
          };
        })).observe(thead);
      })
    }
    
  • URL: /components/raw/uol-index-table/index-table.module.js
  • Filesystem Path: src/library/02-components/index-table/index-table.module.js
  • Size: 6.3 KB
{
  "tables": [
    {
      "stackable": true,
      "caption": "Cheeses",
      "headings": [
        {
          "label": "Name"
        },
        {
          "label": "Description"
        },
        {
          "label": "Country of origin"
        },
        {
          "label": "Fat percentage"
        }
      ],
      "rows": [
        {
          "cells": [
            {
              "content": "Cheddar"
            },
            {
              "content": "Cheddar cheese is a relatively hard, off-white, sometimes sharp-tasting, natural cheese. Originating in the English village of Cheddar in Somerset, cheeses of this style are now produced beyond the region and in several countries around the world"
            },
            {
              "content": "UK"
            },
            {
              "type": "numeric",
              "content": "16%"
            }
          ]
        },
        {
          "cells": [
            {
              "content": "Brie"
            },
            {
              "content": "Brie is a soft cow's-milk cheese named after Brie, the French region from which it originated. It is pale in color with a slight grayish tinge under a rind of white mould. The rind is typically eaten, with its flavor depending largely upon the ingredients used and its manufacturing environment"
            },
            {
              "content": "France"
            },
            {
              "type": "numeric",
              "content": "2%"
            }
          ]
        },
        {
          "cells": [
            {
              "content": "Edam"
            },
            {
              "content": "Edam is a semi-hard cheese that originated in the Netherlands, and is named after the town of Edam in the province of North Holland. Edam is traditionally sold in rounded cylinders with a pale yellow interior and a coat, or rind, of red paraffin wax. Edam ages and travels well, and does not spoil; it only hardens"
            },
            {
              "content": "Netherlands"
            },
            {
              "type": "numeric",
              "content": "11%"
            }
          ]
        },
        {
          "cells": [
            {
              "content": "Manchego"
            },
            {
              "content": "Manchego is a cheese made in the La Mancha region of Spain from the milk of sheep of the Manchega breed. It is aged between 60 days and 2 years. Manchego has a firm and compact consistency and a buttery texture, and often contains small, unevenly distributed air pockets"
            },
            {
              "content": "Spain"
            },
            {
              "type": "numeric",
              "content": "25%"
            }
          ]
        },
        {
          "cells": [
            {
              "content": "Parmigiano-Reggiano"
            },
            {
              "content": "Parmigiano-Reggiano or Parmesan is an Italian hard, granular cheese that is produced from cow's milk and has aged 12-36 months."
            },
            {
              "content": "Italy"
            },
            {
              "type": "numeric",
              "content": "29.7%"
            }
          ]
        },
        {
          "cells": [
            {
              "content": "Cashel Blue"
            },
            {
              "content": "Cashel Blue is a hand-made, semi-soft, blue veined, medium-strength blue cheese with a creamy texture. Cashel Blue was the first Irish blue cheese, named after the Rock of Cashel overlooking the pastures close to the cheese farm of the family Grubb."
            },
            {
              "content": "Ireland"
            },
            {
              "type": "numeric",
              "content": "45%"
            }
          ]
        },
        {
          "cells": [
            {
              "content": "Stilton"
            },
            {
              "content": "Stilton is an English cheese, produced in two varieties: Blue, which has had Penicillium roqueforti added to generate a characteristic smell and taste, and White, which has not."
            },
            {
              "content": "Uk"
            },
            {
              "type": "numeric",
              "content": "35%"
            }
          ]
        },
        {
          "cells": [
            {
              "content": "Shropshire Blue"
            },
            {
              "content": "Shropshire Blue is a cow's milk cheese made in the United Kingdon"
            },
            {
              "content": "Uk"
            },
            {
              "type": "numeric",
              "content": "48%"
            }
          ]
        },
        {
          "cells": [
            {
              "content": "Wensleydale"
            },
            {
              "content": "Wensleydale is a style of cheese originally produced in Wensleydale, North Yorkshire, England, but now mostly made in large commercial creameries throughout the UK. The term \"Yorkshire Wensleydale\" can only be used for cheese that is made in Wensleydale"
            },
            {
              "content": "Uk"
            },
            {
              "type": "numeric",
              "content": "32%"
            }
          ]
        },
        {
          "cells": [
            {
              "content": "Cornish Yarg"
            },
            {
              "content": "Semi-hard cow's milk cheese made in Cornwall from the milk of Friesian cows. Before being left to mature, this cheese is wrapped in nettle leaves to form an edible, though mouldy, rind."
            },
            {
              "content": "Uk"
            },
            {
              "type": "numeric",
              "content": "30%"
            }
          ]
        },
        {
          "cells": [
            {
              "content": "Stinking Bishop"
            },
            {
              "content": "Award-winning, washed-rind cheese produced since 1994 by Charles Martell and Son at Hunts Court Farm, Dymock, Gloucestershire, in the south west of England."
            },
            {
              "content": "Uk"
            },
            {
              "type": "numeric",
              "content": "48%"
            }
          ]
        }
      ]
    }
  ]
}