@nationalarchives/frontend 0.20.0 → 0.20.1
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/nationalarchives/all+analytics.js +1 -1
- package/nationalarchives/all+analytics.js.map +1 -1
- package/nationalarchives/all.js +1 -1
- package/nationalarchives/all.js.map +1 -1
- package/nationalarchives/components/error-summary/error-summary.js +1 -1
- package/nationalarchives/components/error-summary/error-summary.js.map +1 -1
- package/nationalarchives/components/error-summary/error-summary.mjs +108 -0
- package/nationalarchives/components/text-input/fixtures.json +4 -4
- package/nationalarchives/components/textarea/fixtures.json +2 -2
- package/package.json +1 -1
@@ -14,6 +14,8 @@ export class ErrorSummary {
|
|
14
14
|
if (!disableAutoFocus) {
|
15
15
|
this.setFocus(this.$module);
|
16
16
|
}
|
17
|
+
|
18
|
+
this.$module.addEventListener("click", (event) => this.handleClick(event));
|
17
19
|
}
|
18
20
|
|
19
21
|
setFocus($element, options = {}) {
|
@@ -48,4 +50,110 @@ export class ErrorSummary {
|
|
48
50
|
options.onBeforeFocus?.call($element);
|
49
51
|
$element.focus();
|
50
52
|
}
|
53
|
+
|
54
|
+
handleClick(event) {
|
55
|
+
const $target = event.target;
|
56
|
+
if ($target && this.focusTarget($target)) {
|
57
|
+
event.preventDefault();
|
58
|
+
}
|
59
|
+
}
|
60
|
+
|
61
|
+
getFragmentFromUrl(url) {
|
62
|
+
if (!url.includes("#")) {
|
63
|
+
return undefined;
|
64
|
+
}
|
65
|
+
|
66
|
+
return url.split("#").pop();
|
67
|
+
}
|
68
|
+
|
69
|
+
focusTarget($target) {
|
70
|
+
// If the element that was clicked was not a link, return early
|
71
|
+
if (!($target instanceof HTMLAnchorElement)) {
|
72
|
+
return false;
|
73
|
+
}
|
74
|
+
|
75
|
+
const inputId = this.getFragmentFromUrl($target.href);
|
76
|
+
if (!inputId) {
|
77
|
+
return false;
|
78
|
+
}
|
79
|
+
|
80
|
+
const $input = document.getElementById(inputId);
|
81
|
+
if (!$input) {
|
82
|
+
return false;
|
83
|
+
}
|
84
|
+
|
85
|
+
const $legendOrLabel = this.getAssociatedLegendOrLabel($input);
|
86
|
+
if (!$legendOrLabel) {
|
87
|
+
return false;
|
88
|
+
}
|
89
|
+
|
90
|
+
// Scroll the legend or label into view *before* calling focus on the input
|
91
|
+
// to avoid extra scrolling in browsers that don't support `preventScroll`
|
92
|
+
// (which at time of writing is most of them...)
|
93
|
+
$legendOrLabel.scrollIntoView();
|
94
|
+
$input.focus({ preventScroll: true });
|
95
|
+
|
96
|
+
return true;
|
97
|
+
}
|
98
|
+
|
99
|
+
/**
|
100
|
+
* Get associated legend or label
|
101
|
+
*
|
102
|
+
* Returns the first element that exists from this list:
|
103
|
+
*
|
104
|
+
* - The `<legend>` associated with the closest `<fieldset>` ancestor, as long
|
105
|
+
* as the top of it is no more than half a viewport height away from the
|
106
|
+
* bottom of the input
|
107
|
+
* - The first `<label>` that is associated with the input using for="inputId"
|
108
|
+
* - The closest parent `<label>`
|
109
|
+
*
|
110
|
+
* @private
|
111
|
+
* @param {Element} $input - The input
|
112
|
+
* @returns {Element | null} Associated legend or label, or null if no
|
113
|
+
* associated legend or label can be found
|
114
|
+
*/
|
115
|
+
getAssociatedLegendOrLabel($input) {
|
116
|
+
const $fieldset = $input.closest("fieldset");
|
117
|
+
|
118
|
+
if ($fieldset) {
|
119
|
+
const $legends = $fieldset.getElementsByTagName("legend");
|
120
|
+
|
121
|
+
if ($legends.length) {
|
122
|
+
const $candidateLegend = $legends[0];
|
123
|
+
|
124
|
+
// If the input type is radio or checkbox, always use the legend if
|
125
|
+
// there is one.
|
126
|
+
if (
|
127
|
+
$input instanceof HTMLInputElement &&
|
128
|
+
($input.type === "checkbox" || $input.type === "radio")
|
129
|
+
) {
|
130
|
+
return $candidateLegend;
|
131
|
+
}
|
132
|
+
|
133
|
+
// For other input types, only scroll to the fieldset’s legend (instead
|
134
|
+
// of the label associated with the input) if the input would end up in
|
135
|
+
// the top half of the screen.
|
136
|
+
//
|
137
|
+
// This should avoid situations where the input either ends up off the
|
138
|
+
// screen, or obscured by a software keyboard.
|
139
|
+
const legendTop = $candidateLegend.getBoundingClientRect().top;
|
140
|
+
const inputRect = $input.getBoundingClientRect();
|
141
|
+
|
142
|
+
// If the browser doesn't support Element.getBoundingClientRect().height
|
143
|
+
// or window.innerHeight (like IE8), bail and just link to the label.
|
144
|
+
if (inputRect.height && window.innerHeight) {
|
145
|
+
const inputBottom = inputRect.top + inputRect.height;
|
146
|
+
|
147
|
+
if (inputBottom - legendTop < window.innerHeight / 2) {
|
148
|
+
return $candidateLegend;
|
149
|
+
}
|
150
|
+
}
|
151
|
+
}
|
152
|
+
}
|
153
|
+
|
154
|
+
return (
|
155
|
+
document.querySelector(`label[for='${$input.getAttribute("id")}']`) ??
|
156
|
+
$input.closest("label")
|
157
|
+
);
|
158
|
+
}
|
51
159
|
}
|
@@ -109,7 +109,7 @@
|
|
109
109
|
"id": "text",
|
110
110
|
"name": "text",
|
111
111
|
"size": "m",
|
112
|
-
"spellcheck":
|
112
|
+
"spellcheck": true
|
113
113
|
},
|
114
114
|
"html": "<div class=\"tna-form__group\" data-module=\"tna-text-input\"><div class=\"tna-form__group-contents\"><h4 class=\"tna-form__heading tna-form__heading--m\"><label class=\"tna-form__label\" for=\"text\">Enter some text</label></h4></div><input id=\"text\" class=\"tna-text-input tna-text-input--m \" name=\"text\" value=\"\" type=\"text\" spellcheck=\"true\" autocapitalize=\"off\" autocorrect=\"off\"></div>"
|
115
115
|
},
|
@@ -122,9 +122,9 @@
|
|
122
122
|
"id": "text",
|
123
123
|
"name": "text",
|
124
124
|
"size": "m",
|
125
|
-
"autocapitalize": "
|
125
|
+
"autocapitalize": "on"
|
126
126
|
},
|
127
|
-
"html": "<div class=\"tna-form__group\" data-module=\"tna-text-input\"><div class=\"tna-form__group-contents\"><h4 class=\"tna-form__heading tna-form__heading--m\"><label class=\"tna-form__label\" for=\"text\">Enter some text</label></h4></div><input id=\"text\" class=\"tna-text-input tna-text-input--m \" name=\"text\" value=\"\" type=\"text\" spellcheck=\"false\" autocapitalize=\"
|
127
|
+
"html": "<div class=\"tna-form__group\" data-module=\"tna-text-input\"><div class=\"tna-form__group-contents\"><h4 class=\"tna-form__heading tna-form__heading--m\"><label class=\"tna-form__label\" for=\"text\">Enter some text</label></h4></div><input id=\"text\" class=\"tna-text-input tna-text-input--m \" name=\"text\" value=\"\" type=\"text\" spellcheck=\"false\" autocapitalize=\"on\" autocorrect=\"off\"></div>"
|
128
128
|
},
|
129
129
|
{
|
130
130
|
"name": "autocorrect",
|
@@ -135,7 +135,7 @@
|
|
135
135
|
"id": "text",
|
136
136
|
"name": "text",
|
137
137
|
"size": "m",
|
138
|
-
"autocorrect":
|
138
|
+
"autocorrect": true
|
139
139
|
},
|
140
140
|
"html": "<div class=\"tna-form__group\" data-module=\"tna-text-input\"><div class=\"tna-form__group-contents\"><h4 class=\"tna-form__heading tna-form__heading--m\"><label class=\"tna-form__label\" for=\"text\">Enter some text</label></h4></div><input id=\"text\" class=\"tna-text-input tna-text-input--m \" name=\"text\" value=\"\" type=\"text\" spellcheck=\"false\" autocapitalize=\"off\" autocorrect=\"on\"></div>"
|
141
141
|
},
|
@@ -106,9 +106,9 @@
|
|
106
106
|
"headingSize": "m",
|
107
107
|
"id": "feedback",
|
108
108
|
"name": "feedback",
|
109
|
-
"autocapitalize":
|
109
|
+
"autocapitalize": "on"
|
110
110
|
},
|
111
|
-
"html": "<div class=\"tna-form__group\"><div class=\"tna-form__group-contents\"><h4 class=\"tna-form__heading tna-form__heading--m\"><label class=\"tna-form__label\" for=\"feedback\">Enter your feedback</label></h4></div><textarea id=\"feedback\" class=\"tna-textarea \" name=\"feedback\" spellcheck=\"false\" autocapitalize=\"
|
111
|
+
"html": "<div class=\"tna-form__group\"><div class=\"tna-form__group-contents\"><h4 class=\"tna-form__heading tna-form__heading--m\"><label class=\"tna-form__label\" for=\"feedback\">Enter your feedback</label></h4></div><textarea id=\"feedback\" class=\"tna-textarea \" name=\"feedback\" spellcheck=\"false\" autocapitalize=\"on\" autocorrect=\"off\" rows=\"5\"></textarea></div>"
|
112
112
|
},
|
113
113
|
{
|
114
114
|
"name": "autocorrect",
|