<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
}
]
}
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)
);
}
});
};
@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%;
}
}
}
<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>