govuk_publishing_components 35.10.0 → 35.12.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/assets/javascripts/govuk_publishing_components/analytics-ga4/ga4-core.js +2 -48
- data/app/assets/javascripts/govuk_publishing_components/analytics-ga4/ga4-form-tracker.js +5 -0
- data/app/assets/javascripts/govuk_publishing_components/analytics-ga4/ga4-link-tracker.js +2 -2
- data/app/assets/javascripts/govuk_publishing_components/analytics-ga4/ga4-schemas.js +51 -5
- data/app/assets/javascripts/govuk_publishing_components/analytics-ga4/ga4-scroll-tracker.js +225 -0
- data/app/assets/javascripts/govuk_publishing_components/analytics-ga4/init-ga4.js +0 -5
- data/app/assets/javascripts/govuk_publishing_components/analytics-ga4.js +1 -0
- data/app/assets/stylesheets/govuk_publishing_components/components/_attachment.scss +7 -0
- data/app/assets/stylesheets/govuk_publishing_components/components/_feedback.scss +8 -0
- data/app/assets/stylesheets/govuk_publishing_components/components/govspeak/_tables.scss +41 -0
- data/app/views/govuk_publishing_components/components/_attachment.html.erb +3 -1
- data/app/views/govuk_publishing_components/components/_contents_list.html.erb +9 -9
- data/app/views/govuk_publishing_components/components/_metadata.html.erb +2 -1
- data/app/views/govuk_publishing_components/components/_tabs.html.erb +30 -14
- data/app/views/govuk_publishing_components/components/docs/govspeak.yml +22 -0
- data/app/views/govuk_publishing_components/components/docs/tabs.yml +25 -2
- data/lib/govuk_publishing_components/version.rb +1 -1
- data/node_modules/govuk-frontend/govuk/all.js +406 -1
- data/node_modules/govuk-frontend/govuk/all.js.map +1 -1
- data/node_modules/govuk-frontend/govuk/common/govuk-frontend-version.js +1 -1
- data/node_modules/govuk-frontend/govuk/components/_all.scss +2 -1
- data/node_modules/govuk-frontend/govuk/components/back-link/_index.scss +8 -0
- data/node_modules/govuk-frontend/govuk/components/back-link/fixtures.json +9 -0
- data/node_modules/govuk-frontend/govuk/components/breadcrumbs/_index.scss +12 -0
- data/node_modules/govuk-frontend/govuk/components/breadcrumbs/fixtures.json +21 -0
- data/node_modules/govuk-frontend/govuk/components/button/_index.scss +41 -3
- data/node_modules/govuk-frontend/govuk/components/button/fixtures.json +44 -0
- data/node_modules/govuk-frontend/govuk/components/checkboxes/macro-options.json +9 -8
- data/node_modules/govuk-frontend/govuk/components/exit-this-page/README.md +15 -0
- data/node_modules/govuk-frontend/govuk/components/exit-this-page/_exit-this-page.scss +2 -0
- data/node_modules/govuk-frontend/govuk/components/exit-this-page/_index.scss +97 -0
- data/node_modules/govuk-frontend/govuk/components/exit-this-page/exit-this-page.js +2120 -0
- data/node_modules/govuk-frontend/govuk/components/exit-this-page/exit-this-page.js.map +1 -0
- data/node_modules/govuk-frontend/govuk/components/exit-this-page/fixtures.json +50 -0
- data/node_modules/govuk-frontend/govuk/components/exit-this-page/macro-options.json +62 -0
- data/node_modules/govuk-frontend/govuk/components/exit-this-page/macro.njk +3 -0
- data/node_modules/govuk-frontend/govuk/components/exit-this-page/template.njk +16 -0
- data/node_modules/govuk-frontend/govuk/components/radios/macro-options.json +9 -8
- data/node_modules/govuk-frontend/govuk/core/_govuk-frontend-version.scss +1 -1
- data/node_modules/govuk-frontend/govuk/helpers/_visually-hidden.scss +12 -0
- data/node_modules/govuk-frontend/govuk/objects/_template.scss +20 -0
- data/node_modules/govuk-frontend/govuk-esm/all.mjs +8 -0
- data/node_modules/govuk-frontend/govuk-esm/all.mjs.map +1 -1
- data/node_modules/govuk-frontend/govuk-esm/common/govuk-frontend-version.mjs +1 -1
- data/node_modules/govuk-frontend/govuk-esm/components/exit-this-page/exit-this-page.mjs +406 -0
- data/node_modules/govuk-frontend/govuk-esm/components/exit-this-page/exit-this-page.mjs.map +1 -0
- data/node_modules/govuk-frontend/govuk-prototype-kit.config.json +4 -0
- data/node_modules/govuk-frontend/package.json +4 -2
- metadata +15 -3
@@ -472,6 +472,28 @@ examples:
|
|
472
472
|
<li>تابعنا باللغة العربية عبر</li>
|
473
473
|
<li>تابعنا باللغة العربية عبر تويتر </li>
|
474
474
|
</ul>
|
475
|
+
<table>
|
476
|
+
<thead>
|
477
|
+
<tr>
|
478
|
+
<th scope="col">السنة</th>
|
479
|
+
<th scope="col">الدور</th>
|
480
|
+
</tr>
|
481
|
+
</thead>
|
482
|
+
<tbody>
|
483
|
+
<tr>
|
484
|
+
<td>2020 - 2022</td>
|
485
|
+
<td>وزارة الخارجية والتنمية البريطانية</td>
|
486
|
+
</tr>
|
487
|
+
<tr>
|
488
|
+
<td>2016 - 2020</td>
|
489
|
+
<td>القنصل العام البريطاني في القنصلية البريطانية العامة في شونغشينغ</td>
|
490
|
+
</tr>
|
491
|
+
<tr>
|
492
|
+
<td>2012 - 2015</td>
|
493
|
+
<td>الدوحة، نائب رئيس البعثة</td>
|
494
|
+
</tr>
|
495
|
+
</tbody>
|
496
|
+
</table>
|
475
497
|
with_youtube_embed:
|
476
498
|
data:
|
477
499
|
block: |
|
@@ -30,6 +30,17 @@ examples:
|
|
30
30
|
label: "Second section"
|
31
31
|
content: |
|
32
32
|
<p class="govuk-body-m">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam congue elementum commodo. Vestibulum elit turpis, efficitur quis posuere vitae, commodo vitae augue. Donec ut pharetra ligula. Phasellus ac mauris eu felis bibendum dapibus rutrum sed quam. Pellentesque posuere ante id consequat pretium.</p>
|
33
|
+
as_links:
|
34
|
+
description: With this option the tabs operate as links, rather than switching between elements within a single page.
|
35
|
+
data:
|
36
|
+
as_links: true
|
37
|
+
tabs:
|
38
|
+
- href: "link1"
|
39
|
+
label: "Page one"
|
40
|
+
active: true
|
41
|
+
- href: "link2"
|
42
|
+
label: "Page two"
|
43
|
+
active: false
|
33
44
|
without_panel_border:
|
34
45
|
data:
|
35
46
|
panel_border: false
|
@@ -84,8 +95,8 @@ examples:
|
|
84
95
|
tracking: GTM-123AB
|
85
96
|
content: |
|
86
97
|
<p class="govuk-body-m">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam congue elementum commodo. Vestibulum elit turpis, efficitur quis posuere vitae, commodo vitae augue. Donec ut pharetra ligula. Phasellus ac mauris eu felis bibendum dapibus rutrum sed quam. Pellentesque posuere ante id consequat pretium.</p>
|
87
|
-
|
88
|
-
description: Enables GA4 tracking
|
98
|
+
with_ga4_tracking_on_tabs:
|
99
|
+
description: Enables GA4 tracking by adding the event tracker and required data attributes to the tabs. See the [ga4-event-tracker documentation](https://github.com/alphagov/govuk_publishing_components/blob/main/docs/analytics-ga4/ga4-event-tracker.md) for more information.
|
89
100
|
data:
|
90
101
|
ga4_tracking: true
|
91
102
|
tabs:
|
@@ -99,3 +110,15 @@ examples:
|
|
99
110
|
title: "Second section"
|
100
111
|
content: |
|
101
112
|
<p class="govuk-body-m">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam congue elementum commodo. Vestibulum elit turpis, efficitur quis posuere vitae, commodo vitae augue. Donec ut pharetra ligula. Phasellus ac mauris eu felis bibendum dapibus rutrum sed quam. Pellentesque posuere ante id consequat pretium.</p>
|
113
|
+
with_ga4_tracking_on_tabs_as_links:
|
114
|
+
description: Enables GA4 tracking by adding the link tracker and required data attributes to the tabs. See the [ga4-link-tracker documentation](https://github.com/alphagov/govuk_publishing_components/blob/main/docs/analytics-ga4/ga4-link-tracker.md) for more information.
|
115
|
+
data:
|
116
|
+
as_links: true
|
117
|
+
ga4_tracking: true
|
118
|
+
tabs:
|
119
|
+
- href: "/page1"
|
120
|
+
label: "Link 1"
|
121
|
+
active: true
|
122
|
+
- href: "/page2"
|
123
|
+
label: "Link 2"
|
124
|
+
active: false
|
@@ -9,7 +9,7 @@
|
|
9
9
|
* It doesn't need to be updated manually.
|
10
10
|
*/
|
11
11
|
|
12
|
-
var version = '4.
|
12
|
+
var version = '4.7.0';
|
13
13
|
|
14
14
|
/**
|
15
15
|
* Common helpers which do not require polyfill.
|
@@ -3640,6 +3640,404 @@
|
|
3640
3640
|
* summary will not be focussed when the page loads.
|
3641
3641
|
*/
|
3642
3642
|
|
3643
|
+
// Implementation of common function is gathered in the `common` folder
|
3644
|
+
|
3645
|
+
/* eslint-disable es-x/no-function-prototype-bind -- Polyfill imported */
|
3646
|
+
|
3647
|
+
/**
|
3648
|
+
* @constant
|
3649
|
+
* @type {ExitThisPageTranslations}
|
3650
|
+
* @see Default value for {@link ExitThisPageConfig.i18n}
|
3651
|
+
* @default
|
3652
|
+
*/
|
3653
|
+
var EXIT_THIS_PAGE_TRANSLATIONS = {
|
3654
|
+
activated: 'Loading.',
|
3655
|
+
timedOut: 'Exit this page expired.',
|
3656
|
+
pressTwoMoreTimes: 'Shift, press 2 more times to exit.',
|
3657
|
+
pressOneMoreTime: 'Shift, press 1 more time to exit.'
|
3658
|
+
};
|
3659
|
+
|
3660
|
+
/**
|
3661
|
+
* Exit This Page component
|
3662
|
+
*
|
3663
|
+
* @class
|
3664
|
+
* @param {HTMLElement} $module - HTML element that wraps the Exit This Page button
|
3665
|
+
* @param {ExitThisPageConfig} [config] - Exit This Page config
|
3666
|
+
*/
|
3667
|
+
function ExitThisPage ($module, config) {
|
3668
|
+
/** @type {ExitThisPageConfig} */
|
3669
|
+
var defaultConfig = {
|
3670
|
+
i18n: EXIT_THIS_PAGE_TRANSLATIONS
|
3671
|
+
};
|
3672
|
+
|
3673
|
+
if (!($module instanceof HTMLElement)) {
|
3674
|
+
return this
|
3675
|
+
}
|
3676
|
+
|
3677
|
+
var $button = $module.querySelector('.govuk-exit-this-page__button');
|
3678
|
+
if (!($button instanceof HTMLElement)) {
|
3679
|
+
return this
|
3680
|
+
}
|
3681
|
+
|
3682
|
+
/**
|
3683
|
+
* @deprecated Will be made private in v5.0
|
3684
|
+
* @type {ExitThisPageConfig}
|
3685
|
+
*/
|
3686
|
+
this.config = mergeConfigs(
|
3687
|
+
defaultConfig,
|
3688
|
+
config || {},
|
3689
|
+
normaliseDataset($module.dataset)
|
3690
|
+
);
|
3691
|
+
|
3692
|
+
this.i18n = new I18n(extractConfigByNamespace(this.config, 'i18n'));
|
3693
|
+
|
3694
|
+
/** @deprecated Will be made private in v5.0 */
|
3695
|
+
this.$module = $module;
|
3696
|
+
|
3697
|
+
/** @deprecated Will be made private in v5.0 */
|
3698
|
+
this.$button = $button;
|
3699
|
+
|
3700
|
+
/** @deprecated Will be made private in v5.0 */
|
3701
|
+
this.$skiplinkButton = document.querySelector('.govuk-js-exit-this-page-skiplink');
|
3702
|
+
|
3703
|
+
/** @deprecated Will be made private in v5.0 */
|
3704
|
+
this.$updateSpan = null;
|
3705
|
+
|
3706
|
+
/** @deprecated Will be made private in v5.0 */
|
3707
|
+
this.$indicatorContainer = null;
|
3708
|
+
|
3709
|
+
/** @deprecated Will be made private in v5.0 */
|
3710
|
+
this.$overlay = null;
|
3711
|
+
|
3712
|
+
/** @deprecated Will be made private in v5.0 */
|
3713
|
+
this.keypressCounter = 0;
|
3714
|
+
|
3715
|
+
/** @deprecated Will be made private in v5.0 */
|
3716
|
+
this.lastKeyWasModified = false;
|
3717
|
+
|
3718
|
+
/** @deprecated Will be made private in v5.0 */
|
3719
|
+
this.timeoutTime = 5000; // milliseconds
|
3720
|
+
|
3721
|
+
// Store the timeout events so that we can clear them to avoid user keypresses overlapping
|
3722
|
+
// setTimeout returns an id that we can use to clear it with clearTimeout,
|
3723
|
+
// hence the 'Id' suffix
|
3724
|
+
|
3725
|
+
/** @deprecated Will be made private in v5.0 */
|
3726
|
+
this.keypressTimeoutId = null;
|
3727
|
+
|
3728
|
+
/** @deprecated Will be made private in v5.0 */
|
3729
|
+
this.timeoutMessageId = null;
|
3730
|
+
}
|
3731
|
+
|
3732
|
+
/**
|
3733
|
+
* Create the <span> we use for screen reader announcements.
|
3734
|
+
*
|
3735
|
+
* @deprecated Will be made private in v5.0
|
3736
|
+
*/
|
3737
|
+
ExitThisPage.prototype.initUpdateSpan = function () {
|
3738
|
+
this.$updateSpan = document.createElement('span');
|
3739
|
+
this.$updateSpan.setAttribute('role', 'status');
|
3740
|
+
this.$updateSpan.className = 'govuk-visually-hidden';
|
3741
|
+
|
3742
|
+
this.$module.appendChild(this.$updateSpan);
|
3743
|
+
};
|
3744
|
+
|
3745
|
+
/**
|
3746
|
+
* Create button click handlers.
|
3747
|
+
*
|
3748
|
+
* @deprecated Will be made private in v5.0
|
3749
|
+
*/
|
3750
|
+
ExitThisPage.prototype.initButtonClickHandler = function () {
|
3751
|
+
// Main EtP button
|
3752
|
+
this.$button.addEventListener('click', this.handleClick.bind(this));
|
3753
|
+
|
3754
|
+
// EtP skiplink
|
3755
|
+
if (this.$skiplinkButton) {
|
3756
|
+
this.$skiplinkButton.addEventListener('click', this.handleClick.bind(this));
|
3757
|
+
}
|
3758
|
+
};
|
3759
|
+
|
3760
|
+
/**
|
3761
|
+
* Create the HTML for the 'three lights' indicator on the button.
|
3762
|
+
*
|
3763
|
+
* @deprecated Will be made private in v5.0
|
3764
|
+
*/
|
3765
|
+
ExitThisPage.prototype.buildIndicator = function () {
|
3766
|
+
// Build container
|
3767
|
+
// Putting `aria-hidden` on it as it won't contain any readable information
|
3768
|
+
this.$indicatorContainer = document.createElement('div');
|
3769
|
+
this.$indicatorContainer.className = 'govuk-exit-this-page__indicator';
|
3770
|
+
this.$indicatorContainer.setAttribute('aria-hidden', 'true');
|
3771
|
+
|
3772
|
+
// Create three 'lights' and place them within the container
|
3773
|
+
for (var i = 0; i < 3; i++) {
|
3774
|
+
var $indicator = document.createElement('div');
|
3775
|
+
$indicator.className = 'govuk-exit-this-page__indicator-light';
|
3776
|
+
this.$indicatorContainer.appendChild($indicator);
|
3777
|
+
}
|
3778
|
+
|
3779
|
+
// Append it all to the module
|
3780
|
+
this.$button.appendChild(this.$indicatorContainer);
|
3781
|
+
};
|
3782
|
+
|
3783
|
+
/**
|
3784
|
+
* Update whether the lights are visible and which ones are lit up depending on
|
3785
|
+
* the value of `keypressCounter`.
|
3786
|
+
*
|
3787
|
+
* @deprecated Will be made private in v5.0
|
3788
|
+
*/
|
3789
|
+
ExitThisPage.prototype.updateIndicator = function () {
|
3790
|
+
// Show or hide the indicator container depending on keypressCounter value
|
3791
|
+
if (this.keypressCounter > 0) {
|
3792
|
+
this.$indicatorContainer.classList.add('govuk-exit-this-page__indicator--visible');
|
3793
|
+
} else {
|
3794
|
+
this.$indicatorContainer.classList.remove('govuk-exit-this-page__indicator--visible');
|
3795
|
+
}
|
3796
|
+
|
3797
|
+
// Turn on only the indicators we want on
|
3798
|
+
var $indicators = this.$indicatorContainer.querySelectorAll(
|
3799
|
+
'.govuk-exit-this-page__indicator-light'
|
3800
|
+
);
|
3801
|
+
nodeListForEach($indicators, function ($indicator, index) {
|
3802
|
+
$indicator.classList.toggle(
|
3803
|
+
'govuk-exit-this-page__indicator-light--on',
|
3804
|
+
index < this.keypressCounter
|
3805
|
+
);
|
3806
|
+
}.bind(this));
|
3807
|
+
};
|
3808
|
+
|
3809
|
+
/**
|
3810
|
+
* Initiates the redirection away from the current page.
|
3811
|
+
* Includes the loading overlay functionality, which covers the current page with a
|
3812
|
+
* white overlay so that the contents are not visible during the loading
|
3813
|
+
* process. This is particularly important on slow network connections.
|
3814
|
+
*
|
3815
|
+
* @deprecated Will be made private in v5.0
|
3816
|
+
*/
|
3817
|
+
ExitThisPage.prototype.exitPage = function () {
|
3818
|
+
this.$updateSpan.innerText = '';
|
3819
|
+
|
3820
|
+
// Blank the page
|
3821
|
+
// As well as creating an overlay with text, we also set the body to hidden
|
3822
|
+
// to prevent screen reader and sequential navigation users potentially
|
3823
|
+
// navigating through the page behind the overlay during loading
|
3824
|
+
document.body.classList.add('govuk-exit-this-page-hide-content');
|
3825
|
+
this.$overlay = document.createElement('div');
|
3826
|
+
this.$overlay.className = 'govuk-exit-this-page-overlay';
|
3827
|
+
this.$overlay.setAttribute('role', 'alert');
|
3828
|
+
|
3829
|
+
// we do these this way round, thus incurring a second paint, because changing
|
3830
|
+
// the element text after adding it means that screen readers pick up the
|
3831
|
+
// announcement more reliably.
|
3832
|
+
document.body.appendChild(this.$overlay);
|
3833
|
+
this.$overlay.innerText = this.i18n.t('activated');
|
3834
|
+
|
3835
|
+
window.location.href = this.$button.getAttribute('href');
|
3836
|
+
};
|
3837
|
+
|
3838
|
+
/**
|
3839
|
+
* Pre-activation logic for when the button is clicked/activated via mouse or
|
3840
|
+
* pointer.
|
3841
|
+
*
|
3842
|
+
* We do this to differentiate it from the keyboard activation event because we
|
3843
|
+
* need to run `e.preventDefault` as the button or skiplink are both links and we
|
3844
|
+
* want to apply some additional logic in `exitPage` before navigating.
|
3845
|
+
*
|
3846
|
+
* @deprecated Will be made private in v5.0
|
3847
|
+
* @param {MouseEvent} event - mouse click event
|
3848
|
+
*/
|
3849
|
+
ExitThisPage.prototype.handleClick = function (event) {
|
3850
|
+
event.preventDefault();
|
3851
|
+
this.exitPage();
|
3852
|
+
};
|
3853
|
+
|
3854
|
+
/**
|
3855
|
+
* Logic for the 'quick escape' keyboard sequence functionality (pressing the
|
3856
|
+
* Shift key three times without interruption, within a time limit).
|
3857
|
+
*
|
3858
|
+
* @deprecated Will be made private in v5.0
|
3859
|
+
* @param {KeyboardEvent} event - keyup event
|
3860
|
+
*/
|
3861
|
+
ExitThisPage.prototype.handleKeypress = function (event) {
|
3862
|
+
// Detect if the 'Shift' key has been pressed. We want to only do things if it
|
3863
|
+
// was pressed by itself and not in a combination with another key—so we keep
|
3864
|
+
// track of whether the preceding keyup had shiftKey: true on it, and if it
|
3865
|
+
// did, we ignore the next Shift keyup event.
|
3866
|
+
//
|
3867
|
+
// This works because using Shift as a modifier key (e.g. pressing Shift + A)
|
3868
|
+
// will fire TWO keyup events, one for A (with e.shiftKey: true) and the other
|
3869
|
+
// for Shift (with e.shiftKey: false).
|
3870
|
+
if (
|
3871
|
+
(event.key === 'Shift' || event.keyCode === 16 || event.which === 16) &&
|
3872
|
+
!this.lastKeyWasModified
|
3873
|
+
) {
|
3874
|
+
this.keypressCounter += 1;
|
3875
|
+
|
3876
|
+
// Update the indicator before the below if statement can reset it back to 0
|
3877
|
+
this.updateIndicator();
|
3878
|
+
|
3879
|
+
// Clear the timeout for the keypress timeout message clearing itself
|
3880
|
+
if (this.timeoutMessageId !== null) {
|
3881
|
+
clearTimeout(this.timeoutMessageId);
|
3882
|
+
this.timeoutMessageId = null;
|
3883
|
+
}
|
3884
|
+
|
3885
|
+
if (this.keypressCounter >= 3) {
|
3886
|
+
this.keypressCounter = 0;
|
3887
|
+
|
3888
|
+
if (this.keypressTimeoutId !== null) {
|
3889
|
+
clearTimeout(this.keypressTimeoutId);
|
3890
|
+
this.keypressTimeoutId = null;
|
3891
|
+
}
|
3892
|
+
|
3893
|
+
this.exitPage();
|
3894
|
+
} else {
|
3895
|
+
if (this.keypressCounter === 1) {
|
3896
|
+
this.$updateSpan.innerText = this.i18n.t('pressTwoMoreTimes');
|
3897
|
+
} else {
|
3898
|
+
this.$updateSpan.innerText = this.i18n.t('pressOneMoreTime');
|
3899
|
+
}
|
3900
|
+
}
|
3901
|
+
|
3902
|
+
this.setKeypressTimer();
|
3903
|
+
} else if (this.keypressTimeoutId !== null) {
|
3904
|
+
// If the user pressed any key other than 'Shift', after having pressed
|
3905
|
+
// 'Shift' and activating the timer, stop and reset the timer.
|
3906
|
+
this.resetKeypressTimer();
|
3907
|
+
}
|
3908
|
+
|
3909
|
+
// Keep track of whether the Shift modifier key was held during this keypress
|
3910
|
+
this.lastKeyWasModified = event.shiftKey;
|
3911
|
+
};
|
3912
|
+
|
3913
|
+
/**
|
3914
|
+
* Starts the 'quick escape' keyboard sequence timer.
|
3915
|
+
*
|
3916
|
+
* This can be invoked several times. We want this to be possible so that the
|
3917
|
+
* timer is restarted each time the shortcut key is pressed (e.g. the user has
|
3918
|
+
* up to n seconds between each keypress, rather than n seconds to invoke the
|
3919
|
+
* entire sequence.)
|
3920
|
+
*
|
3921
|
+
* @deprecated Will be made private in v5.0
|
3922
|
+
*/
|
3923
|
+
ExitThisPage.prototype.setKeypressTimer = function () {
|
3924
|
+
// Clear any existing timeout. This is so only one timer is running even if
|
3925
|
+
// there are multiple keypresses in quick succession.
|
3926
|
+
clearTimeout(this.keypressTimeoutId);
|
3927
|
+
|
3928
|
+
// Set a fresh timeout
|
3929
|
+
this.keypressTimeoutId = setTimeout(
|
3930
|
+
this.resetKeypressTimer.bind(this),
|
3931
|
+
this.timeoutTime
|
3932
|
+
);
|
3933
|
+
};
|
3934
|
+
|
3935
|
+
/**
|
3936
|
+
* Stops and resets the 'quick escape' keyboard sequence timer.
|
3937
|
+
*
|
3938
|
+
* @deprecated Will be made private in v5.0
|
3939
|
+
*/
|
3940
|
+
ExitThisPage.prototype.resetKeypressTimer = function () {
|
3941
|
+
clearTimeout(this.keypressTimeoutId);
|
3942
|
+
this.keypressTimeoutId = null;
|
3943
|
+
|
3944
|
+
this.keypressCounter = 0;
|
3945
|
+
this.$updateSpan.innerText = this.i18n.t('timedOut');
|
3946
|
+
|
3947
|
+
this.timeoutMessageId = setTimeout(function () {
|
3948
|
+
this.$updateSpan.innerText = '';
|
3949
|
+
}.bind(this), this.timeoutTime);
|
3950
|
+
|
3951
|
+
this.updateIndicator();
|
3952
|
+
};
|
3953
|
+
|
3954
|
+
/**
|
3955
|
+
* Reset the page using the EtP button
|
3956
|
+
*
|
3957
|
+
* We use this in situations where a user may re-enter a page using the browser
|
3958
|
+
* back button. In these cases, the browser can choose to restore the state of
|
3959
|
+
* the page as it was previously, including restoring the 'ghost page' overlay,
|
3960
|
+
* the announcement span having it's role set to "alert" and the keypress
|
3961
|
+
* indicator still active, leaving the page in an unusable state.
|
3962
|
+
*
|
3963
|
+
* By running this check when the page is shown, we can programatically restore
|
3964
|
+
* the page and the component to a "default" state
|
3965
|
+
*
|
3966
|
+
* @deprecated Will be made private in v5.0
|
3967
|
+
*/
|
3968
|
+
ExitThisPage.prototype.resetPage = function () {
|
3969
|
+
// If an overlay is set, remove it and reset the value
|
3970
|
+
document.body.classList.remove('govuk-exit-this-page-hide-content');
|
3971
|
+
|
3972
|
+
if (this.$overlay) {
|
3973
|
+
this.$overlay.remove();
|
3974
|
+
this.$overlay = null;
|
3975
|
+
}
|
3976
|
+
|
3977
|
+
// Ensure the announcement span's role is status, not alert and clear any text
|
3978
|
+
this.$updateSpan.setAttribute('role', 'status');
|
3979
|
+
this.$updateSpan.innerText = '';
|
3980
|
+
|
3981
|
+
// Sync the keypress indicator lights
|
3982
|
+
this.updateIndicator();
|
3983
|
+
|
3984
|
+
// If the timeouts are active, clear them
|
3985
|
+
if (this.keypressTimeoutId) {
|
3986
|
+
clearTimeout(this.keypressTimeoutId);
|
3987
|
+
}
|
3988
|
+
|
3989
|
+
if (this.timeoutMessageId) {
|
3990
|
+
clearTimeout(this.timeoutMessageId);
|
3991
|
+
}
|
3992
|
+
};
|
3993
|
+
|
3994
|
+
/**
|
3995
|
+
* Initialise component
|
3996
|
+
*/
|
3997
|
+
ExitThisPage.prototype.init = function () {
|
3998
|
+
this.buildIndicator();
|
3999
|
+
this.initUpdateSpan();
|
4000
|
+
this.initButtonClickHandler();
|
4001
|
+
|
4002
|
+
// Check to see if this has already been done by a previous initialisation of ExitThisPage
|
4003
|
+
if (!('govukFrontendExitThisPageKeypress' in document.body.dataset)) {
|
4004
|
+
document.addEventListener('keyup', this.handleKeypress.bind(this), true);
|
4005
|
+
document.body.dataset.govukFrontendExitThisPageKeypress = 'true';
|
4006
|
+
}
|
4007
|
+
|
4008
|
+
// When the page is restored after navigating 'back' in some browsers the
|
4009
|
+
// blank overlay remains present, rendering the page unusable. Here, we check
|
4010
|
+
// to see if it's present on page (re)load, and remove it if so.
|
4011
|
+
window.addEventListener(
|
4012
|
+
'onpageshow' in window ? 'pageshow' : 'DOMContentLoaded',
|
4013
|
+
this.resetPage.bind(this)
|
4014
|
+
);
|
4015
|
+
};
|
4016
|
+
|
4017
|
+
/**
|
4018
|
+
* Exit this Page config
|
4019
|
+
*
|
4020
|
+
* @typedef {object} ExitThisPageConfig
|
4021
|
+
* @property {ExitThisPageTranslations} [i18n = EXIT_THIS_PAGE_TRANSLATIONS] - See constant {@link EXIT_THIS_PAGE_TRANSLATIONS}
|
4022
|
+
*/
|
4023
|
+
|
4024
|
+
/**
|
4025
|
+
* Exit this Page translations
|
4026
|
+
*
|
4027
|
+
* @typedef {object} ExitThisPageTranslations
|
4028
|
+
*
|
4029
|
+
* Messages used by the component programatically inserted text, including
|
4030
|
+
* overlay text and screen reader announcements.
|
4031
|
+
* @property {string} [activated] - Screen reader announcement for when EtP
|
4032
|
+
* keypress functionality has been successfully activated.
|
4033
|
+
* @property {string} [timedOut] - Screen reader announcement for when the EtP
|
4034
|
+
* keypress functionality has timed out.
|
4035
|
+
* @property {string} [pressTwoMoreTimes] - Screen reader announcement informing
|
4036
|
+
* the user they must press the activation key two more times.
|
4037
|
+
* @property {string} [pressOneMoreTime] - Screen reader announcement informing
|
4038
|
+
* the user they must press the activation key one more time.
|
4039
|
+
*/
|
4040
|
+
|
3643
4041
|
/* eslint-disable es-x/no-function-prototype-bind -- Polyfill imported */
|
3644
4042
|
|
3645
4043
|
/**
|
@@ -4709,6 +5107,11 @@
|
|
4709
5107
|
new ErrorSummary($errorSummary, config.errorSummary).init();
|
4710
5108
|
}
|
4711
5109
|
|
5110
|
+
var $exitThisPageButtons = $scope.querySelectorAll('[data-module="govuk-exit-this-page"]');
|
5111
|
+
nodeListForEach($exitThisPageButtons, function ($button) {
|
5112
|
+
new ExitThisPage($button, config.exitThisPage).init();
|
5113
|
+
});
|
5114
|
+
|
4712
5115
|
// Find first header module to enhance.
|
4713
5116
|
var $header = $scope.querySelector('[data-module="govuk-header"]');
|
4714
5117
|
if ($header) {
|
@@ -4746,6 +5149,7 @@
|
|
4746
5149
|
* @property {import('./components/button/button.mjs').ButtonConfig} [button] - Button config
|
4747
5150
|
* @property {import('./components/character-count/character-count.mjs').CharacterCountConfig} [characterCount] - Character Count config
|
4748
5151
|
* @property {import('./components/error-summary/error-summary.mjs').ErrorSummaryConfig} [errorSummary] - Error Summary config
|
5152
|
+
* @property {import('./components/exit-this-page/exit-this-page.mjs').ExitThisPageConfig} [exitThisPage] - Exit This Page config
|
4749
5153
|
* @property {import('./components/notification-banner/notification-banner.mjs').NotificationBannerConfig} [notificationBanner] - Notification Banner config
|
4750
5154
|
*/
|
4751
5155
|
|
@@ -4757,6 +5161,7 @@
|
|
4757
5161
|
exports.CharacterCount = CharacterCount;
|
4758
5162
|
exports.Checkboxes = Checkboxes;
|
4759
5163
|
exports.ErrorSummary = ErrorSummary;
|
5164
|
+
exports.ExitThisPage = ExitThisPage;
|
4760
5165
|
exports.Header = Header;
|
4761
5166
|
exports.NotificationBanner = NotificationBanner;
|
4762
5167
|
exports.Radios = Radios;
|