@ons/design-system 45.2.1 → 46.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/components/address-input/autosuggest.address.js +93 -118
- package/components/autosuggest/autosuggest.js +3 -11
- package/components/autosuggest/autosuggest.ui.js +3 -10
- package/components/footer/_footer.scss +6 -0
- package/components/footer/_macro.njk +2 -1
- package/components/lists/_macro.njk +8 -12
- package/components/modal/_macro.njk +1 -1
- package/components/panel/_macro.njk +5 -1
- package/components/panel/_panel.scss +4 -0
- package/components/timeout-modal/_macro.njk +3 -2
- package/components/timeout-modal/{timeout.dom.js → timeout-modal.dom.js} +2 -2
- package/components/timeout-modal/timeout-modal.js +62 -0
- package/components/timeout-panel/_macro.njk +26 -0
- package/components/timeout-panel/timeout-panel.dom.js +17 -0
- package/css/census.css +1 -1
- package/css/main.css +1 -1
- package/js/abortable-fetch.js +13 -38
- package/js/main.js +2 -1
- package/{components/timeout-modal → js}/timeout.js +42 -79
- package/layout/_template.njk +32 -4
- package/package.json +1 -1
- package/scripts/main.es5.js +1 -1
- package/scripts/main.js +2 -2
package/js/abortable-fetch.js
CHANGED
|
@@ -6,28 +6,20 @@ class AbortableFetch {
|
|
|
6
6
|
this.status = 'UNSENT';
|
|
7
7
|
}
|
|
8
8
|
|
|
9
|
-
send() {
|
|
9
|
+
async send() {
|
|
10
10
|
this.status = 'LOADING';
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
reject(response);
|
|
24
|
-
}
|
|
25
|
-
})
|
|
26
|
-
.catch(error => {
|
|
27
|
-
this.status = 'undefined';
|
|
28
|
-
reject(error);
|
|
29
|
-
});
|
|
30
|
-
});
|
|
11
|
+
try {
|
|
12
|
+
const response = await window.fetch(this.url, { signal: this.controller.signal, ...this.options });
|
|
13
|
+
const isResponseOK = (response.status >= 200 && response.status < 300) || response.status >= 400;
|
|
14
|
+
if (!isResponseOK) {
|
|
15
|
+
const error = new Error(`HTTP error! status: ${response.status}`);
|
|
16
|
+
error.response = response;
|
|
17
|
+
throw error;
|
|
18
|
+
}
|
|
19
|
+
return response;
|
|
20
|
+
} finally {
|
|
21
|
+
this.status = 'DONE';
|
|
22
|
+
}
|
|
31
23
|
}
|
|
32
24
|
|
|
33
25
|
abort() {
|
|
@@ -35,21 +27,4 @@ class AbortableFetch {
|
|
|
35
27
|
}
|
|
36
28
|
}
|
|
37
29
|
|
|
38
|
-
function abortableFetch(url, options) {
|
|
39
|
-
return window
|
|
40
|
-
.fetch(url, options)
|
|
41
|
-
.then(response => {
|
|
42
|
-
if (response) {
|
|
43
|
-
return response;
|
|
44
|
-
} else {
|
|
45
|
-
const error = new Error(response.status);
|
|
46
|
-
error.response = response;
|
|
47
|
-
throw error;
|
|
48
|
-
}
|
|
49
|
-
})
|
|
50
|
-
.catch(error => {
|
|
51
|
-
throw error;
|
|
52
|
-
});
|
|
53
|
-
}
|
|
54
|
-
|
|
55
30
|
export default (url, options) => new AbortableFetch(url, options);
|
package/js/main.js
CHANGED
|
@@ -24,4 +24,5 @@ import '../components/skip-to-content/skip-to-content.dom';
|
|
|
24
24
|
import '../components/download-resources/download-resources';
|
|
25
25
|
import '../components/select/select';
|
|
26
26
|
import '../components/modal/modal.dom';
|
|
27
|
-
import '../components/timeout-modal/timeout.dom';
|
|
27
|
+
import '../components/timeout-modal/timeout-modal.dom';
|
|
28
|
+
import '../components/timeout-panel/timeout-panel.dom';
|
|
@@ -1,15 +1,13 @@
|
|
|
1
|
-
import Modal from '../modal/modal';
|
|
2
|
-
|
|
3
1
|
export default class Timeout {
|
|
4
|
-
constructor(context,
|
|
2
|
+
constructor(context, sessionExpiryEndpoint, initialExpiryTime, enableTimeoutReset, startOnLoad) {
|
|
5
3
|
this.context = context;
|
|
6
|
-
this.sessionExpiryEndpoint =
|
|
7
|
-
this.initialExpiryTime =
|
|
8
|
-
this.
|
|
4
|
+
this.sessionExpiryEndpoint = sessionExpiryEndpoint;
|
|
5
|
+
this.initialExpiryTime = initialExpiryTime;
|
|
6
|
+
this.enableTimeoutReset = enableTimeoutReset || false;
|
|
7
|
+
this.startOnLoad = startOnLoad || false;
|
|
9
8
|
this.countdown = context.querySelector('.ons-js-timeout-timer');
|
|
10
9
|
this.accessibleCountdown = context.querySelector('.ons-js-timeout-timer-acc');
|
|
11
10
|
this.timeOutRedirectUrl = context.getAttribute('data-redirect-url');
|
|
12
|
-
this.modalVisibleInMilliseconds = context.getAttribute('data-show-modal-time') * 1000;
|
|
13
11
|
|
|
14
12
|
// Language dependent text strings
|
|
15
13
|
this.minutesTextSingular = context.getAttribute('data-minutes-text-singular');
|
|
@@ -17,17 +15,15 @@ export default class Timeout {
|
|
|
17
15
|
this.secondsTextSingular = context.getAttribute('data-seconds-text-singular');
|
|
18
16
|
this.secondsTextPlural = context.getAttribute('data-seconds-text-plural');
|
|
19
17
|
this.countdownText = context.getAttribute('data-countdown-text');
|
|
20
|
-
this.
|
|
18
|
+
this.countdownExpiredText = context.getAttribute('data-countdown-expired-text');
|
|
19
|
+
this.endWithFullStop = context.getAttribute('data-full-stop');
|
|
21
20
|
|
|
22
21
|
// Settings
|
|
23
|
-
this.expiryTimeInMilliseconds = 0;
|
|
24
22
|
this.expiryTime = '';
|
|
25
|
-
this.
|
|
23
|
+
this.expiryTimeInMilliseconds = 0;
|
|
26
24
|
this.timers = [];
|
|
27
25
|
this.timerRunOnce = false;
|
|
28
|
-
|
|
29
|
-
// Create modal instance
|
|
30
|
-
this.modal = new Modal(this.context);
|
|
26
|
+
this.countdownStarted = false;
|
|
31
27
|
|
|
32
28
|
// Start module
|
|
33
29
|
this.initialise();
|
|
@@ -39,43 +35,31 @@ export default class Timeout {
|
|
|
39
35
|
} else {
|
|
40
36
|
this.expiryTime = await this.setNewExpiryTime();
|
|
41
37
|
}
|
|
42
|
-
|
|
43
38
|
this.expiryTimeInMilliseconds = this.convertTimeToMilliSeconds(this.expiryTime);
|
|
44
39
|
|
|
45
|
-
this.
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
bindEventListeners() {
|
|
49
|
-
window.onload = this.startTimeout();
|
|
50
|
-
window.addEventListener('focus', this.handleWindowFocus.bind(this));
|
|
51
|
-
window.addEventListener('keydown', this.escToClose.bind(this));
|
|
52
|
-
this.continueButton.addEventListener('click', this.closeModalAndRestartTimeout.bind(this));
|
|
53
|
-
this.addThrottledEvents();
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
startTimeout() {
|
|
57
|
-
clearTimeout(this.showModalTimeout);
|
|
58
|
-
this.showModalTimeout = setTimeout(this.openModal.bind(this), this.expiryTimeInMilliseconds - this.modalVisibleInMilliseconds);
|
|
59
|
-
}
|
|
40
|
+
if (this.enableTimeoutReset) {
|
|
41
|
+
this.addThrottledResetEvents();
|
|
42
|
+
}
|
|
60
43
|
|
|
61
|
-
|
|
62
|
-
const modalWillOpen = await this.hasExpiryTimeResetInAnotherTab();
|
|
63
|
-
if (modalWillOpen && !this.modal.isDialogOpen()) {
|
|
64
|
-
this.modal.openDialog();
|
|
44
|
+
if (this.startOnLoad) {
|
|
65
45
|
this.startUiCountdown();
|
|
66
46
|
}
|
|
47
|
+
|
|
48
|
+
window.addEventListener('focus', this.handleWindowFocus.bind(this));
|
|
67
49
|
}
|
|
68
50
|
|
|
69
51
|
async startUiCountdown() {
|
|
70
52
|
this.clearTimers();
|
|
71
|
-
|
|
53
|
+
this.countdownStarted = true;
|
|
72
54
|
|
|
73
|
-
this.
|
|
74
|
-
|
|
75
|
-
|
|
55
|
+
if (this.enableTimeoutReset) {
|
|
56
|
+
this.shouldRestartCheck = setInterval(async () => {
|
|
57
|
+
await this.hasExpiryTimeResetInAnotherTab();
|
|
58
|
+
}, 20000);
|
|
59
|
+
}
|
|
76
60
|
|
|
77
|
-
let
|
|
78
|
-
let seconds =
|
|
61
|
+
let milliseconds = this.convertTimeToMilliSeconds(this.expiryTime);
|
|
62
|
+
let seconds = milliseconds / 1000;
|
|
79
63
|
let timers = this.timers;
|
|
80
64
|
let $this = this;
|
|
81
65
|
|
|
@@ -95,14 +79,15 @@ export default class Timeout {
|
|
|
95
79
|
(minutesLeft > 0 ? minutesText : '') +
|
|
96
80
|
(minutesLeft > 0 && secondsLeft > 0 ? ' ' : '') +
|
|
97
81
|
(secondsLeft > 0 ? secondsText : '') +
|
|
98
|
-
'</span
|
|
82
|
+
'</span>' +
|
|
83
|
+
($this.endWithFullStop ? '.' : '');
|
|
99
84
|
|
|
100
85
|
if (timerExpired) {
|
|
101
|
-
const shouldExpire = await $this.hasExpiryTimeResetInAnotherTab();
|
|
86
|
+
const shouldExpire = this.enableTimeoutReset ? await $this.hasExpiryTimeResetInAnotherTab() : true;
|
|
102
87
|
|
|
103
88
|
if (shouldExpire) {
|
|
104
|
-
$this.countdown.innerHTML = '<span class="ons-u-fw-b">' + $this.
|
|
105
|
-
$this.accessibleCountdown.innerHTML = $this.
|
|
89
|
+
$this.countdown.innerHTML = '<span class="ons-u-fw-b">' + $this.countdownExpiredText + '</span>';
|
|
90
|
+
$this.accessibleCountdown.innerHTML = $this.countdownExpiredText;
|
|
106
91
|
setTimeout($this.redirect.bind($this), 2000);
|
|
107
92
|
}
|
|
108
93
|
} else {
|
|
@@ -132,25 +117,16 @@ export default class Timeout {
|
|
|
132
117
|
if (checkExpiryTime != this.expiryTime) {
|
|
133
118
|
this.expiryTime = checkExpiryTime;
|
|
134
119
|
this.expiryTimeInMilliseconds = this.convertTimeToMilliSeconds(checkExpiryTime);
|
|
135
|
-
this.
|
|
120
|
+
this.restartTimeout(this.expiryTimeInMilliseconds);
|
|
136
121
|
} else {
|
|
137
122
|
return true;
|
|
138
123
|
}
|
|
139
124
|
}
|
|
140
125
|
|
|
141
|
-
closeModalAndRestartTimeout(timeInMilliSeconds) {
|
|
142
|
-
if (typeof timeInMilliSeconds !== 'string') {
|
|
143
|
-
timeInMilliSeconds = false;
|
|
144
|
-
}
|
|
145
|
-
if (this.modal.isDialogOpen()) {
|
|
146
|
-
this.modal.closeDialog();
|
|
147
|
-
}
|
|
148
|
-
this.restartTimeout(timeInMilliSeconds);
|
|
149
|
-
}
|
|
150
|
-
|
|
151
126
|
async restartTimeout(timeInMilliSeconds) {
|
|
152
127
|
this.clearTimers();
|
|
153
|
-
clearInterval(this.
|
|
128
|
+
clearInterval(this.shouldRestartCheck);
|
|
129
|
+
this.countdownStarted = false;
|
|
154
130
|
|
|
155
131
|
if (timeInMilliSeconds) {
|
|
156
132
|
this.expiryTimeInMilliseconds = timeInMilliSeconds;
|
|
@@ -159,26 +135,13 @@ export default class Timeout {
|
|
|
159
135
|
this.expiryTime = createNewExpiryTime;
|
|
160
136
|
this.expiryTimeInMilliseconds = this.convertTimeToMilliSeconds(createNewExpiryTime);
|
|
161
137
|
}
|
|
162
|
-
|
|
163
|
-
this.startTimeout();
|
|
164
138
|
}
|
|
165
139
|
|
|
166
140
|
async handleWindowFocus() {
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
} else {
|
|
172
|
-
const newExpiryTimeInMilliseconds = this.convertTimeToMilliSeconds(canSetNewExpiry).toString();
|
|
173
|
-
this.closeModalAndRestartTimeout(newExpiryTimeInMilliseconds);
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
escToClose(event) {
|
|
179
|
-
if (this.modal.isDialogOpen() && event.keyCode === 27) {
|
|
180
|
-
this.closeModalAndRestartTimeout();
|
|
181
|
-
}
|
|
141
|
+
this.expiryTime = await this.getExpiryTime();
|
|
142
|
+
this.clearTimers();
|
|
143
|
+
clearInterval(this.shouldRestartCheck);
|
|
144
|
+
this.startUiCountdown();
|
|
182
145
|
}
|
|
183
146
|
|
|
184
147
|
async setNewExpiryTime() {
|
|
@@ -235,45 +198,45 @@ export default class Timeout {
|
|
|
235
198
|
}
|
|
236
199
|
}
|
|
237
200
|
|
|
238
|
-
|
|
201
|
+
addThrottledResetEvents() {
|
|
239
202
|
window.onclick = this.throttle(() => {
|
|
240
203
|
/* istanbul ignore next */
|
|
241
|
-
if (!this.
|
|
204
|
+
if (!this.countdownStarted) {
|
|
242
205
|
this.restartTimeout();
|
|
243
206
|
}
|
|
244
207
|
}, 61000);
|
|
245
208
|
|
|
246
209
|
window.onmousemove = this.throttle(() => {
|
|
247
210
|
/* istanbul ignore next */
|
|
248
|
-
if (!this.
|
|
211
|
+
if (!this.countdownStarted) {
|
|
249
212
|
this.restartTimeout();
|
|
250
213
|
}
|
|
251
214
|
}, 61000);
|
|
252
215
|
|
|
253
216
|
window.onmousedown = this.throttle(() => {
|
|
254
217
|
/* istanbul ignore next */
|
|
255
|
-
if (!this.
|
|
218
|
+
if (!this.countdownStarted) {
|
|
256
219
|
this.restartTimeout();
|
|
257
220
|
}
|
|
258
221
|
}, 61000);
|
|
259
222
|
|
|
260
223
|
window.onscroll = this.throttle(() => {
|
|
261
224
|
/* istanbul ignore next */
|
|
262
|
-
if (!this.
|
|
225
|
+
if (!this.countdownStarted) {
|
|
263
226
|
this.restartTimeout();
|
|
264
227
|
}
|
|
265
228
|
}, 61000);
|
|
266
229
|
|
|
267
230
|
window.onkeypress = this.throttle(() => {
|
|
268
231
|
/* istanbul ignore next */
|
|
269
|
-
if (!this.
|
|
232
|
+
if (!this.countdownStarted) {
|
|
270
233
|
this.restartTimeout();
|
|
271
234
|
}
|
|
272
235
|
}, 61000);
|
|
273
236
|
|
|
274
237
|
window.onkeyup = this.throttle(() => {
|
|
275
238
|
/* istanbul ignore next */
|
|
276
|
-
if (!this.
|
|
239
|
+
if (!this.countdownStarted) {
|
|
277
240
|
this.restartTimeout();
|
|
278
241
|
}
|
|
279
242
|
}, 61000);
|
package/layout/_template.njk
CHANGED
|
@@ -18,8 +18,6 @@
|
|
|
18
18
|
{% set metaicons = "" %}
|
|
19
19
|
{% endif %}
|
|
20
20
|
|
|
21
|
-
{% set pageColNumber = pageConfig.pageColNumber | default("8") %}
|
|
22
|
-
|
|
23
21
|
{% if pageConfig.cdn is defined and pageConfig.cdn or release_version is defined and release_version %}
|
|
24
22
|
{# Production #}
|
|
25
23
|
{% set cdn_url = (pageConfig.cdn.url if pageConfig.cdn is defined and pageConfig.cdn and pageConfig.cdn.url is defined and pageConfig.cdn.url) or "https://cdn.ons.gov.uk/sdc/design-system" %}
|
|
@@ -44,6 +42,21 @@
|
|
|
44
42
|
{% set page_title = "ONS Design System" %}
|
|
45
43
|
{% endif %}
|
|
46
44
|
|
|
45
|
+
{# Page columns #}
|
|
46
|
+
{% set mainColNumber = "8" %}
|
|
47
|
+
|
|
48
|
+
{% if pageConfig.mainCol is defined and pageConfig.mainCol %}
|
|
49
|
+
{% set mainColNumber = pageConfig.mainCol.columns if pageConfig.mainCol.columns is defined and pageConfig.mainCol.columns %}
|
|
50
|
+
{% set mainColClasses = (' ' + pageConfig.mainCol.colClasses) if pageConfig.mainCol.colClasses is defined and pageConfig.mainCol.colClasses %}
|
|
51
|
+
{% set mainClasses = (' ' + pageConfig.mainCol.classes) if pageConfig.mainCol.classes is defined and pageConfig.mainCol.classes %}
|
|
52
|
+
{% endif %}
|
|
53
|
+
|
|
54
|
+
{% if pageConfig.asideCol is defined and pageConfig.asideCol %}
|
|
55
|
+
{% set asideColNumber = 12 - mainColNumber if pageConfig.asideCol.position is defined and pageConfig.asideCol.position %}
|
|
56
|
+
{% set asideColClasses = (' ' + pageConfig.asideCol.colClasses) if pageConfig.asideCol.colClasses is defined and pageConfig.asideCol.colClasses %}
|
|
57
|
+
{% set asideClasses = (' ' + pageConfig.asideCol.classes) if pageConfig.asideCol.classes is defined and pageConfig.asideCol.classes %}
|
|
58
|
+
{% endif %}
|
|
59
|
+
|
|
47
60
|
<!doctype html>
|
|
48
61
|
<html lang="{{ currentLanguageISOCode }}">
|
|
49
62
|
<head>
|
|
@@ -169,11 +182,26 @@
|
|
|
169
182
|
{% endif %}
|
|
170
183
|
{% block preMain %}{% endblock %}
|
|
171
184
|
<div class="ons-grid">
|
|
172
|
-
|
|
173
|
-
|
|
185
|
+
{% if pageConfig.asideCol is defined and pageConfig.asideCol %}
|
|
186
|
+
{% set aside %}
|
|
187
|
+
<div class="ons-grid__col ons-col-{{ asideColNumber }}@m{{ asideColClasses }}">
|
|
188
|
+
<aside {% if pageConfig.asideCol.id is defined and pageConfig.asideCol.id %}id="{{ asideId }}" {% endif %}class="ons-page__aside{{ asideClasses }}">
|
|
189
|
+
{% block aside %}{% endblock %}
|
|
190
|
+
</aside>
|
|
191
|
+
</div>
|
|
192
|
+
{% endset %}
|
|
193
|
+
{% endif %}
|
|
194
|
+
{% if pageConfig.asideCol.position is defined and pageConfig.asideCol.position == "before" %}
|
|
195
|
+
{{ aside | safe }}
|
|
196
|
+
{% endif %}
|
|
197
|
+
<div class="ons-grid__col ons-col-{{ mainColNumber }}@m{{ mainColClasses }}">
|
|
198
|
+
<main id="main-content" class="ons-page__main{{ mainClasses }}">
|
|
174
199
|
{% block main %}{% endblock %}
|
|
175
200
|
</main>
|
|
176
201
|
</div>
|
|
202
|
+
{% if pageConfig.asideCol.position is defined and pageConfig.asideCol.position == "after" %}
|
|
203
|
+
{{ aside | safe }}
|
|
204
|
+
{% endif %}
|
|
177
205
|
</div>
|
|
178
206
|
</div>
|
|
179
207
|
{% endblock %}
|