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.
Files changed (50) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/javascripts/govuk_publishing_components/analytics-ga4/ga4-core.js +2 -48
  3. data/app/assets/javascripts/govuk_publishing_components/analytics-ga4/ga4-form-tracker.js +5 -0
  4. data/app/assets/javascripts/govuk_publishing_components/analytics-ga4/ga4-link-tracker.js +2 -2
  5. data/app/assets/javascripts/govuk_publishing_components/analytics-ga4/ga4-schemas.js +51 -5
  6. data/app/assets/javascripts/govuk_publishing_components/analytics-ga4/ga4-scroll-tracker.js +225 -0
  7. data/app/assets/javascripts/govuk_publishing_components/analytics-ga4/init-ga4.js +0 -5
  8. data/app/assets/javascripts/govuk_publishing_components/analytics-ga4.js +1 -0
  9. data/app/assets/stylesheets/govuk_publishing_components/components/_attachment.scss +7 -0
  10. data/app/assets/stylesheets/govuk_publishing_components/components/_feedback.scss +8 -0
  11. data/app/assets/stylesheets/govuk_publishing_components/components/govspeak/_tables.scss +41 -0
  12. data/app/views/govuk_publishing_components/components/_attachment.html.erb +3 -1
  13. data/app/views/govuk_publishing_components/components/_contents_list.html.erb +9 -9
  14. data/app/views/govuk_publishing_components/components/_metadata.html.erb +2 -1
  15. data/app/views/govuk_publishing_components/components/_tabs.html.erb +30 -14
  16. data/app/views/govuk_publishing_components/components/docs/govspeak.yml +22 -0
  17. data/app/views/govuk_publishing_components/components/docs/tabs.yml +25 -2
  18. data/lib/govuk_publishing_components/version.rb +1 -1
  19. data/node_modules/govuk-frontend/govuk/all.js +406 -1
  20. data/node_modules/govuk-frontend/govuk/all.js.map +1 -1
  21. data/node_modules/govuk-frontend/govuk/common/govuk-frontend-version.js +1 -1
  22. data/node_modules/govuk-frontend/govuk/components/_all.scss +2 -1
  23. data/node_modules/govuk-frontend/govuk/components/back-link/_index.scss +8 -0
  24. data/node_modules/govuk-frontend/govuk/components/back-link/fixtures.json +9 -0
  25. data/node_modules/govuk-frontend/govuk/components/breadcrumbs/_index.scss +12 -0
  26. data/node_modules/govuk-frontend/govuk/components/breadcrumbs/fixtures.json +21 -0
  27. data/node_modules/govuk-frontend/govuk/components/button/_index.scss +41 -3
  28. data/node_modules/govuk-frontend/govuk/components/button/fixtures.json +44 -0
  29. data/node_modules/govuk-frontend/govuk/components/checkboxes/macro-options.json +9 -8
  30. data/node_modules/govuk-frontend/govuk/components/exit-this-page/README.md +15 -0
  31. data/node_modules/govuk-frontend/govuk/components/exit-this-page/_exit-this-page.scss +2 -0
  32. data/node_modules/govuk-frontend/govuk/components/exit-this-page/_index.scss +97 -0
  33. data/node_modules/govuk-frontend/govuk/components/exit-this-page/exit-this-page.js +2120 -0
  34. data/node_modules/govuk-frontend/govuk/components/exit-this-page/exit-this-page.js.map +1 -0
  35. data/node_modules/govuk-frontend/govuk/components/exit-this-page/fixtures.json +50 -0
  36. data/node_modules/govuk-frontend/govuk/components/exit-this-page/macro-options.json +62 -0
  37. data/node_modules/govuk-frontend/govuk/components/exit-this-page/macro.njk +3 -0
  38. data/node_modules/govuk-frontend/govuk/components/exit-this-page/template.njk +16 -0
  39. data/node_modules/govuk-frontend/govuk/components/radios/macro-options.json +9 -8
  40. data/node_modules/govuk-frontend/govuk/core/_govuk-frontend-version.scss +1 -1
  41. data/node_modules/govuk-frontend/govuk/helpers/_visually-hidden.scss +12 -0
  42. data/node_modules/govuk-frontend/govuk/objects/_template.scss +20 -0
  43. data/node_modules/govuk-frontend/govuk-esm/all.mjs +8 -0
  44. data/node_modules/govuk-frontend/govuk-esm/all.mjs.map +1 -1
  45. data/node_modules/govuk-frontend/govuk-esm/common/govuk-frontend-version.mjs +1 -1
  46. data/node_modules/govuk-frontend/govuk-esm/components/exit-this-page/exit-this-page.mjs +406 -0
  47. data/node_modules/govuk-frontend/govuk-esm/components/exit-this-page/exit-this-page.mjs.map +1 -0
  48. data/node_modules/govuk-frontend/govuk-prototype-kit.config.json +4 -0
  49. data/node_modules/govuk-frontend/package.json +4 -2
  50. 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
- with_ga4_tracking:
88
- description: Enables GA4 tracking. This will add the required data module and 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.
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
@@ -1,3 +1,3 @@
1
1
  module GovukPublishingComponents
2
- VERSION = "35.10.0".freeze
2
+ VERSION = "35.12.0".freeze
3
3
  end
@@ -9,7 +9,7 @@
9
9
  * It doesn't need to be updated manually.
10
10
  */
11
11
 
12
- var version = '4.6.0';
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;