Simplifying table js

This commit is contained in:
Jonathan Bobel
2025-04-09 11:38:36 -04:00
parent 6f6fd01ea2
commit 42ac6912b0
3 changed files with 76 additions and 134 deletions

View File

@@ -1,124 +1,36 @@
(function(Modules) {
"use strict";
(function () {
'use strict';
Modules.FullscreenTable = function() {
function initFullscreenTables() {
const tables = document.querySelectorAll('.fullscreen-table');
this.start = function(component) {
tables.forEach((component) => {
const table = component.querySelector('table');
const wrapper = component.querySelector('.table-wrapper');
const rightShadow = component.querySelector('.fullscreen-right-shadow');
this.$component = $(component);
this.$table = this.$component.find('table');
this.nativeHeight = this.$component.innerHeight() + 20; // 20px to allow room for scrollbar
this.topOffset = this.$component.offset().top;
if (!table || !wrapper) return;
this.insertShims();
this.maintainWidth();
this.maintainHeight();
this.toggleShadows();
const toggleShadows = () => {
const scrollLeft = wrapper.scrollLeft;
const maxScrollLeft = wrapper.scrollWidth - wrapper.clientWidth;
$(window)
.on('scroll resize', this.maintainHeight)
.on('resize', this.maintainWidth);
wrapper.classList.toggle('scrolled', scrollLeft > 0);
this.$scrollableTable
.on('scroll', this.toggleShadows)
.on('scroll', this.maintainHeight)
.on('focus blur', () => this.$component.toggleClass('js-focus-style'));
if (rightShadow) {
rightShadow.classList.toggle('visible', scrollLeft < maxScrollLeft);
}
};
if (
window.GOVUK.stickAtBottomWhenScrolling &&
window.GOVUK.stickAtBottomWhenScrolling.recalculate
) {
window.GOVUK.stickAtBottomWhenScrolling.recalculate();
}
wrapper.addEventListener('scroll', toggleShadows);
toggleShadows(); // init state
});
}
this.maintainWidth();
};
this.insertShims = () => {
const attributesForFocus = 'role aria-labelledby tabindex';
let captionId = this.$table.find('caption').text().toLowerCase().replace(/[^A-Za-z]+/g, '');
this.$table.find('caption').attr('id', captionId);
this.$table.wrap(`<div class="fullscreen-scrollable-table" role="region" aria-labelledby="${captionId}" tabindex="0"/>`);
this.$component
.append(
this.$component.find('.fullscreen-scrollable-table')
.clone()
.addClass('fullscreen-fixed-table')
.removeClass('fullscreen-scrollable-table')
.removeAttr(attributesForFocus)
.attr('aria-hidden', true)
.find('caption')
.removeAttr('id')
.closest('.fullscreen-fixed-table')
)
.append(
'<div class="fullscreen-right-shadow" />'
)
.after(
$("<div class='fullscreen-shim'/>").css({
'height': this.nativeHeight,
'top': this.topOffset
})
)
.css('position', 'absolute');
this.$scrollableTable = this.$component.find('.fullscreen-scrollable-table');
this.$fixedTable = this.$component.find('.fullscreen-fixed-table');
};
this.maintainHeight = () => {
let height = Math.min(
$(window).height() - this.topOffset + $(window).scrollTop(),
this.nativeHeight
);
this.$scrollableTable.outerHeight(height);
this.$fixedTable.outerHeight(height);
};
this.maintainWidth = () => {
let indexColumnWidth = this.$fixedTable.find('.table-field-index').outerWidth();
this.$scrollableTable
.css({
'width': this.$component.parent('main').width() - indexColumnWidth,
'margin-left': indexColumnWidth
});
this.$fixedTable
.width(indexColumnWidth + 4);
};
this.toggleShadows = () => {
this.$fixedTable
.toggleClass(
'fullscreen-scrolled-table',
this.$scrollableTable.scrollLeft() > 0
);
this.$component.find('.fullscreen-right-shadow')
.toggleClass(
'visible',
this.$scrollableTable.scrollLeft() < (this.$table.width() - this.$scrollableTable.width())
);
setTimeout(
() => this.$component.find('.fullscreen-right-shadow').addClass('with-transition'),
3000
);
};
};
})(window.GOVUK.Modules);
// Run once DOM is ready
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', initFullscreenTables);
} else {
initFullscreenTables();
}
})();

View File

@@ -174,8 +174,10 @@ h2.recipient-list {
}
.spreadsheet {
margin-bottom: units (1);
margin-bottom: units(1);
overflow-x: auto;
position: relative;
padding-left: 0;
.table {
margin-bottom: 0;
@@ -186,27 +188,54 @@ h2.recipient-list {
}
th,
.table-field-index {
background: color('gray-cool-10');
td {
padding-inline: 10px;
border: 1px solid color('gray-cool-10');
background: white;
z-index: 1;
}
td {
min-width: calc(194px - 11px);
&:first-child {
min-width: auto;
}
}
th.table-field-heading {
background: color('gray-cool-10');
font-weight: bold;
text-align: center;
}
th, td {
padding-left: 10px;
padding-right: 10px;
border: 1px solid color('gray-cool-10');
}
.table-field-index,
.table-field-heading-first {
position: sticky;
left: 0;
z-index: 10;
background: white;
td {
border-top: 0;
// 194 is the width of the table * 1/3.5, so the overflow cuts off
// at 3.5 columns wide.
// 11 accounts for the padding of the table cell
min-width: 194px - 11px;
&:first-child {
min-width: auto;
&::before {
content: "";
position: absolute;
top: 0;
left: 0;
height: 100%;
width: 0px;
z-index: 11;
outline: 1px solid color('gray-cool-10');
}
&::after {
content: "";
position: absolute;
top: 0;
right: 0;
height: 100%;
width: 1px;
background: color('gray-cool-10');
z-index: 11;
}
}

View File

@@ -5,6 +5,7 @@
{% from "components/table.html" import list_table, text_field, index_field, index_field_heading %}
{% from "components/components/back-link/macro.njk" import usaBackLink %}
<script type="text/javascript" src="{{ asset_url('js/setTimezone.js') }}"></script>
import { FullscreenTable } from './fullscreenTable.js';
{% block service_page_title %}
Upload a list of {{ 999|recipient_count_label(template.template_type) }}
@@ -30,7 +31,7 @@
<h2 class="font-body-lg">Your file needs to look like this example</h2>
<div class="spreadsheet" data-module="fullscreen-table">
<div class="spreadsheet table-wrapper" data-module="fullscreen-table">
{% call(item, row_number) list_table(
example,
caption="Example",