mirror of
https://github.com/GSA/notifications-admin.git
synced 2026-08-26 01:04:00 -04:00
Compare commits
10 Commits
ken_main
...
53034b7e89
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
53034b7e89 | ||
|
|
81d4fc0b8c | ||
|
|
0b441e36f1 | ||
|
|
1bf7e58445 | ||
|
|
487866d81c | ||
|
|
b71a941634 | ||
|
|
c599407850 | ||
|
|
42ac6912b0 | ||
|
|
6f6fd01ea2 | ||
|
|
9921809f90 |
@@ -1,29 +0,0 @@
|
|||||||
(function(Modules) {
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
let isSixDigitHex = value => value.match(/^#[0-9A-F]{6}$/i);
|
|
||||||
let colourOrWhite = value => isSixDigitHex(value) ? value : '#FFFFFF';
|
|
||||||
|
|
||||||
Modules.ColourPreview = function() {
|
|
||||||
|
|
||||||
this.start = component => {
|
|
||||||
|
|
||||||
this.$input = $(component);
|
|
||||||
|
|
||||||
this.$input.closest('.usa-form-group').append(
|
|
||||||
this.$preview = $('<span class="textbox-colour-preview"></span>')
|
|
||||||
);
|
|
||||||
|
|
||||||
this.$input
|
|
||||||
.on('input', this.update)
|
|
||||||
.trigger('input');
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
this.update = () => this.$preview.css(
|
|
||||||
'background', colourOrWhite(this.$input.val())
|
|
||||||
);
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
})(window.GOVUK.Modules);
|
|
||||||
@@ -1,124 +1,41 @@
|
|||||||
(function(Modules) {
|
(function () {
|
||||||
"use strict";
|
'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);
|
if (!table || !wrapper) return;
|
||||||
this.$table = this.$component.find('table');
|
|
||||||
this.nativeHeight = this.$component.innerHeight() + 20; // 20px to allow room for scrollbar
|
|
||||||
this.topOffset = this.$component.offset().top;
|
|
||||||
|
|
||||||
this.insertShims();
|
const toggleShadows = () => {
|
||||||
this.maintainWidth();
|
const scrollLeft = wrapper.scrollLeft;
|
||||||
this.maintainHeight();
|
const maxScrollLeft = wrapper.scrollWidth - wrapper.clientWidth;
|
||||||
this.toggleShadows();
|
|
||||||
|
|
||||||
$(window)
|
wrapper.classList.toggle('scrolled', scrollLeft > 0);
|
||||||
.on('scroll resize', this.maintainHeight)
|
|
||||||
.on('resize', this.maintainWidth);
|
|
||||||
|
|
||||||
this.$scrollableTable
|
if (rightShadow) {
|
||||||
.on('scroll', this.toggleShadows)
|
rightShadow.classList.toggle('visible', scrollLeft < maxScrollLeft);
|
||||||
.on('scroll', this.maintainHeight)
|
}
|
||||||
.on('focus blur', () => this.$component.toggleClass('js-focus-style'));
|
};
|
||||||
|
|
||||||
if (
|
wrapper.addEventListener('scroll', toggleShadows);
|
||||||
window.GOVUK.stickAtBottomWhenScrolling &&
|
toggleShadows(); // init state
|
||||||
window.GOVUK.stickAtBottomWhenScrolling.recalculate
|
});
|
||||||
) {
|
}
|
||||||
window.GOVUK.stickAtBottomWhenScrolling.recalculate();
|
|
||||||
}
|
|
||||||
|
|
||||||
this.maintainWidth();
|
// Auto-init on page load in browser
|
||||||
|
if (document.readyState === 'loading') {
|
||||||
|
document.addEventListener('DOMContentLoaded', initFullscreenTables);
|
||||||
|
} else {
|
||||||
|
initFullscreenTables();
|
||||||
|
}
|
||||||
|
|
||||||
};
|
// Expose it globally in test environments
|
||||||
|
if (typeof window !== 'undefined') {
|
||||||
this.insertShims = () => {
|
window.initFullscreenTables = initFullscreenTables;
|
||||||
|
}
|
||||||
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);
|
|
||||||
|
|||||||
@@ -1,24 +0,0 @@
|
|||||||
(function(window) {
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
window.GOVUK.Modules.Homepage = function() {
|
|
||||||
|
|
||||||
this.start = function(component) {
|
|
||||||
|
|
||||||
let $component = $(component);
|
|
||||||
let iterations = 0;
|
|
||||||
let timeout = null;
|
|
||||||
|
|
||||||
$component.on('click', () => {
|
|
||||||
if (++iterations == 5) {
|
|
||||||
$component.toggleClass('product-page-intro-wrapper--alternative');
|
|
||||||
}
|
|
||||||
clearTimeout(timeout);
|
|
||||||
timeout = setTimeout(() => iterations = 0, 1500);
|
|
||||||
});
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
})(window);
|
|
||||||
@@ -1,27 +1,38 @@
|
|||||||
window.GOVUK.Frontend.initAll();
|
// Initialize GOV.UK Frontend components (modern init)
|
||||||
|
window.GOVUKFrontend.initAll();
|
||||||
$(() => $("time.timeago").timeago());
|
|
||||||
|
|
||||||
var showHideContent = new GOVUK.ShowHideContent();
|
var showHideContent = new GOVUK.ShowHideContent();
|
||||||
showHideContent.init();
|
showHideContent.init();
|
||||||
|
|
||||||
$(() => GOVUK.modules.start());
|
document.addEventListener('DOMContentLoaded', () => {
|
||||||
|
// Autofocus the first error input
|
||||||
$(() => $('.error-message, .usa-error-message').eq(0).parent('label').next('input').trigger('focus'));
|
const errorEl = document.querySelector('.error-message, .usa-error-message');
|
||||||
|
if (errorEl) {
|
||||||
$(() => $('.govuk-header__container').on('click', function() {
|
const label = errorEl.closest('label');
|
||||||
$(this).css('border-color', '#005ea5');
|
if (label) {
|
||||||
}));
|
const input = label.nextElementSibling;
|
||||||
|
if (input && input.focus) {
|
||||||
// Applies our expanded focus style to the siblings of links when that link is wrapped in a heading.
|
input.focus();
|
||||||
//
|
}
|
||||||
// This will be possible in CSS in the future, using the :has pseudo-class. When :has is available
|
}
|
||||||
// in the browsers we support, this code can be replaced with a CSS-only solution.
|
|
||||||
$('.js-mark-focus-on-parent').on('focus blur', '*', e => {
|
|
||||||
$target = $(e.target);
|
|
||||||
if (e.type === 'focusin') {
|
|
||||||
$target.parent().addClass('js-child-has-focus');
|
|
||||||
} else {
|
|
||||||
$target.parent().removeClass('js-child-has-focus');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Optional: highlight header on click
|
||||||
|
const header = document.querySelector('.govuk-header__container');
|
||||||
|
if (header) {
|
||||||
|
header.addEventListener('click', () => {
|
||||||
|
header.style.borderColor = '#005ea5';
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Focus styling for heading-wrapped links
|
||||||
|
const containers = document.querySelectorAll('.js-mark-focus-on-parent');
|
||||||
|
containers.forEach(container => {
|
||||||
|
container.addEventListener('focusin', e => {
|
||||||
|
e.target.parentElement.classList.add('js-child-has-focus');
|
||||||
|
});
|
||||||
|
container.addEventListener('focusout', e => {
|
||||||
|
e.target.parentElement.classList.remove('js-child-has-focus');
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -174,8 +174,10 @@ h2.recipient-list {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.spreadsheet {
|
.spreadsheet {
|
||||||
|
margin-bottom: units(1);
|
||||||
margin-bottom: units (1);
|
overflow-x: auto;
|
||||||
|
position: relative;
|
||||||
|
padding-left: 0;
|
||||||
|
|
||||||
.table {
|
.table {
|
||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
@@ -186,27 +188,56 @@ h2.recipient-list {
|
|||||||
}
|
}
|
||||||
|
|
||||||
th,
|
th,
|
||||||
.table-field-index {
|
td {
|
||||||
background: color('gray-cool-10');
|
padding-inline: 10px;
|
||||||
border: 1px solid color('gray-cool-10');
|
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;
|
font-weight: bold;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
th, td {
|
.table-field-index,
|
||||||
padding-left: 10px;
|
.table-field-heading-first {
|
||||||
padding-right: 10px;
|
position: sticky;
|
||||||
border: 1px solid color('gray-cool-10');
|
left: 0;
|
||||||
}
|
z-index: 10;
|
||||||
|
background: white;
|
||||||
|
text-align: center;
|
||||||
|
width: units(2);
|
||||||
|
|
||||||
td {
|
&::before {
|
||||||
border-top: 0;
|
content: "";
|
||||||
// 194 is the width of the table * 1/3.5, so the overflow cuts off
|
position: absolute;
|
||||||
// at 3.5 columns wide.
|
top: 0;
|
||||||
// 11 accounts for the padding of the table cell
|
left: 0;
|
||||||
min-width: 194px - 11px;
|
height: 100%;
|
||||||
&:first-child {
|
width: 0px;
|
||||||
min-width: auto;
|
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -722,7 +722,6 @@ details form {
|
|||||||
.placeholder,
|
.placeholder,
|
||||||
.placeholder-conditional {
|
.placeholder-conditional {
|
||||||
background-color: #face00;
|
background-color: #face00;
|
||||||
border: 1px solid #face00;
|
|
||||||
border-radius: 7px;
|
border-radius: 7px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -57,7 +57,7 @@
|
|||||||
{{notification.key_name}}
|
{{notification.key_name}}
|
||||||
</span>
|
</span>
|
||||||
<span class="grid-col-6 api-notifications-item__meta-time">
|
<span class="grid-col-6 api-notifications-item__meta-time">
|
||||||
<time class="timeago" datetime="{{ notification.created_at }}">
|
<time datetime="{{ notification.created_at }}">
|
||||||
{{ notification.created_at|format_delta }}
|
{{ notification.created_at|format_delta }}
|
||||||
</time>
|
</time>
|
||||||
</span>
|
</span>
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{% extends "withnav_template.html" %}
|
{% extends "withnav_template.html" %}
|
||||||
{% from "components/banner.html" import banner_wrapper %}
|
{% from "components/banner.html" import banner_wrapper %}
|
||||||
{% from "components/radios.html" import radio_select %}
|
{% from "components/radios.html" import radio_select %}
|
||||||
{% from "components/table.html" import list_table, field, text_field, index_field, hidden_field_heading %}
|
{% from "components/table.html" import list_table, field, text_field, index_field, index_field_heading %}
|
||||||
{% from "components/file-upload.html" import file_upload %}
|
{% from "components/file-upload.html" import file_upload %}
|
||||||
{% from "components/components/back-link/macro.njk" import usaBackLink %}
|
{% from "components/components/back-link/macro.njk" import usaBackLink %}
|
||||||
|
|
||||||
@@ -161,18 +161,15 @@ recipients.column_headers %}
|
|||||||
|
|
||||||
<h2 class="font-body-lg" id="file-preview">{{ original_file_name }}</h2>
|
<h2 class="font-body-lg" id="file-preview">{{ original_file_name }}</h2>
|
||||||
|
|
||||||
<div class="fullscreen-content" data-module="fullscreen-table">
|
<div class="table-wrapper spreadsheet" data-module="fullscreen-table">
|
||||||
{% call(item, row_number) list_table(
|
{% call(item, row_number) list_table(
|
||||||
recipients.displayed_rows,
|
recipients.displayed_rows,
|
||||||
caption=original_file_name,
|
caption=original_file_name,
|
||||||
caption_visible=False,
|
caption_visible=False,
|
||||||
field_headings=[
|
field_headings=[''] + column_headers )%}
|
||||||
'<span class="usa-sr-only">Row in file</span><span aria-hidden="true">1</span>'|safe
|
|
||||||
] + column_headers
|
|
||||||
) %}
|
|
||||||
{% call index_field() %}
|
{% call index_field() %}
|
||||||
<span>
|
<span>
|
||||||
{% set displayed_index = item.index + 2 %}
|
{% set displayed_index = item.index + 1 %}
|
||||||
{{ displayed_index }}
|
{{ displayed_index }}
|
||||||
</span>
|
</span>
|
||||||
{% endcall %}
|
{% endcall %}
|
||||||
|
|||||||
@@ -55,7 +55,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="fullscreen-content" data-module="fullscreen-table">
|
<div class="table-wrapper spreadsheet" data-module="fullscreen-table">
|
||||||
{% call(item, row_number) mapping_table(
|
{% call(item, row_number) mapping_table(
|
||||||
caption="Errors in " + original_file_name,
|
caption="Errors in " + original_file_name,
|
||||||
caption_visible=False,
|
caption_visible=False,
|
||||||
|
|||||||
@@ -60,7 +60,7 @@
|
|||||||
<p class="hint">This person has never logged in</p>
|
<p class="hint">This person has never logged in</p>
|
||||||
{% else %}
|
{% else %}
|
||||||
<p>Last logged in
|
<p>Last logged in
|
||||||
<time class="timeago" datetime="{{ user.logged_in_at }}">
|
<time datetime="{{ user.logged_in_at }}">
|
||||||
{{ user.logged_in_at|format_delta }}
|
{{ user.logged_in_at|format_delta }}
|
||||||
</time>
|
</time>
|
||||||
</p>
|
</p>
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
{% from "components/table.html" import list_table, text_field, index_field, index_field_heading %}
|
{% from "components/table.html" import list_table, text_field, index_field, index_field_heading %}
|
||||||
{% from "components/components/back-link/macro.njk" import usaBackLink %}
|
{% from "components/components/back-link/macro.njk" import usaBackLink %}
|
||||||
<script type="text/javascript" src="{{ asset_url('js/setTimezone.js') }}"></script>
|
<script type="text/javascript" src="{{ asset_url('js/setTimezone.js') }}"></script>
|
||||||
|
import { FullscreenTable } from './fullscreenTable.js';
|
||||||
|
|
||||||
{% block service_page_title %}
|
{% block service_page_title %}
|
||||||
Upload your bulk-sending spreadsheet
|
Upload your bulk-sending spreadsheet
|
||||||
@@ -71,7 +72,7 @@
|
|||||||
|
|
||||||
<h2 class="font-body-lg">A spreadsheet is available to use</h2>
|
<h2 class="font-body-lg">A spreadsheet is available to use</h2>
|
||||||
|
|
||||||
<div class="spreadsheet" data-module="fullscreen-table">
|
<div class="table-wrapper spreadsheet" data-module="fullscreen-table">
|
||||||
{% call(item, row_number) list_table(
|
{% call(item, row_number) list_table(
|
||||||
example,
|
example,
|
||||||
caption="Example",
|
caption="Example",
|
||||||
|
|||||||
@@ -47,7 +47,6 @@ const javascripts = () => {
|
|||||||
paths.npm + 'hogan.js/dist/hogan-3.0.2.js',
|
paths.npm + 'hogan.js/dist/hogan-3.0.2.js',
|
||||||
paths.npm + 'jquery/dist/jquery.min.js',
|
paths.npm + 'jquery/dist/jquery.min.js',
|
||||||
paths.npm + 'query-command-supported/dist/queryCommandSupported.min.js',
|
paths.npm + 'query-command-supported/dist/queryCommandSupported.min.js',
|
||||||
paths.npm + 'timeago/jquery.timeago.js',
|
|
||||||
paths.npm + 'textarea-caret/index.js',
|
paths.npm + 'textarea-caret/index.js',
|
||||||
paths.npm + 'cbor-js/cbor.js',
|
paths.npm + 'cbor-js/cbor.js',
|
||||||
paths.npm + 'd3/dist/d3.min.js',
|
paths.npm + 'd3/dist/d3.min.js',
|
||||||
@@ -68,13 +67,11 @@ const javascripts = () => {
|
|||||||
paths.src + 'javascripts/errorTracking.js',
|
paths.src + 'javascripts/errorTracking.js',
|
||||||
paths.src + 'javascripts/preventDuplicateFormSubmissions.js',
|
paths.src + 'javascripts/preventDuplicateFormSubmissions.js',
|
||||||
paths.src + 'javascripts/fullscreenTable.js',
|
paths.src + 'javascripts/fullscreenTable.js',
|
||||||
paths.src + 'javascripts/colourPreview.js',
|
|
||||||
paths.src + 'javascripts/templateFolderForm.js',
|
paths.src + 'javascripts/templateFolderForm.js',
|
||||||
paths.src + 'javascripts/collapsibleCheckboxes.js',
|
paths.src + 'javascripts/collapsibleCheckboxes.js',
|
||||||
paths.src + 'javascripts/radioSlider.js',
|
paths.src + 'javascripts/radioSlider.js',
|
||||||
paths.src + 'javascripts/updateStatus.js',
|
paths.src + 'javascripts/updateStatus.js',
|
||||||
paths.src + 'javascripts/errorBanner.js',
|
paths.src + 'javascripts/errorBanner.js',
|
||||||
paths.src + 'javascripts/homepage.js',
|
|
||||||
paths.src + 'javascripts/timeoutPopup.js',
|
paths.src + 'javascripts/timeoutPopup.js',
|
||||||
paths.src + 'javascripts/date.js',
|
paths.src + 'javascripts/date.js',
|
||||||
paths.src + 'javascripts/loginAlert.js',
|
paths.src + 'javascripts/loginAlert.js',
|
||||||
|
|||||||
9
package-lock.json
generated
9
package-lock.json
generated
@@ -26,7 +26,6 @@
|
|||||||
"query-command-supported": "1.0.0",
|
"query-command-supported": "1.0.0",
|
||||||
"sass-embedded": "^1.86.3",
|
"sass-embedded": "^1.86.3",
|
||||||
"textarea-caret": "3.1.0",
|
"textarea-caret": "3.1.0",
|
||||||
"timeago": "1.6.7",
|
|
||||||
"vinyl-buffer": "^1.0.1",
|
"vinyl-buffer": "^1.0.1",
|
||||||
"vinyl-source-stream": "^2.0.0"
|
"vinyl-source-stream": "^2.0.0"
|
||||||
},
|
},
|
||||||
@@ -12680,14 +12679,6 @@
|
|||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/timeago": {
|
|
||||||
"version": "1.6.7",
|
|
||||||
"resolved": "https://registry.npmjs.org/timeago/-/timeago-1.6.7.tgz",
|
|
||||||
"integrity": "sha512-FikcjN98+ij0siKH4VO4dZ358PR3oDDq4Vdl1+sN9gWz1/+JXGr3uZbUShYH/hL7bMhcTpPbplJU5Tej4b4jbQ==",
|
|
||||||
"dependencies": {
|
|
||||||
"jquery": ">=1.5.0 <4.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/tmpl": {
|
"node_modules/tmpl": {
|
||||||
"version": "1.0.5",
|
"version": "1.0.5",
|
||||||
"resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz",
|
"resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz",
|
||||||
|
|||||||
@@ -42,7 +42,6 @@
|
|||||||
"query-command-supported": "1.0.0",
|
"query-command-supported": "1.0.0",
|
||||||
"sass-embedded": "^1.86.3",
|
"sass-embedded": "^1.86.3",
|
||||||
"textarea-caret": "3.1.0",
|
"textarea-caret": "3.1.0",
|
||||||
"timeago": "1.6.7",
|
|
||||||
"vinyl-buffer": "^1.0.1",
|
"vinyl-buffer": "^1.0.1",
|
||||||
"vinyl-source-stream": "^2.0.0"
|
"vinyl-source-stream": "^2.0.0"
|
||||||
},
|
},
|
||||||
|
|||||||
2
poetry.lock
generated
2
poetry.lock
generated
@@ -18,7 +18,6 @@ version = "5.0.1"
|
|||||||
description = "Timeout context manager for asyncio programs"
|
description = "Timeout context manager for asyncio programs"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.8"
|
python-versions = ">=3.8"
|
||||||
groups = ["main"]
|
|
||||||
files = [
|
files = [
|
||||||
{file = "async_timeout-5.0.1-py3-none-any.whl", hash = "sha256:39e3809566ff85354557ec2398b55e096c8364bacac9405a7a1fa429e77fe76c"},
|
{file = "async_timeout-5.0.1-py3-none-any.whl", hash = "sha256:39e3809566ff85354557ec2398b55e096c8364bacac9405a7a1fa429e77fe76c"},
|
||||||
{file = "async_timeout-5.0.1.tar.gz", hash = "sha256:d9321a7a3d5a6a5e187e824d2fa0793ce379a202935782d555d6e9d2735677d3"},
|
{file = "async_timeout-5.0.1.tar.gz", hash = "sha256:d9321a7a3d5a6a5e187e824d2fa0793ce379a202935782d555d6e9d2735677d3"},
|
||||||
@@ -1551,7 +1550,6 @@ version = "3.0.2"
|
|||||||
description = "Safely add untrusted strings to HTML/XML markup."
|
description = "Safely add untrusted strings to HTML/XML markup."
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.9"
|
python-versions = ">=3.9"
|
||||||
groups = ["main", "dev"]
|
|
||||||
files = [
|
files = [
|
||||||
{file = "MarkupSafe-3.0.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:7e94c425039cde14257288fd61dcfb01963e658efbc0ff54f5306b06054700f8"},
|
{file = "MarkupSafe-3.0.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:7e94c425039cde14257288fd61dcfb01963e658efbc0ff54f5306b06054700f8"},
|
||||||
{file = "MarkupSafe-3.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9e2d922824181480953426608b81967de705c3cef4d1af983af849d7bd619158"},
|
{file = "MarkupSafe-3.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9e2d922824181480953426608b81967de705c3cef4d1af983af849d7bd619158"},
|
||||||
|
|||||||
@@ -18,6 +18,12 @@ Object.defineProperty(HTMLElement.prototype, 'clientWidth', {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// beforeAll hook to set up the DOM and load D3.js script
|
// beforeAll hook to set up the DOM and load D3.js script
|
||||||
|
beforeAll(() => {
|
||||||
|
jest.spyOn(Intl, 'DateTimeFormat').mockImplementation(() => ({
|
||||||
|
resolvedOptions: () => ({ timeZone: 'UTC' })
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
|
||||||
beforeAll(done => {
|
beforeAll(done => {
|
||||||
// Set up the DOM with the D3 script included
|
// Set up the DOM with the D3 script included
|
||||||
document.body.innerHTML = `
|
document.body.innerHTML = `
|
||||||
|
|||||||
@@ -1,139 +0,0 @@
|
|||||||
const helpers = require('./support/helpers.js');
|
|
||||||
|
|
||||||
beforeAll(() => {
|
|
||||||
require('../../app/assets/javascripts/colourPreview.js');
|
|
||||||
});
|
|
||||||
|
|
||||||
afterAll(() => {
|
|
||||||
require('./support/teardown.js');
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('Colour preview', () => {
|
|
||||||
|
|
||||||
let field;
|
|
||||||
let textbox;
|
|
||||||
let swatchEl;
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
|
|
||||||
// set up DOM
|
|
||||||
document.body.innerHTML = `
|
|
||||||
<div class="usa-form-group">
|
|
||||||
<label class="govuk-form-label" for="colour">
|
|
||||||
Colour
|
|
||||||
</label>
|
|
||||||
<input class="govuk-input govuk-input--width-6" id="colour" name="colour" rows="8" type="text" value="" data-module="colour-preview">
|
|
||||||
</div>`;
|
|
||||||
|
|
||||||
field = document.querySelector('.usa-form-group');
|
|
||||||
textbox = document.querySelector('input[type=text]');
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
afterEach(() => {
|
|
||||||
|
|
||||||
document.body.innerHTML = '';
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
describe("When the page loads", () => {
|
|
||||||
|
|
||||||
test("It should add a swatch element for the preview", () => {
|
|
||||||
|
|
||||||
// start the module
|
|
||||||
window.GOVUK.modules.start();
|
|
||||||
|
|
||||||
swatchEl = document.querySelector('.textbox-colour-preview');
|
|
||||||
|
|
||||||
expect(swatchEl).not.toBeNull();
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
test("If the textbox is empty it should make the swatch white", () => {
|
|
||||||
|
|
||||||
// start the module
|
|
||||||
window.GOVUK.modules.start();
|
|
||||||
|
|
||||||
swatchEl = document.querySelector('.textbox-colour-preview');
|
|
||||||
|
|
||||||
// textbox defaults to empty
|
|
||||||
// colours are output in RGB
|
|
||||||
expect(swatchEl.style.background).toEqual('rgb(255, 255, 255)');
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
test("If the textbox has a value which is a hex code it should add that colour to the swatch", () => {
|
|
||||||
|
|
||||||
textbox.setAttribute('value', '#00FF00');
|
|
||||||
|
|
||||||
// start the module
|
|
||||||
window.GOVUK.modules.start();
|
|
||||||
|
|
||||||
swatchEl = document.querySelector('.textbox-colour-preview');
|
|
||||||
|
|
||||||
// colours are output in RGB
|
|
||||||
expect(swatchEl.style.background).toEqual('rgb(0, 255, 0)');
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
test("If the textbox has a value which isn't a hex code it should make the swatch white", () => {
|
|
||||||
|
|
||||||
textbox.setAttribute('value', 'green');
|
|
||||||
|
|
||||||
// start the module
|
|
||||||
window.GOVUK.modules.start();
|
|
||||||
|
|
||||||
swatchEl = document.querySelector('.textbox-colour-preview');
|
|
||||||
|
|
||||||
// colours are output in RGB
|
|
||||||
expect(swatchEl.style.background).toEqual('rgb(255, 255, 255)');
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
describe("When input is added to the textbox", () => {
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
|
|
||||||
// start the module
|
|
||||||
window.GOVUK.modules.start();
|
|
||||||
|
|
||||||
swatchEl = document.querySelector('.textbox-colour-preview');
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
test("If the textbox is empty it should make the swatch white", () => {
|
|
||||||
|
|
||||||
helpers.triggerEvent(document.querySelector('input[type=text]'), 'input');
|
|
||||||
|
|
||||||
// textbox defaults to empty
|
|
||||||
expect(swatchEl.style.background).toEqual('rgb(255, 255, 255)');
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
test("If the textbox has a value which is a hex code it should add that colour to the swatch", () => {
|
|
||||||
|
|
||||||
textbox.setAttribute('value', '#00FF00');
|
|
||||||
|
|
||||||
helpers.triggerEvent(document.querySelector('input[type=text]'), 'input');
|
|
||||||
|
|
||||||
// textbox defaults to empty
|
|
||||||
expect(swatchEl.style.background).toEqual('rgb(0, 255, 0)');
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
test("If the textbox has a value which isn't a hex code it should make the swatch white", () => {
|
|
||||||
|
|
||||||
textbox.setAttribute('value', 'green');
|
|
||||||
|
|
||||||
helpers.triggerEvent(document.querySelector('input[type=text]'), 'input');
|
|
||||||
|
|
||||||
// textbox defaults to empty
|
|
||||||
expect(swatchEl.style.background).toEqual('rgb(255, 255, 255)');
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
||||||
@@ -1,370 +1,88 @@
|
|||||||
const helpers = require('./support/helpers');
|
require('../../app/assets/javascripts/fullscreenTable.js');
|
||||||
|
|
||||||
beforeAll(() => {
|
describe('fullscreenTable', () => {
|
||||||
// TODO: remove this when tests for sticky JS are written
|
let wrapper, rightShadow;
|
||||||
require('../../app/assets/javascripts/stick-to-window-when-scrolling.js');
|
|
||||||
|
|
||||||
require('../../app/assets/javascripts/fullscreenTable.js');
|
const setupDOM = (scrollLeft = 0, scrollWidth = 1000, clientWidth = 500) => {
|
||||||
});
|
document.body.innerHTML = `
|
||||||
|
<div class="fullscreen-table">
|
||||||
afterAll(() => {
|
<div class="table-wrapper" style="overflow-x: scroll;">
|
||||||
require('./support/teardown.js');
|
<table>
|
||||||
});
|
<tr><td>Test</td></tr>
|
||||||
|
|
||||||
describe('FullscreenTable', () => {
|
|
||||||
let screenMock;
|
|
||||||
let container;
|
|
||||||
let tableFrame;
|
|
||||||
let table;
|
|
||||||
let numberColumnFrame;
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
|
|
||||||
const tableHeadings = () => {
|
|
||||||
let result = '';
|
|
||||||
const headings = ['1', 'name', 'email address', 'age', 'building number', 'address line 1', 'address line 2', 'postcode'];
|
|
||||||
|
|
||||||
headings.forEach((heading, idx) => {
|
|
||||||
if (idx === 0) {
|
|
||||||
result += `<th scope="col" class="table-field-heading-first">
|
|
||||||
<span class="visually-hidden">Row in file</span><span aria-hidden="true" class="table-field-invisible-error">${heading}</span>
|
|
||||||
</th>`;
|
|
||||||
} else {
|
|
||||||
result += `<th scope="col" class="table-field-heading">
|
|
||||||
${heading}
|
|
||||||
</th>`;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
const rowCells = (cells) => {
|
|
||||||
let result = '';
|
|
||||||
|
|
||||||
Object.keys(cells).forEach((key, idx) => {
|
|
||||||
if (idx === 0) {
|
|
||||||
result += `<td class="table-field-index">
|
|
||||||
<span class="table-field-error">
|
|
||||||
${key}
|
|
||||||
</span>
|
|
||||||
</td>`;
|
|
||||||
} else {
|
|
||||||
result += `<td class="table-field-left-aligned ">
|
|
||||||
<div class="table-field-status-default">
|
|
||||||
${key}
|
|
||||||
</div>
|
|
||||||
</td>`;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return result;
|
|
||||||
};
|
|
||||||
|
|
||||||
const tableRows = () => {
|
|
||||||
let result = '';
|
|
||||||
|
|
||||||
const rows = [
|
|
||||||
['John Logie Baird', 'johnlbaird@gmail.com', '37', '22', 'Frith Street', 'Soho, London', 'W1D 4RF'],
|
|
||||||
['Guglielmo Marconi', 'gmarconi@hotmail.com', '21', 'Pontecchio Marconi', 'Via Celestini 1', 'Bologna', ''],
|
|
||||||
['Louis Braille', 'louisbraille@yahoo.co.uk', '', '56', 'Boulevard des Invalides', 'Paris', '75007'],
|
|
||||||
['Ray Tomlinson', 'hedy.lamarr@msn.com', '25', '870', '870 Winter Street', 'Waltham', 'MA 02451']
|
|
||||||
];
|
|
||||||
|
|
||||||
rows.forEach(row => {
|
|
||||||
result += `<tr class="table-row">${rowCells(row)}</tr>`;
|
|
||||||
});
|
|
||||||
|
|
||||||
return result;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
screenMock = new helpers.ScreenMock(jest);
|
|
||||||
screenMock.setWindow({
|
|
||||||
width: 1990,
|
|
||||||
height: 940,
|
|
||||||
scrollTop: 0
|
|
||||||
});
|
|
||||||
|
|
||||||
// set up DOM
|
|
||||||
document.body.innerHTML =
|
|
||||||
`<main>
|
|
||||||
<div class="fullscreen-content" data-module="fullscreen-table">
|
|
||||||
<table class="table table-font-xsmall">
|
|
||||||
<caption class="heading-medium table-heading visuallyhidden">
|
|
||||||
people.csv
|
|
||||||
</caption>
|
|
||||||
<thead class="table-field-headings-visible">
|
|
||||||
<tr>
|
|
||||||
${tableHeadings()}
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
${tableRows()}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
</main>`;
|
<div class="fullscreen-right-shadow"></div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
|
||||||
container = document.querySelector('.fullscreen-content');
|
wrapper = document.querySelector('.table-wrapper');
|
||||||
|
rightShadow = document.querySelector('.fullscreen-right-shadow');
|
||||||
|
|
||||||
});
|
// Mock scroll values
|
||||||
|
Object.defineProperty(wrapper, 'scrollLeft', {
|
||||||
|
get: () => scrollLeft,
|
||||||
|
configurable: true
|
||||||
|
});
|
||||||
|
Object.defineProperty(wrapper, 'scrollWidth', {
|
||||||
|
get: () => scrollWidth,
|
||||||
|
configurable: true
|
||||||
|
});
|
||||||
|
Object.defineProperty(wrapper, 'clientWidth', {
|
||||||
|
get: () => clientWidth,
|
||||||
|
configurable: true
|
||||||
|
});
|
||||||
|
|
||||||
|
// 👇 Now that DOM is ready, initialize the logic
|
||||||
|
window.initFullscreenTables();
|
||||||
|
|
||||||
|
// Force trigger scroll event if needed
|
||||||
|
wrapper.dispatchEvent(new Event('scroll'));
|
||||||
|
};
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
|
|
||||||
document.body.innerHTML = '';
|
document.body.innerHTML = '';
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("when it loads", () => {
|
test('adds right shadow on initial load if scrollable', () => {
|
||||||
|
setupDOM(0, 1000, 500);
|
||||||
test("it fixes the number column for each row without changing the semantics", () => {
|
expect(wrapper.classList.contains('scrolled')).toBe(false);
|
||||||
|
expect(rightShadow.classList.contains('visible')).toBe(true);
|
||||||
// start module
|
|
||||||
window.GOVUK.modules.start();
|
|
||||||
|
|
||||||
tableFrame = document.querySelector('.fullscreen-scrollable-table');
|
|
||||||
numberColumnFrame = document.querySelector('.fullscreen-fixed-table');
|
|
||||||
|
|
||||||
expect(tableFrame).not.toBeNull();
|
|
||||||
expect(numberColumnFrame).not.toBeNull();
|
|
||||||
expect(numberColumnFrame.getAttribute('aria-hidden')).toEqual('true');
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
test("it calls the sticky JS to update any cached dimensions", () => {
|
|
||||||
|
|
||||||
const stickyJSSpy = jest.spyOn(window.GOVUK.stickAtBottomWhenScrolling, 'recalculate');
|
|
||||||
|
|
||||||
// start module
|
|
||||||
window.GOVUK.modules.start();
|
|
||||||
|
|
||||||
expect(stickyJSSpy.mock.calls.length).toBe(1);
|
|
||||||
|
|
||||||
stickyJSSpy.mockClear();
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
test("the scrolling section is focusable and has an accessible name matching the table caption", () => {
|
|
||||||
|
|
||||||
// start module
|
|
||||||
window.GOVUK.modules.start();
|
|
||||||
|
|
||||||
tableFrame = document.querySelector('.fullscreen-scrollable-table');
|
|
||||||
caption = tableFrame.querySelector('caption');
|
|
||||||
|
|
||||||
expect(tableFrame.hasAttribute('role')).toBe(true);
|
|
||||||
expect(tableFrame.getAttribute('role')).toEqual('region');
|
|
||||||
expect(tableFrame.hasAttribute('aria-labelledby')).toBe(true);
|
|
||||||
expect(tableFrame.getAttribute('aria-labelledby')).toEqual(caption.getAttribute('id'));
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
test("the section providing the fixed row headers is not focusable and is hidden from assistive tech'", () => {
|
|
||||||
|
|
||||||
// start module
|
|
||||||
window.GOVUK.modules.start();
|
|
||||||
|
|
||||||
fixedRowHeaders = document.querySelector('.fullscreen-fixed-table');
|
|
||||||
|
|
||||||
expect(fixedRowHeaders.hasAttribute('role')).toBe(false);
|
|
||||||
expect(fixedRowHeaders.hasAttribute('aria-labelledby')).toBe(false);
|
|
||||||
expect(fixedRowHeaders.hasAttribute('tabindex')).toBe(false);
|
|
||||||
expect(fixedRowHeaders.hasAttribute('aria-hidden')).toBe(true);
|
|
||||||
expect(fixedRowHeaders.getAttribute('aria-hidden')).toEqual('true');
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("the height of the table should fit the vertical space available to it", () => {
|
test('hides right shadow when scrolled to max', () => {
|
||||||
|
setupDOM(500, 1000, 500);
|
||||||
let containerBoundingClientRectSpy;
|
expect(wrapper.classList.contains('scrolled')).toBe(true);
|
||||||
let containerClientRectsSpy;
|
expect(rightShadow.classList.contains('visible')).toBe(false);
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
|
|
||||||
// set the height and offset of the window and table container from the top of the document
|
|
||||||
// so just the top 268px of it appears on-screen
|
|
||||||
screenMock.window.setHeightTo(768);
|
|
||||||
screenMock.mockPositionAndDimension('container', container, {
|
|
||||||
'offsetHeight': 1000,
|
|
||||||
'offsetWidth': 641,
|
|
||||||
'offsetTop': 500
|
|
||||||
});
|
|
||||||
|
|
||||||
// start module
|
|
||||||
window.GOVUK.modules.start();
|
|
||||||
|
|
||||||
tableFrame = document.querySelector('.fullscreen-scrollable-table');
|
|
||||||
numberColumnFrame = document.querySelector('.fullscreen-fixed-table');
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
afterEach(() => {
|
|
||||||
|
|
||||||
screenMock.reset();
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
test("when the page has loaded", () => {
|
|
||||||
|
|
||||||
// the frames should crop to the top 268px of the table that is visible
|
|
||||||
expect(window.getComputedStyle(tableFrame)['height']).toEqual('268px');
|
|
||||||
expect(window.getComputedStyle(numberColumnFrame)['height']).toEqual('268px');
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
test("when the page has scrolled", () => {
|
|
||||||
|
|
||||||
// scroll the window so the table fills the height of the window (768px)
|
|
||||||
screenMock.window.scrollTo(500);
|
|
||||||
|
|
||||||
// the frames should crop to the window height
|
|
||||||
expect(window.getComputedStyle(tableFrame)['height']).toEqual('768px');
|
|
||||||
expect(window.getComputedStyle(numberColumnFrame)['height']).toEqual('768px');
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
test("when the page has resized", () => {
|
|
||||||
|
|
||||||
// resize the window by 232px (from 768px to 1000px)
|
|
||||||
screenMock.window.resizeTo({ height: 1000, width: 1024 });
|
|
||||||
|
|
||||||
// the frames should crop to the top 500px of the table now visible
|
|
||||||
expect(window.getComputedStyle(tableFrame)['height']).toEqual('500px');
|
|
||||||
expect(window.getComputedStyle(numberColumnFrame)['height']).toEqual('500px');
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("the width of the table should fit the horizontal space available to it", () => {
|
test('handles mid-scroll: left + right shadows active', () => {
|
||||||
let rowNumberColumnCell;
|
setupDOM(250, 1000, 500);
|
||||||
|
expect(wrapper.classList.contains('scrolled')).toBe(true);
|
||||||
beforeEach(() => {
|
expect(rightShadow.classList.contains('visible')).toBe(true);
|
||||||
|
|
||||||
rowNumberColumnCell = container.querySelector('.table-field-index');
|
|
||||||
|
|
||||||
// set main content column width (used as module as gauge for table width)
|
|
||||||
screenMock.window.setWidthTo(1024);
|
|
||||||
document.querySelector('main').setAttribute('style', 'width: 742px');
|
|
||||||
|
|
||||||
// set total width of column for row numbers in table to 40px
|
|
||||||
rowNumberColumnCell.setAttribute('style', 'width: 40px');
|
|
||||||
|
|
||||||
// start module
|
|
||||||
window.GOVUK.modules.start();
|
|
||||||
|
|
||||||
tableFrame = document.querySelector('.fullscreen-scrollable-table');
|
|
||||||
numberColumnFrame = document.querySelector('.fullscreen-fixed-table');
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
afterEach(() => {
|
|
||||||
|
|
||||||
screenMock.reset();
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
test("when the page has loaded", () => {
|
|
||||||
|
|
||||||
// table should set its width to be that of `<main>`, minus margin-left for the row numbers column
|
|
||||||
expect(window.getComputedStyle(tableFrame)['width']).toEqual('702px'); // width of content column - numbers column
|
|
||||||
expect(window.getComputedStyle(tableFrame)['margin-left']).toEqual('40px'); // width of numbers column
|
|
||||||
|
|
||||||
// table for number column has 4px extra to allow space for drop shadow
|
|
||||||
expect(window.getComputedStyle(numberColumnFrame)['width']).toEqual('44px');
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
test("when the page has resized", () => {
|
|
||||||
|
|
||||||
// resize window and content column
|
|
||||||
document.querySelector('main').setAttribute('style', 'width: 720px');
|
|
||||||
screenMock.window.resizeTo({ height: 768, width: 960 });
|
|
||||||
|
|
||||||
// table should set its width to be that of `<main>`, minus margin-left for the row numbers column
|
|
||||||
expect(window.getComputedStyle(tableFrame)['width']).toEqual('680px'); // width of content column - numbers column
|
|
||||||
expect(window.getComputedStyle(tableFrame)['margin-left']).toEqual('40px'); // width of numbers column
|
|
||||||
|
|
||||||
// table for number column has 4px extra to allow space for drop shadow
|
|
||||||
expect(window.getComputedStyle(numberColumnFrame)['width']).toEqual('44px');
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("when the table scrolls horizontally", () => {
|
test('gracefully handles missing right shadow', () => {
|
||||||
let rightEdgeShadow;
|
document.body.innerHTML = `
|
||||||
|
<div class="fullscreen-table">
|
||||||
|
<div class="table-wrapper">
|
||||||
|
<table>
|
||||||
|
<tr><td>Only content</td></tr>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
|
||||||
beforeEach(() => {
|
wrapper = document.querySelector('.table-wrapper');
|
||||||
|
|
||||||
// start module
|
Object.defineProperty(wrapper, 'scrollLeft', { get: () => 100, configurable: true });
|
||||||
window.GOVUK.modules.start();
|
Object.defineProperty(wrapper, 'scrollWidth', { get: () => 500, configurable: true });
|
||||||
|
Object.defineProperty(wrapper, 'clientWidth', { get: () => 200, configurable: true });
|
||||||
|
|
||||||
tableFrame = document.querySelector('.fullscreen-scrollable-table');
|
// 👇 Call after building DOM
|
||||||
table = tableFrame.querySelector('table');
|
window.initFullscreenTables();
|
||||||
numberColumnFrame = document.querySelector('.fullscreen-fixed-table');
|
wrapper.dispatchEvent(new Event('scroll'));
|
||||||
rightEdgeShadow = container.querySelector('.fullscreen-right-shadow');
|
|
||||||
|
|
||||||
tableFrame.setAttribute('style', 'width: 742px');
|
|
||||||
table.setAttribute('style', 'width: 1000px');
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
test("the right edge of the table scroll area should have a drop-shadow if it isn't scrolled", () => {
|
|
||||||
|
|
||||||
tableFrame.scrollLeft = 0;
|
|
||||||
helpers.triggerEvent(tableFrame, 'scroll');
|
|
||||||
|
|
||||||
expect(numberColumnFrame.classList.contains('fullscreen-scrolled-table')).toBe(false);
|
|
||||||
expect(rightEdgeShadow.classList.contains('visible')).toBe(true);
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
test("the left edge of the table scroll area should have a drop-shadow if the table is scrolled to 100%", () => {
|
|
||||||
|
|
||||||
// scroll to end of table
|
|
||||||
tableFrame.scrollLeft = 258;
|
|
||||||
helpers.triggerEvent(tableFrame, 'scroll');
|
|
||||||
|
|
||||||
expect(numberColumnFrame.classList.contains('fullscreen-scrolled-table')).toBe(true);
|
|
||||||
expect(rightEdgeShadow.classList.contains('visible')).toBe(false);
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
test("both edges of the table scroll area should have a drop-shadow if the table is scrolled between 0% and 100%", () => {
|
|
||||||
|
|
||||||
// scroll to middle of table
|
|
||||||
tableFrame.scrollLeft = 129;
|
|
||||||
helpers.triggerEvent(tableFrame, 'scroll');
|
|
||||||
|
|
||||||
expect(numberColumnFrame.classList.contains('fullscreen-scrolled-table')).toBe(true);
|
|
||||||
expect(rightEdgeShadow.classList.contains('visible')).toBe(true);
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
|
expect(wrapper.classList.contains('scrolled')).toBe(true);
|
||||||
|
// No error thrown for missing .fullscreen-right-shadow
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("when the table is focused", () => {
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
|
|
||||||
// start module
|
|
||||||
window.GOVUK.modules.start();
|
|
||||||
|
|
||||||
tableFrame = document.querySelector('.fullscreen-scrollable-table');
|
|
||||||
tableFrame.focus();
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
test("it should make the parent frame a focus style", () => {
|
|
||||||
|
|
||||||
expect(container.classList.contains('js-focus-style')).toBe(true);
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|||||||
0
tests/javascripts/main.test.js
Normal file
0
tests/javascripts/main.test.js
Normal file
Reference in New Issue
Block a user