govuk_publishing_components 35.3.3 → 35.3.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/app/assets/stylesheets/component_guide/application.scss +37 -1
- data/app/assets/stylesheets/govuk_publishing_components/components/_metadata.scss +10 -6
- data/app/assets/stylesheets/govuk_publishing_components/components/_organisation-logo.scss +2 -2
- data/app/views/govuk_publishing_components/component_guide/example.html.erb +1 -1
- data/app/views/govuk_publishing_components/component_guide/preview.html.erb +1 -1
- data/app/views/govuk_publishing_components/component_guide/show.html.erb +1 -1
- data/app/views/govuk_publishing_components/components/_layout_super_navigation_header.html.erb +2 -2
- data/app/views/govuk_publishing_components/components/_metadata.html.erb +1 -1
- data/app/views/govuk_publishing_components/components/_share_links.html.erb +6 -2
- data/app/views/govuk_publishing_components/components/_step_by_step_nav_related.html.erb +1 -1
- data/app/views/govuk_publishing_components/components/docs/metadata.yml +1 -3
- data/app/views/govuk_publishing_components/components/docs/organisation_logo.yml +5 -5
- data/app/views/govuk_publishing_components/components/docs/step_by_step_nav_related.yml +1 -0
- data/app/views/layouts/govuk_publishing_components/application.html.erb +1 -0
- data/lib/govuk_publishing_components/app_helpers/asset_helper.rb +4 -0
- data/lib/govuk_publishing_components/presenters/breadcrumbs_helper.rb +1 -1
- data/lib/govuk_publishing_components/version.rb +1 -1
- data/node_modules/axe-core/axe.d.ts +77 -6
- data/node_modules/axe-core/axe.js +955 -600
- data/node_modules/axe-core/axe.min.js +2 -2
- data/node_modules/axe-core/locales/_template.json +6 -6
- data/node_modules/axe-core/locales/ja.json +91 -11
- data/node_modules/axe-core/package.json +5 -5
- data/node_modules/axe-core/sri-history.json +4 -0
- data/node_modules/govuk-frontend/README.md +4 -5
- data/node_modules/govuk-frontend/govuk/all-ie8.scss +8 -0
- data/node_modules/govuk-frontend/govuk/all.js +738 -258
- data/node_modules/govuk-frontend/govuk/all.js.map +1 -1
- data/node_modules/govuk-frontend/govuk/common/closest-attribute-value.js +11 -7
- data/node_modules/govuk-frontend/govuk/common/closest-attribute-value.js.map +1 -1
- data/node_modules/govuk-frontend/govuk/common/govuk-frontend-version.js +17 -0
- data/node_modules/govuk-frontend/govuk/common/govuk-frontend-version.js.map +1 -0
- data/node_modules/govuk-frontend/govuk/common/index.js +16 -4
- data/node_modules/govuk-frontend/govuk/common/index.js.map +1 -1
- data/node_modules/govuk-frontend/govuk/common/normalise-dataset.js +20 -10
- data/node_modules/govuk-frontend/govuk/common/normalise-dataset.js.map +1 -1
- data/node_modules/govuk-frontend/govuk/common.js +16 -4
- data/node_modules/govuk-frontend/govuk/common.js.map +1 -1
- data/node_modules/govuk-frontend/govuk/components/accordion/_index.scss +3 -3
- data/node_modules/govuk-frontend/govuk/components/accordion/accordion.js +234 -86
- data/node_modules/govuk-frontend/govuk/components/accordion/accordion.js.map +1 -1
- data/node_modules/govuk-frontend/govuk/components/accordion/fixtures.json +32 -13
- data/node_modules/govuk-frontend/govuk/components/accordion/macro-options.json +8 -2
- data/node_modules/govuk-frontend/govuk/components/accordion/template.njk +1 -0
- data/node_modules/govuk-frontend/govuk/components/back-link/_index.scss +1 -1
- data/node_modules/govuk-frontend/govuk/components/back-link/fixtures.json +1 -1
- data/node_modules/govuk-frontend/govuk/components/back-link/macro-options.json +1 -1
- data/node_modules/govuk-frontend/govuk/components/breadcrumbs/_index.scss +1 -1
- data/node_modules/govuk-frontend/govuk/components/breadcrumbs/fixtures.json +12 -12
- data/node_modules/govuk-frontend/govuk/components/breadcrumbs/macro-options.json +1 -1
- data/node_modules/govuk-frontend/govuk/components/button/_index.scss +8 -6
- data/node_modules/govuk-frontend/govuk/components/button/button.js +54 -19
- data/node_modules/govuk-frontend/govuk/components/button/button.js.map +1 -1
- data/node_modules/govuk-frontend/govuk/components/button/fixtures.json +11 -1
- data/node_modules/govuk-frontend/govuk/components/button/macro-options.json +7 -1
- data/node_modules/govuk-frontend/govuk/components/button/template.njk +1 -1
- data/node_modules/govuk-frontend/govuk/components/character-count/character-count.js +170 -76
- data/node_modules/govuk-frontend/govuk/components/character-count/character-count.js.map +1 -1
- data/node_modules/govuk-frontend/govuk/components/character-count/fixtures.json +24 -24
- data/node_modules/govuk-frontend/govuk/components/character-count/macro-options.json +3 -3
- data/node_modules/govuk-frontend/govuk/components/checkboxes/_index.scss +6 -6
- data/node_modules/govuk-frontend/govuk/components/checkboxes/checkboxes.js +75 -24
- data/node_modules/govuk-frontend/govuk/components/checkboxes/checkboxes.js.map +1 -1
- data/node_modules/govuk-frontend/govuk/components/checkboxes/fixtures.json +47 -47
- data/node_modules/govuk-frontend/govuk/components/checkboxes/macro-options.json +1 -1
- data/node_modules/govuk-frontend/govuk/components/checkboxes/template.njk +3 -3
- data/node_modules/govuk-frontend/govuk/components/cookie-banner/fixtures.json +24 -24
- data/node_modules/govuk-frontend/govuk/components/cookie-banner/macro-options.json +1 -1
- data/node_modules/govuk-frontend/govuk/components/date-input/fixtures.json +26 -26
- data/node_modules/govuk-frontend/govuk/components/date-input/macro-options.json +1 -1
- data/node_modules/govuk-frontend/govuk/components/date-input/template.njk +1 -1
- data/node_modules/govuk-frontend/govuk/components/details/details.js +39 -13
- data/node_modules/govuk-frontend/govuk/components/details/details.js.map +1 -1
- data/node_modules/govuk-frontend/govuk/components/details/fixtures.json +1 -1
- data/node_modules/govuk-frontend/govuk/components/details/macro-options.json +1 -1
- data/node_modules/govuk-frontend/govuk/components/error-message/fixtures.json +10 -10
- data/node_modules/govuk-frontend/govuk/components/error-message/macro-options.json +1 -1
- data/node_modules/govuk-frontend/govuk/components/error-summary/error-summary.js +67 -27
- data/node_modules/govuk-frontend/govuk/components/error-summary/error-summary.js.map +1 -1
- data/node_modules/govuk-frontend/govuk/components/error-summary/fixtures.json +19 -19
- data/node_modules/govuk-frontend/govuk/components/error-summary/macro-options.json +1 -1
- data/node_modules/govuk-frontend/govuk/components/fieldset/fixtures.json +19 -19
- data/node_modules/govuk-frontend/govuk/components/fieldset/macro-options.json +1 -1
- data/node_modules/govuk-frontend/govuk/components/file-upload/_index.scss +6 -1
- data/node_modules/govuk-frontend/govuk/components/file-upload/fixtures.json +14 -14
- data/node_modules/govuk-frontend/govuk/components/file-upload/macro-options.json +7 -1
- data/node_modules/govuk-frontend/govuk/components/file-upload/template.njk +2 -1
- data/node_modules/govuk-frontend/govuk/components/footer/_index.scss +0 -7
- data/node_modules/govuk-frontend/govuk/components/footer/fixtures.json +24 -24
- data/node_modules/govuk-frontend/govuk/components/footer/macro-options.json +1 -1
- data/node_modules/govuk-frontend/govuk/components/header/fixtures.json +22 -22
- data/node_modules/govuk-frontend/govuk/components/header/header.js +46 -14
- data/node_modules/govuk-frontend/govuk/components/header/header.js.map +1 -1
- data/node_modules/govuk-frontend/govuk/components/header/macro-options.json +1 -1
- data/node_modules/govuk-frontend/govuk/components/header/template.njk +1 -1
- data/node_modules/govuk-frontend/govuk/components/hint/fixtures.json +1 -1
- data/node_modules/govuk-frontend/govuk/components/hint/macro-options.json +1 -1
- data/node_modules/govuk-frontend/govuk/components/input/_index.scss +15 -3
- data/node_modules/govuk-frontend/govuk/components/input/fixtures.json +54 -41
- data/node_modules/govuk-frontend/govuk/components/input/macro-options.json +7 -1
- data/node_modules/govuk-frontend/govuk/components/input/template.njk +2 -1
- data/node_modules/govuk-frontend/govuk/components/inset-text/fixtures.json +1 -1
- data/node_modules/govuk-frontend/govuk/components/inset-text/macro-options.json +1 -1
- data/node_modules/govuk-frontend/govuk/components/label/fixtures.json +6 -6
- data/node_modules/govuk-frontend/govuk/components/label/macro-options.json +1 -1
- data/node_modules/govuk-frontend/govuk/components/notification-banner/fixtures.json +1 -1
- data/node_modules/govuk-frontend/govuk/components/notification-banner/macro-options.json +1 -1
- data/node_modules/govuk-frontend/govuk/components/notification-banner/notification-banner.js +49 -22
- data/node_modules/govuk-frontend/govuk/components/notification-banner/notification-banner.js.map +1 -1
- data/node_modules/govuk-frontend/govuk/components/pagination/fixtures.json +16 -16
- data/node_modules/govuk-frontend/govuk/components/pagination/macro-options.json +1 -1
- data/node_modules/govuk-frontend/govuk/components/panel/fixtures.json +10 -10
- data/node_modules/govuk-frontend/govuk/components/panel/macro-options.json +1 -1
- data/node_modules/govuk-frontend/govuk/components/phase-banner/fixtures.json +1 -1
- data/node_modules/govuk-frontend/govuk/components/phase-banner/macro-options.json +1 -1
- data/node_modules/govuk-frontend/govuk/components/radios/_index.scss +5 -5
- data/node_modules/govuk-frontend/govuk/components/radios/fixtures.json +46 -46
- data/node_modules/govuk-frontend/govuk/components/radios/macro-options.json +1 -1
- data/node_modules/govuk-frontend/govuk/components/radios/radios.js +65 -22
- data/node_modules/govuk-frontend/govuk/components/radios/radios.js.map +1 -1
- data/node_modules/govuk-frontend/govuk/components/radios/template.njk +2 -2
- data/node_modules/govuk-frontend/govuk/components/select/_index.scss +7 -1
- data/node_modules/govuk-frontend/govuk/components/select/fixtures.json +19 -20
- data/node_modules/govuk-frontend/govuk/components/select/macro-options.json +7 -1
- data/node_modules/govuk-frontend/govuk/components/select/template.njk +5 -2
- data/node_modules/govuk-frontend/govuk/components/skip-link/fixtures.json +1 -1
- data/node_modules/govuk-frontend/govuk/components/skip-link/macro-options.json +1 -1
- data/node_modules/govuk-frontend/govuk/components/skip-link/skip-link.js +41 -13
- data/node_modules/govuk-frontend/govuk/components/skip-link/skip-link.js.map +1 -1
- data/node_modules/govuk-frontend/govuk/components/summary-list/fixtures.json +34 -34
- data/node_modules/govuk-frontend/govuk/components/summary-list/macro-options.json +1 -1
- data/node_modules/govuk-frontend/govuk/components/table/fixtures.json +21 -21
- data/node_modules/govuk-frontend/govuk/components/table/macro-options.json +1 -1
- data/node_modules/govuk-frontend/govuk/components/tabs/fixtures.json +15 -15
- data/node_modules/govuk-frontend/govuk/components/tabs/macro-options.json +1 -1
- data/node_modules/govuk-frontend/govuk/components/tabs/tabs.js +178 -60
- data/node_modules/govuk-frontend/govuk/components/tabs/tabs.js.map +1 -1
- data/node_modules/govuk-frontend/govuk/components/tabs/template.njk +1 -1
- data/node_modules/govuk-frontend/govuk/components/tag/_index.scss +18 -18
- data/node_modules/govuk-frontend/govuk/components/tag/fixtures.json +1 -1
- data/node_modules/govuk-frontend/govuk/components/tag/macro-options.json +1 -1
- data/node_modules/govuk-frontend/govuk/components/textarea/_index.scss +8 -1
- data/node_modules/govuk-frontend/govuk/components/textarea/fixtures.json +18 -18
- data/node_modules/govuk-frontend/govuk/components/textarea/macro-options.json +7 -1
- data/node_modules/govuk-frontend/govuk/components/textarea/template.njk +2 -1
- data/node_modules/govuk-frontend/govuk/components/warning-text/fixtures.json +9 -5
- data/node_modules/govuk-frontend/govuk/components/warning-text/macro-options.json +3 -3
- data/node_modules/govuk-frontend/govuk/components/warning-text/template.njk +1 -1
- data/node_modules/govuk-frontend/govuk/core/_all.scss +1 -0
- data/node_modules/govuk-frontend/govuk/core/_govuk-frontend-version.scss +5 -0
- data/node_modules/govuk-frontend/govuk/helpers/_colour.scss +5 -2
- data/node_modules/govuk-frontend/govuk/helpers/_focused.scss +1 -1
- data/node_modules/govuk-frontend/govuk/helpers/_font-faces.scss +1 -1
- data/node_modules/govuk-frontend/govuk/i18n.js +38 -30
- data/node_modules/govuk-frontend/govuk/i18n.js.map +1 -1
- data/node_modules/govuk-frontend/govuk/macros/i18n.njk +12 -11
- data/node_modules/govuk-frontend/govuk/objects/_width-container.scss +1 -1
- data/node_modules/govuk-frontend/govuk/settings/_colours-organisations.scss +4 -0
- data/node_modules/govuk-frontend/govuk/settings/_ie8.scss +16 -0
- data/node_modules/govuk-frontend/govuk/settings/_links.scss +5 -1
- data/node_modules/govuk-frontend/govuk/tools/_ie8.scss +38 -2
- data/node_modules/govuk-frontend/govuk/vendor/polyfills/DOMTokenList.js +2 -1
- data/node_modules/govuk-frontend/govuk/vendor/polyfills/DOMTokenList.js.map +1 -1
- data/node_modules/govuk-frontend/govuk/vendor/polyfills/Date/now.js +2 -1
- data/node_modules/govuk-frontend/govuk/vendor/polyfills/Date/now.js.map +1 -1
- data/node_modules/govuk-frontend/govuk/vendor/polyfills/Document.js +2 -1
- data/node_modules/govuk-frontend/govuk/vendor/polyfills/Document.js.map +1 -1
- data/node_modules/govuk-frontend/govuk/vendor/polyfills/Element/prototype/classList.js +10 -3
- data/node_modules/govuk-frontend/govuk/vendor/polyfills/Element/prototype/classList.js.map +1 -1
- data/node_modules/govuk-frontend/govuk/vendor/polyfills/Element/prototype/closest.js +4 -1
- data/node_modules/govuk-frontend/govuk/vendor/polyfills/Element/prototype/closest.js.map +1 -1
- data/node_modules/govuk-frontend/govuk/vendor/polyfills/Element/prototype/dataset.js +13 -7
- data/node_modules/govuk-frontend/govuk/vendor/polyfills/Element/prototype/dataset.js.map +1 -1
- data/node_modules/govuk-frontend/govuk/vendor/polyfills/Element/prototype/matches.js +2 -1
- data/node_modules/govuk-frontend/govuk/vendor/polyfills/Element/prototype/matches.js.map +1 -1
- data/node_modules/govuk-frontend/govuk/vendor/polyfills/Element/prototype/nextElementSibling.js +8 -2
- data/node_modules/govuk-frontend/govuk/vendor/polyfills/Element/prototype/nextElementSibling.js.map +1 -1
- data/node_modules/govuk-frontend/govuk/vendor/polyfills/Element/prototype/previousElementSibling.js +8 -2
- data/node_modules/govuk-frontend/govuk/vendor/polyfills/Element/prototype/previousElementSibling.js.map +1 -1
- data/node_modules/govuk-frontend/govuk/vendor/polyfills/Element.js +4 -1
- data/node_modules/govuk-frontend/govuk/vendor/polyfills/Element.js.map +1 -1
- data/node_modules/govuk-frontend/govuk/vendor/polyfills/Event.js +10 -3
- data/node_modules/govuk-frontend/govuk/vendor/polyfills/Event.js.map +1 -1
- data/node_modules/govuk-frontend/govuk/vendor/polyfills/Function/prototype/bind.js +4 -1
- data/node_modules/govuk-frontend/govuk/vendor/polyfills/Function/prototype/bind.js.map +1 -1
- data/node_modules/govuk-frontend/govuk/vendor/polyfills/Object/defineProperty.js +2 -1
- data/node_modules/govuk-frontend/govuk/vendor/polyfills/Object/defineProperty.js.map +1 -1
- data/node_modules/govuk-frontend/govuk/vendor/polyfills/String/prototype/trim.js +3 -2
- data/node_modules/govuk-frontend/govuk/vendor/polyfills/String/prototype/trim.js.map +1 -1
- data/node_modules/govuk-frontend/govuk/vendor/polyfills/Window.js +2 -1
- data/node_modules/govuk-frontend/govuk/vendor/polyfills/Window.js.map +1 -1
- data/node_modules/govuk-frontend/govuk-esm/all.mjs +81 -60
- data/node_modules/govuk-frontend/govuk-esm/all.mjs.map +1 -0
- data/node_modules/govuk-frontend/govuk-esm/common/closest-attribute-value.mjs +12 -8
- data/node_modules/govuk-frontend/govuk-esm/common/closest-attribute-value.mjs.map +1 -0
- data/node_modules/govuk-frontend/govuk-esm/common/govuk-frontend-version.mjs +9 -0
- data/node_modules/govuk-frontend/govuk-esm/common/govuk-frontend-version.mjs.map +1 -0
- data/node_modules/govuk-frontend/govuk-esm/common/index.mjs +44 -29
- data/node_modules/govuk-frontend/govuk-esm/common/index.mjs.map +1 -0
- data/node_modules/govuk-frontend/govuk-esm/common/normalise-dataset.mjs +15 -9
- data/node_modules/govuk-frontend/govuk-esm/common/normalise-dataset.mjs.map +1 -0
- data/node_modules/govuk-frontend/govuk-esm/common.mjs +3 -5
- data/node_modules/govuk-frontend/govuk-esm/common.mjs.map +1 -0
- data/node_modules/govuk-frontend/govuk-esm/components/accordion/accordion.mjs +319 -211
- data/node_modules/govuk-frontend/govuk-esm/components/accordion/accordion.mjs.map +1 -0
- data/node_modules/govuk-frontend/govuk-esm/components/button/button.mjs +47 -30
- data/node_modules/govuk-frontend/govuk-esm/components/button/button.mjs.map +1 -0
- data/node_modules/govuk-frontend/govuk-esm/components/character-count/character-count.mjs +169 -115
- data/node_modules/govuk-frontend/govuk-esm/components/character-count/character-count.mjs.map +1 -0
- data/node_modules/govuk-frontend/govuk-esm/components/checkboxes/checkboxes.mjs +88 -51
- data/node_modules/govuk-frontend/govuk-esm/components/checkboxes/checkboxes.mjs.map +1 -0
- data/node_modules/govuk-frontend/govuk-esm/components/details/details.mjs +64 -54
- data/node_modules/govuk-frontend/govuk-esm/components/details/details.mjs.map +1 -0
- data/node_modules/govuk-frontend/govuk-esm/components/error-summary/error-summary.mjs +69 -50
- data/node_modules/govuk-frontend/govuk-esm/components/error-summary/error-summary.mjs.map +1 -0
- data/node_modules/govuk-frontend/govuk-esm/components/header/header.mjs +59 -35
- data/node_modules/govuk-frontend/govuk-esm/components/header/header.mjs.map +1 -0
- data/node_modules/govuk-frontend/govuk-esm/components/notification-banner/notification-banner.mjs +36 -25
- data/node_modules/govuk-frontend/govuk-esm/components/notification-banner/notification-banner.mjs.map +1 -0
- data/node_modules/govuk-frontend/govuk-esm/components/radios/radios.mjs +67 -38
- data/node_modules/govuk-frontend/govuk-esm/components/radios/radios.mjs.map +1 -0
- data/node_modules/govuk-frontend/govuk-esm/components/skip-link/skip-link.mjs +49 -32
- data/node_modules/govuk-frontend/govuk-esm/components/skip-link/skip-link.mjs.map +1 -0
- data/node_modules/govuk-frontend/govuk-esm/components/tabs/tabs.mjs +263 -163
- data/node_modules/govuk-frontend/govuk-esm/components/tabs/tabs.mjs.map +1 -0
- data/node_modules/govuk-frontend/govuk-esm/i18n.mjs +68 -57
- data/node_modules/govuk-frontend/govuk-esm/i18n.mjs.map +1 -0
- data/node_modules/govuk-frontend/govuk-esm/vendor/polyfills/DOMTokenList.mjs +5 -3
- data/node_modules/govuk-frontend/govuk-esm/vendor/polyfills/DOMTokenList.mjs.map +1 -0
- data/node_modules/govuk-frontend/govuk-esm/vendor/polyfills/Date/now.mjs +4 -2
- data/node_modules/govuk-frontend/govuk-esm/vendor/polyfills/Date/now.mjs.map +1 -0
- data/node_modules/govuk-frontend/govuk-esm/vendor/polyfills/Document.mjs +4 -2
- data/node_modules/govuk-frontend/govuk-esm/vendor/polyfills/Document.mjs.map +1 -0
- data/node_modules/govuk-frontend/govuk-esm/vendor/polyfills/Element/prototype/classList.mjs +7 -4
- data/node_modules/govuk-frontend/govuk-esm/vendor/polyfills/Element/prototype/classList.mjs.map +1 -0
- data/node_modules/govuk-frontend/govuk-esm/vendor/polyfills/Element/prototype/closest.mjs +5 -2
- data/node_modules/govuk-frontend/govuk-esm/vendor/polyfills/Element/prototype/closest.mjs.map +1 -0
- data/node_modules/govuk-frontend/govuk-esm/vendor/polyfills/Element/prototype/dataset.mjs +13 -10
- data/node_modules/govuk-frontend/govuk-esm/vendor/polyfills/Element/prototype/dataset.mjs.map +1 -0
- data/node_modules/govuk-frontend/govuk-esm/vendor/polyfills/Element/prototype/matches.mjs +4 -2
- data/node_modules/govuk-frontend/govuk-esm/vendor/polyfills/Element/prototype/matches.mjs.map +1 -0
- data/node_modules/govuk-frontend/govuk-esm/vendor/polyfills/Element/prototype/nextElementSibling.mjs +6 -3
- data/node_modules/govuk-frontend/govuk-esm/vendor/polyfills/Element/prototype/nextElementSibling.mjs.map +1 -0
- data/node_modules/govuk-frontend/govuk-esm/vendor/polyfills/Element/prototype/previousElementSibling.mjs +6 -3
- data/node_modules/govuk-frontend/govuk-esm/vendor/polyfills/Element/prototype/previousElementSibling.mjs.map +1 -0
- data/node_modules/govuk-frontend/govuk-esm/vendor/polyfills/Element.mjs +5 -2
- data/node_modules/govuk-frontend/govuk-esm/vendor/polyfills/Element.mjs.map +1 -0
- data/node_modules/govuk-frontend/govuk-esm/vendor/polyfills/Event.mjs +7 -4
- data/node_modules/govuk-frontend/govuk-esm/vendor/polyfills/Event.mjs.map +1 -0
- data/node_modules/govuk-frontend/govuk-esm/vendor/polyfills/Function/prototype/bind.mjs +5 -2
- data/node_modules/govuk-frontend/govuk-esm/vendor/polyfills/Function/prototype/bind.mjs.map +1 -0
- data/node_modules/govuk-frontend/govuk-esm/vendor/polyfills/Object/defineProperty.mjs +4 -2
- data/node_modules/govuk-frontend/govuk-esm/vendor/polyfills/Object/defineProperty.mjs.map +1 -0
- data/node_modules/govuk-frontend/govuk-esm/vendor/polyfills/String/prototype/trim.mjs +5 -3
- data/node_modules/govuk-frontend/govuk-esm/vendor/polyfills/String/prototype/trim.mjs.map +1 -0
- data/node_modules/govuk-frontend/govuk-esm/vendor/polyfills/Window.mjs +4 -2
- data/node_modules/govuk-frontend/govuk-esm/vendor/polyfills/Window.mjs.map +1 -0
- data/node_modules/govuk-frontend/govuk-prototype-kit/init.js +1 -0
- data/node_modules/govuk-frontend/govuk-prototype-kit.config.json +2 -1
- data/node_modules/govuk-frontend/package.json +3 -2
- metadata +43 -6
- /data/app/assets/images/govuk_publishing_components/crests/{dit_crest_13px.png → dbt_crest_13px.png} +0 -0
- /data/app/assets/images/govuk_publishing_components/crests/{dit_crest_13px_x2.png → dbt_crest_13px_x2.png} +0 -0
- /data/app/assets/images/govuk_publishing_components/crests/{dit_crest_18px.png → dbt_crest_18px.png} +0 -0
- /data/app/assets/images/govuk_publishing_components/crests/{dit_crest_18px_x2.png → dbt_crest_18px_x2.png} +0 -0
|
@@ -4,6 +4,13 @@
|
|
|
4
4
|
(factory((global.GOVUKFrontend = {})));
|
|
5
5
|
}(this, (function (exports) { 'use strict';
|
|
6
6
|
|
|
7
|
+
/*
|
|
8
|
+
* This variable is automatically overwritten during builds and releases.
|
|
9
|
+
* It doesn't need to be updated manually.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
var version = '4.6.0';
|
|
13
|
+
|
|
7
14
|
/**
|
|
8
15
|
* Common helpers which do not require polyfill.
|
|
9
16
|
*
|
|
@@ -19,8 +26,10 @@
|
|
|
19
26
|
* This seems to fail in IE8, requires more investigation.
|
|
20
27
|
* See: https://github.com/imagitama/nodelist-foreach-polyfill
|
|
21
28
|
*
|
|
22
|
-
* @
|
|
23
|
-
* @
|
|
29
|
+
* @deprecated Will be made private in v5.0
|
|
30
|
+
* @template {Node} ElementType
|
|
31
|
+
* @param {NodeListOf<ElementType>} nodes - NodeList from querySelectorAll()
|
|
32
|
+
* @param {nodeListIterator<ElementType>} callback - Callback function to run for each node
|
|
24
33
|
* @returns {void}
|
|
25
34
|
*/
|
|
26
35
|
function nodeListForEach (nodes, callback) {
|
|
@@ -37,6 +46,7 @@
|
|
|
37
46
|
* without them conflicting with each other.
|
|
38
47
|
* https://stackoverflow.com/a/8809472
|
|
39
48
|
*
|
|
49
|
+
* @deprecated Will be made private in v5.0
|
|
40
50
|
* @returns {string} Unique ID
|
|
41
51
|
*/
|
|
42
52
|
function generateUniqueID () {
|
|
@@ -58,6 +68,7 @@
|
|
|
58
68
|
* (e.g. {'i18n.showSection': 'Show section'}) and combines them together, with
|
|
59
69
|
* greatest priority on the LAST item passed in.
|
|
60
70
|
*
|
|
71
|
+
* @deprecated Will be made private in v5.0
|
|
61
72
|
* @returns {Object<string, unknown>} A flattened object of key-value pairs.
|
|
62
73
|
*/
|
|
63
74
|
function mergeConfigs (/* configObject1, configObject2, ...configObjects */) {
|
|
@@ -72,6 +83,7 @@
|
|
|
72
83
|
*/
|
|
73
84
|
var flattenObject = function (configObject) {
|
|
74
85
|
// Prepare an empty return object
|
|
86
|
+
/** @type {Object<string, unknown>} */
|
|
75
87
|
var flattenedObject = {};
|
|
76
88
|
|
|
77
89
|
/**
|
|
@@ -108,6 +120,7 @@
|
|
|
108
120
|
};
|
|
109
121
|
|
|
110
122
|
// Start with an empty object as our base
|
|
123
|
+
/** @type {Object<string, unknown>} */
|
|
111
124
|
var formattedConfigObject = {};
|
|
112
125
|
|
|
113
126
|
// Loop through each of the remaining passed objects and push their keys
|
|
@@ -129,6 +142,7 @@
|
|
|
129
142
|
* Extracts keys starting with a particular namespace from a flattened config
|
|
130
143
|
* object, removing the namespace in the process.
|
|
131
144
|
*
|
|
145
|
+
* @deprecated Will be made private in v5.0
|
|
132
146
|
* @param {Object<string, unknown>} configObject - The object to extract key-value pairs from.
|
|
133
147
|
* @param {string} namespace - The namespace to filter keys with.
|
|
134
148
|
* @returns {Object<string, unknown>} Flattened object with dot-separated key namespace removed
|
|
@@ -140,10 +154,14 @@
|
|
|
140
154
|
if (!configObject || typeof configObject !== 'object') {
|
|
141
155
|
throw new Error('Provide a `configObject` of type "object".')
|
|
142
156
|
}
|
|
157
|
+
|
|
143
158
|
if (!namespace || typeof namespace !== 'string') {
|
|
144
159
|
throw new Error('Provide a `namespace` of type "string" to filter the `configObject` by.')
|
|
145
160
|
}
|
|
161
|
+
|
|
162
|
+
/** @type {Object<string, unknown>} */
|
|
146
163
|
var newObject = {};
|
|
164
|
+
|
|
147
165
|
for (var key in configObject) {
|
|
148
166
|
// Split the key into parts, using . as our namespace separator
|
|
149
167
|
var keyParts = key.split('.');
|
|
@@ -164,14 +182,16 @@
|
|
|
164
182
|
}
|
|
165
183
|
|
|
166
184
|
/**
|
|
185
|
+
* @template {Node} ElementType
|
|
167
186
|
* @callback nodeListIterator
|
|
168
|
-
* @param {
|
|
187
|
+
* @param {ElementType} value - The current node being iterated on
|
|
169
188
|
* @param {number} index - The current index in the iteration
|
|
170
|
-
* @param {NodeListOf<
|
|
189
|
+
* @param {NodeListOf<ElementType>} nodes - NodeList from querySelectorAll()
|
|
171
190
|
* @returns {void}
|
|
172
191
|
*/
|
|
173
192
|
|
|
174
|
-
|
|
193
|
+
// @ts-nocheck
|
|
194
|
+
(function (undefined) {
|
|
175
195
|
|
|
176
196
|
// Detection from https://github.com/Financial-Times/polyfill-service/blob/master/packages/polyfill-library/polyfills/Object/defineProperty/detect.js
|
|
177
197
|
var detect = (
|
|
@@ -258,7 +278,8 @@
|
|
|
258
278
|
})
|
|
259
279
|
.call('object' === typeof window && window || 'object' === typeof self && self || 'object' === typeof global && global || {});
|
|
260
280
|
|
|
261
|
-
|
|
281
|
+
// @ts-nocheck
|
|
282
|
+
(function (undefined) {
|
|
262
283
|
|
|
263
284
|
// Detection from https://github.com/Financial-Times/polyfill-service/blob/master/packages/polyfill-library/polyfills/Document/detect.js
|
|
264
285
|
var detect = ("Document" in this);
|
|
@@ -285,6 +306,8 @@
|
|
|
285
306
|
})
|
|
286
307
|
.call('object' === typeof window && window || 'object' === typeof self && self || 'object' === typeof global && global || {});
|
|
287
308
|
|
|
309
|
+
// @ts-nocheck
|
|
310
|
+
|
|
288
311
|
(function(undefined) {
|
|
289
312
|
|
|
290
313
|
// Detection from https://github.com/Financial-Times/polyfill-service/blob/master/packages/polyfill-library/polyfills/Element/detect.js
|
|
@@ -398,6 +421,8 @@
|
|
|
398
421
|
})
|
|
399
422
|
.call('object' === typeof window && window || 'object' === typeof self && self || 'object' === typeof global && global || {});
|
|
400
423
|
|
|
424
|
+
// @ts-nocheck
|
|
425
|
+
|
|
401
426
|
(function(undefined) {
|
|
402
427
|
|
|
403
428
|
// Detection from https://raw.githubusercontent.com/Financial-Times/polyfill-library/13cf7c340974d128d557580b5e2dafcd1b1192d1/polyfills/Element/prototype/dataset/detect.js
|
|
@@ -418,10 +443,10 @@
|
|
|
418
443
|
var element = this;
|
|
419
444
|
var attributes = this.attributes;
|
|
420
445
|
var map = {};
|
|
421
|
-
|
|
446
|
+
|
|
422
447
|
for (var i = 0; i < attributes.length; i++) {
|
|
423
448
|
var attribute = attributes[i];
|
|
424
|
-
|
|
449
|
+
|
|
425
450
|
// This regex has been edited from the original polyfill, to add
|
|
426
451
|
// support for period (.) separators in data-* attribute names. These
|
|
427
452
|
// are allowed in the HTML spec, but were not covered by the original
|
|
@@ -429,11 +454,11 @@
|
|
|
429
454
|
if (attribute && attribute.name && (/^data-\w[.\w-]*$/).test(attribute.name)) {
|
|
430
455
|
var name = attribute.name;
|
|
431
456
|
var value = attribute.value;
|
|
432
|
-
|
|
457
|
+
|
|
433
458
|
var propName = name.substr(5).replace(/-./g, function (prop) {
|
|
434
459
|
return prop.charAt(1).toUpperCase();
|
|
435
460
|
});
|
|
436
|
-
|
|
461
|
+
|
|
437
462
|
// If this browser supports __defineGetter__ and __defineSetter__,
|
|
438
463
|
// continue using defineProperty. If not (like IE 8 and below), we use
|
|
439
464
|
// a hacky fallback which at least gives an object in the right format
|
|
@@ -457,18 +482,19 @@
|
|
|
457
482
|
|
|
458
483
|
}
|
|
459
484
|
}
|
|
460
|
-
|
|
485
|
+
|
|
461
486
|
return map;
|
|
462
487
|
}
|
|
463
488
|
});
|
|
464
489
|
|
|
465
490
|
}).call('object' === typeof window && window || 'object' === typeof self && self || 'object' === typeof global && global || {});
|
|
466
491
|
|
|
467
|
-
|
|
492
|
+
// @ts-nocheck
|
|
493
|
+
(function (undefined) {
|
|
468
494
|
|
|
469
495
|
// Detection from https://github.com/mdn/content/blob/cf607d68522cd35ee7670782d3ee3a361eaef2e4/files/en-us/web/javascript/reference/global_objects/string/trim/index.md#polyfill
|
|
470
496
|
var detect = ('trim' in String.prototype);
|
|
471
|
-
|
|
497
|
+
|
|
472
498
|
if (detect) return
|
|
473
499
|
|
|
474
500
|
// Polyfill from https://github.com/mdn/content/blob/cf607d68522cd35ee7670782d3ee3a361eaef2e4/files/en-us/web/javascript/reference/global_objects/string/trim/index.md#polyfill
|
|
@@ -491,6 +517,7 @@
|
|
|
491
517
|
* Designed to be used to convert config passed via data attributes (which are
|
|
492
518
|
* always strings) into something sensible.
|
|
493
519
|
*
|
|
520
|
+
* @deprecated Will be made private in v5.0
|
|
494
521
|
* @param {string} value - The value to normalise
|
|
495
522
|
* @returns {string | boolean | number | undefined} Normalised data
|
|
496
523
|
*/
|
|
@@ -511,7 +538,7 @@
|
|
|
511
538
|
|
|
512
539
|
// Empty / whitespace-only strings are considered finite so we need to check
|
|
513
540
|
// the length of the trimmed string as well
|
|
514
|
-
if (trimmedValue.length > 0 && isFinite(trimmedValue)) {
|
|
541
|
+
if (trimmedValue.length > 0 && isFinite(Number(trimmedValue))) {
|
|
515
542
|
return Number(trimmedValue)
|
|
516
543
|
}
|
|
517
544
|
|
|
@@ -523,10 +550,12 @@
|
|
|
523
550
|
*
|
|
524
551
|
* Loop over an object and normalise each value using normaliseData function
|
|
525
552
|
*
|
|
553
|
+
* @deprecated Will be made private in v5.0
|
|
526
554
|
* @param {DOMStringMap} dataset - HTML element dataset
|
|
527
555
|
* @returns {Object<string, unknown>} Normalised dataset
|
|
528
556
|
*/
|
|
529
557
|
function normaliseDataset (dataset) {
|
|
558
|
+
/** @type {Object<string, unknown>} */
|
|
530
559
|
var out = {};
|
|
531
560
|
|
|
532
561
|
for (var key in dataset) {
|
|
@@ -571,17 +600,17 @@
|
|
|
571
600
|
}
|
|
572
601
|
|
|
573
602
|
// If the `count` option is set, determine which plural suffix is needed and
|
|
574
|
-
// change the lookupKey to match. We check to see if it's
|
|
603
|
+
// change the lookupKey to match. We check to see if it's numeric instead of
|
|
575
604
|
// falsy, as this could legitimately be 0.
|
|
576
|
-
if (options && typeof options.count
|
|
605
|
+
if (options && typeof options.count === 'number') {
|
|
577
606
|
// Get the plural suffix
|
|
578
607
|
lookupKey = lookupKey + '.' + this.getPluralSuffix(lookupKey, options.count);
|
|
579
608
|
}
|
|
580
609
|
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
var translationString = this.translations[lookupKey];
|
|
610
|
+
// Fetch the translation string for that lookup key
|
|
611
|
+
var translationString = this.translations[lookupKey];
|
|
584
612
|
|
|
613
|
+
if (typeof translationString === 'string') {
|
|
585
614
|
// Check for ${} placeholders in the translation string
|
|
586
615
|
if (translationString.match(/%{(.\S+)}/)) {
|
|
587
616
|
if (!options) {
|
|
@@ -608,32 +637,46 @@
|
|
|
608
637
|
* @returns {string} The translation string to output, with ${} placeholders replaced
|
|
609
638
|
*/
|
|
610
639
|
I18n.prototype.replacePlaceholders = function (translationString, options) {
|
|
640
|
+
/** @type {Intl.NumberFormat | undefined} */
|
|
611
641
|
var formatter;
|
|
612
642
|
|
|
613
643
|
if (this.hasIntlNumberFormatSupport()) {
|
|
614
644
|
formatter = new Intl.NumberFormat(this.locale);
|
|
615
645
|
}
|
|
616
646
|
|
|
617
|
-
return translationString.replace(
|
|
618
|
-
|
|
619
|
-
var placeholderValue = options[placeholderKey];
|
|
647
|
+
return translationString.replace(
|
|
648
|
+
/%{(.\S+)}/g,
|
|
620
649
|
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
650
|
+
/**
|
|
651
|
+
* Replace translation string placeholders
|
|
652
|
+
*
|
|
653
|
+
* @param {string} placeholderWithBraces - Placeholder with braces
|
|
654
|
+
* @param {string} placeholderKey - Placeholder key
|
|
655
|
+
* @returns {string} Placeholder value
|
|
656
|
+
*/
|
|
657
|
+
function (placeholderWithBraces, placeholderKey) {
|
|
658
|
+
if (Object.prototype.hasOwnProperty.call(options, placeholderKey)) {
|
|
659
|
+
var placeholderValue = options[placeholderKey];
|
|
660
|
+
|
|
661
|
+
// If a user has passed `false` as the value for the placeholder
|
|
662
|
+
// treat it as though the value should not be displayed
|
|
663
|
+
if (placeholderValue === false || (
|
|
664
|
+
typeof placeholderValue !== 'number' &&
|
|
665
|
+
typeof placeholderValue !== 'string')
|
|
666
|
+
) {
|
|
667
|
+
return ''
|
|
668
|
+
}
|
|
626
669
|
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
670
|
+
// If the placeholder's value is a number, localise the number formatting
|
|
671
|
+
if (typeof placeholderValue === 'number') {
|
|
672
|
+
return formatter ? formatter.format(placeholderValue) : placeholderValue.toString()
|
|
673
|
+
}
|
|
631
674
|
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
675
|
+
return placeholderValue
|
|
676
|
+
} else {
|
|
677
|
+
throw new Error('i18n: no data found to replace ' + placeholderWithBraces + ' placeholder in string')
|
|
678
|
+
}
|
|
679
|
+
})
|
|
637
680
|
};
|
|
638
681
|
|
|
639
682
|
/**
|
|
@@ -749,7 +792,7 @@
|
|
|
749
792
|
* regardless of region. There are exceptions, however, (e.g. Portuguese) so
|
|
750
793
|
* this searches by both the full and shortened locale codes, just to be sure.
|
|
751
794
|
*
|
|
752
|
-
* @returns {
|
|
795
|
+
* @returns {string | undefined} The name of the pluralisation rule to use (a key for one
|
|
753
796
|
* of the functions in this.pluralRules)
|
|
754
797
|
*/
|
|
755
798
|
I18n.prototype.getPluralRulesForLocale = function () {
|
|
@@ -800,7 +843,7 @@
|
|
|
800
843
|
* Spanish: European Portuguese (pt-PT), Italian (it), Spanish (es)
|
|
801
844
|
* Welsh: Welsh (cy)
|
|
802
845
|
*
|
|
803
|
-
* @type {Object<
|
|
846
|
+
* @type {Object<string, string[]>}
|
|
804
847
|
*/
|
|
805
848
|
I18n.pluralRulesMap = {
|
|
806
849
|
arabic: ['ar'],
|
|
@@ -888,12 +931,6 @@
|
|
|
888
931
|
/* eslint-enable jsdoc/require-jsdoc */
|
|
889
932
|
};
|
|
890
933
|
|
|
891
|
-
/**
|
|
892
|
-
* Supported languages for plural rules
|
|
893
|
-
*
|
|
894
|
-
* @typedef {'arabic' | 'chinese' | 'french' | 'german' | 'irish' | 'russian' | 'scottish' | 'spanish' | 'welsh'} PluralRuleName
|
|
895
|
-
*/
|
|
896
|
-
|
|
897
934
|
/**
|
|
898
935
|
* Plural rule category mnemonic tags
|
|
899
936
|
*
|
|
@@ -915,7 +952,8 @@
|
|
|
915
952
|
* @property {string} [many] - Plural form used for many
|
|
916
953
|
*/
|
|
917
954
|
|
|
918
|
-
|
|
955
|
+
// @ts-nocheck
|
|
956
|
+
(function (undefined) {
|
|
919
957
|
|
|
920
958
|
// Detection from https://raw.githubusercontent.com/Financial-Times/polyfill-service/master/packages/polyfill-library/polyfills/DOMTokenList/detect.js
|
|
921
959
|
var detect = (
|
|
@@ -1180,6 +1218,8 @@
|
|
|
1180
1218
|
|
|
1181
1219
|
}).call('object' === typeof window && window || 'object' === typeof self && self || 'object' === typeof global && global || {});
|
|
1182
1220
|
|
|
1221
|
+
// @ts-nocheck
|
|
1222
|
+
|
|
1183
1223
|
(function(undefined) {
|
|
1184
1224
|
|
|
1185
1225
|
// Detection from https://raw.githubusercontent.com/Financial-Times/polyfill-service/8717a9e04ac7aff99b4980fbedead98036b0929a/packages/polyfill-library/polyfills/Element/prototype/classList/detect.js
|
|
@@ -1270,7 +1310,8 @@
|
|
|
1270
1310
|
|
|
1271
1311
|
}).call('object' === typeof window && window || 'object' === typeof self && self || 'object' === typeof global && global || {});
|
|
1272
1312
|
|
|
1273
|
-
|
|
1313
|
+
// @ts-nocheck
|
|
1314
|
+
(function (undefined) {
|
|
1274
1315
|
|
|
1275
1316
|
// Detection from https://raw.githubusercontent.com/Financial-Times/polyfill-service/1f3c09b402f65bf6e393f933a15ba63f1b86ef1f/packages/polyfill-library/polyfills/Element/prototype/matches/detect.js
|
|
1276
1317
|
var detect = (
|
|
@@ -1294,6 +1335,8 @@
|
|
|
1294
1335
|
|
|
1295
1336
|
}).call('object' === typeof window && window || 'object' === typeof self && self || 'object' === typeof global && global || {});
|
|
1296
1337
|
|
|
1338
|
+
// @ts-nocheck
|
|
1339
|
+
|
|
1297
1340
|
(function(undefined) {
|
|
1298
1341
|
|
|
1299
1342
|
// Detection from https://raw.githubusercontent.com/Financial-Times/polyfill-service/1f3c09b402f65bf6e393f933a15ba63f1b86ef1f/packages/polyfill-library/polyfills/Element/prototype/closest/detect.js
|
|
@@ -1317,7 +1360,8 @@
|
|
|
1317
1360
|
|
|
1318
1361
|
}).call('object' === typeof window && window || 'object' === typeof self && self || 'object' === typeof global && global || {});
|
|
1319
1362
|
|
|
1320
|
-
|
|
1363
|
+
// @ts-nocheck
|
|
1364
|
+
(function (undefined) {
|
|
1321
1365
|
|
|
1322
1366
|
// Detection from https://github.com/Financial-Times/polyfill-service/blob/master/packages/polyfill-library/polyfills/Window/detect.js
|
|
1323
1367
|
var detect = ('Window' in this);
|
|
@@ -1338,6 +1382,8 @@
|
|
|
1338
1382
|
})
|
|
1339
1383
|
.call('object' === typeof window && window || 'object' === typeof self && self || 'object' === typeof global && global || {});
|
|
1340
1384
|
|
|
1385
|
+
// @ts-nocheck
|
|
1386
|
+
|
|
1341
1387
|
(function(undefined) {
|
|
1342
1388
|
|
|
1343
1389
|
// Detection from https://github.com/Financial-Times/polyfill-service/blob/master/packages/polyfill-library/polyfills/Event/detect.js
|
|
@@ -1587,6 +1633,8 @@
|
|
|
1587
1633
|
})
|
|
1588
1634
|
.call('object' === typeof window && window || 'object' === typeof self && self || 'object' === typeof global && global || {});
|
|
1589
1635
|
|
|
1636
|
+
// @ts-nocheck
|
|
1637
|
+
|
|
1590
1638
|
(function(undefined) {
|
|
1591
1639
|
// Detection from https://github.com/Financial-Times/polyfill-service/blob/master/packages/polyfill-library/polyfills/Function/prototype/bind/detect.js
|
|
1592
1640
|
var detect = 'bind' in Function.prototype;
|
|
@@ -1775,57 +1823,119 @@
|
|
|
1775
1823
|
* attribute, which also provides accessibility.
|
|
1776
1824
|
*
|
|
1777
1825
|
* @class
|
|
1778
|
-
* @param {
|
|
1826
|
+
* @param {Element} $module - HTML element to use for accordion
|
|
1779
1827
|
* @param {AccordionConfig} [config] - Accordion config
|
|
1780
1828
|
*/
|
|
1781
1829
|
function Accordion ($module, config) {
|
|
1830
|
+
if (!($module instanceof HTMLElement)) {
|
|
1831
|
+
return this
|
|
1832
|
+
}
|
|
1833
|
+
|
|
1834
|
+
/** @deprecated Will be made private in v5.0 */
|
|
1782
1835
|
this.$module = $module;
|
|
1783
1836
|
|
|
1784
1837
|
var defaultConfig = {
|
|
1785
|
-
i18n: ACCORDION_TRANSLATIONS
|
|
1838
|
+
i18n: ACCORDION_TRANSLATIONS,
|
|
1839
|
+
rememberExpanded: true
|
|
1786
1840
|
};
|
|
1787
1841
|
|
|
1842
|
+
/**
|
|
1843
|
+
* @deprecated Will be made private in v5.0
|
|
1844
|
+
* @type {AccordionConfig}
|
|
1845
|
+
*/
|
|
1788
1846
|
this.config = mergeConfigs(
|
|
1789
1847
|
defaultConfig,
|
|
1790
1848
|
config || {},
|
|
1791
1849
|
normaliseDataset($module.dataset)
|
|
1792
1850
|
);
|
|
1793
1851
|
|
|
1852
|
+
/** @deprecated Will be made private in v5.0 */
|
|
1794
1853
|
this.i18n = new I18n(extractConfigByNamespace(this.config, 'i18n'));
|
|
1795
1854
|
|
|
1855
|
+
/** @deprecated Will be made private in v5.0 */
|
|
1796
1856
|
this.controlsClass = 'govuk-accordion__controls';
|
|
1857
|
+
|
|
1858
|
+
/** @deprecated Will be made private in v5.0 */
|
|
1797
1859
|
this.showAllClass = 'govuk-accordion__show-all';
|
|
1860
|
+
|
|
1861
|
+
/** @deprecated Will be made private in v5.0 */
|
|
1798
1862
|
this.showAllTextClass = 'govuk-accordion__show-all-text';
|
|
1799
1863
|
|
|
1864
|
+
/** @deprecated Will be made private in v5.0 */
|
|
1800
1865
|
this.sectionClass = 'govuk-accordion__section';
|
|
1866
|
+
|
|
1867
|
+
/** @deprecated Will be made private in v5.0 */
|
|
1801
1868
|
this.sectionExpandedClass = 'govuk-accordion__section--expanded';
|
|
1869
|
+
|
|
1870
|
+
/** @deprecated Will be made private in v5.0 */
|
|
1802
1871
|
this.sectionButtonClass = 'govuk-accordion__section-button';
|
|
1872
|
+
|
|
1873
|
+
/** @deprecated Will be made private in v5.0 */
|
|
1803
1874
|
this.sectionHeaderClass = 'govuk-accordion__section-header';
|
|
1875
|
+
|
|
1876
|
+
/** @deprecated Will be made private in v5.0 */
|
|
1804
1877
|
this.sectionHeadingClass = 'govuk-accordion__section-heading';
|
|
1878
|
+
|
|
1879
|
+
/** @deprecated Will be made private in v5.0 */
|
|
1805
1880
|
this.sectionHeadingDividerClass = 'govuk-accordion__section-heading-divider';
|
|
1881
|
+
|
|
1882
|
+
/** @deprecated Will be made private in v5.0 */
|
|
1806
1883
|
this.sectionHeadingTextClass = 'govuk-accordion__section-heading-text';
|
|
1884
|
+
|
|
1885
|
+
/** @deprecated Will be made private in v5.0 */
|
|
1807
1886
|
this.sectionHeadingTextFocusClass = 'govuk-accordion__section-heading-text-focus';
|
|
1808
1887
|
|
|
1888
|
+
/** @deprecated Will be made private in v5.0 */
|
|
1809
1889
|
this.sectionShowHideToggleClass = 'govuk-accordion__section-toggle';
|
|
1890
|
+
|
|
1891
|
+
/** @deprecated Will be made private in v5.0 */
|
|
1810
1892
|
this.sectionShowHideToggleFocusClass = 'govuk-accordion__section-toggle-focus';
|
|
1893
|
+
|
|
1894
|
+
/** @deprecated Will be made private in v5.0 */
|
|
1811
1895
|
this.sectionShowHideTextClass = 'govuk-accordion__section-toggle-text';
|
|
1896
|
+
|
|
1897
|
+
/** @deprecated Will be made private in v5.0 */
|
|
1812
1898
|
this.upChevronIconClass = 'govuk-accordion-nav__chevron';
|
|
1899
|
+
|
|
1900
|
+
/** @deprecated Will be made private in v5.0 */
|
|
1813
1901
|
this.downChevronIconClass = 'govuk-accordion-nav__chevron--down';
|
|
1814
1902
|
|
|
1903
|
+
/** @deprecated Will be made private in v5.0 */
|
|
1815
1904
|
this.sectionSummaryClass = 'govuk-accordion__section-summary';
|
|
1905
|
+
|
|
1906
|
+
/** @deprecated Will be made private in v5.0 */
|
|
1816
1907
|
this.sectionSummaryFocusClass = 'govuk-accordion__section-summary-focus';
|
|
1908
|
+
|
|
1909
|
+
/** @deprecated Will be made private in v5.0 */
|
|
1817
1910
|
this.sectionContentClass = 'govuk-accordion__section-content';
|
|
1818
1911
|
|
|
1819
|
-
|
|
1912
|
+
var $sections = this.$module.querySelectorAll('.' + this.sectionClass);
|
|
1913
|
+
if (!$sections.length) {
|
|
1914
|
+
return this
|
|
1915
|
+
}
|
|
1916
|
+
|
|
1917
|
+
/** @deprecated Will be made private in v5.0 */
|
|
1918
|
+
this.$sections = $sections;
|
|
1919
|
+
|
|
1920
|
+
/** @deprecated Will be made private in v5.0 */
|
|
1820
1921
|
this.browserSupportsSessionStorage = helper.checkForSessionStorage();
|
|
1922
|
+
|
|
1923
|
+
/** @deprecated Will be made private in v5.0 */
|
|
1924
|
+
this.$showAllButton = null;
|
|
1925
|
+
|
|
1926
|
+
/** @deprecated Will be made private in v5.0 */
|
|
1927
|
+
this.$showAllIcon = null;
|
|
1928
|
+
|
|
1929
|
+
/** @deprecated Will be made private in v5.0 */
|
|
1930
|
+
this.$showAllText = null;
|
|
1821
1931
|
}
|
|
1822
1932
|
|
|
1823
1933
|
/**
|
|
1824
1934
|
* Initialise component
|
|
1825
1935
|
*/
|
|
1826
1936
|
Accordion.prototype.init = function () {
|
|
1827
|
-
// Check
|
|
1828
|
-
if (!this.$module) {
|
|
1937
|
+
// Check that required elements are present
|
|
1938
|
+
if (!this.$module || !this.$sections) {
|
|
1829
1939
|
return
|
|
1830
1940
|
}
|
|
1831
1941
|
|
|
@@ -1839,6 +1949,8 @@
|
|
|
1839
1949
|
|
|
1840
1950
|
/**
|
|
1841
1951
|
* Initialise controls and set attributes
|
|
1952
|
+
*
|
|
1953
|
+
* @deprecated Will be made private in v5.0
|
|
1842
1954
|
*/
|
|
1843
1955
|
Accordion.prototype.initControls = function () {
|
|
1844
1956
|
// Create "Show all" button and set attributes
|
|
@@ -1874,28 +1986,38 @@
|
|
|
1874
1986
|
|
|
1875
1987
|
/**
|
|
1876
1988
|
* Initialise section headers
|
|
1989
|
+
*
|
|
1990
|
+
* @deprecated Will be made private in v5.0
|
|
1877
1991
|
*/
|
|
1878
1992
|
Accordion.prototype.initSectionHeaders = function () {
|
|
1879
|
-
|
|
1880
|
-
|
|
1993
|
+
var $component = this;
|
|
1994
|
+
var $sections = this.$sections;
|
|
1995
|
+
|
|
1996
|
+
// Loop through sections
|
|
1997
|
+
nodeListForEach($sections, function ($section, i) {
|
|
1998
|
+
var $header = $section.querySelector('.' + $component.sectionHeaderClass);
|
|
1999
|
+
if (!$header) {
|
|
2000
|
+
return
|
|
2001
|
+
}
|
|
2002
|
+
|
|
1881
2003
|
// Set header attributes
|
|
1882
|
-
|
|
1883
|
-
|
|
1884
|
-
this.setExpanded(this.isExpanded($section), $section);
|
|
2004
|
+
$component.constructHeaderMarkup($header, i);
|
|
2005
|
+
$component.setExpanded($component.isExpanded($section), $section);
|
|
1885
2006
|
|
|
1886
2007
|
// Handle events
|
|
1887
|
-
$header.addEventListener('click',
|
|
2008
|
+
$header.addEventListener('click', $component.onSectionToggle.bind($component, $section));
|
|
1888
2009
|
|
|
1889
2010
|
// See if there is any state stored in sessionStorage and set the sections to
|
|
1890
2011
|
// open or closed.
|
|
1891
|
-
|
|
1892
|
-
}
|
|
2012
|
+
$component.setInitialState($section);
|
|
2013
|
+
});
|
|
1893
2014
|
};
|
|
1894
2015
|
|
|
1895
2016
|
/**
|
|
1896
2017
|
* Construct section header
|
|
1897
2018
|
*
|
|
1898
|
-
* @
|
|
2019
|
+
* @deprecated Will be made private in v5.0
|
|
2020
|
+
* @param {Element} $header - Section header
|
|
1899
2021
|
* @param {number} index - Section index
|
|
1900
2022
|
*/
|
|
1901
2023
|
Accordion.prototype.constructHeaderMarkup = function ($header, index) {
|
|
@@ -1903,10 +2025,14 @@
|
|
|
1903
2025
|
var $heading = $header.querySelector('.' + this.sectionHeadingClass);
|
|
1904
2026
|
var $summary = $header.querySelector('.' + this.sectionSummaryClass);
|
|
1905
2027
|
|
|
2028
|
+
if (!$span || !$heading) {
|
|
2029
|
+
return
|
|
2030
|
+
}
|
|
2031
|
+
|
|
1906
2032
|
// Create a button element that will replace the '.govuk-accordion__section-button' span
|
|
1907
2033
|
var $button = document.createElement('button');
|
|
1908
2034
|
$button.setAttribute('type', 'button');
|
|
1909
|
-
$button.setAttribute('aria-controls', this.$module.id + '-content-' + (index + 1));
|
|
2035
|
+
$button.setAttribute('aria-controls', this.$module.id + '-content-' + (index + 1).toString());
|
|
1910
2036
|
|
|
1911
2037
|
// Copy all attributes (https://developer.mozilla.org/en-US/docs/Web/API/Element/attributes) from $span to $button
|
|
1912
2038
|
for (var i = 0; i < $span.attributes.length; i++) {
|
|
@@ -1960,7 +2086,7 @@
|
|
|
1960
2086
|
$button.appendChild(this.getButtonPunctuationEl());
|
|
1961
2087
|
|
|
1962
2088
|
// If summary content exists add to DOM in correct order
|
|
1963
|
-
if (
|
|
2089
|
+
if ($summary) {
|
|
1964
2090
|
// Create a new `span` element and copy the summary line content from the original `div` to the
|
|
1965
2091
|
// new `span`
|
|
1966
2092
|
// This is because the summary line text is now inside a button element, which can only contain
|
|
@@ -1997,10 +2123,19 @@
|
|
|
1997
2123
|
/**
|
|
1998
2124
|
* When a section is opened by the user agent via the 'beforematch' event
|
|
1999
2125
|
*
|
|
2126
|
+
* @deprecated Will be made private in v5.0
|
|
2000
2127
|
* @param {Event} event - Generic event
|
|
2001
2128
|
*/
|
|
2002
2129
|
Accordion.prototype.onBeforeMatch = function (event) {
|
|
2003
|
-
var $
|
|
2130
|
+
var $fragment = event.target;
|
|
2131
|
+
|
|
2132
|
+
// Handle elements with `.closest()` support only
|
|
2133
|
+
if (!($fragment instanceof Element)) {
|
|
2134
|
+
return
|
|
2135
|
+
}
|
|
2136
|
+
|
|
2137
|
+
// Handle when fragment is inside section
|
|
2138
|
+
var $section = $fragment.closest('.' + this.sectionClass);
|
|
2004
2139
|
if ($section) {
|
|
2005
2140
|
this.setExpanded(true, $section);
|
|
2006
2141
|
}
|
|
@@ -2009,7 +2144,8 @@
|
|
|
2009
2144
|
/**
|
|
2010
2145
|
* When section toggled, set and store state
|
|
2011
2146
|
*
|
|
2012
|
-
* @
|
|
2147
|
+
* @deprecated Will be made private in v5.0
|
|
2148
|
+
* @param {Element} $section - Section element
|
|
2013
2149
|
*/
|
|
2014
2150
|
Accordion.prototype.onSectionToggle = function ($section) {
|
|
2015
2151
|
var expanded = this.isExpanded($section);
|
|
@@ -2021,26 +2157,31 @@
|
|
|
2021
2157
|
|
|
2022
2158
|
/**
|
|
2023
2159
|
* When Open/Close All toggled, set and store state
|
|
2160
|
+
*
|
|
2161
|
+
* @deprecated Will be made private in v5.0
|
|
2024
2162
|
*/
|
|
2025
2163
|
Accordion.prototype.onShowOrHideAllToggle = function () {
|
|
2026
|
-
var $
|
|
2164
|
+
var $component = this;
|
|
2027
2165
|
var $sections = this.$sections;
|
|
2166
|
+
|
|
2028
2167
|
var nowExpanded = !this.checkIfAllSectionsOpen();
|
|
2029
2168
|
|
|
2169
|
+
// Loop through sections
|
|
2030
2170
|
nodeListForEach($sections, function ($section) {
|
|
2031
|
-
$
|
|
2171
|
+
$component.setExpanded(nowExpanded, $section);
|
|
2032
2172
|
// Store the state in sessionStorage when a change is triggered
|
|
2033
|
-
$
|
|
2173
|
+
$component.storeState($section);
|
|
2034
2174
|
});
|
|
2035
2175
|
|
|
2036
|
-
$
|
|
2176
|
+
$component.updateShowAllButton(nowExpanded);
|
|
2037
2177
|
};
|
|
2038
2178
|
|
|
2039
2179
|
/**
|
|
2040
2180
|
* Set section attributes when opened/closed
|
|
2041
2181
|
*
|
|
2182
|
+
* @deprecated Will be made private in v5.0
|
|
2042
2183
|
* @param {boolean} expanded - Section expanded
|
|
2043
|
-
* @param {
|
|
2184
|
+
* @param {Element} $section - Section element
|
|
2044
2185
|
*/
|
|
2045
2186
|
Accordion.prototype.setExpanded = function (expanded, $section) {
|
|
2046
2187
|
var $showHideIcon = $section.querySelector('.' + this.upChevronIconClass);
|
|
@@ -2048,23 +2189,30 @@
|
|
|
2048
2189
|
var $button = $section.querySelector('.' + this.sectionButtonClass);
|
|
2049
2190
|
var $content = $section.querySelector('.' + this.sectionContentClass);
|
|
2050
2191
|
|
|
2192
|
+
if (!$showHideIcon ||
|
|
2193
|
+
!($showHideText instanceof HTMLElement) ||
|
|
2194
|
+
!$button ||
|
|
2195
|
+
!$content) {
|
|
2196
|
+
return
|
|
2197
|
+
}
|
|
2198
|
+
|
|
2051
2199
|
var newButtonText = expanded
|
|
2052
2200
|
? this.i18n.t('hideSection')
|
|
2053
2201
|
: this.i18n.t('showSection');
|
|
2054
2202
|
|
|
2055
2203
|
$showHideText.innerText = newButtonText;
|
|
2056
|
-
$button.setAttribute('aria-expanded', expanded);
|
|
2204
|
+
$button.setAttribute('aria-expanded', expanded.toString());
|
|
2057
2205
|
|
|
2058
2206
|
// Update aria-label combining
|
|
2059
2207
|
var ariaLabelParts = [];
|
|
2060
2208
|
|
|
2061
2209
|
var $headingText = $section.querySelector('.' + this.sectionHeadingTextClass);
|
|
2062
|
-
if ($headingText) {
|
|
2210
|
+
if ($headingText instanceof HTMLElement) {
|
|
2063
2211
|
ariaLabelParts.push($headingText.innerText.trim());
|
|
2064
2212
|
}
|
|
2065
2213
|
|
|
2066
2214
|
var $summary = $section.querySelector('.' + this.sectionSummaryClass);
|
|
2067
|
-
if ($summary) {
|
|
2215
|
+
if ($summary instanceof HTMLElement) {
|
|
2068
2216
|
ariaLabelParts.push($summary.innerText.trim());
|
|
2069
2217
|
}
|
|
2070
2218
|
|
|
@@ -2099,7 +2247,8 @@
|
|
|
2099
2247
|
/**
|
|
2100
2248
|
* Get state of section
|
|
2101
2249
|
*
|
|
2102
|
-
* @
|
|
2250
|
+
* @deprecated Will be made private in v5.0
|
|
2251
|
+
* @param {Element} $section - Section element
|
|
2103
2252
|
* @returns {boolean} True if expanded
|
|
2104
2253
|
*/
|
|
2105
2254
|
Accordion.prototype.isExpanded = function ($section) {
|
|
@@ -2109,6 +2258,7 @@
|
|
|
2109
2258
|
/**
|
|
2110
2259
|
* Check if all sections are open
|
|
2111
2260
|
*
|
|
2261
|
+
* @deprecated Will be made private in v5.0
|
|
2112
2262
|
* @returns {boolean} True if all sections are open
|
|
2113
2263
|
*/
|
|
2114
2264
|
Accordion.prototype.checkIfAllSectionsOpen = function () {
|
|
@@ -2124,6 +2274,7 @@
|
|
|
2124
2274
|
/**
|
|
2125
2275
|
* Update "Show all sections" button
|
|
2126
2276
|
*
|
|
2277
|
+
* @deprecated Will be made private in v5.0
|
|
2127
2278
|
* @param {boolean} expanded - Section expanded
|
|
2128
2279
|
*/
|
|
2129
2280
|
Accordion.prototype.updateShowAllButton = function (expanded) {
|
|
@@ -2131,7 +2282,7 @@
|
|
|
2131
2282
|
? this.i18n.t('hideAllSections')
|
|
2132
2283
|
: this.i18n.t('showAllSections');
|
|
2133
2284
|
|
|
2134
|
-
this.$showAllButton.setAttribute('aria-expanded', expanded);
|
|
2285
|
+
this.$showAllButton.setAttribute('aria-expanded', expanded.toString());
|
|
2135
2286
|
this.$showAllText.innerText = newButtonText;
|
|
2136
2287
|
|
|
2137
2288
|
// Swap icon, toggle class
|
|
@@ -2165,10 +2316,11 @@
|
|
|
2165
2316
|
/**
|
|
2166
2317
|
* Set the state of the accordions in sessionStorage
|
|
2167
2318
|
*
|
|
2168
|
-
* @
|
|
2319
|
+
* @deprecated Will be made private in v5.0
|
|
2320
|
+
* @param {Element} $section - Section element
|
|
2169
2321
|
*/
|
|
2170
2322
|
Accordion.prototype.storeState = function ($section) {
|
|
2171
|
-
if (this.browserSupportsSessionStorage) {
|
|
2323
|
+
if (this.browserSupportsSessionStorage && this.config.rememberExpanded) {
|
|
2172
2324
|
// We need a unique way of identifying each content in the Accordion. Since
|
|
2173
2325
|
// an `#id` should be unique and an `id` is required for `aria-` attributes
|
|
2174
2326
|
// `id` can be safely used.
|
|
@@ -2189,10 +2341,11 @@
|
|
|
2189
2341
|
/**
|
|
2190
2342
|
* Read the state of the accordions from sessionStorage
|
|
2191
2343
|
*
|
|
2192
|
-
* @
|
|
2344
|
+
* @deprecated Will be made private in v5.0
|
|
2345
|
+
* @param {Element} $section - Section element
|
|
2193
2346
|
*/
|
|
2194
2347
|
Accordion.prototype.setInitialState = function ($section) {
|
|
2195
|
-
if (this.browserSupportsSessionStorage) {
|
|
2348
|
+
if (this.browserSupportsSessionStorage && this.config.rememberExpanded) {
|
|
2196
2349
|
var $button = $section.querySelector('.' + this.sectionButtonClass);
|
|
2197
2350
|
|
|
2198
2351
|
if ($button) {
|
|
@@ -2213,7 +2366,8 @@
|
|
|
2213
2366
|
* into thematic chunks.
|
|
2214
2367
|
* See https://github.com/alphagov/govuk-frontend/issues/2327#issuecomment-922957442
|
|
2215
2368
|
*
|
|
2216
|
-
* @
|
|
2369
|
+
* @deprecated Will be made private in v5.0
|
|
2370
|
+
* @returns {Element} DOM element
|
|
2217
2371
|
*/
|
|
2218
2372
|
Accordion.prototype.getButtonPunctuationEl = function () {
|
|
2219
2373
|
var $punctuationEl = document.createElement('span');
|
|
@@ -2227,6 +2381,8 @@
|
|
|
2227
2381
|
*
|
|
2228
2382
|
* @typedef {object} AccordionConfig
|
|
2229
2383
|
* @property {AccordionTranslations} [i18n = ACCORDION_TRANSLATIONS] - See constant {@link ACCORDION_TRANSLATIONS}
|
|
2384
|
+
* @property {boolean} [rememberExpanded] - Whether the expanded and collapsed
|
|
2385
|
+
* state of each section is remembered and restored when navigating.
|
|
2230
2386
|
*/
|
|
2231
2387
|
|
|
2232
2388
|
/**
|
|
@@ -2238,17 +2394,17 @@
|
|
|
2238
2394
|
* the visible text shown on screen, and text to help assistive technology users
|
|
2239
2395
|
* for the buttons toggling each section.
|
|
2240
2396
|
* @property {string} [hideAllSections] - The text content for the 'Hide all
|
|
2241
|
-
*
|
|
2397
|
+
* sections' button, used when at least one section is expanded.
|
|
2242
2398
|
* @property {string} [hideSection] - The text content for the 'Hide'
|
|
2243
|
-
*
|
|
2399
|
+
* button, used when a section is expanded.
|
|
2244
2400
|
* @property {string} [hideSectionAriaLabel] - The text content appended to the
|
|
2245
|
-
*
|
|
2401
|
+
* 'Hide' button's accessible name when a section is expanded.
|
|
2246
2402
|
* @property {string} [showAllSections] - The text content for the 'Show all
|
|
2247
|
-
*
|
|
2403
|
+
* sections' button, used when all sections are collapsed.
|
|
2248
2404
|
* @property {string} [showSection] - The text content for the 'Show'
|
|
2249
|
-
*
|
|
2405
|
+
* button, used when a section is collapsed.
|
|
2250
2406
|
* @property {string} [showSectionAriaLabel] - The text content appended to the
|
|
2251
|
-
*
|
|
2407
|
+
* 'Show' button's accessible name when a section is expanded.
|
|
2252
2408
|
*/
|
|
2253
2409
|
|
|
2254
2410
|
/* eslint-disable es-x/no-function-prototype-bind -- Polyfill imported */
|
|
@@ -2260,20 +2416,28 @@
|
|
|
2260
2416
|
* JavaScript enhancements for the Button component
|
|
2261
2417
|
*
|
|
2262
2418
|
* @class
|
|
2263
|
-
* @param {
|
|
2419
|
+
* @param {Element} $module - HTML element to use for button
|
|
2264
2420
|
* @param {ButtonConfig} [config] - Button config
|
|
2265
2421
|
*/
|
|
2266
2422
|
function Button ($module, config) {
|
|
2267
|
-
if (
|
|
2423
|
+
if (!($module instanceof HTMLElement)) {
|
|
2268
2424
|
return this
|
|
2269
2425
|
}
|
|
2270
2426
|
|
|
2427
|
+
/** @deprecated Will be made private in v5.0 */
|
|
2271
2428
|
this.$module = $module;
|
|
2429
|
+
|
|
2430
|
+
/** @deprecated Will be made private in v5.0 */
|
|
2272
2431
|
this.debounceFormSubmitTimer = null;
|
|
2273
2432
|
|
|
2274
2433
|
var defaultConfig = {
|
|
2275
2434
|
preventDoubleClick: false
|
|
2276
2435
|
};
|
|
2436
|
+
|
|
2437
|
+
/**
|
|
2438
|
+
* @deprecated Will be made private in v5.0
|
|
2439
|
+
* @type {ButtonConfig}
|
|
2440
|
+
*/
|
|
2277
2441
|
this.config = mergeConfigs(
|
|
2278
2442
|
defaultConfig,
|
|
2279
2443
|
config || {},
|
|
@@ -2285,6 +2449,7 @@
|
|
|
2285
2449
|
* Initialise component
|
|
2286
2450
|
*/
|
|
2287
2451
|
Button.prototype.init = function () {
|
|
2452
|
+
// Check that required elements are present
|
|
2288
2453
|
if (!this.$module) {
|
|
2289
2454
|
return
|
|
2290
2455
|
}
|
|
@@ -2301,12 +2466,19 @@
|
|
|
2301
2466
|
*
|
|
2302
2467
|
* See https://github.com/alphagov/govuk_elements/pull/272#issuecomment-233028270
|
|
2303
2468
|
*
|
|
2469
|
+
* @deprecated Will be made private in v5.0
|
|
2304
2470
|
* @param {KeyboardEvent} event - Keydown event
|
|
2305
2471
|
*/
|
|
2306
2472
|
Button.prototype.handleKeyDown = function (event) {
|
|
2307
2473
|
var $target = event.target;
|
|
2308
2474
|
|
|
2309
|
-
|
|
2475
|
+
// Handle space bar only
|
|
2476
|
+
if (event.keyCode !== KEY_SPACE) {
|
|
2477
|
+
return
|
|
2478
|
+
}
|
|
2479
|
+
|
|
2480
|
+
// Handle elements with [role="button"] only
|
|
2481
|
+
if ($target instanceof HTMLElement && $target.getAttribute('role') === 'button') {
|
|
2310
2482
|
event.preventDefault(); // prevent the page from scrolling
|
|
2311
2483
|
$target.click();
|
|
2312
2484
|
}
|
|
@@ -2319,6 +2491,7 @@
|
|
|
2319
2491
|
* stops people accidentally causing multiple form submissions by double
|
|
2320
2492
|
* clicking buttons.
|
|
2321
2493
|
*
|
|
2494
|
+
* @deprecated Will be made private in v5.0
|
|
2322
2495
|
* @param {MouseEvent} event - Mouse click event
|
|
2323
2496
|
* @returns {undefined | false} Returns undefined, or false when debounced
|
|
2324
2497
|
*/
|
|
@@ -2343,26 +2516,27 @@
|
|
|
2343
2516
|
* Button config
|
|
2344
2517
|
*
|
|
2345
2518
|
* @typedef {object} ButtonConfig
|
|
2346
|
-
* @property {boolean} [preventDoubleClick = false] -
|
|
2347
|
-
*
|
|
2348
|
-
* multiple times.
|
|
2519
|
+
* @property {boolean} [preventDoubleClick = false] - Prevent accidental double
|
|
2520
|
+
* clicks on submit buttons from submitting forms multiple times.
|
|
2349
2521
|
*/
|
|
2350
2522
|
|
|
2351
2523
|
/**
|
|
2352
2524
|
* Returns the value of the given attribute closest to the given element (including itself)
|
|
2353
2525
|
*
|
|
2354
|
-
* @
|
|
2526
|
+
* @deprecated Will be made private in v5.0
|
|
2527
|
+
* @param {Element} $element - The element to start walking the DOM tree up
|
|
2355
2528
|
* @param {string} attributeName - The name of the attribute
|
|
2356
|
-
* @returns {string |
|
|
2529
|
+
* @returns {string | null} Attribute value
|
|
2357
2530
|
*/
|
|
2358
2531
|
function closestAttributeValue ($element, attributeName) {
|
|
2359
|
-
var closestElementWithAttribute = $element.closest('[' + attributeName + ']');
|
|
2360
|
-
|
|
2361
|
-
|
|
2362
|
-
|
|
2532
|
+
var $closestElementWithAttribute = $element.closest('[' + attributeName + ']');
|
|
2533
|
+
return $closestElementWithAttribute
|
|
2534
|
+
? $closestElementWithAttribute.getAttribute(attributeName)
|
|
2535
|
+
: null
|
|
2363
2536
|
}
|
|
2364
2537
|
|
|
2365
|
-
|
|
2538
|
+
// @ts-nocheck
|
|
2539
|
+
(function (undefined) {
|
|
2366
2540
|
|
|
2367
2541
|
// Detection from https://github.com/Financial-Times/polyfill-library/blob/v3.111.0/polyfills/Date/now/detect.js
|
|
2368
2542
|
var detect = ('Date' in self && 'now' in self.Date && 'getTime' in self.Date.prototype);
|
|
@@ -2421,11 +2595,21 @@
|
|
|
2421
2595
|
* of the available characters/words has been entered.
|
|
2422
2596
|
*
|
|
2423
2597
|
* @class
|
|
2424
|
-
* @param {
|
|
2598
|
+
* @param {Element} $module - HTML element to use for character count
|
|
2425
2599
|
* @param {CharacterCountConfig} [config] - Character count config
|
|
2426
2600
|
*/
|
|
2427
2601
|
function CharacterCount ($module, config) {
|
|
2428
|
-
if (
|
|
2602
|
+
if (!($module instanceof HTMLElement)) {
|
|
2603
|
+
return this
|
|
2604
|
+
}
|
|
2605
|
+
|
|
2606
|
+
var $textarea = $module.querySelector('.govuk-js-character-count');
|
|
2607
|
+
if (
|
|
2608
|
+
!(
|
|
2609
|
+
$textarea instanceof HTMLTextAreaElement ||
|
|
2610
|
+
$textarea instanceof HTMLInputElement
|
|
2611
|
+
)
|
|
2612
|
+
) {
|
|
2429
2613
|
return this
|
|
2430
2614
|
}
|
|
2431
2615
|
|
|
@@ -2451,6 +2635,10 @@
|
|
|
2451
2635
|
};
|
|
2452
2636
|
}
|
|
2453
2637
|
|
|
2638
|
+
/**
|
|
2639
|
+
* @deprecated Will be made private in v5.0
|
|
2640
|
+
* @type {CharacterCountConfig}
|
|
2641
|
+
*/
|
|
2454
2642
|
this.config = mergeConfigs(
|
|
2455
2643
|
defaultConfig,
|
|
2456
2644
|
config || {},
|
|
@@ -2458,25 +2646,43 @@
|
|
|
2458
2646
|
datasetConfig
|
|
2459
2647
|
);
|
|
2460
2648
|
|
|
2649
|
+
/** @deprecated Will be made private in v5.0 */
|
|
2461
2650
|
this.i18n = new I18n(extractConfigByNamespace(this.config, 'i18n'), {
|
|
2462
2651
|
// Read the fallback if necessary rather than have it set in the defaults
|
|
2463
2652
|
locale: closestAttributeValue($module, 'lang')
|
|
2464
2653
|
});
|
|
2465
2654
|
|
|
2655
|
+
/** @deprecated Will be made private in v5.0 */
|
|
2656
|
+
this.maxLength = Infinity;
|
|
2466
2657
|
// Determine the limit attribute (characters or words)
|
|
2467
|
-
if (this.config.maxwords) {
|
|
2658
|
+
if ('maxwords' in this.config && this.config.maxwords) {
|
|
2468
2659
|
this.maxLength = this.config.maxwords;
|
|
2469
|
-
} else if (this.config.maxlength) {
|
|
2660
|
+
} else if ('maxlength' in this.config && this.config.maxlength) {
|
|
2470
2661
|
this.maxLength = this.config.maxlength;
|
|
2471
2662
|
} else {
|
|
2472
2663
|
return
|
|
2473
2664
|
}
|
|
2474
2665
|
|
|
2666
|
+
/** @deprecated Will be made private in v5.0 */
|
|
2475
2667
|
this.$module = $module;
|
|
2476
|
-
|
|
2668
|
+
|
|
2669
|
+
/** @deprecated Will be made private in v5.0 */
|
|
2670
|
+
this.$textarea = $textarea;
|
|
2671
|
+
|
|
2672
|
+
/** @deprecated Will be made private in v5.0 */
|
|
2477
2673
|
this.$visibleCountMessage = null;
|
|
2674
|
+
|
|
2675
|
+
/** @deprecated Will be made private in v5.0 */
|
|
2478
2676
|
this.$screenReaderCountMessage = null;
|
|
2677
|
+
|
|
2678
|
+
/** @deprecated Will be made private in v5.0 */
|
|
2479
2679
|
this.lastInputTimestamp = null;
|
|
2680
|
+
|
|
2681
|
+
/** @deprecated Will be made private in v5.0 */
|
|
2682
|
+
this.lastInputValue = '';
|
|
2683
|
+
|
|
2684
|
+
/** @deprecated Will be made private in v5.0 */
|
|
2685
|
+
this.valueChecker = null;
|
|
2480
2686
|
}
|
|
2481
2687
|
|
|
2482
2688
|
/**
|
|
@@ -2484,14 +2690,17 @@
|
|
|
2484
2690
|
*/
|
|
2485
2691
|
CharacterCount.prototype.init = function () {
|
|
2486
2692
|
// Check that required elements are present
|
|
2487
|
-
if (!this.$textarea) {
|
|
2693
|
+
if (!this.$module || !this.$textarea) {
|
|
2488
2694
|
return
|
|
2489
2695
|
}
|
|
2490
2696
|
|
|
2491
2697
|
var $textarea = this.$textarea;
|
|
2492
2698
|
var $textareaDescription = document.getElementById($textarea.id + '-info');
|
|
2699
|
+
if (!$textareaDescription) {
|
|
2700
|
+
return
|
|
2701
|
+
}
|
|
2493
2702
|
|
|
2494
|
-
// Inject a
|
|
2703
|
+
// Inject a description for the textarea if none is present already
|
|
2495
2704
|
// for when the component was rendered with no maxlength, maxwords
|
|
2496
2705
|
// nor custom textareaDescriptionText
|
|
2497
2706
|
if ($textareaDescription.innerText.match(/^\s*$/)) {
|
|
@@ -2532,11 +2741,11 @@
|
|
|
2532
2741
|
// state of the character count is not restored until *after* the
|
|
2533
2742
|
// DOMContentLoaded event is fired, so we need to manually update it after the
|
|
2534
2743
|
// pageshow event in browsers that support it.
|
|
2535
|
-
|
|
2536
|
-
window
|
|
2537
|
-
|
|
2538
|
-
|
|
2539
|
-
|
|
2744
|
+
window.addEventListener(
|
|
2745
|
+
'onpageshow' in window ? 'pageshow' : 'DOMContentLoaded',
|
|
2746
|
+
this.updateCountMessage.bind(this)
|
|
2747
|
+
);
|
|
2748
|
+
|
|
2540
2749
|
this.updateCountMessage();
|
|
2541
2750
|
};
|
|
2542
2751
|
|
|
@@ -2545,6 +2754,8 @@
|
|
|
2545
2754
|
*
|
|
2546
2755
|
* Set up event listeners on the $textarea so that the count messages update
|
|
2547
2756
|
* when the user types.
|
|
2757
|
+
*
|
|
2758
|
+
* @deprecated Will be made private in v5.0
|
|
2548
2759
|
*/
|
|
2549
2760
|
CharacterCount.prototype.bindChangeEvents = function () {
|
|
2550
2761
|
var $textarea = this.$textarea;
|
|
@@ -2560,6 +2771,8 @@
|
|
|
2560
2771
|
*
|
|
2561
2772
|
* Update the visible character counter and keep track of when the last update
|
|
2562
2773
|
* happened for each keypress
|
|
2774
|
+
*
|
|
2775
|
+
* @deprecated Will be made private in v5.0
|
|
2563
2776
|
*/
|
|
2564
2777
|
CharacterCount.prototype.handleKeyUp = function () {
|
|
2565
2778
|
this.updateVisibleCountMessage();
|
|
@@ -2578,6 +2791,8 @@
|
|
|
2578
2791
|
*
|
|
2579
2792
|
* This is so that the update triggered by the manual comparison doesn't
|
|
2580
2793
|
* conflict with debounced KeyboardEvent updates.
|
|
2794
|
+
*
|
|
2795
|
+
* @deprecated Will be made private in v5.0
|
|
2581
2796
|
*/
|
|
2582
2797
|
CharacterCount.prototype.handleFocus = function () {
|
|
2583
2798
|
this.valueChecker = setInterval(function () {
|
|
@@ -2591,6 +2806,8 @@
|
|
|
2591
2806
|
* Handle blur event
|
|
2592
2807
|
*
|
|
2593
2808
|
* Stop checking the textarea value once the textarea no longer has focus
|
|
2809
|
+
*
|
|
2810
|
+
* @deprecated Will be made private in v5.0
|
|
2594
2811
|
*/
|
|
2595
2812
|
CharacterCount.prototype.handleBlur = function () {
|
|
2596
2813
|
// Cancel value checking on blur
|
|
@@ -2599,11 +2816,12 @@
|
|
|
2599
2816
|
|
|
2600
2817
|
/**
|
|
2601
2818
|
* Update count message if textarea value has changed
|
|
2819
|
+
*
|
|
2820
|
+
* @deprecated Will be made private in v5.0
|
|
2602
2821
|
*/
|
|
2603
2822
|
CharacterCount.prototype.updateIfValueChanged = function () {
|
|
2604
|
-
if (
|
|
2605
|
-
|
|
2606
|
-
this.$textarea.oldValue = this.$textarea.value;
|
|
2823
|
+
if (this.$textarea.value !== this.lastInputValue) {
|
|
2824
|
+
this.lastInputValue = this.$textarea.value;
|
|
2607
2825
|
this.updateCountMessage();
|
|
2608
2826
|
}
|
|
2609
2827
|
};
|
|
@@ -2613,6 +2831,8 @@
|
|
|
2613
2831
|
*
|
|
2614
2832
|
* Helper function to update both the visible and screen reader-specific
|
|
2615
2833
|
* counters simultaneously (e.g. on init)
|
|
2834
|
+
*
|
|
2835
|
+
* @deprecated Will be made private in v5.0
|
|
2616
2836
|
*/
|
|
2617
2837
|
CharacterCount.prototype.updateCountMessage = function () {
|
|
2618
2838
|
this.updateVisibleCountMessage();
|
|
@@ -2621,6 +2841,8 @@
|
|
|
2621
2841
|
|
|
2622
2842
|
/**
|
|
2623
2843
|
* Update visible count message
|
|
2844
|
+
*
|
|
2845
|
+
* @deprecated Will be made private in v5.0
|
|
2624
2846
|
*/
|
|
2625
2847
|
CharacterCount.prototype.updateVisibleCountMessage = function () {
|
|
2626
2848
|
var $textarea = this.$textarea;
|
|
@@ -2652,6 +2874,8 @@
|
|
|
2652
2874
|
|
|
2653
2875
|
/**
|
|
2654
2876
|
* Update screen reader count message
|
|
2877
|
+
*
|
|
2878
|
+
* @deprecated Will be made private in v5.0
|
|
2655
2879
|
*/
|
|
2656
2880
|
CharacterCount.prototype.updateScreenReaderCountMessage = function () {
|
|
2657
2881
|
var $screenReaderCountMessage = this.$screenReaderCountMessage;
|
|
@@ -2661,7 +2885,7 @@
|
|
|
2661
2885
|
if (this.isOverThreshold()) {
|
|
2662
2886
|
$screenReaderCountMessage.removeAttribute('aria-hidden');
|
|
2663
2887
|
} else {
|
|
2664
|
-
$screenReaderCountMessage.setAttribute('aria-hidden', true);
|
|
2888
|
+
$screenReaderCountMessage.setAttribute('aria-hidden', 'true');
|
|
2665
2889
|
}
|
|
2666
2890
|
|
|
2667
2891
|
// Update message
|
|
@@ -2672,11 +2896,12 @@
|
|
|
2672
2896
|
* Count the number of characters (or words, if `config.maxwords` is set)
|
|
2673
2897
|
* in the given text
|
|
2674
2898
|
*
|
|
2899
|
+
* @deprecated Will be made private in v5.0
|
|
2675
2900
|
* @param {string} text - The text to count the characters of
|
|
2676
2901
|
* @returns {number} the number of characters (or words) in the text
|
|
2677
2902
|
*/
|
|
2678
2903
|
CharacterCount.prototype.count = function (text) {
|
|
2679
|
-
if (this.config.maxwords) {
|
|
2904
|
+
if ('maxwords' in this.config && this.config.maxwords) {
|
|
2680
2905
|
var tokens = text.match(/\S+/g) || []; // Matches consecutive non-whitespace chars
|
|
2681
2906
|
return tokens.length
|
|
2682
2907
|
} else {
|
|
@@ -2687,12 +2912,13 @@
|
|
|
2687
2912
|
/**
|
|
2688
2913
|
* Get count message
|
|
2689
2914
|
*
|
|
2915
|
+
* @deprecated Will be made private in v5.0
|
|
2690
2916
|
* @returns {string} Status message
|
|
2691
2917
|
*/
|
|
2692
2918
|
CharacterCount.prototype.getCountMessage = function () {
|
|
2693
2919
|
var remainingNumber = this.maxLength - this.count(this.$textarea.value);
|
|
2694
2920
|
|
|
2695
|
-
var countType = this.config.maxwords ? 'words' : 'characters';
|
|
2921
|
+
var countType = 'maxwords' in this.config && this.config.maxwords ? 'words' : 'characters';
|
|
2696
2922
|
return this.formatCountMessage(remainingNumber, countType)
|
|
2697
2923
|
};
|
|
2698
2924
|
|
|
@@ -2700,6 +2926,7 @@
|
|
|
2700
2926
|
* Formats the message shown to users according to what's counted
|
|
2701
2927
|
* and how many remain
|
|
2702
2928
|
*
|
|
2929
|
+
* @deprecated Will be made private in v5.0
|
|
2703
2930
|
* @param {number} remainingNumber - The number of words/characaters remaining
|
|
2704
2931
|
* @param {string} countType - "words" or "characters"
|
|
2705
2932
|
* @returns {string} Status message
|
|
@@ -2721,6 +2948,7 @@
|
|
|
2721
2948
|
* If there is no configured threshold, it is set to 0 and this function will
|
|
2722
2949
|
* always return true.
|
|
2723
2950
|
*
|
|
2951
|
+
* @deprecated Will be made private in v5.0
|
|
2724
2952
|
* @returns {boolean} true if the current count is over the config.threshold
|
|
2725
2953
|
* (or no threshold is set)
|
|
2726
2954
|
*/
|
|
@@ -2752,10 +2980,10 @@
|
|
|
2752
2980
|
*
|
|
2753
2981
|
* @typedef {object} CharacterCountConfigWithMaxLength
|
|
2754
2982
|
* @property {number} [maxlength] - The maximum number of characters.
|
|
2755
|
-
*
|
|
2983
|
+
* If maxwords is provided, the maxlength option will be ignored.
|
|
2756
2984
|
* @property {number} [threshold = 0] - The percentage value of the limit at
|
|
2757
|
-
*
|
|
2758
|
-
*
|
|
2985
|
+
* which point the count message is displayed. If this attribute is set, the
|
|
2986
|
+
* count message will be hidden by default.
|
|
2759
2987
|
* @property {CharacterCountTranslations} [i18n = CHARACTER_COUNT_TRANSLATIONS] - See constant {@link CHARACTER_COUNT_TRANSLATIONS}
|
|
2760
2988
|
*/
|
|
2761
2989
|
|
|
@@ -2764,10 +2992,10 @@
|
|
|
2764
2992
|
*
|
|
2765
2993
|
* @typedef {object} CharacterCountConfigWithMaxWords
|
|
2766
2994
|
* @property {number} [maxwords] - The maximum number of words. If maxwords is
|
|
2767
|
-
*
|
|
2995
|
+
* provided, the maxlength option will be ignored.
|
|
2768
2996
|
* @property {number} [threshold = 0] - The percentage value of the limit at
|
|
2769
|
-
*
|
|
2770
|
-
*
|
|
2997
|
+
* which point the count message is displayed. If this attribute is set, the
|
|
2998
|
+
* count message will be hidden by default.
|
|
2771
2999
|
* @property {CharacterCountTranslations} [i18n = CHARACTER_COUNT_TRANSLATIONS] - See constant {@link CHARACTER_COUNT_TRANSLATIONS}
|
|
2772
3000
|
*/
|
|
2773
3001
|
|
|
@@ -2827,11 +3055,23 @@
|
|
|
2827
3055
|
* Checkboxes component
|
|
2828
3056
|
*
|
|
2829
3057
|
* @class
|
|
2830
|
-
* @param {
|
|
3058
|
+
* @param {Element} $module - HTML element to use for checkboxes
|
|
2831
3059
|
*/
|
|
2832
3060
|
function Checkboxes ($module) {
|
|
3061
|
+
if (!($module instanceof HTMLElement)) {
|
|
3062
|
+
return this
|
|
3063
|
+
}
|
|
3064
|
+
|
|
3065
|
+
var $inputs = $module.querySelectorAll('input[type="checkbox"]');
|
|
3066
|
+
if (!$inputs.length) {
|
|
3067
|
+
return this
|
|
3068
|
+
}
|
|
3069
|
+
|
|
3070
|
+
/** @deprecated Will be made private in v5.0 */
|
|
2833
3071
|
this.$module = $module;
|
|
2834
|
-
|
|
3072
|
+
|
|
3073
|
+
/** @deprecated Will be made private in v5.0 */
|
|
3074
|
+
this.$inputs = $inputs;
|
|
2835
3075
|
}
|
|
2836
3076
|
|
|
2837
3077
|
/**
|
|
@@ -2849,6 +3089,11 @@
|
|
|
2849
3089
|
* the reveal in sync with the checkbox state.
|
|
2850
3090
|
*/
|
|
2851
3091
|
Checkboxes.prototype.init = function () {
|
|
3092
|
+
// Check that required elements are present
|
|
3093
|
+
if (!this.$module || !this.$inputs) {
|
|
3094
|
+
return
|
|
3095
|
+
}
|
|
3096
|
+
|
|
2852
3097
|
var $module = this.$module;
|
|
2853
3098
|
var $inputs = this.$inputs;
|
|
2854
3099
|
|
|
@@ -2871,11 +3116,10 @@
|
|
|
2871
3116
|
// state of form controls is not restored until *after* the DOMContentLoaded
|
|
2872
3117
|
// event is fired, so we need to sync after the pageshow event in browsers
|
|
2873
3118
|
// that support it.
|
|
2874
|
-
|
|
2875
|
-
window
|
|
2876
|
-
|
|
2877
|
-
|
|
2878
|
-
}
|
|
3119
|
+
window.addEventListener(
|
|
3120
|
+
'onpageshow' in window ? 'pageshow' : 'DOMContentLoaded',
|
|
3121
|
+
this.syncAllConditionalReveals.bind(this)
|
|
3122
|
+
);
|
|
2879
3123
|
|
|
2880
3124
|
// Although we've set up handlers to sync state on the pageshow or
|
|
2881
3125
|
// DOMContentLoaded event, init could be called after those events have fired,
|
|
@@ -2888,6 +3132,8 @@
|
|
|
2888
3132
|
|
|
2889
3133
|
/**
|
|
2890
3134
|
* Sync the conditional reveal states for all checkboxes in this $module.
|
|
3135
|
+
*
|
|
3136
|
+
* @deprecated Will be made private in v5.0
|
|
2891
3137
|
*/
|
|
2892
3138
|
Checkboxes.prototype.syncAllConditionalReveals = function () {
|
|
2893
3139
|
nodeListForEach(this.$inputs, this.syncConditionalRevealWithInputState.bind(this));
|
|
@@ -2899,15 +3145,20 @@
|
|
|
2899
3145
|
* Synchronise the visibility of the conditional reveal, and its accessible
|
|
2900
3146
|
* state, with the input's checked state.
|
|
2901
3147
|
*
|
|
3148
|
+
* @deprecated Will be made private in v5.0
|
|
2902
3149
|
* @param {HTMLInputElement} $input - Checkbox input
|
|
2903
3150
|
*/
|
|
2904
3151
|
Checkboxes.prototype.syncConditionalRevealWithInputState = function ($input) {
|
|
2905
|
-
var
|
|
3152
|
+
var targetId = $input.getAttribute('aria-controls');
|
|
3153
|
+
if (!targetId) {
|
|
3154
|
+
return
|
|
3155
|
+
}
|
|
2906
3156
|
|
|
3157
|
+
var $target = document.getElementById(targetId);
|
|
2907
3158
|
if ($target && $target.classList.contains('govuk-checkboxes__conditional')) {
|
|
2908
3159
|
var inputIsChecked = $input.checked;
|
|
2909
3160
|
|
|
2910
|
-
$input.setAttribute('aria-expanded', inputIsChecked);
|
|
3161
|
+
$input.setAttribute('aria-expanded', inputIsChecked.toString());
|
|
2911
3162
|
$target.classList.toggle('govuk-checkboxes__conditional--hidden', !inputIsChecked);
|
|
2912
3163
|
}
|
|
2913
3164
|
};
|
|
@@ -2918,18 +3169,25 @@
|
|
|
2918
3169
|
* Find any other checkbox inputs with the same name value, and uncheck them.
|
|
2919
3170
|
* This is useful for when a “None of these" checkbox is checked.
|
|
2920
3171
|
*
|
|
2921
|
-
* @
|
|
3172
|
+
* @deprecated Will be made private in v5.0
|
|
3173
|
+
* @param {HTMLInputElement} $input - Checkbox input
|
|
2922
3174
|
*/
|
|
2923
3175
|
Checkboxes.prototype.unCheckAllInputsExcept = function ($input) {
|
|
2924
|
-
var
|
|
3176
|
+
var $component = this;
|
|
3177
|
+
|
|
3178
|
+
/** @type {NodeListOf<HTMLInputElement>} */
|
|
3179
|
+
// @ts-expect-error `NodeListOf<HTMLInputElement>` type expected
|
|
3180
|
+
var allInputsWithSameName = document.querySelectorAll(
|
|
3181
|
+
'input[type="checkbox"][name="' + $input.name + '"]'
|
|
3182
|
+
);
|
|
2925
3183
|
|
|
2926
3184
|
nodeListForEach(allInputsWithSameName, function ($inputWithSameName) {
|
|
2927
3185
|
var hasSameFormOwner = ($input.form === $inputWithSameName.form);
|
|
2928
3186
|
if (hasSameFormOwner && $inputWithSameName !== $input) {
|
|
2929
3187
|
$inputWithSameName.checked = false;
|
|
2930
|
-
|
|
3188
|
+
$component.syncConditionalRevealWithInputState($inputWithSameName);
|
|
2931
3189
|
}
|
|
2932
|
-
}
|
|
3190
|
+
});
|
|
2933
3191
|
};
|
|
2934
3192
|
|
|
2935
3193
|
/**
|
|
@@ -2939,9 +3197,14 @@
|
|
|
2939
3197
|
* and uncheck them. This helps prevent someone checking both a regular checkbox and a
|
|
2940
3198
|
* "None of these" checkbox in the same fieldset.
|
|
2941
3199
|
*
|
|
3200
|
+
* @deprecated Will be made private in v5.0
|
|
2942
3201
|
* @param {HTMLInputElement} $input - Checkbox input
|
|
2943
3202
|
*/
|
|
2944
3203
|
Checkboxes.prototype.unCheckExclusiveInputs = function ($input) {
|
|
3204
|
+
var $component = this;
|
|
3205
|
+
|
|
3206
|
+
/** @type {NodeListOf<HTMLInputElement>} */
|
|
3207
|
+
// @ts-expect-error `NodeListOf<HTMLInputElement>` type expected
|
|
2945
3208
|
var allInputsWithSameNameAndExclusiveBehaviour = document.querySelectorAll(
|
|
2946
3209
|
'input[data-behaviour="exclusive"][type="checkbox"][name="' + $input.name + '"]'
|
|
2947
3210
|
);
|
|
@@ -2950,9 +3213,9 @@
|
|
|
2950
3213
|
var hasSameFormOwner = ($input.form === $exclusiveInput.form);
|
|
2951
3214
|
if (hasSameFormOwner) {
|
|
2952
3215
|
$exclusiveInput.checked = false;
|
|
2953
|
-
|
|
3216
|
+
$component.syncConditionalRevealWithInputState($exclusiveInput);
|
|
2954
3217
|
}
|
|
2955
|
-
}
|
|
3218
|
+
});
|
|
2956
3219
|
};
|
|
2957
3220
|
|
|
2958
3221
|
/**
|
|
@@ -2961,13 +3224,14 @@
|
|
|
2961
3224
|
* Handle a click within the $module – if the click occurred on a checkbox, sync
|
|
2962
3225
|
* the state of any associated conditional reveal with the checkbox state.
|
|
2963
3226
|
*
|
|
3227
|
+
* @deprecated Will be made private in v5.0
|
|
2964
3228
|
* @param {MouseEvent} event - Click event
|
|
2965
3229
|
*/
|
|
2966
3230
|
Checkboxes.prototype.handleClick = function (event) {
|
|
2967
3231
|
var $clickedInput = event.target;
|
|
2968
3232
|
|
|
2969
3233
|
// Ignore clicks on things that aren't checkbox inputs
|
|
2970
|
-
if ($clickedInput.type !== 'checkbox') {
|
|
3234
|
+
if (!($clickedInput instanceof HTMLInputElement) || $clickedInput.type !== 'checkbox') {
|
|
2971
3235
|
return
|
|
2972
3236
|
}
|
|
2973
3237
|
|
|
@@ -3000,32 +3264,45 @@
|
|
|
3000
3264
|
* Details component
|
|
3001
3265
|
*
|
|
3002
3266
|
* @class
|
|
3003
|
-
* @param {
|
|
3267
|
+
* @param {Element} $module - HTML element to use for details
|
|
3004
3268
|
*/
|
|
3005
3269
|
function Details ($module) {
|
|
3270
|
+
if (!($module instanceof HTMLElement)) {
|
|
3271
|
+
return this
|
|
3272
|
+
}
|
|
3273
|
+
|
|
3274
|
+
/** @deprecated Will be made private in v5.0 */
|
|
3006
3275
|
this.$module = $module;
|
|
3276
|
+
|
|
3277
|
+
/** @deprecated Will be made private in v5.0 */
|
|
3278
|
+
this.$summary = null;
|
|
3279
|
+
|
|
3280
|
+
/** @deprecated Will be made private in v5.0 */
|
|
3281
|
+
this.$content = null;
|
|
3007
3282
|
}
|
|
3008
3283
|
|
|
3009
3284
|
/**
|
|
3010
3285
|
* Initialise component
|
|
3011
3286
|
*/
|
|
3012
3287
|
Details.prototype.init = function () {
|
|
3288
|
+
// Check that required elements are present
|
|
3013
3289
|
if (!this.$module) {
|
|
3014
3290
|
return
|
|
3015
3291
|
}
|
|
3016
3292
|
|
|
3017
3293
|
// If there is native details support, we want to avoid running code to polyfill native behaviour.
|
|
3018
|
-
var hasNativeDetails =
|
|
3294
|
+
var hasNativeDetails = 'HTMLDetailsElement' in window &&
|
|
3295
|
+
this.$module instanceof HTMLDetailsElement;
|
|
3019
3296
|
|
|
3020
|
-
if (hasNativeDetails) {
|
|
3021
|
-
|
|
3297
|
+
if (!hasNativeDetails) {
|
|
3298
|
+
this.polyfillDetails();
|
|
3022
3299
|
}
|
|
3023
|
-
|
|
3024
|
-
this.polyfillDetails();
|
|
3025
3300
|
};
|
|
3026
3301
|
|
|
3027
3302
|
/**
|
|
3028
3303
|
* Polyfill component in older browsers
|
|
3304
|
+
*
|
|
3305
|
+
* @deprecated Will be made private in v5.0
|
|
3029
3306
|
*/
|
|
3030
3307
|
Details.prototype.polyfillDetails = function () {
|
|
3031
3308
|
var $module = this.$module;
|
|
@@ -3076,6 +3353,7 @@
|
|
|
3076
3353
|
/**
|
|
3077
3354
|
* Define a statechange function that updates aria-expanded and style.display
|
|
3078
3355
|
*
|
|
3356
|
+
* @deprecated Will be made private in v5.0
|
|
3079
3357
|
* @returns {boolean} Returns true
|
|
3080
3358
|
*/
|
|
3081
3359
|
Details.prototype.polyfillSetAttributes = function () {
|
|
@@ -3095,6 +3373,7 @@
|
|
|
3095
3373
|
/**
|
|
3096
3374
|
* Handle cross-modal click events
|
|
3097
3375
|
*
|
|
3376
|
+
* @deprecated Will be made private in v5.0
|
|
3098
3377
|
* @param {polyfillHandleInputsCallback} callback - function
|
|
3099
3378
|
*/
|
|
3100
3379
|
Details.prototype.polyfillHandleInputs = function (callback) {
|
|
@@ -3102,7 +3381,7 @@
|
|
|
3102
3381
|
var $target = event.target;
|
|
3103
3382
|
// When the key gets pressed - check if it is enter or space
|
|
3104
3383
|
if (event.keyCode === KEY_ENTER || event.keyCode === KEY_SPACE$1) {
|
|
3105
|
-
if ($target.nodeName.toLowerCase() === 'summary') {
|
|
3384
|
+
if ($target instanceof HTMLElement && $target.nodeName.toLowerCase() === 'summary') {
|
|
3106
3385
|
// Prevent space from scrolling the page
|
|
3107
3386
|
// and enter from submitting a form
|
|
3108
3387
|
event.preventDefault();
|
|
@@ -3121,7 +3400,7 @@
|
|
|
3121
3400
|
this.$summary.addEventListener('keyup', function (event) {
|
|
3122
3401
|
var $target = event.target;
|
|
3123
3402
|
if (event.keyCode === KEY_SPACE$1) {
|
|
3124
|
-
if ($target.nodeName.toLowerCase() === 'summary') {
|
|
3403
|
+
if ($target instanceof HTMLElement && $target.nodeName.toLowerCase() === 'summary') {
|
|
3125
3404
|
event.preventDefault();
|
|
3126
3405
|
}
|
|
3127
3406
|
}
|
|
@@ -3144,7 +3423,7 @@
|
|
|
3144
3423
|
* Takes focus on initialisation for accessible announcement, unless disabled in configuration.
|
|
3145
3424
|
*
|
|
3146
3425
|
* @class
|
|
3147
|
-
* @param {
|
|
3426
|
+
* @param {Element} $module - HTML element to use for error summary
|
|
3148
3427
|
* @param {ErrorSummaryConfig} [config] - Error summary config
|
|
3149
3428
|
*/
|
|
3150
3429
|
function ErrorSummary ($module, config) {
|
|
@@ -3155,17 +3434,23 @@
|
|
|
3155
3434
|
// To avoid breaking further JavaScript initialisation
|
|
3156
3435
|
// we need to safeguard against this so things keep
|
|
3157
3436
|
// working the same now we read the elements data attributes
|
|
3158
|
-
if (
|
|
3437
|
+
if (!($module instanceof HTMLElement)) {
|
|
3159
3438
|
// Little safety in case code gets ported as-is
|
|
3160
3439
|
// into and ES6 class constructor, where the return value matters
|
|
3161
3440
|
return this
|
|
3162
3441
|
}
|
|
3163
3442
|
|
|
3443
|
+
/** @deprecated Will be made private in v5.0 */
|
|
3164
3444
|
this.$module = $module;
|
|
3165
3445
|
|
|
3166
3446
|
var defaultConfig = {
|
|
3167
3447
|
disableAutoFocus: false
|
|
3168
3448
|
};
|
|
3449
|
+
|
|
3450
|
+
/**
|
|
3451
|
+
* @deprecated Will be made private in v5.0
|
|
3452
|
+
* @type {ErrorSummaryConfig}
|
|
3453
|
+
*/
|
|
3169
3454
|
this.config = mergeConfigs(
|
|
3170
3455
|
defaultConfig,
|
|
3171
3456
|
config || {},
|
|
@@ -3177,17 +3462,21 @@
|
|
|
3177
3462
|
* Initialise component
|
|
3178
3463
|
*/
|
|
3179
3464
|
ErrorSummary.prototype.init = function () {
|
|
3180
|
-
|
|
3181
|
-
if (
|
|
3465
|
+
// Check that required elements are present
|
|
3466
|
+
if (!this.$module) {
|
|
3182
3467
|
return
|
|
3183
3468
|
}
|
|
3184
3469
|
|
|
3470
|
+
var $module = this.$module;
|
|
3471
|
+
|
|
3185
3472
|
this.setFocus();
|
|
3186
3473
|
$module.addEventListener('click', this.handleClick.bind(this));
|
|
3187
3474
|
};
|
|
3188
3475
|
|
|
3189
3476
|
/**
|
|
3190
3477
|
* Focus the error summary
|
|
3478
|
+
*
|
|
3479
|
+
* @deprecated Will be made private in v5.0
|
|
3191
3480
|
*/
|
|
3192
3481
|
ErrorSummary.prototype.setFocus = function () {
|
|
3193
3482
|
var $module = this.$module;
|
|
@@ -3210,6 +3499,7 @@
|
|
|
3210
3499
|
/**
|
|
3211
3500
|
* Click event handler
|
|
3212
3501
|
*
|
|
3502
|
+
* @deprecated Will be made private in v5.0
|
|
3213
3503
|
* @param {MouseEvent} event - Click event
|
|
3214
3504
|
*/
|
|
3215
3505
|
ErrorSummary.prototype.handleClick = function (event) {
|
|
@@ -3234,16 +3524,21 @@
|
|
|
3234
3524
|
* NVDA (as tested in 2018.3.2) - without this only the field type is announced
|
|
3235
3525
|
* (e.g. "Edit, has autocomplete").
|
|
3236
3526
|
*
|
|
3527
|
+
* @deprecated Will be made private in v5.0
|
|
3237
3528
|
* @param {EventTarget} $target - Event target
|
|
3238
3529
|
* @returns {boolean} True if the target was able to be focussed
|
|
3239
3530
|
*/
|
|
3240
3531
|
ErrorSummary.prototype.focusTarget = function ($target) {
|
|
3241
3532
|
// If the element that was clicked was not a link, return early
|
|
3242
|
-
if ($target
|
|
3533
|
+
if (!($target instanceof HTMLAnchorElement)) {
|
|
3243
3534
|
return false
|
|
3244
3535
|
}
|
|
3245
3536
|
|
|
3246
3537
|
var inputId = this.getFragmentFromUrl($target.href);
|
|
3538
|
+
if (!inputId) {
|
|
3539
|
+
return false
|
|
3540
|
+
}
|
|
3541
|
+
|
|
3247
3542
|
var $input = document.getElementById(inputId);
|
|
3248
3543
|
if (!$input) {
|
|
3249
3544
|
return false
|
|
@@ -3269,12 +3564,13 @@
|
|
|
3269
3564
|
* Extract the fragment (everything after the hash) from a URL, but not including
|
|
3270
3565
|
* the hash.
|
|
3271
3566
|
*
|
|
3567
|
+
* @deprecated Will be made private in v5.0
|
|
3272
3568
|
* @param {string} url - URL
|
|
3273
|
-
* @returns {string} Fragment from URL, without the hash
|
|
3569
|
+
* @returns {string | undefined} Fragment from URL, without the hash
|
|
3274
3570
|
*/
|
|
3275
3571
|
ErrorSummary.prototype.getFragmentFromUrl = function (url) {
|
|
3276
3572
|
if (url.indexOf('#') === -1) {
|
|
3277
|
-
return
|
|
3573
|
+
return undefined
|
|
3278
3574
|
}
|
|
3279
3575
|
|
|
3280
3576
|
return url.split('#').pop()
|
|
@@ -3291,9 +3587,10 @@
|
|
|
3291
3587
|
* - The first `<label>` that is associated with the input using for="inputId"
|
|
3292
3588
|
* - The closest parent `<label>`
|
|
3293
3589
|
*
|
|
3294
|
-
* @
|
|
3295
|
-
* @
|
|
3296
|
-
*
|
|
3590
|
+
* @deprecated Will be made private in v5.0
|
|
3591
|
+
* @param {Element} $input - The input
|
|
3592
|
+
* @returns {Element | null} Associated legend or label, or null if no associated
|
|
3593
|
+
* legend or label can be found
|
|
3297
3594
|
*/
|
|
3298
3595
|
ErrorSummary.prototype.getAssociatedLegendOrLabel = function ($input) {
|
|
3299
3596
|
var $fieldset = $input.closest('fieldset');
|
|
@@ -3306,7 +3603,7 @@
|
|
|
3306
3603
|
|
|
3307
3604
|
// If the input type is radio or checkbox, always use the legend if there
|
|
3308
3605
|
// is one.
|
|
3309
|
-
if ($input.type === 'checkbox' || $input.type === 'radio') {
|
|
3606
|
+
if ($input instanceof HTMLInputElement && ($input.type === 'checkbox' || $input.type === 'radio')) {
|
|
3310
3607
|
return $candidateLegend
|
|
3311
3608
|
}
|
|
3312
3609
|
|
|
@@ -3339,8 +3636,8 @@
|
|
|
3339
3636
|
* Error summary config
|
|
3340
3637
|
*
|
|
3341
3638
|
* @typedef {object} ErrorSummaryConfig
|
|
3342
|
-
* @property {boolean} [disableAutoFocus = false] -
|
|
3343
|
-
*
|
|
3639
|
+
* @property {boolean} [disableAutoFocus = false] - If set to `true` the error
|
|
3640
|
+
* summary will not be focussed when the page loads.
|
|
3344
3641
|
*/
|
|
3345
3642
|
|
|
3346
3643
|
/* eslint-disable es-x/no-function-prototype-bind -- Polyfill imported */
|
|
@@ -3349,24 +3646,41 @@
|
|
|
3349
3646
|
* Header component
|
|
3350
3647
|
*
|
|
3351
3648
|
* @class
|
|
3352
|
-
* @param {
|
|
3649
|
+
* @param {Element} $module - HTML element to use for header
|
|
3353
3650
|
*/
|
|
3354
3651
|
function Header ($module) {
|
|
3652
|
+
if (!($module instanceof HTMLElement)) {
|
|
3653
|
+
return this
|
|
3654
|
+
}
|
|
3655
|
+
|
|
3656
|
+
/** @deprecated Will be made private in v5.0 */
|
|
3355
3657
|
this.$module = $module;
|
|
3356
|
-
|
|
3658
|
+
|
|
3659
|
+
/** @deprecated Will be made private in v5.0 */
|
|
3660
|
+
this.$menuButton = $module.querySelector('.govuk-js-header-toggle');
|
|
3661
|
+
|
|
3662
|
+
/** @deprecated Will be made private in v5.0 */
|
|
3357
3663
|
this.$menu = this.$menuButton && $module.querySelector(
|
|
3358
3664
|
'#' + this.$menuButton.getAttribute('aria-controls')
|
|
3359
3665
|
);
|
|
3360
3666
|
|
|
3361
|
-
|
|
3362
|
-
|
|
3363
|
-
|
|
3667
|
+
/**
|
|
3668
|
+
* Save the opened/closed state for the nav in memory so that we can
|
|
3669
|
+
* accurately maintain state when the screen is changed from small to
|
|
3670
|
+
* big and back to small
|
|
3671
|
+
*
|
|
3672
|
+
* @deprecated Will be made private in v5.0
|
|
3673
|
+
*/
|
|
3364
3674
|
this.menuIsOpen = false;
|
|
3365
3675
|
|
|
3366
|
-
|
|
3367
|
-
|
|
3368
|
-
|
|
3369
|
-
|
|
3676
|
+
/**
|
|
3677
|
+
* A global const for storing a matchMedia instance which we'll use to
|
|
3678
|
+
* detect when a screen size change happens. We set this later during the
|
|
3679
|
+
* init function and rely on it being null if the feature isn't available
|
|
3680
|
+
* to initially apply hidden attributes
|
|
3681
|
+
*
|
|
3682
|
+
* @deprecated Will be made private in v5.0
|
|
3683
|
+
*/
|
|
3370
3684
|
this.mql = null;
|
|
3371
3685
|
}
|
|
3372
3686
|
|
|
@@ -3381,6 +3695,7 @@
|
|
|
3381
3695
|
* version of the menu to the user.
|
|
3382
3696
|
*/
|
|
3383
3697
|
Header.prototype.init = function () {
|
|
3698
|
+
// Check that required elements are present
|
|
3384
3699
|
if (!this.$module || !this.$menuButton || !this.$menu) {
|
|
3385
3700
|
return
|
|
3386
3701
|
}
|
|
@@ -3393,8 +3708,9 @@
|
|
|
3393
3708
|
this.mql.addEventListener('change', this.syncState.bind(this));
|
|
3394
3709
|
} else {
|
|
3395
3710
|
// addListener is a deprecated function, however addEventListener
|
|
3396
|
-
// isn't supported by IE or Safari. We therefore add this in as
|
|
3711
|
+
// isn't supported by IE or Safari < 14. We therefore add this in as
|
|
3397
3712
|
// a fallback for those browsers
|
|
3713
|
+
// @ts-expect-error Property 'addListener' does not exist
|
|
3398
3714
|
this.mql.addListener(this.syncState.bind(this));
|
|
3399
3715
|
}
|
|
3400
3716
|
|
|
@@ -3412,6 +3728,8 @@
|
|
|
3412
3728
|
* visual states of the menu and the menu button.
|
|
3413
3729
|
* Additionally will force the menu to be visible and the menu button to be
|
|
3414
3730
|
* hidden if the matchMedia is triggered to desktop.
|
|
3731
|
+
*
|
|
3732
|
+
* @deprecated Will be made private in v5.0
|
|
3415
3733
|
*/
|
|
3416
3734
|
Header.prototype.syncState = function () {
|
|
3417
3735
|
if (this.mql.matches) {
|
|
@@ -3419,7 +3737,7 @@
|
|
|
3419
3737
|
this.$menuButton.setAttribute('hidden', '');
|
|
3420
3738
|
} else {
|
|
3421
3739
|
this.$menuButton.removeAttribute('hidden');
|
|
3422
|
-
this.$menuButton.setAttribute('aria-expanded', this.menuIsOpen);
|
|
3740
|
+
this.$menuButton.setAttribute('aria-expanded', this.menuIsOpen.toString());
|
|
3423
3741
|
|
|
3424
3742
|
if (this.menuIsOpen) {
|
|
3425
3743
|
this.$menu.removeAttribute('hidden');
|
|
@@ -3434,6 +3752,8 @@
|
|
|
3434
3752
|
*
|
|
3435
3753
|
* When the menu button is clicked, change the visibility of the menu and then
|
|
3436
3754
|
* sync the accessibility state and menu button state
|
|
3755
|
+
*
|
|
3756
|
+
* @deprecated Will be made private in v5.0
|
|
3437
3757
|
*/
|
|
3438
3758
|
Header.prototype.handleMenuButtonClick = function () {
|
|
3439
3759
|
this.menuIsOpen = !this.menuIsOpen;
|
|
@@ -3444,15 +3764,25 @@
|
|
|
3444
3764
|
* Notification Banner component
|
|
3445
3765
|
*
|
|
3446
3766
|
* @class
|
|
3447
|
-
* @param {
|
|
3767
|
+
* @param {Element} $module - HTML element to use for notification banner
|
|
3448
3768
|
* @param {NotificationBannerConfig} [config] - Notification banner config
|
|
3449
3769
|
*/
|
|
3450
3770
|
function NotificationBanner ($module, config) {
|
|
3771
|
+
if (!($module instanceof HTMLElement)) {
|
|
3772
|
+
return this
|
|
3773
|
+
}
|
|
3774
|
+
|
|
3775
|
+
/** @deprecated Will be made private in v5.0 */
|
|
3451
3776
|
this.$module = $module;
|
|
3452
3777
|
|
|
3453
3778
|
var defaultConfig = {
|
|
3454
3779
|
disableAutoFocus: false
|
|
3455
3780
|
};
|
|
3781
|
+
|
|
3782
|
+
/**
|
|
3783
|
+
* @deprecated Will be made private in v5.0
|
|
3784
|
+
* @type {NotificationBannerConfig}
|
|
3785
|
+
*/
|
|
3456
3786
|
this.config = mergeConfigs(
|
|
3457
3787
|
defaultConfig,
|
|
3458
3788
|
config || {},
|
|
@@ -3464,9 +3794,8 @@
|
|
|
3464
3794
|
* Initialise component
|
|
3465
3795
|
*/
|
|
3466
3796
|
NotificationBanner.prototype.init = function () {
|
|
3467
|
-
|
|
3468
|
-
|
|
3469
|
-
if (!$module) {
|
|
3797
|
+
// Check that required elements are present
|
|
3798
|
+
if (!this.$module) {
|
|
3470
3799
|
return
|
|
3471
3800
|
}
|
|
3472
3801
|
|
|
@@ -3482,6 +3811,8 @@
|
|
|
3482
3811
|
* You can turn off the auto-focus functionality by setting `data-disable-auto-focus="true"` in the
|
|
3483
3812
|
* component HTML. You might wish to do this based on user research findings, or to avoid a clash
|
|
3484
3813
|
* with another element which should be focused when the page loads.
|
|
3814
|
+
*
|
|
3815
|
+
* @deprecated Will be made private in v5.0
|
|
3485
3816
|
*/
|
|
3486
3817
|
NotificationBanner.prototype.setFocus = function () {
|
|
3487
3818
|
var $module = this.$module;
|
|
@@ -3512,11 +3843,10 @@
|
|
|
3512
3843
|
* Notification banner config
|
|
3513
3844
|
*
|
|
3514
3845
|
* @typedef {object} NotificationBannerConfig
|
|
3515
|
-
* @property {boolean} [disableAutoFocus = false] -
|
|
3516
|
-
*
|
|
3517
|
-
*
|
|
3518
|
-
*
|
|
3519
|
-
* this option.
|
|
3846
|
+
* @property {boolean} [disableAutoFocus = false] - If set to `true` the
|
|
3847
|
+
* notification banner will not be focussed when the page loads. This only
|
|
3848
|
+
* applies if the component has a `role` of `alert` – in other cases the
|
|
3849
|
+
* component will not be focused on page load, regardless of this option.
|
|
3520
3850
|
*/
|
|
3521
3851
|
|
|
3522
3852
|
/* eslint-disable es-x/no-function-prototype-bind -- Polyfill imported */
|
|
@@ -3525,11 +3855,23 @@
|
|
|
3525
3855
|
* Radios component
|
|
3526
3856
|
*
|
|
3527
3857
|
* @class
|
|
3528
|
-
* @param {
|
|
3858
|
+
* @param {Element} $module - HTML element to use for radios
|
|
3529
3859
|
*/
|
|
3530
3860
|
function Radios ($module) {
|
|
3861
|
+
if (!($module instanceof HTMLElement)) {
|
|
3862
|
+
return this
|
|
3863
|
+
}
|
|
3864
|
+
|
|
3865
|
+
var $inputs = $module.querySelectorAll('input[type="radio"]');
|
|
3866
|
+
if (!$inputs.length) {
|
|
3867
|
+
return this
|
|
3868
|
+
}
|
|
3869
|
+
|
|
3870
|
+
/** @deprecated Will be made private in v5.0 */
|
|
3531
3871
|
this.$module = $module;
|
|
3532
|
-
|
|
3872
|
+
|
|
3873
|
+
/** @deprecated Will be made private in v5.0 */
|
|
3874
|
+
this.$inputs = $inputs;
|
|
3533
3875
|
}
|
|
3534
3876
|
|
|
3535
3877
|
/**
|
|
@@ -3547,6 +3889,11 @@
|
|
|
3547
3889
|
* the reveal in sync with the radio state.
|
|
3548
3890
|
*/
|
|
3549
3891
|
Radios.prototype.init = function () {
|
|
3892
|
+
// Check that required elements are present
|
|
3893
|
+
if (!this.$module || !this.$inputs) {
|
|
3894
|
+
return
|
|
3895
|
+
}
|
|
3896
|
+
|
|
3550
3897
|
var $module = this.$module;
|
|
3551
3898
|
var $inputs = this.$inputs;
|
|
3552
3899
|
|
|
@@ -3569,11 +3916,10 @@
|
|
|
3569
3916
|
// state of form controls is not restored until *after* the DOMContentLoaded
|
|
3570
3917
|
// event is fired, so we need to sync after the pageshow event in browsers
|
|
3571
3918
|
// that support it.
|
|
3572
|
-
|
|
3573
|
-
window
|
|
3574
|
-
|
|
3575
|
-
|
|
3576
|
-
}
|
|
3919
|
+
window.addEventListener(
|
|
3920
|
+
'onpageshow' in window ? 'pageshow' : 'DOMContentLoaded',
|
|
3921
|
+
this.syncAllConditionalReveals.bind(this)
|
|
3922
|
+
);
|
|
3577
3923
|
|
|
3578
3924
|
// Although we've set up handlers to sync state on the pageshow or
|
|
3579
3925
|
// DOMContentLoaded event, init could be called after those events have fired,
|
|
@@ -3586,6 +3932,8 @@
|
|
|
3586
3932
|
|
|
3587
3933
|
/**
|
|
3588
3934
|
* Sync the conditional reveal states for all radio buttons in this $module.
|
|
3935
|
+
*
|
|
3936
|
+
* @deprecated Will be made private in v5.0
|
|
3589
3937
|
*/
|
|
3590
3938
|
Radios.prototype.syncAllConditionalReveals = function () {
|
|
3591
3939
|
nodeListForEach(this.$inputs, this.syncConditionalRevealWithInputState.bind(this));
|
|
@@ -3597,15 +3945,20 @@
|
|
|
3597
3945
|
* Synchronise the visibility of the conditional reveal, and its accessible
|
|
3598
3946
|
* state, with the input's checked state.
|
|
3599
3947
|
*
|
|
3948
|
+
* @deprecated Will be made private in v5.0
|
|
3600
3949
|
* @param {HTMLInputElement} $input - Radio input
|
|
3601
3950
|
*/
|
|
3602
3951
|
Radios.prototype.syncConditionalRevealWithInputState = function ($input) {
|
|
3603
|
-
var
|
|
3952
|
+
var targetId = $input.getAttribute('aria-controls');
|
|
3953
|
+
if (!targetId) {
|
|
3954
|
+
return
|
|
3955
|
+
}
|
|
3604
3956
|
|
|
3957
|
+
var $target = document.getElementById(targetId);
|
|
3605
3958
|
if ($target && $target.classList.contains('govuk-radios__conditional')) {
|
|
3606
3959
|
var inputIsChecked = $input.checked;
|
|
3607
3960
|
|
|
3608
|
-
$input.setAttribute('aria-expanded', inputIsChecked);
|
|
3961
|
+
$input.setAttribute('aria-expanded', inputIsChecked.toString());
|
|
3609
3962
|
$target.classList.toggle('govuk-radios__conditional--hidden', !inputIsChecked);
|
|
3610
3963
|
}
|
|
3611
3964
|
};
|
|
@@ -3618,13 +3971,15 @@
|
|
|
3618
3971
|
* with the same name (because checking one radio could have un-checked a radio
|
|
3619
3972
|
* in another $module)
|
|
3620
3973
|
*
|
|
3974
|
+
* @deprecated Will be made private in v5.0
|
|
3621
3975
|
* @param {MouseEvent} event - Click event
|
|
3622
3976
|
*/
|
|
3623
3977
|
Radios.prototype.handleClick = function (event) {
|
|
3978
|
+
var $component = this;
|
|
3624
3979
|
var $clickedInput = event.target;
|
|
3625
3980
|
|
|
3626
3981
|
// Ignore clicks on things that aren't radio buttons
|
|
3627
|
-
if ($clickedInput.type !== 'radio') {
|
|
3982
|
+
if (!($clickedInput instanceof HTMLInputElement) || $clickedInput.type !== 'radio') {
|
|
3628
3983
|
return
|
|
3629
3984
|
}
|
|
3630
3985
|
|
|
@@ -3632,14 +3987,17 @@
|
|
|
3632
3987
|
// aria-controls attributes.
|
|
3633
3988
|
var $allInputs = document.querySelectorAll('input[type="radio"][aria-controls]');
|
|
3634
3989
|
|
|
3990
|
+
var $clickedInputForm = $clickedInput.form;
|
|
3991
|
+
var $clickedInputName = $clickedInput.name;
|
|
3992
|
+
|
|
3635
3993
|
nodeListForEach($allInputs, function ($input) {
|
|
3636
|
-
var hasSameFormOwner =
|
|
3637
|
-
var hasSameName =
|
|
3994
|
+
var hasSameFormOwner = $input.form === $clickedInputForm;
|
|
3995
|
+
var hasSameName = $input.name === $clickedInputName;
|
|
3638
3996
|
|
|
3639
3997
|
if (hasSameName && hasSameFormOwner) {
|
|
3640
|
-
|
|
3998
|
+
$component.syncConditionalRevealWithInputState($input);
|
|
3641
3999
|
}
|
|
3642
|
-
}
|
|
4000
|
+
});
|
|
3643
4001
|
};
|
|
3644
4002
|
|
|
3645
4003
|
/* eslint-disable es-x/no-function-prototype-bind -- Polyfill imported */
|
|
@@ -3648,11 +4006,20 @@
|
|
|
3648
4006
|
* Skip link component
|
|
3649
4007
|
*
|
|
3650
4008
|
* @class
|
|
3651
|
-
* @param {
|
|
4009
|
+
* @param {Element} $module - HTML element to use for skip link
|
|
3652
4010
|
*/
|
|
3653
4011
|
function SkipLink ($module) {
|
|
4012
|
+
if (!($module instanceof HTMLAnchorElement)) {
|
|
4013
|
+
return this
|
|
4014
|
+
}
|
|
4015
|
+
|
|
4016
|
+
/** @deprecated Will be made private in v5.0 */
|
|
3654
4017
|
this.$module = $module;
|
|
4018
|
+
|
|
4019
|
+
/** @deprecated Will be made private in v5.0 */
|
|
3655
4020
|
this.$linkedElement = null;
|
|
4021
|
+
|
|
4022
|
+
/** @deprecated Will be made private in v5.0 */
|
|
3656
4023
|
this.linkedElementListener = false;
|
|
3657
4024
|
}
|
|
3658
4025
|
|
|
@@ -3660,30 +4027,31 @@
|
|
|
3660
4027
|
* Initialise component
|
|
3661
4028
|
*/
|
|
3662
4029
|
SkipLink.prototype.init = function () {
|
|
3663
|
-
// Check
|
|
4030
|
+
// Check that required elements are present
|
|
3664
4031
|
if (!this.$module) {
|
|
3665
4032
|
return
|
|
3666
4033
|
}
|
|
3667
4034
|
|
|
3668
4035
|
// Check for linked element
|
|
3669
|
-
|
|
3670
|
-
if (
|
|
4036
|
+
var $linkedElement = this.getLinkedElement();
|
|
4037
|
+
if (!$linkedElement) {
|
|
3671
4038
|
return
|
|
3672
4039
|
}
|
|
3673
4040
|
|
|
4041
|
+
this.$linkedElement = $linkedElement;
|
|
3674
4042
|
this.$module.addEventListener('click', this.focusLinkedElement.bind(this));
|
|
3675
4043
|
};
|
|
3676
4044
|
|
|
3677
4045
|
/**
|
|
3678
4046
|
* Get linked element
|
|
3679
4047
|
*
|
|
3680
|
-
* @
|
|
4048
|
+
* @deprecated Will be made private in v5.0
|
|
4049
|
+
* @returns {HTMLElement | null} $linkedElement - DOM element linked to from the skip link
|
|
3681
4050
|
*/
|
|
3682
4051
|
SkipLink.prototype.getLinkedElement = function () {
|
|
3683
4052
|
var linkedElementId = this.getFragmentFromUrl();
|
|
3684
|
-
|
|
3685
4053
|
if (!linkedElementId) {
|
|
3686
|
-
return
|
|
4054
|
+
return null
|
|
3687
4055
|
}
|
|
3688
4056
|
|
|
3689
4057
|
return document.getElementById(linkedElementId)
|
|
@@ -3693,6 +4061,8 @@
|
|
|
3693
4061
|
* Focus the linked element
|
|
3694
4062
|
*
|
|
3695
4063
|
* Set tabindex and helper CSS class. Set listener to remove them on blur.
|
|
4064
|
+
*
|
|
4065
|
+
* @deprecated Will be made private in v5.0
|
|
3696
4066
|
*/
|
|
3697
4067
|
SkipLink.prototype.focusLinkedElement = function () {
|
|
3698
4068
|
var $linkedElement = this.$linkedElement;
|
|
@@ -3708,6 +4078,7 @@
|
|
|
3708
4078
|
this.linkedElementListener = true;
|
|
3709
4079
|
}
|
|
3710
4080
|
}
|
|
4081
|
+
|
|
3711
4082
|
$linkedElement.focus();
|
|
3712
4083
|
};
|
|
3713
4084
|
|
|
@@ -3716,6 +4087,8 @@
|
|
|
3716
4087
|
* focusable until it has received programmatic focus and a screen reader has announced it.
|
|
3717
4088
|
*
|
|
3718
4089
|
* Remove the CSS class that removes the native focus styles.
|
|
4090
|
+
*
|
|
4091
|
+
* @deprecated Will be made private in v5.0
|
|
3719
4092
|
*/
|
|
3720
4093
|
SkipLink.prototype.removeFocusProperties = function () {
|
|
3721
4094
|
this.$linkedElement.removeAttribute('tabindex');
|
|
@@ -3728,17 +4101,20 @@
|
|
|
3728
4101
|
* Extract the fragment (everything after the hash symbol) from a URL, but not including
|
|
3729
4102
|
* the symbol.
|
|
3730
4103
|
*
|
|
3731
|
-
* @
|
|
4104
|
+
* @deprecated Will be made private in v5.0
|
|
4105
|
+
* @returns {string | undefined} Fragment from URL, without the hash symbol
|
|
3732
4106
|
*/
|
|
3733
4107
|
SkipLink.prototype.getFragmentFromUrl = function () {
|
|
3734
4108
|
// Bail if the anchor link doesn't have a hash
|
|
3735
4109
|
if (!this.$module.hash) {
|
|
3736
|
-
return
|
|
4110
|
+
return
|
|
3737
4111
|
}
|
|
3738
4112
|
|
|
3739
4113
|
return this.$module.hash.split('#').pop()
|
|
3740
4114
|
};
|
|
3741
4115
|
|
|
4116
|
+
// @ts-nocheck
|
|
4117
|
+
|
|
3742
4118
|
(function(undefined) {
|
|
3743
4119
|
|
|
3744
4120
|
// Detection from https://raw.githubusercontent.com/Financial-Times/polyfill-library/master/polyfills/Element/prototype/nextElementSibling/detect.js
|
|
@@ -3759,6 +4135,8 @@
|
|
|
3759
4135
|
|
|
3760
4136
|
}).call('object' === typeof window && window || 'object' === typeof self && self || 'object' === typeof global && global || {});
|
|
3761
4137
|
|
|
4138
|
+
// @ts-nocheck
|
|
4139
|
+
|
|
3762
4140
|
(function(undefined) {
|
|
3763
4141
|
|
|
3764
4142
|
// Detection from https://raw.githubusercontent.com/Financial-Times/polyfill-library/master/polyfills/Element/prototype/previousElementSibling/detect.js
|
|
@@ -3785,20 +4163,54 @@
|
|
|
3785
4163
|
* Tabs component
|
|
3786
4164
|
*
|
|
3787
4165
|
* @class
|
|
3788
|
-
* @param {
|
|
4166
|
+
* @param {Element} $module - HTML element to use for tabs
|
|
3789
4167
|
*/
|
|
3790
4168
|
function Tabs ($module) {
|
|
4169
|
+
if (!($module instanceof HTMLElement)) {
|
|
4170
|
+
return this
|
|
4171
|
+
}
|
|
4172
|
+
|
|
4173
|
+
var $tabs = $module.querySelectorAll('a.govuk-tabs__tab');
|
|
4174
|
+
if (!$tabs.length) {
|
|
4175
|
+
return this
|
|
4176
|
+
}
|
|
4177
|
+
|
|
4178
|
+
/** @deprecated Will be made private in v5.0 */
|
|
3791
4179
|
this.$module = $module;
|
|
3792
|
-
this.$tabs = $module.querySelectorAll('.govuk-tabs__tab');
|
|
3793
4180
|
|
|
4181
|
+
/** @deprecated Will be made private in v5.0 */
|
|
4182
|
+
this.$tabs = $tabs;
|
|
4183
|
+
|
|
4184
|
+
/** @deprecated Will be made private in v5.0 */
|
|
3794
4185
|
this.keys = { left: 37, right: 39, up: 38, down: 40 };
|
|
4186
|
+
|
|
4187
|
+
/** @deprecated Will be made private in v5.0 */
|
|
3795
4188
|
this.jsHiddenClass = 'govuk-tabs__panel--hidden';
|
|
4189
|
+
|
|
4190
|
+
// Save bounded functions to use when removing event listeners during teardown
|
|
4191
|
+
|
|
4192
|
+
/** @deprecated Will be made private in v5.0 */
|
|
4193
|
+
this.boundTabClick = this.onTabClick.bind(this);
|
|
4194
|
+
|
|
4195
|
+
/** @deprecated Will be made private in v5.0 */
|
|
4196
|
+
this.boundTabKeydown = this.onTabKeydown.bind(this);
|
|
4197
|
+
|
|
4198
|
+
/** @deprecated Will be made private in v5.0 */
|
|
4199
|
+
this.boundOnHashChange = this.onHashChange.bind(this);
|
|
4200
|
+
|
|
4201
|
+
/** @deprecated Will be made private in v5.0 */
|
|
4202
|
+
this.changingHash = false;
|
|
3796
4203
|
}
|
|
3797
4204
|
|
|
3798
4205
|
/**
|
|
3799
4206
|
* Initialise component
|
|
3800
4207
|
*/
|
|
3801
4208
|
Tabs.prototype.init = function () {
|
|
4209
|
+
// Check that required elements are present
|
|
4210
|
+
if (!this.$module || !this.$tabs) {
|
|
4211
|
+
return
|
|
4212
|
+
}
|
|
4213
|
+
|
|
3802
4214
|
if (typeof window.matchMedia === 'function') {
|
|
3803
4215
|
this.setupResponsiveChecks();
|
|
3804
4216
|
} else {
|
|
@@ -3808,8 +4220,11 @@
|
|
|
3808
4220
|
|
|
3809
4221
|
/**
|
|
3810
4222
|
* Setup viewport resize check
|
|
4223
|
+
*
|
|
4224
|
+
* @deprecated Will be made private in v5.0
|
|
3811
4225
|
*/
|
|
3812
4226
|
Tabs.prototype.setupResponsiveChecks = function () {
|
|
4227
|
+
/** @deprecated Will be made private in v5.0 */
|
|
3813
4228
|
this.mql = window.matchMedia('(min-width: 40.0625em)');
|
|
3814
4229
|
this.mql.addListener(this.checkMode.bind(this));
|
|
3815
4230
|
this.checkMode();
|
|
@@ -3817,6 +4232,8 @@
|
|
|
3817
4232
|
|
|
3818
4233
|
/**
|
|
3819
4234
|
* Setup or teardown handler for viewport resize check
|
|
4235
|
+
*
|
|
4236
|
+
* @deprecated Will be made private in v5.0
|
|
3820
4237
|
*/
|
|
3821
4238
|
Tabs.prototype.checkMode = function () {
|
|
3822
4239
|
if (this.mql.matches) {
|
|
@@ -3828,8 +4245,11 @@
|
|
|
3828
4245
|
|
|
3829
4246
|
/**
|
|
3830
4247
|
* Setup tab component
|
|
4248
|
+
*
|
|
4249
|
+
* @deprecated Will be made private in v5.0
|
|
3831
4250
|
*/
|
|
3832
4251
|
Tabs.prototype.setup = function () {
|
|
4252
|
+
var $component = this;
|
|
3833
4253
|
var $module = this.$module;
|
|
3834
4254
|
var $tabs = this.$tabs;
|
|
3835
4255
|
var $tabList = $module.querySelector('.govuk-tabs__list');
|
|
@@ -3847,37 +4267,39 @@
|
|
|
3847
4267
|
|
|
3848
4268
|
nodeListForEach($tabs, function ($tab) {
|
|
3849
4269
|
// Set HTML attributes
|
|
3850
|
-
|
|
3851
|
-
|
|
3852
|
-
// Save bounded functions to use when removing event listeners during teardown
|
|
3853
|
-
$tab.boundTabClick = this.onTabClick.bind(this);
|
|
3854
|
-
$tab.boundTabKeydown = this.onTabKeydown.bind(this);
|
|
4270
|
+
$component.setAttributes($tab);
|
|
3855
4271
|
|
|
3856
4272
|
// Handle events
|
|
3857
|
-
$tab.addEventListener('click', $
|
|
3858
|
-
$tab.addEventListener('keydown', $
|
|
4273
|
+
$tab.addEventListener('click', $component.boundTabClick, true);
|
|
4274
|
+
$tab.addEventListener('keydown', $component.boundTabKeydown, true);
|
|
3859
4275
|
|
|
3860
4276
|
// Remove old active panels
|
|
3861
|
-
|
|
3862
|
-
}
|
|
4277
|
+
$component.hideTab($tab);
|
|
4278
|
+
});
|
|
3863
4279
|
|
|
3864
4280
|
// Show either the active tab according to the URL's hash or the first tab
|
|
3865
4281
|
var $activeTab = this.getTab(window.location.hash) || this.$tabs[0];
|
|
4282
|
+
if (!$activeTab) {
|
|
4283
|
+
return
|
|
4284
|
+
}
|
|
4285
|
+
|
|
3866
4286
|
this.showTab($activeTab);
|
|
3867
4287
|
|
|
3868
4288
|
// Handle hashchange events
|
|
3869
|
-
|
|
3870
|
-
window.addEventListener('hashchange', $module.boundOnHashChange, true);
|
|
4289
|
+
window.addEventListener('hashchange', this.boundOnHashChange, true);
|
|
3871
4290
|
};
|
|
3872
4291
|
|
|
3873
4292
|
/**
|
|
3874
4293
|
* Teardown tab component
|
|
4294
|
+
*
|
|
4295
|
+
* @deprecated Will be made private in v5.0
|
|
3875
4296
|
*/
|
|
3876
4297
|
Tabs.prototype.teardown = function () {
|
|
4298
|
+
var $component = this;
|
|
3877
4299
|
var $module = this.$module;
|
|
3878
4300
|
var $tabs = this.$tabs;
|
|
3879
4301
|
var $tabList = $module.querySelector('.govuk-tabs__list');
|
|
3880
|
-
var $tabListItems = $module.querySelectorAll('.govuk-tabs__list-item');
|
|
4302
|
+
var $tabListItems = $module.querySelectorAll('a.govuk-tabs__list-item');
|
|
3881
4303
|
|
|
3882
4304
|
if (!$tabs || !$tabList || !$tabListItems) {
|
|
3883
4305
|
return
|
|
@@ -3886,29 +4308,29 @@
|
|
|
3886
4308
|
$tabList.removeAttribute('role');
|
|
3887
4309
|
|
|
3888
4310
|
nodeListForEach($tabListItems, function ($item) {
|
|
3889
|
-
$item.removeAttribute('role'
|
|
4311
|
+
$item.removeAttribute('role');
|
|
3890
4312
|
});
|
|
3891
4313
|
|
|
3892
4314
|
nodeListForEach($tabs, function ($tab) {
|
|
3893
4315
|
// Remove events
|
|
3894
|
-
$tab.removeEventListener('click', $
|
|
3895
|
-
$tab.removeEventListener('keydown', $
|
|
4316
|
+
$tab.removeEventListener('click', $component.boundTabClick, true);
|
|
4317
|
+
$tab.removeEventListener('keydown', $component.boundTabKeydown, true);
|
|
3896
4318
|
|
|
3897
4319
|
// Unset HTML attributes
|
|
3898
|
-
|
|
3899
|
-
}
|
|
4320
|
+
$component.unsetAttributes($tab);
|
|
4321
|
+
});
|
|
3900
4322
|
|
|
3901
4323
|
// Remove hashchange event handler
|
|
3902
|
-
window.removeEventListener('hashchange',
|
|
4324
|
+
window.removeEventListener('hashchange', this.boundOnHashChange, true);
|
|
3903
4325
|
};
|
|
3904
4326
|
|
|
3905
4327
|
/**
|
|
3906
4328
|
* Handle hashchange event
|
|
3907
4329
|
*
|
|
3908
|
-
* @
|
|
4330
|
+
* @deprecated Will be made private in v5.0
|
|
3909
4331
|
* @returns {void | undefined} Returns void, or undefined when prevented
|
|
3910
4332
|
*/
|
|
3911
|
-
Tabs.prototype.onHashChange = function (
|
|
4333
|
+
Tabs.prototype.onHashChange = function () {
|
|
3912
4334
|
var hash = window.location.hash;
|
|
3913
4335
|
var $tabWithHash = this.getTab(hash);
|
|
3914
4336
|
if (!$tabWithHash) {
|
|
@@ -3923,6 +4345,9 @@
|
|
|
3923
4345
|
|
|
3924
4346
|
// Show either the active tab according to the URL's hash or the first tab
|
|
3925
4347
|
var $previousTab = this.getCurrentTab();
|
|
4348
|
+
if (!$previousTab) {
|
|
4349
|
+
return
|
|
4350
|
+
}
|
|
3926
4351
|
|
|
3927
4352
|
this.hideTab($previousTab);
|
|
3928
4353
|
this.showTab($tabWithHash);
|
|
@@ -3932,6 +4357,7 @@
|
|
|
3932
4357
|
/**
|
|
3933
4358
|
* Hide panel for tab link
|
|
3934
4359
|
*
|
|
4360
|
+
* @deprecated Will be made private in v5.0
|
|
3935
4361
|
* @param {HTMLAnchorElement} $tab - Tab link
|
|
3936
4362
|
*/
|
|
3937
4363
|
Tabs.prototype.hideTab = function ($tab) {
|
|
@@ -3942,6 +4368,7 @@
|
|
|
3942
4368
|
/**
|
|
3943
4369
|
* Show panel for tab link
|
|
3944
4370
|
*
|
|
4371
|
+
* @deprecated Will be made private in v5.0
|
|
3945
4372
|
* @param {HTMLAnchorElement} $tab - Tab link
|
|
3946
4373
|
*/
|
|
3947
4374
|
Tabs.prototype.showTab = function ($tab) {
|
|
@@ -3952,16 +4379,19 @@
|
|
|
3952
4379
|
/**
|
|
3953
4380
|
* Get tab link by hash
|
|
3954
4381
|
*
|
|
4382
|
+
* @deprecated Will be made private in v5.0
|
|
3955
4383
|
* @param {string} hash - Hash fragment including #
|
|
3956
4384
|
* @returns {HTMLAnchorElement | null} Tab link
|
|
3957
4385
|
*/
|
|
3958
4386
|
Tabs.prototype.getTab = function (hash) {
|
|
3959
|
-
|
|
4387
|
+
// @ts-expect-error `HTMLAnchorElement` type expected
|
|
4388
|
+
return this.$module.querySelector('a.govuk-tabs__tab[href="' + hash + '"]')
|
|
3960
4389
|
};
|
|
3961
4390
|
|
|
3962
4391
|
/**
|
|
3963
4392
|
* Set tab link and panel attributes
|
|
3964
4393
|
*
|
|
4394
|
+
* @deprecated Will be made private in v5.0
|
|
3965
4395
|
* @param {HTMLAnchorElement} $tab - Tab link
|
|
3966
4396
|
*/
|
|
3967
4397
|
Tabs.prototype.setAttributes = function ($tab) {
|
|
@@ -3975,6 +4405,10 @@
|
|
|
3975
4405
|
|
|
3976
4406
|
// set panel attributes
|
|
3977
4407
|
var $panel = this.getPanel($tab);
|
|
4408
|
+
if (!$panel) {
|
|
4409
|
+
return
|
|
4410
|
+
}
|
|
4411
|
+
|
|
3978
4412
|
$panel.setAttribute('role', 'tabpanel');
|
|
3979
4413
|
$panel.setAttribute('aria-labelledby', $tab.id);
|
|
3980
4414
|
$panel.classList.add(this.jsHiddenClass);
|
|
@@ -3983,6 +4417,7 @@
|
|
|
3983
4417
|
/**
|
|
3984
4418
|
* Unset tab link and panel attributes
|
|
3985
4419
|
*
|
|
4420
|
+
* @deprecated Will be made private in v5.0
|
|
3986
4421
|
* @param {HTMLAnchorElement} $tab - Tab link
|
|
3987
4422
|
*/
|
|
3988
4423
|
Tabs.prototype.unsetAttributes = function ($tab) {
|
|
@@ -3995,6 +4430,10 @@
|
|
|
3995
4430
|
|
|
3996
4431
|
// unset panel attributes
|
|
3997
4432
|
var $panel = this.getPanel($tab);
|
|
4433
|
+
if (!$panel) {
|
|
4434
|
+
return
|
|
4435
|
+
}
|
|
4436
|
+
|
|
3998
4437
|
$panel.removeAttribute('role');
|
|
3999
4438
|
$panel.removeAttribute('aria-labelledby');
|
|
4000
4439
|
$panel.classList.remove(this.jsHiddenClass);
|
|
@@ -4003,20 +4442,23 @@
|
|
|
4003
4442
|
/**
|
|
4004
4443
|
* Handle tab link clicks
|
|
4005
4444
|
*
|
|
4445
|
+
* @deprecated Will be made private in v5.0
|
|
4006
4446
|
* @param {MouseEvent} event - Mouse click event
|
|
4007
|
-
* @returns {void
|
|
4447
|
+
* @returns {void} Returns void
|
|
4008
4448
|
*/
|
|
4009
4449
|
Tabs.prototype.onTabClick = function (event) {
|
|
4010
|
-
|
|
4011
|
-
|
|
4012
|
-
|
|
4450
|
+
var $currentTab = this.getCurrentTab();
|
|
4451
|
+
var $nextTab = event.currentTarget;
|
|
4452
|
+
|
|
4453
|
+
if (!$currentTab || !($nextTab instanceof HTMLAnchorElement)) {
|
|
4454
|
+
return
|
|
4013
4455
|
}
|
|
4456
|
+
|
|
4014
4457
|
event.preventDefault();
|
|
4015
|
-
|
|
4016
|
-
var $currentTab = this.getCurrentTab();
|
|
4458
|
+
|
|
4017
4459
|
this.hideTab($currentTab);
|
|
4018
|
-
this.showTab($
|
|
4019
|
-
this.createHistoryEntry($
|
|
4460
|
+
this.showTab($nextTab);
|
|
4461
|
+
this.createHistoryEntry($nextTab);
|
|
4020
4462
|
};
|
|
4021
4463
|
|
|
4022
4464
|
/**
|
|
@@ -4025,10 +4467,14 @@
|
|
|
4025
4467
|
* - Allows back/forward to navigate tabs
|
|
4026
4468
|
* - Avoids page jump when hash changes
|
|
4027
4469
|
*
|
|
4470
|
+
* @deprecated Will be made private in v5.0
|
|
4028
4471
|
* @param {HTMLAnchorElement} $tab - Tab link
|
|
4029
4472
|
*/
|
|
4030
4473
|
Tabs.prototype.createHistoryEntry = function ($tab) {
|
|
4031
4474
|
var $panel = this.getPanel($tab);
|
|
4475
|
+
if (!$panel) {
|
|
4476
|
+
return
|
|
4477
|
+
}
|
|
4032
4478
|
|
|
4033
4479
|
// Save and restore the id
|
|
4034
4480
|
// so the page doesn't jump when a user clicks a tab (which changes the hash)
|
|
@@ -4045,6 +4491,7 @@
|
|
|
4045
4491
|
* - Press right/down arrow for next tab
|
|
4046
4492
|
* - Press left/up arrow for previous tab
|
|
4047
4493
|
*
|
|
4494
|
+
* @deprecated Will be made private in v5.0
|
|
4048
4495
|
* @param {KeyboardEvent} event - Keydown event
|
|
4049
4496
|
*/
|
|
4050
4497
|
Tabs.prototype.onTabKeydown = function (event) {
|
|
@@ -4064,10 +4511,12 @@
|
|
|
4064
4511
|
|
|
4065
4512
|
/**
|
|
4066
4513
|
* Activate next tab
|
|
4514
|
+
*
|
|
4515
|
+
* @deprecated Will be made private in v5.0
|
|
4067
4516
|
*/
|
|
4068
4517
|
Tabs.prototype.activateNextTab = function () {
|
|
4069
4518
|
var $currentTab = this.getCurrentTab();
|
|
4070
|
-
if (!$currentTab) {
|
|
4519
|
+
if (!$currentTab || !$currentTab.parentElement) {
|
|
4071
4520
|
return
|
|
4072
4521
|
}
|
|
4073
4522
|
|
|
@@ -4076,21 +4525,25 @@
|
|
|
4076
4525
|
return
|
|
4077
4526
|
}
|
|
4078
4527
|
|
|
4079
|
-
var $nextTab = $nextTabListItem.querySelector('.govuk-tabs__tab');
|
|
4080
|
-
if (
|
|
4081
|
-
|
|
4082
|
-
this.showTab($nextTab);
|
|
4083
|
-
$nextTab.focus();
|
|
4084
|
-
this.createHistoryEntry($nextTab);
|
|
4528
|
+
var $nextTab = $nextTabListItem.querySelector('a.govuk-tabs__tab');
|
|
4529
|
+
if (!$nextTab) {
|
|
4530
|
+
return
|
|
4085
4531
|
}
|
|
4532
|
+
|
|
4533
|
+
this.hideTab($currentTab);
|
|
4534
|
+
this.showTab($nextTab);
|
|
4535
|
+
$nextTab.focus();
|
|
4536
|
+
this.createHistoryEntry($nextTab);
|
|
4086
4537
|
};
|
|
4087
4538
|
|
|
4088
4539
|
/**
|
|
4089
4540
|
* Activate previous tab
|
|
4541
|
+
*
|
|
4542
|
+
* @deprecated Will be made private in v5.0
|
|
4090
4543
|
*/
|
|
4091
4544
|
Tabs.prototype.activatePreviousTab = function () {
|
|
4092
4545
|
var $currentTab = this.getCurrentTab();
|
|
4093
|
-
if (!$currentTab) {
|
|
4546
|
+
if (!$currentTab || !$currentTab.parentElement) {
|
|
4094
4547
|
return
|
|
4095
4548
|
}
|
|
4096
4549
|
|
|
@@ -4099,75 +4552,98 @@
|
|
|
4099
4552
|
return
|
|
4100
4553
|
}
|
|
4101
4554
|
|
|
4102
|
-
var $previousTab = $previousTabListItem.querySelector('.govuk-tabs__tab');
|
|
4103
|
-
if (
|
|
4104
|
-
|
|
4105
|
-
this.showTab($previousTab);
|
|
4106
|
-
$previousTab.focus();
|
|
4107
|
-
this.createHistoryEntry($previousTab);
|
|
4555
|
+
var $previousTab = $previousTabListItem.querySelector('a.govuk-tabs__tab');
|
|
4556
|
+
if (!$previousTab) {
|
|
4557
|
+
return
|
|
4108
4558
|
}
|
|
4559
|
+
|
|
4560
|
+
this.hideTab($currentTab);
|
|
4561
|
+
this.showTab($previousTab);
|
|
4562
|
+
$previousTab.focus();
|
|
4563
|
+
this.createHistoryEntry($previousTab);
|
|
4109
4564
|
};
|
|
4110
4565
|
|
|
4111
4566
|
/**
|
|
4112
4567
|
* Get tab panel for tab link
|
|
4113
4568
|
*
|
|
4569
|
+
* @deprecated Will be made private in v5.0
|
|
4114
4570
|
* @param {HTMLAnchorElement} $tab - Tab link
|
|
4115
|
-
* @returns {
|
|
4571
|
+
* @returns {Element | null} Tab panel
|
|
4116
4572
|
*/
|
|
4117
4573
|
Tabs.prototype.getPanel = function ($tab) {
|
|
4118
|
-
|
|
4119
|
-
return $panel
|
|
4574
|
+
return this.$module.querySelector(this.getHref($tab))
|
|
4120
4575
|
};
|
|
4121
4576
|
|
|
4122
4577
|
/**
|
|
4123
4578
|
* Show tab panel for tab link
|
|
4124
4579
|
*
|
|
4580
|
+
* @deprecated Will be made private in v5.0
|
|
4125
4581
|
* @param {HTMLAnchorElement} $tab - Tab link
|
|
4126
4582
|
*/
|
|
4127
4583
|
Tabs.prototype.showPanel = function ($tab) {
|
|
4128
4584
|
var $panel = this.getPanel($tab);
|
|
4585
|
+
if (!$panel) {
|
|
4586
|
+
return
|
|
4587
|
+
}
|
|
4588
|
+
|
|
4129
4589
|
$panel.classList.remove(this.jsHiddenClass);
|
|
4130
4590
|
};
|
|
4131
4591
|
|
|
4132
4592
|
/**
|
|
4133
4593
|
* Hide tab panel for tab link
|
|
4134
4594
|
*
|
|
4595
|
+
* @deprecated Will be made private in v5.0
|
|
4135
4596
|
* @param {HTMLAnchorElement} $tab - Tab link
|
|
4136
4597
|
*/
|
|
4137
4598
|
Tabs.prototype.hidePanel = function ($tab) {
|
|
4138
4599
|
var $panel = this.getPanel($tab);
|
|
4600
|
+
if (!$panel) {
|
|
4601
|
+
return
|
|
4602
|
+
}
|
|
4603
|
+
|
|
4139
4604
|
$panel.classList.add(this.jsHiddenClass);
|
|
4140
4605
|
};
|
|
4141
4606
|
|
|
4142
4607
|
/**
|
|
4143
4608
|
* Unset 'selected' state for tab link
|
|
4144
4609
|
*
|
|
4610
|
+
* @deprecated Will be made private in v5.0
|
|
4145
4611
|
* @param {HTMLAnchorElement} $tab - Tab link
|
|
4146
4612
|
*/
|
|
4147
4613
|
Tabs.prototype.unhighlightTab = function ($tab) {
|
|
4614
|
+
if (!$tab.parentElement) {
|
|
4615
|
+
return
|
|
4616
|
+
}
|
|
4617
|
+
|
|
4148
4618
|
$tab.setAttribute('aria-selected', 'false');
|
|
4149
|
-
$tab.
|
|
4619
|
+
$tab.parentElement.classList.remove('govuk-tabs__list-item--selected');
|
|
4150
4620
|
$tab.setAttribute('tabindex', '-1');
|
|
4151
4621
|
};
|
|
4152
4622
|
|
|
4153
4623
|
/**
|
|
4154
4624
|
* Set 'selected' state for tab link
|
|
4155
4625
|
*
|
|
4626
|
+
* @deprecated Will be made private in v5.0
|
|
4156
4627
|
* @param {HTMLAnchorElement} $tab - Tab link
|
|
4157
4628
|
*/
|
|
4158
4629
|
Tabs.prototype.highlightTab = function ($tab) {
|
|
4630
|
+
if (!$tab.parentElement) {
|
|
4631
|
+
return
|
|
4632
|
+
}
|
|
4633
|
+
|
|
4159
4634
|
$tab.setAttribute('aria-selected', 'true');
|
|
4160
|
-
$tab.
|
|
4635
|
+
$tab.parentElement.classList.add('govuk-tabs__list-item--selected');
|
|
4161
4636
|
$tab.setAttribute('tabindex', '0');
|
|
4162
4637
|
};
|
|
4163
4638
|
|
|
4164
4639
|
/**
|
|
4165
4640
|
* Get current tab link
|
|
4166
4641
|
*
|
|
4167
|
-
* @
|
|
4642
|
+
* @deprecated Will be made private in v5.0
|
|
4643
|
+
* @returns {HTMLAnchorElement | null} Tab link
|
|
4168
4644
|
*/
|
|
4169
4645
|
Tabs.prototype.getCurrentTab = function () {
|
|
4170
|
-
return this.$module.querySelector('.govuk-tabs__list-item--selected .govuk-tabs__tab')
|
|
4646
|
+
return this.$module.querySelector('.govuk-tabs__list-item--selected a.govuk-tabs__tab')
|
|
4171
4647
|
};
|
|
4172
4648
|
|
|
4173
4649
|
/**
|
|
@@ -4177,6 +4653,7 @@
|
|
|
4177
4653
|
* should be a utility function most prob
|
|
4178
4654
|
* {@link http://labs.thesedays.com/blog/2010/01/08/getting-the-href-value-with-jquery-in-ie/}
|
|
4179
4655
|
*
|
|
4656
|
+
* @deprecated Will be made private in v5.0
|
|
4180
4657
|
* @param {HTMLAnchorElement} $tab - Tab link
|
|
4181
4658
|
* @returns {string} Hash fragment including #
|
|
4182
4659
|
*/
|
|
@@ -4199,7 +4676,7 @@
|
|
|
4199
4676
|
|
|
4200
4677
|
// Allow the user to initialise GOV.UK Frontend in only certain sections of the page
|
|
4201
4678
|
// Defaults to the entire document if nothing is set.
|
|
4202
|
-
var $scope =
|
|
4679
|
+
var $scope = config.scope instanceof HTMLElement ? config.scope : document;
|
|
4203
4680
|
|
|
4204
4681
|
var $accordions = $scope.querySelectorAll('[data-module="govuk-accordion"]');
|
|
4205
4682
|
nodeListForEach($accordions, function ($accordion) {
|
|
@@ -4250,7 +4727,9 @@
|
|
|
4250
4727
|
|
|
4251
4728
|
// Find first skip link module to enhance.
|
|
4252
4729
|
var $skipLink = $scope.querySelector('[data-module="govuk-skip-link"]');
|
|
4253
|
-
|
|
4730
|
+
if ($skipLink) {
|
|
4731
|
+
new SkipLink($skipLink).init();
|
|
4732
|
+
}
|
|
4254
4733
|
|
|
4255
4734
|
var $tabs = $scope.querySelectorAll('[data-module="govuk-tabs"]');
|
|
4256
4735
|
nodeListForEach($tabs, function ($tabs) {
|
|
@@ -4262,7 +4741,7 @@
|
|
|
4262
4741
|
* Config for all components
|
|
4263
4742
|
*
|
|
4264
4743
|
* @typedef {object} Config
|
|
4265
|
-
* @property {
|
|
4744
|
+
* @property {Element} [scope=document] - Scope to query for components
|
|
4266
4745
|
* @property {import('./components/accordion/accordion.mjs').AccordionConfig} [accordion] - Accordion config
|
|
4267
4746
|
* @property {import('./components/button/button.mjs').ButtonConfig} [button] - Button config
|
|
4268
4747
|
* @property {import('./components/character-count/character-count.mjs').CharacterCountConfig} [characterCount] - Character Count config
|
|
@@ -4271,6 +4750,7 @@
|
|
|
4271
4750
|
*/
|
|
4272
4751
|
|
|
4273
4752
|
exports.initAll = initAll;
|
|
4753
|
+
exports.version = version;
|
|
4274
4754
|
exports.Accordion = Accordion;
|
|
4275
4755
|
exports.Button = Button;
|
|
4276
4756
|
exports.Details = Details;
|