<div class="caps-table-component">

    <div class="caps-table--container">

        <table class="caps-table" data-first-ballot="70%" data-second-ballot="mini ballot" data-third-ballot="30%">
            <thead>
                <tr>
                    <th>
                        <p class="caps-table--title">Caps</p>
                        <p class="caps-table--sub-title">Number of caps earned since June 2022.</p>
                    </th>
                    <th>
                        <p class="caps-table--title">Total Members</p>
                        <p class="caps-table--sub-title">Total count of members who have earned this number of caps.</p>
                    </th>
                    <th>
                        <p class="caps-table--title">ESC Members</p>
                        <p class="caps-table--sub-title">Members who have earned this number of caps.</p>
                    </th>
                    <th>
                        <p class="caps-table--title">ESTC Members</p>
                        <p class="caps-table--sub-title">Travel Club members who have earned this number of caps.</p>
                    </th>
                    <th>
                        <p class="caps-table--title">Total Above</p>
                        <p class="caps-table--sub-title">Total of this caps level and above</p>
                    </th>
                </tr>
            </thead>
            <tbody>
                <tr class="empty-tr"></tr>
                <tr>
                    <th>34</th>
                    <td>809</td>
                    <td>3</td>
                    <td>806</td>
                    <td>0</td>
                </tr>
                <tr>
                    <th>33</th>
                    <td>809</td>
                    <td>3</td>
                    <td>806</td>
                    <td>2,00</td>
                </tr>
                <tr>
                    <th>32</th>
                    <td>809</td>
                    <td>3</td>
                    <td>806</td>
                    <td>3,00</td>
                </tr>
                <tr>
                    <th>31</th>
                    <td>809</td>
                    <td>3</td>
                    <td>806</td>
                    <td>4,00</td>
                </tr>
                <tr>
                    <th>30</th>
                    <td>809</td>
                    <td>3</td>
                    <td>806</td>
                    <td>5,00</td>
                </tr>
                <tr>
                    <th>29</th>
                    <td>809</td>
                    <td>3</td>
                    <td>806</td>
                    <td>6,00</td>
                </tr>
                <tr>
                    <th>34</th>
                    <td>809</td>
                    <td>3</td>
                    <td>806</td>
                    <td>7,00</td>
                </tr>
                <tr>
                    <th>34</th>
                    <td>809</td>
                    <td>3</td>
                    <td>806</td>
                    <td>8,00</td>
                </tr>
                <tr>
                    <th>34</th>
                    <td>809</td>
                    <td>3</td>
                    <td>806</td>
                    <td>9,00</td>
                </tr>
                <tr>
                    <th>34</th>
                    <td>809</td>
                    <td>3</td>
                    <td>806</td>
                    <td>1,000</td>
                </tr>
                <tr>
                    <th>34</th>
                    <td>809</td>
                    <td>3</td>
                    <td>806</td>
                    <td>1,100</td>
                </tr>
                <tr>
                    <th>34</th>
                    <td>809</td>
                    <td>3</td>
                    <td>806</td>
                    <td>1,200</td>
                </tr>
                <tr>
                    <th>34</th>
                    <td>809</td>
                    <td>3</td>
                    <td>806</td>
                    <td>1,300</td>
                </tr>
                <tr>
                    <th>34</th>
                    <td>809</td>
                    <td>3</td>
                    <td>806</td>
                    <td>1,400</td>
                </tr>
                <tr>
                    <th>34</th>
                    <td>809</td>
                    <td>3</td>
                    <td>806</td>
                    <td>1500</td>
                </tr>

            </tbody>

        </table>
    </div>

    <div class="enter-away-application">
        <p class="enter-away-application--title">Enter Away Allocation</p>
        <div class="enter-away-application--input-container">
            <input class="enter-away-application--input" type="number" min="0" inputmode="numeric" placeholder="Enter ticket allocation" />
            <img aria-describedby="tooltip" src="./../../../assets/example-content/info-icon.svg" class="info-tooltip" alt="info icon" />
            <div id="tooltip" role="tooltip" class="info-tooltip-text">Enter the total number of allocated tickets for
                an away fixture. We’ll calculate and highlight which cap levels are
                guaranteed to receive a ticket and which levels will be entered into a second ballot.
                <div id="arrow" data-popper-arrow></div>
            </div>
        </div>
    </div>
    <div class="caps-table-component__caption-container">
        <p>Special thanks to ESTC members <span class="members">Matt Isle</span> and <span class="members">David Lilley
            </span> for their valuable
            contributions and inspiration behind
            this
            enhanced caps table.</p>

        <p>This calculator is for illustrative purposes only. Actual chances of securing a ticket may vary based on
            final
            allocations and demand.</p>
    </div>
</div>

No notes defined.

{
  "application": {
    "title": "Enter Away Allocation",
    "placeholder": "Enter ticket allocation",
    "tooltip": "tool tip"
  },
  "th": {
    "first": {
      "title": "Caps",
      "sub-title": "Number of caps earned since June 2022."
    },
    "second": {
      "title": "Total Members",
      "sub-title": "Total count of members who have earned this number of caps."
    },
    "third": {
      "title": "ESC Members",
      "sub-title": "Members who have earned this number of caps."
    },
    "fourth": {
      "title": "ESTC Members",
      "sub-title": "Travel Club members who have earned this number of caps."
    },
    "sixth": {
      "title": "Total Above",
      "sub-title": "Total of this caps level and above"
    }
  },
  "tr": [
    {
      "guaranteed": "caps-table--guaranteed-rows",
      "tag": "caps-table--tag-guaranteed",
      "first": 34,
      "second": 809,
      "third": 3,
      "fourth": 806,
      "sixth": "0"
    },
    {
      "second-ballots": "caps-table--second-ballots",
      "tag": "caps-table--tag-second-ballot",
      "first": 33,
      "second": 809,
      "third": 3,
      "fourth": 806,
      "sixth": "2,00"
    },
    {
      "first": 32,
      "second": 809,
      "third": 3,
      "fourth": 806,
      "sixth": "3,00"
    },
    {
      "first": 31,
      "second": 809,
      "third": 3,
      "fourth": 806,
      "sixth": "4,00"
    },
    {
      "first": 30,
      "second": 809,
      "third": 3,
      "fourth": 806,
      "sixth": "5,00"
    },
    {
      "first": 29,
      "second": 809,
      "third": 3,
      "fourth": 806,
      "sixth": "6,00"
    },
    {
      "first": 34,
      "second": 809,
      "third": 3,
      "fourth": 806,
      "sixth": "7,00"
    },
    {
      "first": 34,
      "second": 809,
      "third": 3,
      "fourth": 806,
      "sixth": "8,00"
    },
    {
      "first": 34,
      "second": 809,
      "third": 3,
      "fourth": 806,
      "sixth": "9,00"
    },
    {
      "first": 34,
      "second": 809,
      "third": 3,
      "fourth": 806,
      "sixth": "1,000"
    },
    {
      "first": 34,
      "second": 809,
      "third": 3,
      "fourth": 806,
      "sixth": "1,100"
    },
    {
      "first": 34,
      "second": 809,
      "third": 3,
      "fourth": 806,
      "sixth": "1,200"
    },
    {
      "first": 34,
      "second": 809,
      "third": 3,
      "fourth": 806,
      "sixth": "1,300"
    },
    {
      "first": 34,
      "second": 809,
      "third": 3,
      "fourth": 806,
      "sixth": "1,400"
    },
    {
      "first": 34,
      "second": 809,
      "third": 3,
      "fourth": 806,
      "sixth": 1500
    }
  ]
}
  • Content:
    import floatingTooltip from '../floating-tooltip/floating-tooltip';
    
    const convertToNum = string => {
      const num = Number(string.replaceAll(/,/g, ''));
    
      return num;
    };
    
    export default (currentElement, capsOverview) => {
      const button = document.querySelector('.info-tooltip');
      const tooltip = document.querySelector('.info-tooltip-text');
    
      floatingTooltip(button, tooltip, {
        placement: 'right',
      });
      const resetHeighlight = row => {
        row.classList.remove('caps-table--guaranteed-rows');
        row.classList.remove('caps-table--second-ballots');
      };
    
      const myActiveAcp = (table, maycap) => {
        table.querySelectorAll('tr').forEach((row, index) => {
          if (index > 1) {
            const cell = row.cells[0].textContent;
    
            if (Number(cell) === Number(maycap)) {
              row.classList.add('caps-table--active-row');
            }
          }
        });
      };
    
      const removeTag = row => {
        const tagTds = row.querySelectorAll('.caps-table--tag');
    
        tagTds.forEach(td => td.remove());
      };
    
      const resetTable = table => {
        const rows = table.querySelectorAll('tr');
    
        rows.forEach(row => {
          resetHeighlight(row);
          removeTag(row);
        });
      };
    
      const addTag = (row, text) => {
        const cell = row.insertCell(5);
    
        cell.classList.add('caps-table--tag');
        cell.innerText = text;
      };
    
      const getGuranteedRows = (allocation, table, cutOff = 70) => {
        let guranteedIndex = [];
        const guranteedAllocation = Math.ceil((allocation * cutOff) / 100);
        const rows = table.querySelectorAll('tr');
    
        rows.forEach((element, index) => {
          if (index > 1) {
            const totalEstc =
              element.lastElementChild &&
              convertToNum(element.lastElementChild.innerText);
    
            if (totalEstc <= guranteedAllocation) {
              guranteedIndex = [...guranteedIndex, index];
            }
          }
        });
        return guranteedIndex;
      };
    
      const heighlightRows = (table, rowsIndexes, seventyPercentage) => {
        let miniBalletIndex = 2;
    
        const { firstBallot, secondBallot, thirdBallot } = table.dataset;
    
        if (rowsIndexes.length > 0) {
          addTag(table.rows[2], firstBallot);
          rowsIndexes.forEach(rIndex => {
            const row = table.rows[rIndex];
    
            row.classList.add('caps-table--guaranteed-rows');
          });
          if (
            seventyPercentage >
            convertToNum(
              table.rows[rowsIndexes[rowsIndexes.length - 1]].cells[4].innerText
            )
          ) {
            miniBalletIndex = rowsIndexes[rowsIndexes.length - 1] + 1;
          } else {
            miniBalletIndex = rowsIndexes[rowsIndexes.length - 1];
          }
        }
    
        if (miniBalletIndex !== rowsIndexes[rowsIndexes.length - 1]) {
          table.rows[miniBalletIndex].classList.add('caps-table--second-ballots');
          addTag(table.rows[miniBalletIndex], secondBallot);
        }
    
        addTag(table.rows[miniBalletIndex + 1], thirdBallot);
      };
    
      const [capsTable, allocationInput] = currentElement.querySelectorAll(
        '.caps-table--container .caps-table, .enter-away-application--input'
      );
    
      const mycapElement = capsOverview.querySelector('.profile-page-caps .number')
        .innerText;
    
      myActiveAcp(capsTable, mycapElement);
    
      allocationInput.addEventListener(
        'keydown',
        event => {
          if (
            ![
              'Backspace',
              'ArrowRight',
              'ArrowLeft',
              'Tab',
              'ArrowDown',
              'ArrowUp',
              'Delete',
              'End',
              '0',
              '1',
              '2',
              '3',
              '4',
              '5',
              '6',
              '7',
              '8',
              '9',
            ].includes(event.key)
          ) {
            event.preventDefault();
          }
        },
        false
      );
    
      allocationInput.addEventListener('keyup', event => {
        resetTable(capsTable);
    
        if (Number(event.target.value) > 0) {
          heighlightRows(
            capsTable,
            getGuranteedRows(event.target.value, capsTable, capsTable.dataSet),
            Math.ceil(event.target.value * 0.7)
          );
        }
      });
    };
    
  • URL: /components/raw/caps-table/caps-table.js
  • Filesystem Path: src/library/components/caps-table/caps-table.js
  • Size: 4 KB
  • Content:
    @mixin breakpoint($breakpoint) {
      @media screen and (max-width: $breakpoint) {
        @content;
      }
    }
    
    %typography {
      font-family: 'England FC', arial, helvetica, sans-serif;
      font-weight: 400;
    }
    
    .profile-page__body .profile-info-card:first-child {
      z-index: 4;
    }
    
    .caps-table--container {
      max-height: 70vh;
      overflow-y: scroll;
    
      @media screen and (max-width: 744px) {
        overflow: scroll;
      }
    
      @include breakpoint(744px) {
        overflow-x: scroll;
        width: 100%;
    
        thead {
          top: -1px;
    
          th {
            width: 115px !important;
          }
        }
      }
    }
    
    .caps-table-component {
      border: 1px solid $grey-light;
      border: 0;
      margin-top: -2px;
    
      .info-tooltip-text {
        font-weight: 400;
        font-size: 14px;
        line-height: 20px;
        letter-spacing: 0.32px;
        max-width: 223px;
        padding: 16px;
        font-family: 'FS Dillon', arial, helvetica, sans-serif;
      }
    
      &__caption-container {
        padding: 16px;
        background-color: white;
    
        p {
          text-align: center;
          font-family: 'FS Dillon', arial, helvetica, sans-serif;
          font-weight: 400;
          font-size: 14px;
          line-height: 20px;
          letter-spacing: 0.32px;
          color: $color-interface-light;
    
          &:not(:first-child) {
            margin-top: 16px;
          }
    
          .members {
            color: $crest-blue;
            text-decoration: underline;
          }
        }
      }
    
      @include breakpoint(744px) {
        border: 0;
    
        &__caption-container {
          display: none;
        }
      }
    }
    
    .caps-table {
      $column-width: calc(100% / 5);
    
      background-color: white;
      table-layout: fixed;
      width: 100%;
      text-align: center;
      font-family: 'Grot12 Normal', arial, helvetica, sans-serif;
      height: 100%;
      position: relative; // making it relative to float 70% flag absolute
    
      &--title {
        @extend %typography;
    
        font-size: 33px;
        line-height: 34px;
        letter-spacing: 0.16px;
        padding: 16px 0;
        padding-bottom: 8px;
        color: $blue-accent6;
      }
    
      &--sub-title {
        font-size: 14px;
        color: #5e7182;
        line-height: 20px;
        letter-spacing: 0.32px;
        font-weight: 400;
      }
    
      &--active-row {
        background-color: #dbf0ff;
      }
    
      &--guaranteed-rows {
        background-color: #d1fadf;
      }
    
      &--second-ballots {
        background-color: #ecfdf3;
      }
    
      thead {
        position: sticky;
        top: 0;
        background-color: white;
        z-index: 2;
    
        th {
          width: $column-width;
          padding: 8px;
        }
      }
    
      tbody {
        position: relative;
    
        th {
          font-weight: 700;
          border-right: 1px solid $grey;
        }
    
        th:not(.caps-table--tag),
        td {
          height: 55px;
          vertical-align: middle;
        }
    
        tr {
          color: $black;
          font-weight: 400;
          font-size: 16px;
          line-height: 24px;
          border-bottom: 1px solid $grey;
        }
    
        tr:first-child {
          height: 15px;
        }
    
        tr:has(td.caps-table--tag) {
          border-top: 2px solid $blue;
        }
      }
    
      &--tag {
        color: white;
        width: fit-content;
        font-family: $registration-font;
        font-weight: 700;
        line-height: 10px;
        letter-spacing: 0.32px;
        position: absolute;
        margin-left: 16px;
        max-height: 26px;
        margin-top: -13px;
        padding: 8px;
        padding-left: 26px;
        left: 0;
        background-color: $blue;
    
        &::before {
          content: '';
          background-image: url('./assets/example-content/keyboard_arrow_up_ballet.png');
          display: inline-block;
          background-repeat: no-repeat;
          background-size: contain;
          position: absolute;
          width: 10px;
          height: 10px;
          left: 8px;
          top: 10px;
        }
      }
    
      @include breakpoint(744px) {
        &-title {
          font-size: 24px;
        }
    
        &--sub-title {
          display: none;
        }
      }
    }
    
    .enter-away-application {
      display: flex;
      align-items: center;
      justify-content: center;
      border-top: 1px solid $grey;
      background-color: $grey-light;
      padding: 20px;
    
      &--title {
        @extend %typography;
    
        color: $blue;
        font-size: 40px;
        letter-spacing: 0.32px;
        line-height: 40px;
        margin-right: 24px;
      }
    
      &--input-container {
        display: flex;
        justify-content: start;
        align-items: center;
      }
    
      &--input {
        height: 48px;
        width: 240px;
        border: 1px solid $grey;
        font-family: 'Grot12 Normal', arial, helvetica, sans-serif;
        font-weight: 400;
        font-size: 18px;
        line-height: 40px;
        letter-spacing: -0.16px;
        margin-right: 8px;
        padding: 4px 16px;
    
        &:hover,
        &:focus {
          border-color: $blue-accent6;
          outline: none;
        }
    
        &--info {
          height: 24px;
          width: 24px;
        }
      }
    
      @include breakpoint(744px) {
        flex-direction: column;
        align-items: start;
        padding: 16px;
    
        &--title {
          font-size: 30px;
          line-height: 40px;
          margin-bottom: 8px;
        }
      }
    
      @media screen and (max-width: 370px) {
        &--input {
          width: 70%;
        }
      }
    }
    
  • URL: /components/raw/caps-table/caps-table.scss
  • Filesystem Path: src/library/components/caps-table/caps-table.scss
  • Size: 5.1 KB
<div class="caps-table-component">

    <div class="caps-table--container">

        <table class="caps-table" data-first-ballot="70%" data-second-ballot="mini ballot" data-third-ballot="30%">
            <thead>
                <tr>
                    <th>
                        <p class="caps-table--title">{{th.first.title}}</p>
                        <p class="caps-table--sub-title">{{th.first.sub-title}}</p>
                    </th>
                    <th>
                        <p class="caps-table--title">{{th.second.title}}</p>
                        <p class="caps-table--sub-title">{{th.second.sub-title}}</p>
                    </th>
                    <th>
                        <p class="caps-table--title">{{th.third.title}}</p>
                        <p class="caps-table--sub-title">{{th.third.sub-title}}</p>
                    </th>
                    <th>
                        <p class="caps-table--title">{{th.fourth.title}}</p>
                        <p class="caps-table--sub-title">{{th.fourth.sub-title}}</p>
                    </th>
                    <th>
                        <p class="caps-table--title">{{th.sixth.title}}</p>
                        <p class="caps-table--sub-title">{{th.sixth.sub-title}}</p>
                    </th>
                </tr>
            </thead>
            <tbody>
                <tr class="empty-tr"></tr>
                {{#each tr}}
                <tr>
                    <th>{{first}}</th>
                    <td>{{second}}</td>
                    <td>{{third}}</td>
                    <td>{{fourth}}</td>
                    <td>{{sixth}}</td>
                </tr>
                {{/each}}

            </tbody>

        </table>
    </div>

    <div class="enter-away-application">
        <p class="enter-away-application--title">{{application.title}}</p>
        <div class="enter-away-application--input-container">
            <input class="enter-away-application--input" type="number" min="0" inputmode="numeric"
                placeholder="{{application.placeholder}}" />
            <img aria-describedby="tooltip" src="./../../../assets/example-content/info-icon.svg" class="info-tooltip"
                alt="info icon" />
            <div id="tooltip" role="tooltip" class="info-tooltip-text">Enter the total number of allocated tickets for
                an away fixture. We’ll calculate and highlight which cap levels are
                guaranteed to receive a ticket and which levels will be entered into a second ballot.
                <div id="arrow" data-popper-arrow></div>
            </div>
        </div>
    </div>
    <div class="caps-table-component__caption-container">
        <p>Special thanks to ESTC members <span class="members">Matt Isle</span> and <span class="members">David Lilley
            </span> for their valuable
            contributions and inspiration behind
            this
            enhanced caps table.</p>

        <p>This calculator is for illustrative purposes only. Actual chances of securing a ticket may vary based on
            final
            allocations and demand.</p>
    </div>
</div>