@ministryofjustice/frontend 4.0.1 → 5.1.0
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.
- package/govuk-prototype-kit.config.json +19 -4
- package/moj/_base.scss +2 -0
- package/moj/_base.scss.map +1 -0
- package/moj/all.bundle.js +3010 -0
- package/moj/all.bundle.js.map +1 -0
- package/moj/all.bundle.mjs +3293 -0
- package/moj/all.bundle.mjs.map +1 -0
- package/moj/all.mjs +17 -110
- package/moj/all.mjs.map +1 -1
- package/moj/all.scss +3 -0
- package/moj/all.scss.map +1 -0
- package/moj/common/index.mjs +57 -0
- package/moj/common/index.mjs.map +1 -0
- package/moj/common/moj-frontend-version.mjs +14 -0
- package/moj/common/moj-frontend-version.mjs.map +1 -0
- package/moj/components/_all.scss +2 -0
- package/moj/components/_all.scss.map +1 -0
- package/moj/components/action-bar/_action-bar.scss +2 -0
- package/moj/components/action-bar/_action-bar.scss.map +1 -0
- package/moj/components/add-another/_add-another.scss +2 -0
- package/moj/components/add-another/_add-another.scss.map +1 -0
- package/moj/components/add-another/add-another.bundle.js +157 -0
- package/moj/components/add-another/add-another.bundle.js.map +1 -0
- package/moj/components/add-another/add-another.bundle.mjs +271 -0
- package/moj/components/add-another/add-another.bundle.mjs.map +1 -0
- package/moj/components/add-another/add-another.mjs +135 -91
- package/moj/components/add-another/add-another.mjs.map +1 -1
- package/moj/components/alert/_alert.scss +4 -0
- package/moj/components/alert/_alert.scss.map +1 -0
- package/moj/components/alert/alert.bundle.js +254 -0
- package/moj/components/alert/alert.bundle.js.map +1 -0
- package/moj/components/alert/alert.bundle.mjs +490 -0
- package/moj/components/alert/alert.bundle.mjs.map +1 -0
- package/moj/components/alert/alert.mjs +97 -218
- package/moj/components/alert/alert.mjs.map +1 -1
- package/moj/components/alert/{alert.spec.helper.js → alert.spec.helper.bundle.js} +1 -1
- package/moj/components/alert/alert.spec.helper.bundle.js.map +1 -0
- package/moj/components/alert/alert.spec.helper.bundle.mjs +67 -0
- package/moj/components/alert/alert.spec.helper.bundle.mjs.map +1 -0
- package/moj/components/alert/alert.spec.helper.mjs.map +1 -1
- package/moj/components/badge/_badge.scss +2 -0
- package/moj/components/badge/_badge.scss.map +1 -0
- package/moj/components/banner/_banner.scss +2 -0
- package/moj/components/banner/_banner.scss.map +1 -0
- package/moj/components/button-menu/README.md +12 -6
- package/moj/components/button-menu/_button-menu.scss +4 -1
- package/moj/components/button-menu/_button-menu.scss.map +1 -0
- package/moj/components/button-menu/button-menu.bundle.js +270 -0
- package/moj/components/button-menu/button-menu.bundle.js.map +1 -0
- package/moj/components/button-menu/button-menu.bundle.mjs +506 -0
- package/moj/components/button-menu/button-menu.bundle.mjs.map +1 -0
- package/moj/components/button-menu/button-menu.mjs +214 -280
- package/moj/components/button-menu/button-menu.mjs.map +1 -1
- package/moj/components/cookie-banner/_cookie-banner.scss +2 -0
- package/moj/components/cookie-banner/_cookie-banner.scss.map +1 -0
- package/moj/components/currency-input/_currency-input.scss +2 -0
- package/moj/components/currency-input/_currency-input.scss.map +1 -0
- package/moj/components/date-picker/_date-picker.scss +2 -0
- package/moj/components/date-picker/_date-picker.scss.map +1 -0
- package/moj/components/date-picker/date-picker.bundle.js +804 -0
- package/moj/components/date-picker/date-picker.bundle.js.map +1 -0
- package/moj/components/date-picker/date-picker.bundle.mjs +1040 -0
- package/moj/components/date-picker/date-picker.bundle.mjs.map +1 -0
- package/moj/components/date-picker/date-picker.mjs +663 -827
- package/moj/components/date-picker/date-picker.mjs.map +1 -1
- package/moj/components/filter/_filter.scss +2 -0
- package/moj/components/filter/_filter.scss.map +1 -0
- package/moj/components/filter/template.njk +1 -1
- package/moj/components/filter-toggle-button/filter-toggle-button.bundle.js +185 -0
- package/moj/components/filter-toggle-button/filter-toggle-button.bundle.js.map +1 -0
- package/moj/components/filter-toggle-button/filter-toggle-button.bundle.mjs +421 -0
- package/moj/components/filter-toggle-button/filter-toggle-button.bundle.mjs.map +1 -0
- package/moj/components/filter-toggle-button/filter-toggle-button.mjs +166 -81
- package/moj/components/filter-toggle-button/filter-toggle-button.mjs.map +1 -1
- package/moj/components/form-validator/form-validator.bundle.js +288 -0
- package/moj/components/form-validator/form-validator.bundle.js.map +1 -0
- package/moj/components/form-validator/form-validator.bundle.mjs +524 -0
- package/moj/components/form-validator/form-validator.bundle.mjs.map +1 -0
- package/moj/components/form-validator/form-validator.mjs +226 -149
- package/moj/components/form-validator/form-validator.mjs.map +1 -1
- package/moj/components/header/_header.scss +2 -0
- package/moj/components/header/_header.scss.map +1 -0
- package/moj/components/identity-bar/_identity-bar.scss +2 -0
- package/moj/components/identity-bar/_identity-bar.scss.map +1 -0
- package/moj/components/interruption-card/_interruption-card.scss +2 -0
- package/moj/components/interruption-card/_interruption-card.scss.map +1 -0
- package/moj/components/messages/_messages.scss +2 -0
- package/moj/components/messages/_messages.scss.map +1 -0
- package/moj/components/multi-file-upload/_multi-file-upload.scss +2 -0
- package/moj/components/multi-file-upload/_multi-file-upload.scss.map +1 -0
- package/moj/components/multi-file-upload/multi-file-upload.bundle.js +397 -0
- package/moj/components/multi-file-upload/multi-file-upload.bundle.js.map +1 -0
- package/moj/components/multi-file-upload/multi-file-upload.bundle.mjs +633 -0
- package/moj/components/multi-file-upload/multi-file-upload.bundle.mjs.map +1 -0
- package/moj/components/multi-file-upload/multi-file-upload.mjs +384 -213
- package/moj/components/multi-file-upload/multi-file-upload.mjs.map +1 -1
- package/moj/components/multi-file-upload/template.njk +1 -1
- package/moj/components/multi-select/_multi-select.scss +2 -0
- package/moj/components/multi-select/_multi-select.scss.map +1 -0
- package/moj/components/multi-select/multi-select.bundle.js +143 -0
- package/moj/components/multi-select/multi-select.bundle.js.map +1 -0
- package/moj/components/multi-select/multi-select.bundle.mjs +379 -0
- package/moj/components/multi-select/multi-select.bundle.mjs.map +1 -0
- package/moj/components/multi-select/multi-select.mjs +123 -64
- package/moj/components/multi-select/multi-select.mjs.map +1 -1
- package/moj/components/notification-badge/_notification-badge.scss +2 -0
- package/moj/components/notification-badge/_notification-badge.scss.map +1 -0
- package/moj/components/organisation-switcher/_organisation-switcher.scss +2 -0
- package/moj/components/organisation-switcher/_organisation-switcher.scss.map +1 -0
- package/moj/components/page-header-actions/_page-header-actions.scss +2 -0
- package/moj/components/page-header-actions/_page-header-actions.scss.map +1 -0
- package/moj/components/pagination/_pagination.scss +2 -2
- package/moj/components/pagination/_pagination.scss.map +1 -0
- package/moj/components/password-reveal/_password-reveal.scss +5 -1
- package/moj/components/password-reveal/_password-reveal.scss.map +1 -0
- package/moj/components/password-reveal/password-reveal.bundle.js +52 -0
- package/moj/components/password-reveal/password-reveal.bundle.js.map +1 -0
- package/moj/components/password-reveal/password-reveal.bundle.mjs +166 -0
- package/moj/components/password-reveal/password-reveal.bundle.mjs.map +1 -0
- package/moj/components/password-reveal/password-reveal.mjs +39 -29
- package/moj/components/password-reveal/password-reveal.mjs.map +1 -1
- package/moj/components/primary-navigation/_primary-navigation.scss +2 -0
- package/moj/components/primary-navigation/_primary-navigation.scss.map +1 -0
- package/moj/components/progress-bar/_progress-bar.scss +2 -0
- package/moj/components/progress-bar/_progress-bar.scss.map +1 -0
- package/moj/components/rich-text-editor/README.md +16 -9
- package/moj/components/rich-text-editor/_rich-text-editor.scss +2 -0
- package/moj/components/rich-text-editor/_rich-text-editor.scss.map +1 -0
- package/moj/components/rich-text-editor/rich-text-editor.bundle.js +210 -0
- package/moj/components/rich-text-editor/rich-text-editor.bundle.js.map +1 -0
- package/moj/components/rich-text-editor/rich-text-editor.bundle.mjs +446 -0
- package/moj/components/rich-text-editor/rich-text-editor.bundle.mjs.map +1 -0
- package/moj/components/rich-text-editor/rich-text-editor.mjs +186 -140
- package/moj/components/rich-text-editor/rich-text-editor.mjs.map +1 -1
- package/moj/components/search/_search.scss +2 -0
- package/moj/components/search/_search.scss.map +1 -0
- package/moj/components/search-toggle/{search-toggle.scss → _search-toggle.scss} +2 -0
- package/moj/components/search-toggle/_search-toggle.scss.map +1 -0
- package/moj/components/search-toggle/search-toggle.bundle.js +122 -0
- package/moj/components/search-toggle/search-toggle.bundle.js.map +1 -0
- package/moj/components/search-toggle/search-toggle.bundle.mjs +358 -0
- package/moj/components/search-toggle/search-toggle.bundle.mjs.map +1 -0
- package/moj/components/search-toggle/search-toggle.mjs +104 -43
- package/moj/components/search-toggle/search-toggle.mjs.map +1 -1
- package/moj/components/side-navigation/_side-navigation.scss +2 -0
- package/moj/components/side-navigation/_side-navigation.scss.map +1 -0
- package/moj/components/sortable-table/_sortable-table.scss +2 -2
- package/moj/components/sortable-table/_sortable-table.scss.map +1 -0
- package/moj/components/sortable-table/sortable-table.bundle.js +202 -0
- package/moj/components/sortable-table/sortable-table.bundle.js.map +1 -0
- package/moj/components/sortable-table/sortable-table.bundle.mjs +438 -0
- package/moj/components/sortable-table/sortable-table.bundle.mjs.map +1 -0
- package/moj/components/sortable-table/sortable-table.mjs +179 -122
- package/moj/components/sortable-table/sortable-table.mjs.map +1 -1
- package/moj/components/sub-navigation/_sub-navigation.scss +2 -0
- package/moj/components/sub-navigation/_sub-navigation.scss.map +1 -0
- package/moj/components/tag/_tag.scss +2 -0
- package/moj/components/tag/_tag.scss.map +1 -0
- package/moj/components/task-list/_task-list.scss +2 -0
- package/moj/components/task-list/_task-list.scss.map +1 -0
- package/moj/components/ticket-panel/_ticket-panel.scss +2 -0
- package/moj/components/ticket-panel/_ticket-panel.scss.map +1 -0
- package/moj/components/timeline/_timeline.scss +2 -0
- package/moj/components/timeline/_timeline.scss.map +1 -0
- package/moj/core/_all.scss +3 -0
- package/moj/core/_all.scss.map +1 -0
- package/moj/core/_moj-frontend-properties.scss +7 -0
- package/moj/core/_moj-frontend-properties.scss.map +1 -0
- package/moj/filters/all.js +44 -22
- package/moj/filters/prototype-kit-13-filters.js +4 -3
- package/moj/helpers/_all.scss +2 -0
- package/moj/helpers/_all.scss.map +1 -0
- package/moj/helpers/_hidden.scss +2 -0
- package/moj/helpers/_hidden.scss.map +1 -0
- package/moj/helpers/_links.scss +2 -0
- package/moj/helpers/_links.scss.map +1 -0
- package/moj/helpers.bundle.js +140 -0
- package/moj/helpers.bundle.js.map +1 -0
- package/moj/helpers.bundle.mjs +128 -0
- package/moj/helpers.bundle.mjs.map +1 -0
- package/moj/helpers.mjs +50 -77
- package/moj/helpers.mjs.map +1 -1
- package/moj/init.js +11 -2
- package/moj/moj-frontend.min.css +1 -1
- package/moj/moj-frontend.min.css.map +1 -1
- package/moj/moj-frontend.min.js +1 -1
- package/moj/moj-frontend.min.js.map +1 -1
- package/moj/objects/_all.scss +2 -0
- package/moj/objects/_all.scss.map +1 -0
- package/moj/objects/_button-group.scss +2 -0
- package/moj/objects/_button-group.scss.map +1 -0
- package/moj/objects/_filter-layout.scss +2 -0
- package/moj/objects/_filter-layout.scss.map +1 -0
- package/moj/objects/_scrollable-pane.scss +2 -0
- package/moj/objects/_scrollable-pane.scss.map +1 -0
- package/moj/objects/_width-container.scss +2 -0
- package/moj/objects/_width-container.scss.map +1 -0
- package/moj/settings/_all.scss +2 -0
- package/moj/settings/_all.scss.map +1 -0
- package/moj/settings/_assets.scss +2 -0
- package/moj/settings/_assets.scss.map +1 -0
- package/moj/settings/_colours.scss +2 -0
- package/moj/settings/_colours.scss.map +1 -0
- package/moj/settings/_measurements.scss +2 -0
- package/moj/settings/_measurements.scss.map +1 -0
- package/moj/settings/_typography.scss +2 -0
- package/moj/settings/_typography.scss.map +1 -0
- package/moj/template.njk +13 -0
- package/moj/utilities/_all.scss +2 -0
- package/moj/utilities/_all.scss.map +1 -0
- package/moj/utilities/_hidden.scss +2 -0
- package/moj/utilities/_hidden.scss.map +1 -0
- package/moj/utilities/_width-container.scss +2 -0
- package/moj/utilities/_width-container.scss.map +1 -0
- package/moj/vendor/govuk-frontend/_base.scss +2 -0
- package/moj/vendor/govuk-frontend/_base.scss.map +1 -0
- package/moj/vendor/govuk-frontend/_index.scss +2 -0
- package/moj/vendor/govuk-frontend/_index.scss.map +1 -0
- package/package.json +5 -6
- package/moj/all.jquery.min.js +0 -1
- package/moj/all.jquery.min.js.map +0 -1
- package/moj/all.js +0 -2662
- package/moj/all.js.map +0 -1
- package/moj/components/add-another/add-another.js +0 -115
- package/moj/components/add-another/add-another.js.map +0 -1
- package/moj/components/alert/alert.js +0 -356
- package/moj/components/alert/alert.js.map +0 -1
- package/moj/components/alert/alert.spec.helper.js.map +0 -1
- package/moj/components/button-menu/button-menu.js +0 -338
- package/moj/components/button-menu/button-menu.js.map +0 -1
- package/moj/components/date-picker/date-picker.js +0 -970
- package/moj/components/date-picker/date-picker.js.map +0 -1
- package/moj/components/filter-toggle-button/filter-toggle-button.js +0 -102
- package/moj/components/filter-toggle-button/filter-toggle-button.js.map +0 -1
- package/moj/components/form-validator/form-validator.js +0 -205
- package/moj/components/form-validator/form-validator.js.map +0 -1
- package/moj/components/multi-file-upload/multi-file-upload.js +0 -241
- package/moj/components/multi-file-upload/multi-file-upload.js.map +0 -1
- package/moj/components/multi-select/multi-select.js +0 -86
- package/moj/components/multi-select/multi-select.js.map +0 -1
- package/moj/components/password-reveal/password-reveal.js +0 -44
- package/moj/components/password-reveal/password-reveal.js.map +0 -1
- package/moj/components/rich-text-editor/rich-text-editor.js +0 -166
- package/moj/components/rich-text-editor/rich-text-editor.js.map +0 -1
- package/moj/components/search-toggle/search-toggle.js +0 -63
- package/moj/components/search-toggle/search-toggle.js.map +0 -1
- package/moj/components/sortable-table/sortable-table.js +0 -147
- package/moj/components/sortable-table/sortable-table.js.map +0 -1
- package/moj/helpers.js +0 -200
- package/moj/helpers.js.map +0 -1
- package/moj/vendor/html5shiv.js +0 -326
- package/moj/vendor/jquery.js +0 -9300
- package/moj/version.js +0 -12
- package/moj/version.js.map +0 -1
- package/moj/version.mjs +0 -4
- package/moj/version.mjs.map +0 -1
|
@@ -1,94 +1,179 @@
|
|
|
1
|
-
|
|
2
|
-
this.options = options;
|
|
3
|
-
this.container = $(this.options.toggleButton.container);
|
|
4
|
-
this.filterContainer = $(this.options.filter.container);
|
|
1
|
+
import { ConfigurableComponent } from 'govuk-frontend';
|
|
5
2
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
3
|
+
/**
|
|
4
|
+
* @augments {ConfigurableComponent<FilterToggleButtonConfig>}
|
|
5
|
+
*/
|
|
6
|
+
class FilterToggleButton extends ConfigurableComponent {
|
|
7
|
+
/**
|
|
8
|
+
* @param {Element | null} $root - HTML element to use for filter toggle button
|
|
9
|
+
* @param {FilterToggleButtonConfig} [config] - Filter toggle button config
|
|
10
|
+
*/
|
|
11
|
+
constructor($root, config = {}) {
|
|
12
|
+
var _this$config$toggleBu, _this$config$closeBut;
|
|
13
|
+
super($root, config);
|
|
14
|
+
const $toggleButtonContainer = (_this$config$toggleBu = this.config.toggleButtonContainer.element) != null ? _this$config$toggleBu : document.querySelector(this.config.toggleButtonContainer.selector);
|
|
15
|
+
const $closeButtonContainer = (_this$config$closeBut = this.config.closeButtonContainer.element) != null ? _this$config$closeBut : this.$root.querySelector(this.config.closeButtonContainer.selector);
|
|
16
|
+
if (!($toggleButtonContainer instanceof HTMLElement && $closeButtonContainer instanceof HTMLElement)) {
|
|
17
|
+
return this;
|
|
18
|
+
}
|
|
19
|
+
this.$toggleButtonContainer = $toggleButtonContainer;
|
|
20
|
+
this.$closeButtonContainer = $closeButtonContainer;
|
|
21
|
+
this.createToggleButton();
|
|
22
|
+
this.setupResponsiveChecks();
|
|
23
|
+
this.$root.setAttribute('tabindex', '-1');
|
|
24
|
+
if (this.config.startHidden) {
|
|
25
|
+
this.hideMenu();
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
setupResponsiveChecks() {
|
|
29
|
+
this.mq = window.matchMedia(this.config.bigModeMediaQuery);
|
|
30
|
+
this.mq.addListener(this.checkMode.bind(this));
|
|
31
|
+
this.checkMode();
|
|
32
|
+
}
|
|
33
|
+
createToggleButton() {
|
|
34
|
+
this.$menuButton = document.createElement('button');
|
|
35
|
+
this.$menuButton.setAttribute('type', 'button');
|
|
36
|
+
this.$menuButton.setAttribute('aria-haspopup', 'true');
|
|
37
|
+
this.$menuButton.setAttribute('aria-expanded', 'false');
|
|
38
|
+
this.$menuButton.className = `govuk-button ${this.config.toggleButton.classes}`;
|
|
39
|
+
this.$menuButton.textContent = this.config.toggleButton.showText;
|
|
40
|
+
this.$menuButton.addEventListener('click', this.onMenuButtonClick.bind(this));
|
|
41
|
+
this.$toggleButtonContainer.append(this.$menuButton);
|
|
42
|
+
}
|
|
43
|
+
checkMode() {
|
|
44
|
+
if (this.mq.matches) {
|
|
45
|
+
this.enableBigMode();
|
|
46
|
+
} else {
|
|
47
|
+
this.enableSmallMode();
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
enableBigMode() {
|
|
51
|
+
this.showMenu();
|
|
52
|
+
this.removeCloseButton();
|
|
53
|
+
}
|
|
54
|
+
enableSmallMode() {
|
|
10
55
|
this.hideMenu();
|
|
56
|
+
this.addCloseButton();
|
|
11
57
|
}
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
FilterToggleButton.prototype.createToggleButton = function () {
|
|
21
|
-
this.menuButton = $(
|
|
22
|
-
`<button class="govuk-button ${this.options.toggleButton.classes}" type="button" aria-haspopup="true" aria-expanded="false">${this.options.toggleButton.showText}</button>`
|
|
23
|
-
);
|
|
24
|
-
this.menuButton.on('click', $.proxy(this, 'onMenuButtonClick'));
|
|
25
|
-
this.container.append(this.menuButton);
|
|
26
|
-
};
|
|
27
|
-
|
|
28
|
-
FilterToggleButton.prototype.checkMode = function (mq) {
|
|
29
|
-
if (mq.matches) {
|
|
30
|
-
this.enableBigMode();
|
|
31
|
-
} else {
|
|
32
|
-
this.enableSmallMode();
|
|
58
|
+
addCloseButton() {
|
|
59
|
+
this.$closeButton = document.createElement('button');
|
|
60
|
+
this.$closeButton.setAttribute('type', 'button');
|
|
61
|
+
this.$closeButton.className = this.config.closeButton.classes;
|
|
62
|
+
this.$closeButton.textContent = this.config.closeButton.text;
|
|
63
|
+
this.$closeButton.addEventListener('click', this.onCloseClick.bind(this));
|
|
64
|
+
this.$closeButtonContainer.append(this.$closeButton);
|
|
33
65
|
}
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
this.showMenu();
|
|
38
|
-
this.removeCloseButton();
|
|
39
|
-
};
|
|
40
|
-
|
|
41
|
-
FilterToggleButton.prototype.enableSmallMode = function () {
|
|
42
|
-
this.hideMenu();
|
|
43
|
-
this.addCloseButton();
|
|
44
|
-
};
|
|
45
|
-
|
|
46
|
-
FilterToggleButton.prototype.addCloseButton = function () {
|
|
47
|
-
if (this.options.closeButton) {
|
|
48
|
-
this.closeButton = $(
|
|
49
|
-
`<button class="moj-filter__close" type="button">${this.options.closeButton.text}</button>`
|
|
50
|
-
);
|
|
51
|
-
this.closeButton.on('click', $.proxy(this, 'onCloseClick'));
|
|
52
|
-
$(this.options.closeButton.container).append(this.closeButton);
|
|
66
|
+
onCloseClick() {
|
|
67
|
+
this.hideMenu();
|
|
68
|
+
this.$menuButton.focus();
|
|
53
69
|
}
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
this.
|
|
64
|
-
|
|
70
|
+
removeCloseButton() {
|
|
71
|
+
if (this.$closeButton) {
|
|
72
|
+
this.$closeButton.remove();
|
|
73
|
+
this.$closeButton = null;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
hideMenu() {
|
|
77
|
+
this.$menuButton.setAttribute('aria-expanded', 'false');
|
|
78
|
+
this.$root.classList.add('moj-js-hidden');
|
|
79
|
+
this.$menuButton.textContent = this.config.toggleButton.showText;
|
|
80
|
+
}
|
|
81
|
+
showMenu() {
|
|
82
|
+
this.$menuButton.setAttribute('aria-expanded', 'true');
|
|
83
|
+
this.$root.classList.remove('moj-js-hidden');
|
|
84
|
+
this.$menuButton.textContent = this.config.toggleButton.hideText;
|
|
85
|
+
}
|
|
86
|
+
onMenuButtonClick() {
|
|
87
|
+
this.toggle();
|
|
88
|
+
}
|
|
89
|
+
toggle() {
|
|
90
|
+
if (this.$menuButton.getAttribute('aria-expanded') === 'false') {
|
|
91
|
+
this.showMenu();
|
|
92
|
+
this.$root.focus();
|
|
93
|
+
} else {
|
|
94
|
+
this.hideMenu();
|
|
95
|
+
}
|
|
65
96
|
}
|
|
66
|
-
};
|
|
67
|
-
|
|
68
|
-
FilterToggleButton.prototype.hideMenu = function () {
|
|
69
|
-
this.menuButton.attr('aria-expanded', 'false');
|
|
70
|
-
this.filterContainer.addClass('moj-js-hidden');
|
|
71
|
-
this.menuButton.text(this.options.toggleButton.showText);
|
|
72
|
-
};
|
|
73
97
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
};
|
|
98
|
+
/**
|
|
99
|
+
* Name for the component used when initialising using data-module attributes.
|
|
100
|
+
*/
|
|
101
|
+
}
|
|
79
102
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
}
|
|
103
|
+
/**
|
|
104
|
+
* @typedef {object} FilterToggleButtonConfig
|
|
105
|
+
* @property {string} [bigModeMediaQuery] - Media query for big mode
|
|
106
|
+
* @property {boolean} [startHidden] - Whether to start hidden
|
|
107
|
+
* @property {object} [toggleButton] - Toggle button config
|
|
108
|
+
* @property {string} [toggleButton.showText] - Text for show button
|
|
109
|
+
* @property {string} [toggleButton.hideText] - Text for hide button
|
|
110
|
+
* @property {string} [toggleButton.classes] - Classes for toggle button
|
|
111
|
+
* @property {object} [toggleButtonContainer] - Toggle button container config
|
|
112
|
+
* @property {string} [toggleButtonContainer.selector] - Selector for toggle button container
|
|
113
|
+
* @property {Element | null} [toggleButtonContainer.element] - HTML element for toggle button container
|
|
114
|
+
* @property {object} [closeButton] - Close button config
|
|
115
|
+
* @property {string} [closeButton.text] - Text for close button
|
|
116
|
+
* @property {string} [closeButton.classes] - Classes for close button
|
|
117
|
+
* @property {object} [closeButtonContainer] - Close button container config
|
|
118
|
+
* @property {string} [closeButtonContainer.selector] - Selector for close button container
|
|
119
|
+
* @property {Element | null} [closeButtonContainer.element] - HTML element for close button container
|
|
120
|
+
*/
|
|
83
121
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
122
|
+
/**
|
|
123
|
+
* @import { Schema } from 'govuk-frontend/dist/govuk/common/configuration.mjs'
|
|
124
|
+
*/
|
|
125
|
+
FilterToggleButton.moduleName = 'moj-filter';
|
|
126
|
+
/**
|
|
127
|
+
* Filter toggle button config
|
|
128
|
+
*
|
|
129
|
+
* @type {FilterToggleButtonConfig}
|
|
130
|
+
*/
|
|
131
|
+
FilterToggleButton.defaults = Object.freeze({
|
|
132
|
+
bigModeMediaQuery: '(min-width: 48.0625em)',
|
|
133
|
+
startHidden: true,
|
|
134
|
+
toggleButton: {
|
|
135
|
+
showText: 'Show filter',
|
|
136
|
+
hideText: 'Hide filter',
|
|
137
|
+
classes: 'govuk-button--secondary'
|
|
138
|
+
},
|
|
139
|
+
toggleButtonContainer: {
|
|
140
|
+
selector: '.moj-action-bar__filter'
|
|
141
|
+
},
|
|
142
|
+
closeButton: {
|
|
143
|
+
text: 'Close',
|
|
144
|
+
classes: 'moj-filter__close'
|
|
145
|
+
},
|
|
146
|
+
closeButtonContainer: {
|
|
147
|
+
selector: '.moj-filter__header-action'
|
|
148
|
+
}
|
|
149
|
+
});
|
|
150
|
+
/**
|
|
151
|
+
* Filter toggle button config schema
|
|
152
|
+
*
|
|
153
|
+
* @satisfies {Schema<FilterToggleButtonConfig>}
|
|
154
|
+
*/
|
|
155
|
+
FilterToggleButton.schema = Object.freeze(/** @type {const} */{
|
|
156
|
+
properties: {
|
|
157
|
+
bigModeMediaQuery: {
|
|
158
|
+
type: 'string'
|
|
159
|
+
},
|
|
160
|
+
startHidden: {
|
|
161
|
+
type: 'boolean'
|
|
162
|
+
},
|
|
163
|
+
toggleButton: {
|
|
164
|
+
type: 'object'
|
|
165
|
+
},
|
|
166
|
+
toggleButtonContainer: {
|
|
167
|
+
type: 'object'
|
|
168
|
+
},
|
|
169
|
+
closeButton: {
|
|
170
|
+
type: 'object'
|
|
171
|
+
},
|
|
172
|
+
closeButtonContainer: {
|
|
173
|
+
type: 'object'
|
|
174
|
+
}
|
|
90
175
|
}
|
|
91
|
-
};
|
|
176
|
+
});
|
|
92
177
|
|
|
93
178
|
export { FilterToggleButton };
|
|
94
179
|
//# sourceMappingURL=filter-toggle-button.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"filter-toggle-button.mjs","sources":["../../../../src/moj/components/filter-toggle-button/filter-toggle-button.mjs"],"sourcesContent":["import $ from 'jquery'\n\nexport function FilterToggleButton(options) {\n this.options = options\n this.container = $(this.options.toggleButton.container)\n this.filterContainer = $(this.options.filter.container)\n\n this.createToggleButton()\n this.setupResponsiveChecks()\n this.filterContainer.attr('tabindex', '-1')\n if (this.options.startHidden) {\n this.hideMenu()\n }\n}\n\nFilterToggleButton.prototype.setupResponsiveChecks = function () {\n this.mq = window.matchMedia(this.options.bigModeMediaQuery)\n this.mq.addListener($.proxy(this, 'checkMode'))\n this.checkMode(this.mq)\n}\n\nFilterToggleButton.prototype.createToggleButton = function () {\n this.menuButton = $(\n `<button class=\"govuk-button ${this.options.toggleButton.classes}\" type=\"button\" aria-haspopup=\"true\" aria-expanded=\"false\">${this.options.toggleButton.showText}</button>`\n )\n this.menuButton.on('click', $.proxy(this, 'onMenuButtonClick'))\n this.container.append(this.menuButton)\n}\n\nFilterToggleButton.prototype.checkMode = function (mq) {\n if (mq.matches) {\n this.enableBigMode()\n } else {\n this.enableSmallMode()\n }\n}\n\nFilterToggleButton.prototype.enableBigMode = function () {\n this.showMenu()\n this.removeCloseButton()\n}\n\nFilterToggleButton.prototype.enableSmallMode = function () {\n this.hideMenu()\n this.addCloseButton()\n}\n\nFilterToggleButton.prototype.addCloseButton = function () {\n if (this.options.closeButton) {\n this.closeButton = $(\n `<button class=\"moj-filter__close\" type=\"button\">${this.options.closeButton.text}</button>`\n )\n this.closeButton.on('click', $.proxy(this, 'onCloseClick'))\n $(this.options.closeButton.container).append(this.closeButton)\n }\n}\n\nFilterToggleButton.prototype.onCloseClick = function () {\n this.hideMenu()\n this.menuButton.focus()\n}\n\nFilterToggleButton.prototype.removeCloseButton = function () {\n if (this.closeButton) {\n this.closeButton.remove()\n this.closeButton = null\n }\n}\n\nFilterToggleButton.prototype.hideMenu = function () {\n this.menuButton.attr('aria-expanded', 'false')\n this.filterContainer.addClass('moj-js-hidden')\n this.menuButton.text(this.options.toggleButton.showText)\n}\n\nFilterToggleButton.prototype.showMenu = function () {\n this.menuButton.attr('aria-expanded', 'true')\n this.filterContainer.removeClass('moj-js-hidden')\n this.menuButton.text(this.options.toggleButton.hideText)\n}\n\nFilterToggleButton.prototype.onMenuButtonClick = function () {\n this.toggle()\n}\n\nFilterToggleButton.prototype.toggle = function () {\n if (this.menuButton.attr('aria-expanded') === 'false') {\n this.showMenu()\n this.filterContainer.get(0).focus()\n } else {\n this.hideMenu()\n }\n}\n"],"names":[],"mappings":"AAEA,SAAA,kBAAA,CAAA,OAAA,EAAA;AACA,EAAA,IAAA,CAAA,OAAA,GAAA;AACA,EAAA,IAAA,CAAA,SAAA,GAAA,CAAA,CAAA,IAAA,CAAA,OAAA,CAAA,YAAA,CAAA,SAAA;AACA,EAAA,IAAA,CAAA,eAAA,GAAA,CAAA,CAAA,IAAA,CAAA,OAAA,CAAA,MAAA,CAAA,SAAA;;AAEA,EAAA,IAAA,CAAA,kBAAA;AACA,EAAA,IAAA,CAAA,qBAAA;AACA,EAAA,IAAA,CAAA,eAAA,CAAA,IAAA,CAAA,UAAA,EAAA,IAAA;AACA,EAAA,IAAA,IAAA,CAAA,OAAA,CAAA,WAAA,EAAA;AACA,IAAA,IAAA,CAAA,QAAA;AACA;AACA;;AAEA,kBAAA,CAAA,SAAA,CAAA,qBAAA,GAAA,YAAA;AACA,EAAA,IAAA,CAAA,EAAA,GAAA,MAAA,CAAA,UAAA,CAAA,IAAA,CAAA,OAAA,CAAA,iBAAA;AACA,EAAA,IAAA,CAAA,EAAA,CAAA,WAAA,CAAA,CAAA,CAAA,KAAA,CAAA,IAAA,EAAA,WAAA,CAAA;AACA,EAAA,IAAA,CAAA,SAAA,CAAA,IAAA,CAAA,EAAA;AACA;;AAEA,kBAAA,CAAA,SAAA,CAAA,kBAAA,GAAA,YAAA;AACA,EAAA,IAAA,CAAA,UAAA,GAAA,CAAA;AACA,IAAA,CAAA,4BAAA,EAAA,IAAA,CAAA,OAAA,CAAA,YAAA,CAAA,OAAA,CAAA,2DAAA,EAAA,IAAA,CAAA,OAAA,CAAA,YAAA,CAAA,QAAA,CAAA,SAAA;AACA;AACA,EAAA,IAAA,CAAA,UAAA,CAAA,EAAA,CAAA,OAAA,EAAA,CAAA,CAAA,KAAA,CAAA,IAAA,EAAA,mBAAA,CAAA;AACA,EAAA,IAAA,CAAA,SAAA,CAAA,MAAA,CAAA,IAAA,CAAA,UAAA;AACA;;AAEA,kBAAA,CAAA,SAAA,CAAA,SAAA,GAAA,UAAA,EAAA,EAAA;AACA,EAAA,IAAA,EAAA,CAAA,OAAA,EAAA;AACA,IAAA,IAAA,CAAA,aAAA;AACA,GAAA,MAAA;AACA,IAAA,IAAA,CAAA,eAAA;AACA;AACA;;AAEA,kBAAA,CAAA,SAAA,CAAA,aAAA,GAAA,YAAA;AACA,EAAA,IAAA,CAAA,QAAA;AACA,EAAA,IAAA,CAAA,iBAAA;AACA;;AAEA,kBAAA,CAAA,SAAA,CAAA,eAAA,GAAA,YAAA;AACA,EAAA,IAAA,CAAA,QAAA;AACA,EAAA,IAAA,CAAA,cAAA;AACA;;AAEA,kBAAA,CAAA,SAAA,CAAA,cAAA,GAAA,YAAA;AACA,EAAA,IAAA,IAAA,CAAA,OAAA,CAAA,WAAA,EAAA;AACA,IAAA,IAAA,CAAA,WAAA,GAAA,CAAA;AACA,MAAA,CAAA,gDAAA,EAAA,IAAA,CAAA,OAAA,CAAA,WAAA,CAAA,IAAA,CAAA,SAAA;AACA;AACA,IAAA,IAAA,CAAA,WAAA,CAAA,EAAA,CAAA,OAAA,EAAA,CAAA,CAAA,KAAA,CAAA,IAAA,EAAA,cAAA,CAAA;AACA,IAAA,CAAA,CAAA,IAAA,CAAA,OAAA,CAAA,WAAA,CAAA,SAAA,CAAA,CAAA,MAAA,CAAA,IAAA,CAAA,WAAA;AACA;AACA;;AAEA,kBAAA,CAAA,SAAA,CAAA,YAAA,GAAA,YAAA;AACA,EAAA,IAAA,CAAA,QAAA;AACA,EAAA,IAAA,CAAA,UAAA,CAAA,KAAA;AACA;;AAEA,kBAAA,CAAA,SAAA,CAAA,iBAAA,GAAA,YAAA;AACA,EAAA,IAAA,IAAA,CAAA,WAAA,EAAA;AACA,IAAA,IAAA,CAAA,WAAA,CAAA,MAAA;AACA,IAAA,IAAA,CAAA,WAAA,GAAA;AACA;AACA;;AAEA,kBAAA,CAAA,SAAA,CAAA,QAAA,GAAA,YAAA;AACA,EAAA,IAAA,CAAA,UAAA,CAAA,IAAA,CAAA,eAAA,EAAA,OAAA;AACA,EAAA,IAAA,CAAA,eAAA,CAAA,QAAA,CAAA,eAAA;AACA,EAAA,IAAA,CAAA,UAAA,CAAA,IAAA,CAAA,IAAA,CAAA,OAAA,CAAA,YAAA,CAAA,QAAA;AACA;;AAEA,kBAAA,CAAA,SAAA,CAAA,QAAA,GAAA,YAAA;AACA,EAAA,IAAA,CAAA,UAAA,CAAA,IAAA,CAAA,eAAA,EAAA,MAAA;AACA,EAAA,IAAA,CAAA,eAAA,CAAA,WAAA,CAAA,eAAA;AACA,EAAA,IAAA,CAAA,UAAA,CAAA,IAAA,CAAA,IAAA,CAAA,OAAA,CAAA,YAAA,CAAA,QAAA;AACA;;AAEA,kBAAA,CAAA,SAAA,CAAA,iBAAA,GAAA,YAAA;AACA,EAAA,IAAA,CAAA,MAAA;AACA;;AAEA,kBAAA,CAAA,SAAA,CAAA,MAAA,GAAA,YAAA;AACA,EAAA,IAAA,IAAA,CAAA,UAAA,CAAA,IAAA,CAAA,eAAA,CAAA,KAAA,OAAA,EAAA;AACA,IAAA,IAAA,CAAA,QAAA;AACA,IAAA,IAAA,CAAA,eAAA,CAAA,GAAA,CAAA,CAAA,CAAA,CAAA,KAAA;AACA,GAAA,MAAA;AACA,IAAA,IAAA,CAAA,QAAA;AACA;AACA;;;;"}
|
|
1
|
+
{"version":3,"file":"filter-toggle-button.mjs","sources":["../../../../src/moj/components/filter-toggle-button/filter-toggle-button.mjs"],"sourcesContent":["import { ConfigurableComponent } from 'govuk-frontend'\n\n/**\n * @augments {ConfigurableComponent<FilterToggleButtonConfig>}\n */\nexport class FilterToggleButton extends ConfigurableComponent {\n /**\n * @param {Element | null} $root - HTML element to use for filter toggle button\n * @param {FilterToggleButtonConfig} [config] - Filter toggle button config\n */\n constructor($root, config = {}) {\n super($root, config)\n\n const $toggleButtonContainer =\n this.config.toggleButtonContainer.element ??\n document.querySelector(this.config.toggleButtonContainer.selector)\n\n const $closeButtonContainer =\n this.config.closeButtonContainer.element ??\n this.$root.querySelector(this.config.closeButtonContainer.selector)\n\n if (\n !(\n $toggleButtonContainer instanceof HTMLElement &&\n $closeButtonContainer instanceof HTMLElement\n )\n ) {\n return this\n }\n\n this.$toggleButtonContainer = $toggleButtonContainer\n this.$closeButtonContainer = $closeButtonContainer\n\n this.createToggleButton()\n this.setupResponsiveChecks()\n\n this.$root.setAttribute('tabindex', '-1')\n\n if (this.config.startHidden) {\n this.hideMenu()\n }\n }\n\n setupResponsiveChecks() {\n this.mq = window.matchMedia(this.config.bigModeMediaQuery)\n this.mq.addListener(this.checkMode.bind(this))\n this.checkMode()\n }\n\n createToggleButton() {\n this.$menuButton = document.createElement('button')\n this.$menuButton.setAttribute('type', 'button')\n this.$menuButton.setAttribute('aria-haspopup', 'true')\n this.$menuButton.setAttribute('aria-expanded', 'false')\n\n this.$menuButton.className = `govuk-button ${this.config.toggleButton.classes}`\n this.$menuButton.textContent = this.config.toggleButton.showText\n\n this.$menuButton.addEventListener(\n 'click',\n this.onMenuButtonClick.bind(this)\n )\n\n this.$toggleButtonContainer.append(this.$menuButton)\n }\n\n checkMode() {\n if (this.mq.matches) {\n this.enableBigMode()\n } else {\n this.enableSmallMode()\n }\n }\n\n enableBigMode() {\n this.showMenu()\n this.removeCloseButton()\n }\n\n enableSmallMode() {\n this.hideMenu()\n this.addCloseButton()\n }\n\n addCloseButton() {\n this.$closeButton = document.createElement('button')\n this.$closeButton.setAttribute('type', 'button')\n\n this.$closeButton.className = this.config.closeButton.classes\n this.$closeButton.textContent = this.config.closeButton.text\n\n this.$closeButton.addEventListener('click', this.onCloseClick.bind(this))\n this.$closeButtonContainer.append(this.$closeButton)\n }\n\n onCloseClick() {\n this.hideMenu()\n this.$menuButton.focus()\n }\n\n removeCloseButton() {\n if (this.$closeButton) {\n this.$closeButton.remove()\n this.$closeButton = null\n }\n }\n\n hideMenu() {\n this.$menuButton.setAttribute('aria-expanded', 'false')\n this.$root.classList.add('moj-js-hidden')\n this.$menuButton.textContent = this.config.toggleButton.showText\n }\n\n showMenu() {\n this.$menuButton.setAttribute('aria-expanded', 'true')\n this.$root.classList.remove('moj-js-hidden')\n this.$menuButton.textContent = this.config.toggleButton.hideText\n }\n\n onMenuButtonClick() {\n this.toggle()\n }\n\n toggle() {\n if (this.$menuButton.getAttribute('aria-expanded') === 'false') {\n this.showMenu()\n this.$root.focus()\n } else {\n this.hideMenu()\n }\n }\n\n /**\n * Name for the component used when initialising using data-module attributes.\n */\n static moduleName = 'moj-filter'\n\n /**\n * Filter toggle button config\n *\n * @type {FilterToggleButtonConfig}\n */\n static defaults = Object.freeze({\n bigModeMediaQuery: '(min-width: 48.0625em)',\n startHidden: true,\n toggleButton: {\n showText: 'Show filter',\n hideText: 'Hide filter',\n classes: 'govuk-button--secondary'\n },\n toggleButtonContainer: {\n selector: '.moj-action-bar__filter'\n },\n closeButton: {\n text: 'Close',\n classes: 'moj-filter__close'\n },\n closeButtonContainer: {\n selector: '.moj-filter__header-action'\n }\n })\n\n /**\n * Filter toggle button config schema\n *\n * @satisfies {Schema<FilterToggleButtonConfig>}\n */\n static schema = Object.freeze(\n /** @type {const} */ ({\n properties: {\n bigModeMediaQuery: { type: 'string' },\n startHidden: { type: 'boolean' },\n toggleButton: { type: 'object' },\n toggleButtonContainer: { type: 'object' },\n closeButton: { type: 'object' },\n closeButtonContainer: { type: 'object' }\n }\n })\n )\n}\n\n/**\n * @typedef {object} FilterToggleButtonConfig\n * @property {string} [bigModeMediaQuery] - Media query for big mode\n * @property {boolean} [startHidden] - Whether to start hidden\n * @property {object} [toggleButton] - Toggle button config\n * @property {string} [toggleButton.showText] - Text for show button\n * @property {string} [toggleButton.hideText] - Text for hide button\n * @property {string} [toggleButton.classes] - Classes for toggle button\n * @property {object} [toggleButtonContainer] - Toggle button container config\n * @property {string} [toggleButtonContainer.selector] - Selector for toggle button container\n * @property {Element | null} [toggleButtonContainer.element] - HTML element for toggle button container\n * @property {object} [closeButton] - Close button config\n * @property {string} [closeButton.text] - Text for close button\n * @property {string} [closeButton.classes] - Classes for close button\n * @property {object} [closeButtonContainer] - Close button container config\n * @property {string} [closeButtonContainer.selector] - Selector for close button container\n * @property {Element | null} [closeButtonContainer.element] - HTML element for close button container\n */\n\n/**\n * @import { Schema } from 'govuk-frontend/dist/govuk/common/configuration.mjs'\n */\n"],"names":["FilterToggleButton","ConfigurableComponent","constructor","$root","config","_this$config$toggleBu","_this$config$closeBut","$toggleButtonContainer","toggleButtonContainer","element","document","querySelector","selector","$closeButtonContainer","closeButtonContainer","HTMLElement","createToggleButton","setupResponsiveChecks","setAttribute","startHidden","hideMenu","mq","window","matchMedia","bigModeMediaQuery","addListener","checkMode","bind","$menuButton","createElement","className","toggleButton","classes","textContent","showText","addEventListener","onMenuButtonClick","append","matches","enableBigMode","enableSmallMode","showMenu","removeCloseButton","addCloseButton","$closeButton","closeButton","text","onCloseClick","focus","remove","classList","add","hideText","toggle","getAttribute","moduleName","defaults","Object","freeze","schema","properties","type"],"mappings":";;AAEA;AACA;AACA;AACO,MAAMA,kBAAkB,SAASC,qBAAqB,CAAC;AAC5D;AACF;AACA;AACA;AACEC,EAAAA,WAAWA,CAACC,KAAK,EAAEC,MAAM,GAAG,EAAE,EAAE;IAAA,IAAAC,qBAAA,EAAAC,qBAAA;AAC9B,IAAA,KAAK,CAACH,KAAK,EAAEC,MAAM,CAAC;IAEpB,MAAMG,sBAAsB,GAAAF,CAAAA,qBAAA,GAC1B,IAAI,CAACD,MAAM,CAACI,qBAAqB,CAACC,OAAO,KAAA,IAAA,GAAAJ,qBAAA,GACzCK,QAAQ,CAACC,aAAa,CAAC,IAAI,CAACP,MAAM,CAACI,qBAAqB,CAACI,QAAQ,CAAC;IAEpE,MAAMC,qBAAqB,GAAAP,CAAAA,qBAAA,GACzB,IAAI,CAACF,MAAM,CAACU,oBAAoB,CAACL,OAAO,KAAAH,IAAAA,GAAAA,qBAAA,GACxC,IAAI,CAACH,KAAK,CAACQ,aAAa,CAAC,IAAI,CAACP,MAAM,CAACU,oBAAoB,CAACF,QAAQ,CAAC;IAErE,IACE,EACEL,sBAAsB,YAAYQ,WAAW,IAC7CF,qBAAqB,YAAYE,WAAW,CAC7C,EACD;AACA,MAAA,OAAO,IAAI;AACb;IAEA,IAAI,CAACR,sBAAsB,GAAGA,sBAAsB;IACpD,IAAI,CAACM,qBAAqB,GAAGA,qBAAqB;IAElD,IAAI,CAACG,kBAAkB,EAAE;IACzB,IAAI,CAACC,qBAAqB,EAAE;IAE5B,IAAI,CAACd,KAAK,CAACe,YAAY,CAAC,UAAU,EAAE,IAAI,CAAC;AAEzC,IAAA,IAAI,IAAI,CAACd,MAAM,CAACe,WAAW,EAAE;MAC3B,IAAI,CAACC,QAAQ,EAAE;AACjB;AACF;AAEAH,EAAAA,qBAAqBA,GAAG;AACtB,IAAA,IAAI,CAACI,EAAE,GAAGC,MAAM,CAACC,UAAU,CAAC,IAAI,CAACnB,MAAM,CAACoB,iBAAiB,CAAC;AAC1D,IAAA,IAAI,CAACH,EAAE,CAACI,WAAW,CAAC,IAAI,CAACC,SAAS,CAACC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC9C,IAAI,CAACD,SAAS,EAAE;AAClB;AAEAV,EAAAA,kBAAkBA,GAAG;IACnB,IAAI,CAACY,WAAW,GAAGlB,QAAQ,CAACmB,aAAa,CAAC,QAAQ,CAAC;IACnD,IAAI,CAACD,WAAW,CAACV,YAAY,CAAC,MAAM,EAAE,QAAQ,CAAC;IAC/C,IAAI,CAACU,WAAW,CAACV,YAAY,CAAC,eAAe,EAAE,MAAM,CAAC;IACtD,IAAI,CAACU,WAAW,CAACV,YAAY,CAAC,eAAe,EAAE,OAAO,CAAC;AAEvD,IAAA,IAAI,CAACU,WAAW,CAACE,SAAS,GAAG,CAAA,aAAA,EAAgB,IAAI,CAAC1B,MAAM,CAAC2B,YAAY,CAACC,OAAO,CAAE,CAAA;IAC/E,IAAI,CAACJ,WAAW,CAACK,WAAW,GAAG,IAAI,CAAC7B,MAAM,CAAC2B,YAAY,CAACG,QAAQ;AAEhE,IAAA,IAAI,CAACN,WAAW,CAACO,gBAAgB,CAC/B,OAAO,EACP,IAAI,CAACC,iBAAiB,CAACT,IAAI,CAAC,IAAI,CAClC,CAAC;IAED,IAAI,CAACpB,sBAAsB,CAAC8B,MAAM,CAAC,IAAI,CAACT,WAAW,CAAC;AACtD;AAEAF,EAAAA,SAASA,GAAG;AACV,IAAA,IAAI,IAAI,CAACL,EAAE,CAACiB,OAAO,EAAE;MACnB,IAAI,CAACC,aAAa,EAAE;AACtB,KAAC,MAAM;MACL,IAAI,CAACC,eAAe,EAAE;AACxB;AACF;AAEAD,EAAAA,aAAaA,GAAG;IACd,IAAI,CAACE,QAAQ,EAAE;IACf,IAAI,CAACC,iBAAiB,EAAE;AAC1B;AAEAF,EAAAA,eAAeA,GAAG;IAChB,IAAI,CAACpB,QAAQ,EAAE;IACf,IAAI,CAACuB,cAAc,EAAE;AACvB;AAEAA,EAAAA,cAAcA,GAAG;IACf,IAAI,CAACC,YAAY,GAAGlC,QAAQ,CAACmB,aAAa,CAAC,QAAQ,CAAC;IACpD,IAAI,CAACe,YAAY,CAAC1B,YAAY,CAAC,MAAM,EAAE,QAAQ,CAAC;IAEhD,IAAI,CAAC0B,YAAY,CAACd,SAAS,GAAG,IAAI,CAAC1B,MAAM,CAACyC,WAAW,CAACb,OAAO;IAC7D,IAAI,CAACY,YAAY,CAACX,WAAW,GAAG,IAAI,CAAC7B,MAAM,CAACyC,WAAW,CAACC,IAAI;AAE5D,IAAA,IAAI,CAACF,YAAY,CAACT,gBAAgB,CAAC,OAAO,EAAE,IAAI,CAACY,YAAY,CAACpB,IAAI,CAAC,IAAI,CAAC,CAAC;IACzE,IAAI,CAACd,qBAAqB,CAACwB,MAAM,CAAC,IAAI,CAACO,YAAY,CAAC;AACtD;AAEAG,EAAAA,YAAYA,GAAG;IACb,IAAI,CAAC3B,QAAQ,EAAE;AACf,IAAA,IAAI,CAACQ,WAAW,CAACoB,KAAK,EAAE;AAC1B;AAEAN,EAAAA,iBAAiBA,GAAG;IAClB,IAAI,IAAI,CAACE,YAAY,EAAE;AACrB,MAAA,IAAI,CAACA,YAAY,CAACK,MAAM,EAAE;MAC1B,IAAI,CAACL,YAAY,GAAG,IAAI;AAC1B;AACF;AAEAxB,EAAAA,QAAQA,GAAG;IACT,IAAI,CAACQ,WAAW,CAACV,YAAY,CAAC,eAAe,EAAE,OAAO,CAAC;IACvD,IAAI,CAACf,KAAK,CAAC+C,SAAS,CAACC,GAAG,CAAC,eAAe,CAAC;IACzC,IAAI,CAACvB,WAAW,CAACK,WAAW,GAAG,IAAI,CAAC7B,MAAM,CAAC2B,YAAY,CAACG,QAAQ;AAClE;AAEAO,EAAAA,QAAQA,GAAG;IACT,IAAI,CAACb,WAAW,CAACV,YAAY,CAAC,eAAe,EAAE,MAAM,CAAC;IACtD,IAAI,CAACf,KAAK,CAAC+C,SAAS,CAACD,MAAM,CAAC,eAAe,CAAC;IAC5C,IAAI,CAACrB,WAAW,CAACK,WAAW,GAAG,IAAI,CAAC7B,MAAM,CAAC2B,YAAY,CAACqB,QAAQ;AAClE;AAEAhB,EAAAA,iBAAiBA,GAAG;IAClB,IAAI,CAACiB,MAAM,EAAE;AACf;AAEAA,EAAAA,MAAMA,GAAG;IACP,IAAI,IAAI,CAACzB,WAAW,CAAC0B,YAAY,CAAC,eAAe,CAAC,KAAK,OAAO,EAAE;MAC9D,IAAI,CAACb,QAAQ,EAAE;AACf,MAAA,IAAI,CAACtC,KAAK,CAAC6C,KAAK,EAAE;AACpB,KAAC,MAAM;MACL,IAAI,CAAC5B,QAAQ,EAAE;AACjB;AACF;;AAEA;AACF;AACA;AA6CA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AArMapB,kBAAkB,CAkItBuD,UAAU,GAAG,YAAY;AAEhC;AACF;AACA;AACA;AACA;AAxIavD,kBAAkB,CAyItBwD,QAAQ,GAAGC,MAAM,CAACC,MAAM,CAAC;AAC9BlC,EAAAA,iBAAiB,EAAE,wBAAwB;AAC3CL,EAAAA,WAAW,EAAE,IAAI;AACjBY,EAAAA,YAAY,EAAE;AACZG,IAAAA,QAAQ,EAAE,aAAa;AACvBkB,IAAAA,QAAQ,EAAE,aAAa;AACvBpB,IAAAA,OAAO,EAAE;GACV;AACDxB,EAAAA,qBAAqB,EAAE;AACrBI,IAAAA,QAAQ,EAAE;GACX;AACDiC,EAAAA,WAAW,EAAE;AACXC,IAAAA,IAAI,EAAE,OAAO;AACbd,IAAAA,OAAO,EAAE;GACV;AACDlB,EAAAA,oBAAoB,EAAE;AACpBF,IAAAA,QAAQ,EAAE;AACZ;AACF,CAAC,CAAC;AAEF;AACF;AACA;AACA;AACA;AAjKaZ,kBAAkB,CAkKtB2D,MAAM,GAAGF,MAAM,CAACC,MAAM,qBACL;AACpBE,EAAAA,UAAU,EAAE;AACVpC,IAAAA,iBAAiB,EAAE;AAAEqC,MAAAA,IAAI,EAAE;KAAU;AACrC1C,IAAAA,WAAW,EAAE;AAAE0C,MAAAA,IAAI,EAAE;KAAW;AAChC9B,IAAAA,YAAY,EAAE;AAAE8B,MAAAA,IAAI,EAAE;KAAU;AAChCrD,IAAAA,qBAAqB,EAAE;AAAEqD,MAAAA,IAAI,EAAE;KAAU;AACzChB,IAAAA,WAAW,EAAE;AAAEgB,MAAAA,IAAI,EAAE;KAAU;AAC/B/C,IAAAA,oBAAoB,EAAE;AAAE+C,MAAAA,IAAI,EAAE;AAAS;AACzC;AACF,CACF,CAAC;;;;"}
|
|
@@ -0,0 +1,288 @@
|
|
|
1
|
+
(function (global, factory) {
|
|
2
|
+
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('govuk-frontend')) :
|
|
3
|
+
typeof define === 'function' && define.amd ? define(['exports', 'govuk-frontend'], factory) :
|
|
4
|
+
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.MOJFrontend = global.MOJFrontend || {}, global.GOVUKFrontend));
|
|
5
|
+
})(this, (function (exports, govukFrontend) { 'use strict';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* @param {Element} $element - Element to remove attribute value from
|
|
9
|
+
* @param {string} attr - Attribute name
|
|
10
|
+
* @param {string} value - Attribute value
|
|
11
|
+
*/
|
|
12
|
+
function removeAttributeValue($element, attr, value) {
|
|
13
|
+
let re, m;
|
|
14
|
+
if ($element.getAttribute(attr)) {
|
|
15
|
+
if ($element.getAttribute(attr) === value) {
|
|
16
|
+
$element.removeAttribute(attr);
|
|
17
|
+
} else {
|
|
18
|
+
re = new RegExp(`(^|\\s)${value}(\\s|$)`);
|
|
19
|
+
m = $element.getAttribute(attr).match(re);
|
|
20
|
+
if (m && m.length === 3) {
|
|
21
|
+
$element.setAttribute(attr, $element.getAttribute(attr).replace(re, m[1] && m[2] ? ' ' : ''));
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* @param {Element} $element - Element to add attribute value to
|
|
29
|
+
* @param {string} attr - Attribute name
|
|
30
|
+
* @param {string} value - Attribute value
|
|
31
|
+
*/
|
|
32
|
+
function addAttributeValue($element, attr, value) {
|
|
33
|
+
let re;
|
|
34
|
+
if (!$element.getAttribute(attr)) {
|
|
35
|
+
$element.setAttribute(attr, value);
|
|
36
|
+
} else {
|
|
37
|
+
re = new RegExp(`(^|\\s)${value}(\\s|$)`);
|
|
38
|
+
if (!re.test($element.getAttribute(attr))) {
|
|
39
|
+
$element.setAttribute(attr, `${$element.getAttribute(attr)} ${value}`);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* @augments {ConfigurableComponent<FormValidatorConfig, HTMLFormElement>}
|
|
46
|
+
*/
|
|
47
|
+
class FormValidator extends govukFrontend.ConfigurableComponent {
|
|
48
|
+
/**
|
|
49
|
+
* @param {Element | null} $root - HTML element to use for form validator
|
|
50
|
+
* @param {FormValidatorConfig} [config] - Form validator config
|
|
51
|
+
*/
|
|
52
|
+
constructor($root, config = {}) {
|
|
53
|
+
super($root, config);
|
|
54
|
+
const $summary = this.config.summary.element || document.querySelector(this.config.summary.selector);
|
|
55
|
+
if (!$summary || !($summary instanceof HTMLElement)) {
|
|
56
|
+
return this;
|
|
57
|
+
}
|
|
58
|
+
this.$summary = $summary;
|
|
59
|
+
this.errors = /** @type {ValidationError[]} */[];
|
|
60
|
+
this.validators = /** @type {Validator[]} */[];
|
|
61
|
+
this.originalTitle = document.title;
|
|
62
|
+
this.$root.addEventListener('submit', this.onSubmit.bind(this));
|
|
63
|
+
}
|
|
64
|
+
escapeHtml(string = '') {
|
|
65
|
+
return String(string).replace(/[&<>"'`=/]/g, name => FormValidator.entityMap[name]);
|
|
66
|
+
}
|
|
67
|
+
resetTitle() {
|
|
68
|
+
document.title = this.originalTitle;
|
|
69
|
+
}
|
|
70
|
+
updateTitle() {
|
|
71
|
+
document.title = `${this.errors.length} errors - ${document.title}`;
|
|
72
|
+
}
|
|
73
|
+
showSummary() {
|
|
74
|
+
this.$summary.innerHTML = this.getSummaryHtml();
|
|
75
|
+
this.$summary.classList.remove('moj-hidden');
|
|
76
|
+
this.$summary.setAttribute('aria-labelledby', 'errorSummary-heading');
|
|
77
|
+
this.$summary.focus();
|
|
78
|
+
}
|
|
79
|
+
getSummaryHtml() {
|
|
80
|
+
let html = '<h2 id="error-summary-title" class="govuk-error-summary__title">There is a problem</h2>';
|
|
81
|
+
html += '<div class="govuk-error-summary__body">';
|
|
82
|
+
html += '<ul class="govuk-list govuk-error-summary__list">';
|
|
83
|
+
for (const error of this.errors) {
|
|
84
|
+
html += '<li>';
|
|
85
|
+
html += `<a href="#${this.escapeHtml(error.fieldName)}">`;
|
|
86
|
+
html += this.escapeHtml(error.message);
|
|
87
|
+
html += '</a>';
|
|
88
|
+
html += '</li>';
|
|
89
|
+
}
|
|
90
|
+
html += '</ul>';
|
|
91
|
+
html += '</div>';
|
|
92
|
+
return html;
|
|
93
|
+
}
|
|
94
|
+
hideSummary() {
|
|
95
|
+
this.$summary.classList.add('moj-hidden');
|
|
96
|
+
this.$summary.removeAttribute('aria-labelledby');
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* @param {SubmitEvent} event - Form submit event
|
|
101
|
+
*/
|
|
102
|
+
onSubmit(event) {
|
|
103
|
+
this.removeInlineErrors();
|
|
104
|
+
this.hideSummary();
|
|
105
|
+
this.resetTitle();
|
|
106
|
+
if (!this.validate()) {
|
|
107
|
+
event.preventDefault();
|
|
108
|
+
this.updateTitle();
|
|
109
|
+
this.showSummary();
|
|
110
|
+
this.showInlineErrors();
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
showInlineErrors() {
|
|
114
|
+
for (const error of this.errors) {
|
|
115
|
+
this.showInlineError(error);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* @param {ValidationError} error
|
|
121
|
+
*/
|
|
122
|
+
showInlineError(error) {
|
|
123
|
+
const $errorSpan = document.createElement('span');
|
|
124
|
+
$errorSpan.id = `${error.fieldName}-error`;
|
|
125
|
+
$errorSpan.classList.add('govuk-error-message');
|
|
126
|
+
$errorSpan.innerHTML = this.escapeHtml(error.message);
|
|
127
|
+
const $control = document.querySelector(`#${error.fieldName}`);
|
|
128
|
+
const $fieldset = $control.closest('.govuk-fieldset');
|
|
129
|
+
const $fieldContainer = ($fieldset || $control).closest('.govuk-form-group');
|
|
130
|
+
const $label = $fieldContainer.querySelector('label');
|
|
131
|
+
const $legend = $fieldContainer.querySelector('legend');
|
|
132
|
+
$fieldContainer.classList.add('govuk-form-group--error');
|
|
133
|
+
if ($fieldset && $legend) {
|
|
134
|
+
$legend.after($errorSpan);
|
|
135
|
+
$fieldContainer.setAttribute('aria-invalid', 'true');
|
|
136
|
+
addAttributeValue($fieldset, 'aria-describedby', $errorSpan.id);
|
|
137
|
+
} else if ($label && $control) {
|
|
138
|
+
$label.after($errorSpan);
|
|
139
|
+
$control.setAttribute('aria-invalid', 'true');
|
|
140
|
+
addAttributeValue($control, 'aria-describedby', $errorSpan.id);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
removeInlineErrors() {
|
|
144
|
+
for (const error of this.errors) {
|
|
145
|
+
this.removeInlineError(error);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* @param {ValidationError} error
|
|
151
|
+
*/
|
|
152
|
+
removeInlineError(error) {
|
|
153
|
+
const $errorSpan = document.querySelector(`#${error.fieldName}-error`);
|
|
154
|
+
const $control = document.querySelector(`#${error.fieldName}`);
|
|
155
|
+
const $fieldset = $control.closest('.govuk-fieldset');
|
|
156
|
+
const $fieldContainer = ($fieldset || $control).closest('.govuk-form-group');
|
|
157
|
+
const $label = $fieldContainer.querySelector('label');
|
|
158
|
+
const $legend = $fieldContainer.querySelector('legend');
|
|
159
|
+
$errorSpan.remove();
|
|
160
|
+
$fieldContainer.classList.remove('govuk-form-group--error');
|
|
161
|
+
if ($fieldset && $legend) {
|
|
162
|
+
$fieldContainer.removeAttribute('aria-invalid');
|
|
163
|
+
removeAttributeValue($fieldset, 'aria-describedby', $errorSpan.id);
|
|
164
|
+
} else if ($label && $control) {
|
|
165
|
+
$control.removeAttribute('aria-invalid');
|
|
166
|
+
removeAttributeValue($control, 'aria-describedby', $errorSpan.id);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* @param {string} fieldName - Field name
|
|
172
|
+
* @param {ValidationRule[]} rules - Validation rules
|
|
173
|
+
*/
|
|
174
|
+
addValidator(fieldName, rules) {
|
|
175
|
+
this.validators.push({
|
|
176
|
+
fieldName,
|
|
177
|
+
rules,
|
|
178
|
+
field: this.$root.elements.namedItem(fieldName)
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
validate() {
|
|
182
|
+
this.errors = [];
|
|
183
|
+
|
|
184
|
+
/** @type {Validator | null} */
|
|
185
|
+
let validator = null;
|
|
186
|
+
|
|
187
|
+
/** @type {boolean | string} */
|
|
188
|
+
let validatorReturnValue = true;
|
|
189
|
+
let i;
|
|
190
|
+
let j;
|
|
191
|
+
for (i = 0; i < this.validators.length; i++) {
|
|
192
|
+
validator = this.validators[i];
|
|
193
|
+
for (j = 0; j < validator.rules.length; j++) {
|
|
194
|
+
validatorReturnValue = validator.rules[j].method(validator.field, validator.rules[j].params);
|
|
195
|
+
if (typeof validatorReturnValue === 'boolean' && !validatorReturnValue) {
|
|
196
|
+
this.errors.push({
|
|
197
|
+
fieldName: validator.fieldName,
|
|
198
|
+
message: validator.rules[j].message
|
|
199
|
+
});
|
|
200
|
+
break;
|
|
201
|
+
} else if (typeof validatorReturnValue === 'string') {
|
|
202
|
+
this.errors.push({
|
|
203
|
+
fieldName: validatorReturnValue,
|
|
204
|
+
message: validator.rules[j].message
|
|
205
|
+
});
|
|
206
|
+
break;
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
return this.errors.length === 0;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* @type {Record<string, string>}
|
|
215
|
+
*/
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* @typedef {object} FormValidatorConfig
|
|
220
|
+
* @property {object} [summary] - Error summary config
|
|
221
|
+
* @property {string} [summary.selector] - Selector for error summary
|
|
222
|
+
* @property {Element | null} [summary.element] - HTML element for error summary
|
|
223
|
+
*/
|
|
224
|
+
|
|
225
|
+
/**
|
|
226
|
+
* @typedef {object} ValidationRule
|
|
227
|
+
* @property {(field: Validator['field'], params: Record<string, Validator['field']>) => boolean | string} method - Validation method
|
|
228
|
+
* @property {string} message - Error message
|
|
229
|
+
* @property {Record<string, Validator['field']>} [params] - Parameters for validation
|
|
230
|
+
*/
|
|
231
|
+
|
|
232
|
+
/**
|
|
233
|
+
* @typedef {object} ValidationError
|
|
234
|
+
* @property {string} fieldName - Name of the field
|
|
235
|
+
* @property {string} message - Validation error message
|
|
236
|
+
*/
|
|
237
|
+
|
|
238
|
+
/**
|
|
239
|
+
* @typedef {object} Validator
|
|
240
|
+
* @property {string} fieldName - Name of the field
|
|
241
|
+
* @property {ValidationRule[]} rules - Validation rules
|
|
242
|
+
* @property {Element | RadioNodeList} field - Form field
|
|
243
|
+
*/
|
|
244
|
+
|
|
245
|
+
/**
|
|
246
|
+
* @import { Schema } from 'govuk-frontend/dist/govuk/common/configuration.mjs'
|
|
247
|
+
*/
|
|
248
|
+
FormValidator.entityMap = {
|
|
249
|
+
'&': '&',
|
|
250
|
+
'<': '<',
|
|
251
|
+
'>': '>',
|
|
252
|
+
'"': '"',
|
|
253
|
+
"'": ''',
|
|
254
|
+
'/': '/',
|
|
255
|
+
'`': '`',
|
|
256
|
+
'=': '='
|
|
257
|
+
};
|
|
258
|
+
/**
|
|
259
|
+
* Name for the component used when initialising using data-module attributes.
|
|
260
|
+
*/
|
|
261
|
+
FormValidator.moduleName = 'moj-form-validator';
|
|
262
|
+
/**
|
|
263
|
+
* Multi file upload default config
|
|
264
|
+
*
|
|
265
|
+
* @type {FormValidatorConfig}
|
|
266
|
+
*/
|
|
267
|
+
FormValidator.defaults = Object.freeze({
|
|
268
|
+
summary: {
|
|
269
|
+
selector: '.govuk-error-summary'
|
|
270
|
+
}
|
|
271
|
+
});
|
|
272
|
+
/**
|
|
273
|
+
* Multi file upload config schema
|
|
274
|
+
*
|
|
275
|
+
* @satisfies {Schema<FormValidatorConfig>}
|
|
276
|
+
*/
|
|
277
|
+
FormValidator.schema = Object.freeze(/** @type {const} */{
|
|
278
|
+
properties: {
|
|
279
|
+
summary: {
|
|
280
|
+
type: 'object'
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
});
|
|
284
|
+
|
|
285
|
+
exports.FormValidator = FormValidator;
|
|
286
|
+
|
|
287
|
+
}));
|
|
288
|
+
//# sourceMappingURL=form-validator.bundle.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"form-validator.bundle.js","sources":["../../../../src/moj/helpers.mjs","../../../../src/moj/components/form-validator/form-validator.mjs"],"sourcesContent":["/**\n * @param {Element} $element - Element to remove attribute value from\n * @param {string} attr - Attribute name\n * @param {string} value - Attribute value\n */\nexport function removeAttributeValue($element, attr, value) {\n let re, m\n if ($element.getAttribute(attr)) {\n if ($element.getAttribute(attr) === value) {\n $element.removeAttribute(attr)\n } else {\n re = new RegExp(`(^|\\\\s)${value}(\\\\s|$)`)\n m = $element.getAttribute(attr).match(re)\n if (m && m.length === 3) {\n $element.setAttribute(\n attr,\n $element.getAttribute(attr).replace(re, m[1] && m[2] ? ' ' : '')\n )\n }\n }\n }\n}\n\n/**\n * @param {Element} $element - Element to add attribute value to\n * @param {string} attr - Attribute name\n * @param {string} value - Attribute value\n */\nexport function addAttributeValue($element, attr, value) {\n let re\n if (!$element.getAttribute(attr)) {\n $element.setAttribute(attr, value)\n } else {\n re = new RegExp(`(^|\\\\s)${value}(\\\\s|$)`)\n if (!re.test($element.getAttribute(attr))) {\n $element.setAttribute(attr, `${$element.getAttribute(attr)} ${value}`)\n }\n }\n}\n\n/**\n * Find an elements next sibling\n *\n * Utility function to find an elements next sibling matching the provided\n * selector.\n *\n * @param {Element | null} $element - Element to find siblings for\n * @param {string} [selector] - selector for required sibling\n */\nexport function getNextSibling($element, selector) {\n if (!$element || !($element instanceof HTMLElement)) {\n return\n }\n\n // Get the next sibling element\n let $sibling = $element.nextElementSibling\n\n // If there's no selector, return the first sibling\n if (!selector) return $sibling\n\n // If the sibling matches our selector, use it\n // If not, jump to the next sibling and continue the loop\n while ($sibling) {\n if ($sibling.matches(selector)) return $sibling\n $sibling = $sibling.nextElementSibling\n }\n}\n\n/**\n * Find an elements preceding sibling\n *\n * Utility function to find an elements previous sibling matching the provided\n * selector.\n *\n * @param {Element | null} $element - Element to find siblings for\n * @param {string} [selector] - selector for required sibling\n */\nexport function getPreviousSibling($element, selector) {\n if (!$element || !($element instanceof HTMLElement)) {\n return\n }\n\n // Get the previous sibling element\n let $sibling = $element.previousElementSibling\n\n // If there's no selector, return the first sibling\n if (!selector) return $sibling\n\n // If the sibling matches our selector, use it\n // If not, jump to the next sibling and continue the loop\n while ($sibling) {\n if ($sibling.matches(selector)) return $sibling\n $sibling = $sibling.previousElementSibling\n }\n}\n\n/**\n * @param {Element | null} $element\n * @param {string} [selector]\n */\nexport function findNearestMatchingElement($element, selector) {\n // If no element or selector is provided, return\n if (!$element || !($element instanceof HTMLElement) || !selector) {\n return\n }\n\n // Start with the current element\n let $currentElement = $element\n\n while ($currentElement) {\n // First check the current element\n if ($currentElement.matches(selector)) {\n return $currentElement\n }\n\n // Check all previous siblings\n let $sibling = $currentElement.previousElementSibling\n while ($sibling) {\n // Check if the sibling itself is a heading\n if ($sibling.matches(selector)) {\n return $sibling\n }\n $sibling = $sibling.previousElementSibling\n }\n\n // If no match found in siblings, move up to parent\n $currentElement = $currentElement.parentElement\n }\n}\n","import { ConfigurableComponent } from 'govuk-frontend'\n\nimport { addAttributeValue, removeAttributeValue } from '../../helpers.mjs'\n\n/**\n * @augments {ConfigurableComponent<FormValidatorConfig, HTMLFormElement>}\n */\nexport class FormValidator extends ConfigurableComponent {\n /**\n * @param {Element | null} $root - HTML element to use for form validator\n * @param {FormValidatorConfig} [config] - Form validator config\n */\n constructor($root, config = {}) {\n super($root, config)\n\n const $summary =\n this.config.summary.element ||\n document.querySelector(this.config.summary.selector)\n\n if (!$summary || !($summary instanceof HTMLElement)) {\n return this\n }\n\n this.$summary = $summary\n\n this.errors = /** @type {ValidationError[]} */ ([])\n this.validators = /** @type {Validator[]} */ ([])\n this.originalTitle = document.title\n\n this.$root.addEventListener('submit', this.onSubmit.bind(this))\n }\n\n escapeHtml(string = '') {\n return String(string).replace(\n /[&<>\"'`=/]/g,\n (name) => FormValidator.entityMap[name]\n )\n }\n\n resetTitle() {\n document.title = this.originalTitle\n }\n\n updateTitle() {\n document.title = `${this.errors.length} errors - ${document.title}`\n }\n\n showSummary() {\n this.$summary.innerHTML = this.getSummaryHtml()\n this.$summary.classList.remove('moj-hidden')\n this.$summary.setAttribute('aria-labelledby', 'errorSummary-heading')\n this.$summary.focus()\n }\n\n getSummaryHtml() {\n let html =\n '<h2 id=\"error-summary-title\" class=\"govuk-error-summary__title\">There is a problem</h2>'\n html += '<div class=\"govuk-error-summary__body\">'\n html += '<ul class=\"govuk-list govuk-error-summary__list\">'\n for (const error of this.errors) {\n html += '<li>'\n html += `<a href=\"#${this.escapeHtml(error.fieldName)}\">`\n html += this.escapeHtml(error.message)\n html += '</a>'\n html += '</li>'\n }\n html += '</ul>'\n html += '</div>'\n return html\n }\n\n hideSummary() {\n this.$summary.classList.add('moj-hidden')\n this.$summary.removeAttribute('aria-labelledby')\n }\n\n /**\n * @param {SubmitEvent} event - Form submit event\n */\n onSubmit(event) {\n this.removeInlineErrors()\n this.hideSummary()\n this.resetTitle()\n if (!this.validate()) {\n event.preventDefault()\n this.updateTitle()\n this.showSummary()\n this.showInlineErrors()\n }\n }\n\n showInlineErrors() {\n for (const error of this.errors) {\n this.showInlineError(error)\n }\n }\n\n /**\n * @param {ValidationError} error\n */\n showInlineError(error) {\n const $errorSpan = document.createElement('span')\n $errorSpan.id = `${error.fieldName}-error`\n $errorSpan.classList.add('govuk-error-message')\n $errorSpan.innerHTML = this.escapeHtml(error.message)\n\n const $control = document.querySelector(`#${error.fieldName}`)\n const $fieldset = $control.closest('.govuk-fieldset')\n const $fieldContainer = ($fieldset || $control).closest('.govuk-form-group')\n\n const $label = $fieldContainer.querySelector('label')\n const $legend = $fieldContainer.querySelector('legend')\n\n $fieldContainer.classList.add('govuk-form-group--error')\n\n if ($fieldset && $legend) {\n $legend.after($errorSpan)\n $fieldContainer.setAttribute('aria-invalid', 'true')\n addAttributeValue($fieldset, 'aria-describedby', $errorSpan.id)\n } else if ($label && $control) {\n $label.after($errorSpan)\n $control.setAttribute('aria-invalid', 'true')\n addAttributeValue($control, 'aria-describedby', $errorSpan.id)\n }\n }\n\n removeInlineErrors() {\n for (const error of this.errors) {\n this.removeInlineError(error)\n }\n }\n\n /**\n * @param {ValidationError} error\n */\n removeInlineError(error) {\n const $errorSpan = document.querySelector(`#${error.fieldName}-error`)\n\n const $control = document.querySelector(`#${error.fieldName}`)\n const $fieldset = $control.closest('.govuk-fieldset')\n const $fieldContainer = ($fieldset || $control).closest('.govuk-form-group')\n\n const $label = $fieldContainer.querySelector('label')\n const $legend = $fieldContainer.querySelector('legend')\n\n $errorSpan.remove()\n $fieldContainer.classList.remove('govuk-form-group--error')\n\n if ($fieldset && $legend) {\n $fieldContainer.removeAttribute('aria-invalid')\n removeAttributeValue($fieldset, 'aria-describedby', $errorSpan.id)\n } else if ($label && $control) {\n $control.removeAttribute('aria-invalid')\n removeAttributeValue($control, 'aria-describedby', $errorSpan.id)\n }\n }\n\n /**\n * @param {string} fieldName - Field name\n * @param {ValidationRule[]} rules - Validation rules\n */\n addValidator(fieldName, rules) {\n this.validators.push({\n fieldName,\n rules,\n field: this.$root.elements.namedItem(fieldName)\n })\n }\n\n validate() {\n this.errors = []\n\n /** @type {Validator | null} */\n let validator = null\n\n /** @type {boolean | string} */\n let validatorReturnValue = true\n\n let i\n let j\n\n for (i = 0; i < this.validators.length; i++) {\n validator = this.validators[i]\n for (j = 0; j < validator.rules.length; j++) {\n validatorReturnValue = validator.rules[j].method(\n validator.field,\n validator.rules[j].params\n )\n\n if (\n typeof validatorReturnValue === 'boolean' &&\n !validatorReturnValue\n ) {\n this.errors.push({\n fieldName: validator.fieldName,\n message: validator.rules[j].message\n })\n break\n } else if (typeof validatorReturnValue === 'string') {\n this.errors.push({\n fieldName: validatorReturnValue,\n message: validator.rules[j].message\n })\n break\n }\n }\n }\n return this.errors.length === 0\n }\n\n /**\n * @type {Record<string, string>}\n */\n static entityMap = {\n '&': '&',\n '<': '<',\n '>': '>',\n '\"': '"',\n \"'\": ''',\n '/': '/',\n '`': '`',\n '=': '='\n }\n\n /**\n * Name for the component used when initialising using data-module attributes.\n */\n static moduleName = 'moj-form-validator'\n\n /**\n * Multi file upload default config\n *\n * @type {FormValidatorConfig}\n */\n static defaults = Object.freeze({\n summary: {\n selector: '.govuk-error-summary'\n }\n })\n\n /**\n * Multi file upload config schema\n *\n * @satisfies {Schema<FormValidatorConfig>}\n */\n static schema = Object.freeze(\n /** @type {const} */ ({\n properties: {\n summary: { type: 'object' }\n }\n })\n )\n}\n\n/**\n * @typedef {object} FormValidatorConfig\n * @property {object} [summary] - Error summary config\n * @property {string} [summary.selector] - Selector for error summary\n * @property {Element | null} [summary.element] - HTML element for error summary\n */\n\n/**\n * @typedef {object} ValidationRule\n * @property {(field: Validator['field'], params: Record<string, Validator['field']>) => boolean | string} method - Validation method\n * @property {string} message - Error message\n * @property {Record<string, Validator['field']>} [params] - Parameters for validation\n */\n\n/**\n * @typedef {object} ValidationError\n * @property {string} fieldName - Name of the field\n * @property {string} message - Validation error message\n */\n\n/**\n * @typedef {object} Validator\n * @property {string} fieldName - Name of the field\n * @property {ValidationRule[]} rules - Validation rules\n * @property {Element | RadioNodeList} field - Form field\n */\n\n/**\n * @import { Schema } from 'govuk-frontend/dist/govuk/common/configuration.mjs'\n */\n"],"names":["removeAttributeValue","$element","attr","value","re","m","getAttribute","removeAttribute","RegExp","match","length","setAttribute","replace","addAttributeValue","test","FormValidator","ConfigurableComponent","constructor","$root","config","$summary","summary","element","document","querySelector","selector","HTMLElement","errors","validators","originalTitle","title","addEventListener","onSubmit","bind","escapeHtml","string","String","name","entityMap","resetTitle","updateTitle","showSummary","innerHTML","getSummaryHtml","classList","remove","focus","html","error","fieldName","message","hideSummary","add","event","removeInlineErrors","validate","preventDefault","showInlineErrors","showInlineError","$errorSpan","createElement","id","$control","$fieldset","closest","$fieldContainer","$label","$legend","after","removeInlineError","addValidator","rules","push","field","elements","namedItem","validator","validatorReturnValue","i","j","method","params","moduleName","defaults","Object","freeze","schema","properties","type"],"mappings":"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"}
|