govuk_publishing_components 35.7.0 → 35.9.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/assets/javascripts/govuk_publishing_components/analytics-ga4/ga4-link-tracker.js +1 -1
- data/app/assets/javascripts/govuk_publishing_components/vendor/lux/lux-reporter.js +206 -114
- data/app/assets/stylesheets/govuk_publishing_components/components/_document-list.scss +5 -9
- data/app/assets/stylesheets/govuk_publishing_components/components/_layout-for-public.scss +4 -0
- data/app/views/govuk_publishing_components/audit/show.html.erb +2 -1
- data/app/views/govuk_publishing_components/components/_accordion.html.erb +4 -3
- data/app/views/govuk_publishing_components/components/_document_list.html.erb +8 -7
- data/app/views/govuk_publishing_components/components/_layout_for_public.html.erb +9 -2
- data/app/views/govuk_publishing_components/components/_metadata.html.erb +20 -14
- data/app/views/govuk_publishing_components/components/_single_page_notification_button.html.erb +21 -9
- data/app/views/govuk_publishing_components/components/_step_by_step_nav_related.html.erb +2 -2
- data/app/views/govuk_publishing_components/components/docs/document_list.yml +17 -0
- data/app/views/govuk_publishing_components/components/docs/layout_for_public.yml +6 -0
- data/app/views/govuk_publishing_components/components/docs/notice.yml +1 -1
- data/app/views/govuk_publishing_components/components/docs/single_page_notification_button.yml +13 -0
- data/lib/govuk_publishing_components/app_helpers/asset_helper.rb +1 -1
- data/lib/govuk_publishing_components/presenters/public_layout_helper.rb +5 -0
- data/lib/govuk_publishing_components/presenters/single_page_notification_button_helper.rb +9 -1
- data/lib/govuk_publishing_components/version.rb +1 -1
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 619cac6fc6ecb8078d66be77a50e1fe4d5f320b61a15e574fbd92a892d896d80
|
4
|
+
data.tar.gz: d339abcad29fe3e59dafe2157e3ba605c8817563797b30bead89650ebe5d278f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a163d27c8f13d7019869a16ac1f0c58c4c71e88be7c456e1639cb717bdf3f0da4c483ae7336824ed288d2888e5f0e671e1b1120fe910fa75d838aa85da998f98
|
7
|
+
data.tar.gz: 87d03d1a7c4f50d4065b501c8f415831f218f28e2dd28ebfe61d87d270162ae595899ba46387d5bed9cc3b9472fbc7d47255fd573354bcfcc8477262aa574427
|
@@ -82,7 +82,7 @@ window.GOVUK.Modules = window.GOVUK.Modules || {};
|
|
82
82
|
var text = data.text || event.target.textContent
|
83
83
|
data.text = window.GOVUK.analyticsGa4.core.trackFunctions.removeLinesAndExtraSpaces(text)
|
84
84
|
data.text = this.PIIRemover.stripPIIWithOverride(data.text, true, true)
|
85
|
-
if (!data.text && (element.querySelector('img') || element.querySelector('svg'))) {
|
85
|
+
if (!data.text && (element.querySelector('img') || element.querySelector('svg') || element.tagName === 'IMG' || element.closest('svg'))) {
|
86
86
|
data.text = 'image'
|
87
87
|
}
|
88
88
|
var url = data.url || this.findLink(event.target).getAttribute('href')
|
@@ -42,7 +42,6 @@
|
|
42
42
|
var autoMode = getProperty(obj, "auto", true);
|
43
43
|
return {
|
44
44
|
auto: autoMode,
|
45
|
-
autoWhenHidden: getProperty(obj, "autoWhenHidden", false),
|
46
45
|
beaconUrl: getProperty(obj, "beaconUrl", "https://lux.speedcurve.com/lux/"),
|
47
46
|
conversions: getProperty(obj, "conversions", undefined),
|
48
47
|
customerid: getProperty(obj, "customerid", undefined),
|
@@ -54,9 +53,12 @@
|
|
54
53
|
maxErrors: getProperty(obj, "maxErrors", 5),
|
55
54
|
maxMeasureTime: getProperty(obj, "maxMeasureTime", 60000),
|
56
55
|
minMeasureTime: getProperty(obj, "minMeasureTime", 0),
|
56
|
+
newBeaconOnPageShow: getProperty(obj, "newBeaconOnPageShow", false),
|
57
57
|
samplerate: getProperty(obj, "samplerate", 100),
|
58
58
|
sendBeaconOnPageHidden: getProperty(obj, "sendBeaconOnPageHidden", autoMode),
|
59
|
+
serverTiming: getProperty(obj, "serverTiming", undefined),
|
59
60
|
trackErrors: getProperty(obj, "trackErrors", true),
|
61
|
+
trackHiddenPages: getProperty(obj, "trackHiddenPages", false),
|
60
62
|
pagegroups: getProperty(obj, "pagegroups", undefined),
|
61
63
|
};
|
62
64
|
}
|
@@ -102,9 +104,9 @@
|
|
102
104
|
function valuesToString(values) {
|
103
105
|
var strings = [];
|
104
106
|
for (var key in values) {
|
105
|
-
|
107
|
+
// Convert all values to strings
|
106
108
|
var value = "" + values[key];
|
107
|
-
|
109
|
+
// Strip out reserved characters (, and | are used as delimiters)
|
108
110
|
key = key.replace(/,/g, "").replace(/\|/g, "");
|
109
111
|
value = value.replace(/,/g, "").replace(/\|/g, "");
|
110
112
|
strings.push(key + "|" + value);
|
@@ -115,6 +117,13 @@
|
|
115
117
|
function floor(x) {
|
116
118
|
return Math.floor(x);
|
117
119
|
}
|
120
|
+
var max = Math.max;
|
121
|
+
/**
|
122
|
+
* Clamp a number so that it is never less than 0
|
123
|
+
*/
|
124
|
+
function clamp(x) {
|
125
|
+
return max(0, x);
|
126
|
+
}
|
118
127
|
|
119
128
|
function now() {
|
120
129
|
return Date.now ? Date.now() : +new Date();
|
@@ -147,10 +156,13 @@
|
|
147
156
|
function getNavigationEntry() {
|
148
157
|
var navEntries = getEntriesByType("navigation");
|
149
158
|
if (navEntries.length) {
|
150
|
-
var
|
151
|
-
entry_1
|
152
|
-
|
153
|
-
|
159
|
+
var nativeEntry = navEntries[0];
|
160
|
+
var entry_1 = {
|
161
|
+
navigationStart: 0,
|
162
|
+
activationStart: 0,
|
163
|
+
};
|
164
|
+
for (var key in nativeEntry) {
|
165
|
+
entry_1[key] = nativeEntry[key];
|
154
166
|
}
|
155
167
|
return entry_1;
|
156
168
|
}
|
@@ -164,7 +176,7 @@
|
|
164
176
|
if (__ENABLE_POLYFILLS) {
|
165
177
|
for (var key in timing) {
|
166
178
|
if (typeof timing[key] === "number" && key !== "navigationStart") {
|
167
|
-
entry[key] =
|
179
|
+
entry[key] = floor(timing[key] - timing.navigationStart);
|
168
180
|
}
|
169
181
|
}
|
170
182
|
}
|
@@ -189,26 +201,39 @@
|
|
189
201
|
if (document.visibilityState) {
|
190
202
|
return document.visibilityState === "visible";
|
191
203
|
}
|
192
|
-
|
204
|
+
// For browsers that don't support document.visibilityState, we assume the page is visible.
|
193
205
|
return true;
|
194
206
|
}
|
195
207
|
function onVisible(cb) {
|
196
|
-
|
197
|
-
|
208
|
+
afterPrerender(function () {
|
209
|
+
if (isVisible()) {
|
210
|
+
cb();
|
211
|
+
}
|
212
|
+
else {
|
213
|
+
var onVisibleCallback_1 = function () {
|
214
|
+
if (isVisible()) {
|
215
|
+
cb();
|
216
|
+
removeEventListener("visibilitychange", onVisibleCallback_1);
|
217
|
+
}
|
218
|
+
};
|
219
|
+
addEventListener("visibilitychange", onVisibleCallback_1, true);
|
220
|
+
}
|
221
|
+
});
|
222
|
+
}
|
223
|
+
function afterPrerender(cb) {
|
224
|
+
if (document.prerendering) {
|
225
|
+
document.addEventListener("prerenderingchange", cb, true);
|
198
226
|
}
|
199
227
|
else {
|
200
|
-
|
201
|
-
if (isVisible()) {
|
202
|
-
cb();
|
203
|
-
removeEventListener("visibilitychange", onVisibleCallback_1);
|
204
|
-
}
|
205
|
-
};
|
206
|
-
addEventListener("visibilitychange", onVisibleCallback_1, true);
|
228
|
+
cb();
|
207
229
|
}
|
208
230
|
}
|
209
231
|
function wasPrerendered() {
|
210
232
|
return document.prerendering || getNavigationEntry().activationStart > 0;
|
211
233
|
}
|
234
|
+
function wasRedirected() {
|
235
|
+
return getNavigationEntry().redirectCount > 0 || timing.redirectEnd > 0;
|
236
|
+
}
|
212
237
|
|
213
238
|
var Flags = {
|
214
239
|
InitCalled: 1 << 0,
|
@@ -222,6 +247,7 @@
|
|
222
247
|
PageLabelFromGlobalVariable: 1 << 8,
|
223
248
|
PageLabelFromPagegroup: 1 << 9,
|
224
249
|
PageWasPrerendered: 1 << 10,
|
250
|
+
PageWasBfCacheRestored: 1 << 11,
|
225
251
|
};
|
226
252
|
function addFlag(flags, flag) {
|
227
253
|
return flags | flag;
|
@@ -235,8 +261,8 @@
|
|
235
261
|
}
|
236
262
|
|
237
263
|
/**
|
238
|
-
|
239
|
-
|
264
|
+
* Get the interaction attribution name for an element
|
265
|
+
*/
|
240
266
|
function interactionAttributionForElement(el) {
|
241
267
|
// Our first preference is to use the data-sctrack attribute from anywhere in the tree
|
242
268
|
var trackId = getClosestScTrackAttribute(el);
|
@@ -291,6 +317,7 @@
|
|
291
317
|
UnloadHandlerTriggered: 10,
|
292
318
|
OnloadHandlerTriggered: 11,
|
293
319
|
MarkLoadTimeCalled: 12,
|
320
|
+
SendCancelledPageHidden: 13,
|
294
321
|
// Data collection events
|
295
322
|
SessionIsSampled: 21,
|
296
323
|
SessionIsNotSampled: 22,
|
@@ -315,39 +342,45 @@
|
|
315
342
|
PaintTimingNotSupported: 72,
|
316
343
|
};
|
317
344
|
var Logger = /** @class */ (function () {
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
345
|
+
function Logger() {
|
346
|
+
this.events = [];
|
347
|
+
}
|
348
|
+
Logger.prototype.logEvent = function (event, args) {
|
349
|
+
if (args === void 0) { args = []; }
|
350
|
+
this.events.push([now(), event, args]);
|
351
|
+
};
|
352
|
+
Logger.prototype.getEvents = function () {
|
353
|
+
return this.events;
|
354
|
+
};
|
355
|
+
return Logger;
|
329
356
|
}());
|
330
357
|
var sessionValue = 0;
|
331
358
|
var sessionEntries = [];
|
359
|
+
var maximumSessionValue = 0;
|
332
360
|
function addEntry$2(entry) {
|
333
361
|
if (!entry.hadRecentInput) {
|
334
362
|
var firstEntry = sessionEntries[0];
|
335
363
|
var latestEntry = sessionEntries[sessionEntries.length - 1];
|
336
364
|
if (sessionEntries.length &&
|
337
365
|
(entry.startTime - latestEntry.startTime >= 1000 ||
|
338
|
-
|
339
|
-
|
366
|
+
entry.startTime - firstEntry.startTime >= 5000)) {
|
367
|
+
sessionValue = entry.value;
|
368
|
+
sessionEntries = [entry];
|
340
369
|
}
|
341
|
-
|
342
|
-
|
370
|
+
else {
|
371
|
+
sessionValue += entry.value;
|
372
|
+
sessionEntries.push(entry);
|
373
|
+
}
|
374
|
+
maximumSessionValue = max(maximumSessionValue, sessionValue);
|
343
375
|
}
|
344
376
|
}
|
345
377
|
function reset$1() {
|
346
378
|
sessionValue = 0;
|
347
379
|
sessionEntries = [];
|
380
|
+
maximumSessionValue = 0;
|
348
381
|
}
|
349
382
|
function getCLS() {
|
350
|
-
return
|
383
|
+
return maximumSessionValue;
|
351
384
|
}
|
352
385
|
|
353
386
|
/**
|
@@ -372,7 +405,7 @@
|
|
372
405
|
var duration = entry.duration, startTime = entry.startTime, interactionId = entry.interactionId;
|
373
406
|
var existingEntry = slowestEntriesMap[interactionId];
|
374
407
|
if (existingEntry) {
|
375
|
-
existingEntry.duration =
|
408
|
+
existingEntry.duration = max(duration, existingEntry.duration);
|
376
409
|
}
|
377
410
|
else {
|
378
411
|
interactionCountEstimate++;
|
@@ -405,44 +438,6 @@
|
|
405
438
|
return interactionCountEstimate;
|
406
439
|
}
|
407
440
|
|
408
|
-
/**
|
409
|
-
* Get the number of milliseconds between navigationStart and the given PerformanceNavigationTiming key
|
410
|
-
*/
|
411
|
-
function getNavTimingValue(key) {
|
412
|
-
var navEntry = getNavigationEntry();
|
413
|
-
var relativeTo = key === "activationStart" ? 0 : navEntry.activationStart;
|
414
|
-
if (typeof navEntry[key] === "number") {
|
415
|
-
return Math.max(0, navEntry[key] - relativeTo);
|
416
|
-
}
|
417
|
-
return undefined;
|
418
|
-
}
|
419
|
-
|
420
|
-
/******************************************************************************
|
421
|
-
Copyright (c) Microsoft Corporation.
|
422
|
-
|
423
|
-
Permission to use, copy, modify, and/or distribute this software for any
|
424
|
-
purpose with or without fee is hereby granted.
|
425
|
-
|
426
|
-
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
427
|
-
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
428
|
-
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
429
|
-
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
430
|
-
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
431
|
-
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
432
|
-
PERFORMANCE OF THIS SOFTWARE.
|
433
|
-
***************************************************************************** */
|
434
|
-
|
435
|
-
var __assign = function() {
|
436
|
-
__assign = Object.assign || function __assign(t) {
|
437
|
-
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
438
|
-
s = arguments[i];
|
439
|
-
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
|
440
|
-
}
|
441
|
-
return t;
|
442
|
-
};
|
443
|
-
return __assign.apply(this, arguments);
|
444
|
-
};
|
445
|
-
|
446
441
|
var ALL_ENTRIES = [];
|
447
442
|
function observe(type, callback, options) {
|
448
443
|
if (typeof PerformanceObserver === "function" &&
|
@@ -450,10 +445,10 @@
|
|
450
445
|
var po = new PerformanceObserver(function (list) {
|
451
446
|
list.getEntries().forEach(function (entry) { return callback(entry); });
|
452
447
|
});
|
453
|
-
|
454
|
-
|
455
|
-
|
456
|
-
|
448
|
+
po.observe(Object.assign({ type: type, buffered: true }, { options: options }));
|
449
|
+
return po;
|
450
|
+
}
|
451
|
+
return undefined;
|
457
452
|
}
|
458
453
|
function getEntries(type) {
|
459
454
|
return ALL_ENTRIES.filter(function (entry) { return entry.entryType === type; });
|
@@ -465,6 +460,39 @@
|
|
465
460
|
ALL_ENTRIES.splice(0);
|
466
461
|
}
|
467
462
|
|
463
|
+
/**
|
464
|
+
* A server timing metric that has its value set to the duration field
|
465
|
+
*/
|
466
|
+
var TYPE_DURATION = "r";
|
467
|
+
/**
|
468
|
+
* When a description metric has no value, we consider it to be a boolean and set it to this value.
|
469
|
+
*/
|
470
|
+
var BOOLEAN_TRUE_VALUE = "true";
|
471
|
+
function getKeyValuePairs(config, serverTiming) {
|
472
|
+
var pairs = {};
|
473
|
+
serverTiming.forEach(function (stEntry) {
|
474
|
+
var name = stEntry.name;
|
475
|
+
var description = stEntry.description;
|
476
|
+
if (name in config) {
|
477
|
+
var spec = config[name];
|
478
|
+
var multiplier = spec[1];
|
479
|
+
if (spec[0] === TYPE_DURATION) {
|
480
|
+
pairs[name] = stEntry.duration * (multiplier || 1);
|
481
|
+
}
|
482
|
+
else if (description && multiplier) {
|
483
|
+
var numericValue = parseFloat(description);
|
484
|
+
if (!isNaN(numericValue)) {
|
485
|
+
pairs[name] = numericValue * multiplier;
|
486
|
+
}
|
487
|
+
}
|
488
|
+
else {
|
489
|
+
pairs[name] = description || BOOLEAN_TRUE_VALUE;
|
490
|
+
}
|
491
|
+
}
|
492
|
+
});
|
493
|
+
return pairs;
|
494
|
+
}
|
495
|
+
|
468
496
|
function getMatchesFromPatternMap(patternMap, hostname, pathname, firstOnly) {
|
469
497
|
var matches = [];
|
470
498
|
for (var key in patternMap) {
|
@@ -496,7 +524,7 @@
|
|
496
524
|
return regex.test(hostname + pathname);
|
497
525
|
}
|
498
526
|
function createRegExpFromPattern(pattern) {
|
499
|
-
return new RegExp("^" + escapeStringForRegExp(pattern).
|
527
|
+
return new RegExp("^" + escapeStringForRegExp(pattern).replace(/\*/g, ".*") + "$", "i");
|
500
528
|
}
|
501
529
|
function escapeStringForRegExp(str) {
|
502
530
|
// Note: we don't escape * because it's our own special symbol!
|
@@ -514,7 +542,7 @@
|
|
514
542
|
// -------------------------------------------------------------------------
|
515
543
|
/// End
|
516
544
|
// -------------------------------------------------------------------------
|
517
|
-
var SCRIPT_VERSION = "
|
545
|
+
var SCRIPT_VERSION = "309";
|
518
546
|
var logger = new Logger();
|
519
547
|
var globalConfig = fromObject(LUX);
|
520
548
|
logger.logEvent(LogEvent.EvaluationStart, [SCRIPT_VERSION]);
|
@@ -585,7 +613,7 @@
|
|
585
613
|
observe("first-input", function (entry) {
|
586
614
|
var fid = entry.processingStart - entry.startTime;
|
587
615
|
if (!gFirstInputDelay || gFirstInputDelay < fid) {
|
588
|
-
gFirstInputDelay = fid;
|
616
|
+
gFirstInputDelay = floor(fid);
|
589
617
|
}
|
590
618
|
// Allow first-input events to be considered for INP
|
591
619
|
addEntry$1(entry);
|
@@ -612,7 +640,13 @@
|
|
612
640
|
var gUid = refreshUniqueId(gSyncId); // cookie for this session ("Unique ID")
|
613
641
|
var gCustomerDataTimeout; // setTimeout timer for sending a Customer Data beacon after onload
|
614
642
|
var gMaxMeasureTimeout; // setTimeout timer for sending the beacon after a maximum measurement time
|
615
|
-
var
|
643
|
+
var pageRestoreTime; // ms since navigationStart representing when the page was restored from the bfcache
|
644
|
+
/**
|
645
|
+
* To measure the way a user experienced a metric, we measure metrics relative to the time the user
|
646
|
+
* started viewing the page. On prerendered pages, this is activationStart. On bfcache restores, this
|
647
|
+
* is the page restore time. On all other pages this value will be zero.
|
648
|
+
*/
|
649
|
+
var getZeroTime = function () { return pageRestoreTime || getNavigationEntry().activationStart; };
|
616
650
|
if (_sample()) {
|
617
651
|
logger.logEvent(LogEvent.SessionIsSampled, [globalConfig.samplerate]);
|
618
652
|
}
|
@@ -713,7 +747,7 @@
|
|
713
747
|
var startMark = _getMark(START_MARK);
|
714
748
|
// For SPA page views, we use our internal mark as a reference point
|
715
749
|
if (startMark && !absolute) {
|
716
|
-
return sinceNavigationStart - startMark.startTime;
|
750
|
+
return floor(sinceNavigationStart - startMark.startTime);
|
717
751
|
}
|
718
752
|
// For "regular" page views, we can use performance.now() if it's available...
|
719
753
|
return sinceNavigationStart;
|
@@ -796,6 +830,7 @@
|
|
796
830
|
}
|
797
831
|
// ...Otherwise provide a polyfill
|
798
832
|
if (__ENABLE_POLYFILLS) {
|
833
|
+
var navEntry = getNavigationEntry();
|
799
834
|
var startTime = typeof startMarkName === "number" ? startMarkName : 0;
|
800
835
|
var endTime = typeof endMarkName === "number" ? endMarkName : _now();
|
801
836
|
var throwError = function (missingMark) {
|
@@ -906,7 +941,7 @@
|
|
906
941
|
hUT[name] = { startTime: startTime };
|
907
942
|
}
|
908
943
|
else {
|
909
|
-
hUT[name].startTime =
|
944
|
+
hUT[name].startTime = max(startTime, hUT[name].startTime);
|
910
945
|
}
|
911
946
|
});
|
912
947
|
// measures
|
@@ -939,7 +974,7 @@
|
|
939
974
|
function elementTimingValues() {
|
940
975
|
var aET = [];
|
941
976
|
var startMark = _getMark(START_MARK);
|
942
|
-
var tZero = startMark ? startMark.startTime :
|
977
|
+
var tZero = startMark ? startMark.startTime : getZeroTime();
|
943
978
|
getEntries("element").forEach(function (entry) {
|
944
979
|
if (entry.identifier && entry.startTime) {
|
945
980
|
logger.logEvent(LogEvent.PerformanceEntryProcessed, [entry]);
|
@@ -1164,11 +1199,11 @@
|
|
1164
1199
|
var nThis = ("" + gUid).substr(-2); // number for THIS page - from 00 to 99
|
1165
1200
|
return parseInt(nThis) < globalConfig.samplerate;
|
1166
1201
|
}
|
1167
|
-
|
1168
|
-
|
1169
|
-
|
1170
|
-
|
1171
|
-
function _init() {
|
1202
|
+
/**
|
1203
|
+
* Re-initialize lux.js to start a new "page". This is typically called within a SPA at the
|
1204
|
+
* beginning of a page transition, but is also called internally when the BF cache is restored.
|
1205
|
+
*/
|
1206
|
+
function _init(startTime) {
|
1172
1207
|
// Some customers (incorrectly) call LUX.init on the very first page load of a SPA. This would
|
1173
1208
|
// cause some first-page-only data (like paint metrics) to be lost. To prevent this, we silently
|
1174
1209
|
// bail from this function when we detect an unnecessary LUX.init call.
|
@@ -1176,6 +1211,14 @@
|
|
1176
1211
|
if (!endMark) {
|
1177
1212
|
return;
|
1178
1213
|
}
|
1214
|
+
// Mark the "navigationStart" for this SPA page. A start time can be passed through, for example
|
1215
|
+
// to set a page's start time as an event timestamp.
|
1216
|
+
if (startTime) {
|
1217
|
+
_mark(START_MARK, { startTime: startTime });
|
1218
|
+
}
|
1219
|
+
else {
|
1220
|
+
_mark(START_MARK);
|
1221
|
+
}
|
1179
1222
|
logger.logEvent(LogEvent.InitCalled);
|
1180
1223
|
// Clear all interactions from the previous "page".
|
1181
1224
|
_clearIx();
|
@@ -1197,8 +1240,6 @@
|
|
1197
1240
|
// Clear flags then set the flag that init was called (ie, this is a SPA).
|
1198
1241
|
gFlags = 0;
|
1199
1242
|
gFlags = addFlag(gFlags, Flags.InitCalled);
|
1200
|
-
// Mark the "navigationStart" for this SPA page.
|
1201
|
-
_mark(START_MARK);
|
1202
1243
|
// Reset the maximum measure timeout
|
1203
1244
|
createMaxMeasureTimeout();
|
1204
1245
|
}
|
@@ -1305,8 +1346,9 @@
|
|
1305
1346
|
var ns = timing.navigationStart;
|
1306
1347
|
var startMark = _getMark(START_MARK);
|
1307
1348
|
var endMark = _getMark(END_MARK);
|
1308
|
-
if (startMark && endMark) {
|
1349
|
+
if (startMark && endMark && !pageRestoreTime) {
|
1309
1350
|
// This is a SPA page view, so send the SPA marks & measures instead of Nav Timing.
|
1351
|
+
// Note: pageRestoreTime indicates this was a bfcache restore, which we don't want to treat as a SPA.
|
1310
1352
|
var start = floor(startMark.startTime); // the start mark is "zero"
|
1311
1353
|
ns += start; // "navigationStart" for a SPA is the real navigationStart plus the start mark
|
1312
1354
|
var end = floor(endMark.startTime) - start; // delta from start mark
|
@@ -1322,21 +1364,33 @@
|
|
1322
1364
|
}
|
1323
1365
|
else if (performance.timing) {
|
1324
1366
|
// Return the real Nav Timing metrics because this is the "main" page view (not a SPA)
|
1367
|
+
var navEntry_1 = getNavigationEntry();
|
1325
1368
|
var startRender = getStartRender();
|
1326
1369
|
var fcp = getFcp();
|
1327
1370
|
var lcp = getLcp();
|
1328
1371
|
var prefixNTValue = function (key, prefix) {
|
1329
|
-
|
1330
|
-
|
1331
|
-
|
1372
|
+
// activationStart is always absolute. Other values are relative to activationStart.
|
1373
|
+
var zero = key === "activationStart" ? 0 : getZeroTime();
|
1374
|
+
if (typeof navEntry_1[key] === "number") {
|
1375
|
+
var value = clamp(floor(navEntry_1[key] - zero));
|
1376
|
+
return prefix + value;
|
1332
1377
|
}
|
1333
|
-
return
|
1378
|
+
return "";
|
1334
1379
|
};
|
1380
|
+
var loadEventStartStr = prefixNTValue("loadEventStart", "ls");
|
1381
|
+
var loadEventEndStr = prefixNTValue("loadEventEnd", "le");
|
1382
|
+
if (pageRestoreTime && startMark && endMark) {
|
1383
|
+
// For bfcache restores, we set the load time to the time it took for the page to be restored.
|
1384
|
+
var loadTime = floor(endMark.startTime - startMark.startTime);
|
1385
|
+
loadEventStartStr = "ls" + loadTime;
|
1386
|
+
loadEventEndStr = "le" + loadTime;
|
1387
|
+
}
|
1388
|
+
var redirect = wasRedirected();
|
1335
1389
|
s = [
|
1336
1390
|
ns,
|
1337
1391
|
prefixNTValue("activationStart", "as"),
|
1338
|
-
prefixNTValue("redirectStart", "rs"),
|
1339
|
-
prefixNTValue("redirectEnd", "re"),
|
1392
|
+
redirect ? prefixNTValue("redirectStart", "rs") : "",
|
1393
|
+
redirect ? prefixNTValue("redirectEnd", "re") : "",
|
1340
1394
|
prefixNTValue("fetchStart", "fs"),
|
1341
1395
|
prefixNTValue("domainLookupStart", "ds"),
|
1342
1396
|
prefixNTValue("domainLookupEnd", "de"),
|
@@ -1350,11 +1404,11 @@
|
|
1350
1404
|
prefixNTValue("domContentLoadedEventStart", "os"),
|
1351
1405
|
prefixNTValue("domContentLoadedEventEnd", "oe"),
|
1352
1406
|
prefixNTValue("domComplete", "oc"),
|
1353
|
-
|
1354
|
-
|
1355
|
-
typeof startRender !== "undefined" ? "sr" + startRender : "",
|
1356
|
-
typeof fcp !== "undefined" ? "fc" + fcp : "",
|
1357
|
-
typeof lcp !== "undefined" ? "lc" + lcp : "",
|
1407
|
+
loadEventStartStr,
|
1408
|
+
loadEventEndStr,
|
1409
|
+
typeof startRender !== "undefined" ? "sr" + clamp(startRender) : "",
|
1410
|
+
typeof fcp !== "undefined" ? "fc" + clamp(fcp) : "",
|
1411
|
+
typeof lcp !== "undefined" ? "lc" + clamp(lcp) : "",
|
1358
1412
|
].join("");
|
1359
1413
|
}
|
1360
1414
|
else if (endMark) {
|
@@ -1378,7 +1432,7 @@
|
|
1378
1432
|
for (var i = 0; i < paintEntries.length; i++) {
|
1379
1433
|
var entry = paintEntries[i];
|
1380
1434
|
if (entry.name === "first-contentful-paint") {
|
1381
|
-
return floor(entry.startTime);
|
1435
|
+
return floor(entry.startTime - getZeroTime());
|
1382
1436
|
}
|
1383
1437
|
}
|
1384
1438
|
return undefined;
|
@@ -1389,7 +1443,7 @@
|
|
1389
1443
|
if (lcpEntries.length) {
|
1390
1444
|
var lastEntry = lcpEntries[lcpEntries.length - 1];
|
1391
1445
|
logger.logEvent(LogEvent.PerformanceEntryProcessed, [lastEntry]);
|
1392
|
-
return floor(lastEntry.startTime);
|
1446
|
+
return floor(lastEntry.startTime - getZeroTime());
|
1393
1447
|
}
|
1394
1448
|
return undefined;
|
1395
1449
|
}
|
@@ -1402,7 +1456,7 @@
|
|
1402
1456
|
if (paintEntries.length) {
|
1403
1457
|
// If the Paint Timing API is supported, use the value of the first paint event
|
1404
1458
|
var paintValues = paintEntries.map(function (entry) { return entry.startTime; });
|
1405
|
-
return floor(Math.min.apply(null, paintValues));
|
1459
|
+
return floor(Math.min.apply(null, paintValues) - getZeroTime());
|
1406
1460
|
}
|
1407
1461
|
}
|
1408
1462
|
if (performance.timing && timing.msFirstPaint && __ENABLE_POLYFILLS) {
|
@@ -1474,17 +1528,17 @@
|
|
1474
1528
|
}
|
1475
1529
|
function docHeight(doc) {
|
1476
1530
|
var body = doc.body, docelem = doc.documentElement;
|
1477
|
-
var height =
|
1531
|
+
var height = max(body ? body.scrollHeight : 0, body ? body.offsetHeight : 0, docelem ? docelem.clientHeight : 0, docelem ? docelem.scrollHeight : 0, docelem ? docelem.offsetHeight : 0);
|
1478
1532
|
return height;
|
1479
1533
|
}
|
1480
1534
|
function docWidth(doc) {
|
1481
1535
|
var body = doc.body, docelem = doc.documentElement;
|
1482
|
-
var width =
|
1536
|
+
var width = max(body ? body.scrollWidth : 0, body ? body.offsetWidth : 0, docelem ? docelem.clientWidth : 0, docelem ? docelem.scrollWidth : 0, docelem ? docelem.offsetWidth : 0);
|
1483
1537
|
return width;
|
1484
1538
|
}
|
1485
1539
|
// Return the main HTML document transfer size (in bytes).
|
1486
1540
|
function docSize() {
|
1487
|
-
return
|
1541
|
+
return getNavigationEntry().encodedBodySize || 0;
|
1488
1542
|
}
|
1489
1543
|
// Return the connection type based on Network Information API.
|
1490
1544
|
// Note this API is in flux.
|
@@ -1624,6 +1678,10 @@
|
|
1624
1678
|
// Beacon back the LUX data.
|
1625
1679
|
function _sendLux() {
|
1626
1680
|
var _a;
|
1681
|
+
if (!isVisible() && !globalConfig.trackHiddenPages) {
|
1682
|
+
logger.logEvent(LogEvent.SendCancelledPageHidden);
|
1683
|
+
return;
|
1684
|
+
}
|
1627
1685
|
clearMaxMeasureTimeout();
|
1628
1686
|
var customerid = getCustomerId();
|
1629
1687
|
if (!customerid ||
|
@@ -1663,6 +1721,15 @@
|
|
1663
1721
|
if (wasPrerendered()) {
|
1664
1722
|
gFlags = addFlag(gFlags, Flags.PageWasPrerendered);
|
1665
1723
|
}
|
1724
|
+
if (globalConfig.serverTiming) {
|
1725
|
+
var navEntry = getNavigationEntry();
|
1726
|
+
if (navEntry.serverTiming) {
|
1727
|
+
var stPairs = getKeyValuePairs(globalConfig.serverTiming, navEntry.serverTiming);
|
1728
|
+
for (var name_2 in stPairs) {
|
1729
|
+
_addData(name_2, stPairs[name_2]);
|
1730
|
+
}
|
1731
|
+
}
|
1732
|
+
}
|
1666
1733
|
if (LUX.conversions) {
|
1667
1734
|
getMatchesFromPatternMap(LUX.conversions, location.hostname, location.pathname).forEach(function (conversion) {
|
1668
1735
|
LUX.addData(conversion, BOOLEAN_TRUE);
|
@@ -1757,7 +1824,7 @@
|
|
1757
1824
|
var sIx = ixValues(); // Interaction Metrics
|
1758
1825
|
var INP = getINP();
|
1759
1826
|
if (sIx) {
|
1760
|
-
|
1827
|
+
var beaconUrl = _getBeaconUrl(getUpdatedCustomData()) +
|
1761
1828
|
"&IX=" +
|
1762
1829
|
sIx +
|
1763
1830
|
(typeof gFirstInputDelay !== "undefined" ? "&FID=" + gFirstInputDelay : "") +
|
@@ -2031,8 +2098,8 @@
|
|
2031
2098
|
setTimeout(sendBeaconAfterMinimumMeasureTime_1, timeRemaining);
|
2032
2099
|
}
|
2033
2100
|
};
|
2034
|
-
if (globalConfig.
|
2035
|
-
// The
|
2101
|
+
if (globalConfig.trackHiddenPages) {
|
2102
|
+
// The trackHiddenPages config forces the beacon to be sent even when the page is not visible.
|
2036
2103
|
sendBeaconAfterMinimumMeasureTime_1();
|
2037
2104
|
}
|
2038
2105
|
else {
|
@@ -2040,6 +2107,31 @@
|
|
2040
2107
|
onVisible(sendBeaconAfterMinimumMeasureTime_1);
|
2041
2108
|
}
|
2042
2109
|
}
|
2110
|
+
// When newBeaconOnPageShow = true, we initiate a new page view whenever a page is restored from
|
2111
|
+
// bfcache. Since we have no "onload" event to hook into after a bfcache restore, we rely on the
|
2112
|
+
// unload and maxMeasureTime handlers to send the beacon.
|
2113
|
+
if (globalConfig.newBeaconOnPageShow) {
|
2114
|
+
window.addEventListener("pageshow", function (event) {
|
2115
|
+
if (event.persisted) {
|
2116
|
+
// Record the timestamp of the bfcache restore
|
2117
|
+
pageRestoreTime = event.timeStamp;
|
2118
|
+
// In Chromium, document.visibilityState is still "hidden" when pageshow fires after a bfcache
|
2119
|
+
// restore. Wrapping this in a setTimeout ensures the browser has enough time to update the
|
2120
|
+
// visibility.
|
2121
|
+
// See https://bugs.chromium.org/p/chromium/issues/detail?id=1133363
|
2122
|
+
setTimeout(function () {
|
2123
|
+
if (gbLuxSent) {
|
2124
|
+
// If the beacon was already sent for this page, we start a new page view and mark the
|
2125
|
+
// load time as the time it took to restore the page.
|
2126
|
+
_init(pageRestoreTime);
|
2127
|
+
_markLoadTime();
|
2128
|
+
}
|
2129
|
+
// Flag the current page as a bfcache restore
|
2130
|
+
gFlags = addFlag(gFlags, Flags.PageWasBfCacheRestored);
|
2131
|
+
}, 0);
|
2132
|
+
}
|
2133
|
+
});
|
2134
|
+
}
|
2043
2135
|
// Add the unload handlers when sendBeaconOnPageHidden is enabled
|
2044
2136
|
if (globalConfig.sendBeaconOnPageHidden) {
|
2045
2137
|
_addUnloadHandlers();
|
@@ -8,10 +8,14 @@
|
|
8
8
|
}
|
9
9
|
|
10
10
|
.gem-c-document-list__item {
|
11
|
-
margin-
|
11
|
+
margin-top: govuk-spacing(5);
|
12
12
|
padding-top: govuk-spacing(2);
|
13
13
|
border-top: 1px solid $govuk-border-colour;
|
14
14
|
list-style: none;
|
15
|
+
|
16
|
+
&:first-child {
|
17
|
+
margin-top: 0;
|
18
|
+
}
|
15
19
|
}
|
16
20
|
|
17
21
|
.gem-c-document-list__item-title {
|
@@ -86,14 +90,6 @@
|
|
86
90
|
}
|
87
91
|
}
|
88
92
|
|
89
|
-
.gem-c-document-list--bottom-margin {
|
90
|
-
margin-bottom: govuk-spacing(4);
|
91
|
-
}
|
92
|
-
|
93
|
-
.gem-c-document-list--top-margin {
|
94
|
-
margin-top: govuk-spacing(4);
|
95
|
-
}
|
96
|
-
|
97
93
|
.gem-c-document-list__multi-list {
|
98
94
|
width: 100%;
|
99
95
|
margin-right: 25px;
|
@@ -9,6 +9,10 @@
|
|
9
9
|
height: govuk-spacing(2);
|
10
10
|
}
|
11
11
|
|
12
|
+
.gem-c-layout-for-public__blue-bar-wrapper--browse {
|
13
|
+
background-color: #263135;
|
14
|
+
}
|
15
|
+
|
12
16
|
.js-enabled .gem-c-layout-for-public__global-banner-wrapper {
|
13
17
|
margin-top: - govuk-spacing(2);
|
14
18
|
min-height: govuk-spacing(2);
|
@@ -40,11 +40,12 @@
|
|
40
40
|
ga4_link_data_attributes ||= nil
|
41
41
|
|
42
42
|
if ga4_tracking
|
43
|
+
heading_text = Nokogiri::HTML(item[:heading][:text]).text
|
43
44
|
item[:data_attributes] ||= {}
|
44
45
|
item[:data_attributes][:ga4_event] = {
|
45
46
|
event_name: "select_content",
|
46
47
|
type: "accordion",
|
47
|
-
text:
|
48
|
+
text: heading_text,
|
48
49
|
index: {
|
49
50
|
index_section: index,
|
50
51
|
index_section_count: items.length,
|
@@ -56,12 +57,12 @@
|
|
56
57
|
# tracking attributes
|
57
58
|
ga4_link_data_attributes = {}
|
58
59
|
ga4_link_data_attributes[:module] = "ga4-link-tracker"
|
59
|
-
ga4_link_data_attributes[:
|
60
|
+
ga4_link_data_attributes[:ga4_track_links_only] = ""
|
60
61
|
ga4_link_data_attributes[:ga4_set_indexes] = ""
|
61
62
|
ga4_link_data_attributes[:ga4_link] = {
|
62
63
|
event_name: "navigation",
|
63
64
|
type: "accordion",
|
64
|
-
section:
|
65
|
+
section: heading_text,
|
65
66
|
index: {
|
66
67
|
index_section: index,
|
67
68
|
index_section_count: (items.length),
|
@@ -1,14 +1,15 @@
|
|
1
1
|
<%
|
2
2
|
add_gem_component_stylesheet("document-list")
|
3
3
|
|
4
|
+
local_assigns[:margin_bottom] ||= 5
|
5
|
+
shared_helper = GovukPublishingComponents::Presenters::SharedHelper.new(local_assigns)
|
4
6
|
items ||= []
|
5
7
|
|
6
|
-
classes =
|
7
|
-
classes << "
|
8
|
-
classes << "
|
9
|
-
classes << "
|
10
|
-
classes <<
|
11
|
-
classes << " gem-c-document-list--no-top-border-first-child" if local_assigns[:remove_top_border_from_first_child]
|
8
|
+
classes = %w[gem-c-document-list]
|
9
|
+
classes << "gem-c-document-list--no-underline" if local_assigns[:remove_underline]
|
10
|
+
classes << "gem-c-document-list--no-top-border" if local_assigns[:remove_top_border]
|
11
|
+
classes << "gem-c-document-list--no-top-border-first-child" if local_assigns[:remove_top_border_from_first_child]
|
12
|
+
classes << shared_helper.get_margin_bottom
|
12
13
|
|
13
14
|
within_multitype_list ||= false
|
14
15
|
within_multitype_list_class = " gem-c-document-list__multi-list" if within_multitype_list
|
@@ -19,7 +20,7 @@
|
|
19
20
|
%>
|
20
21
|
<% if items.any? %>
|
21
22
|
<% unless within_multitype_list %>
|
22
|
-
<ul class="<%= classes %>">
|
23
|
+
<ul class="<%= classes.join(" ") %>">
|
23
24
|
<% end %>
|
24
25
|
<% items.each do |item| %>
|
25
26
|
<% highlight_class = " gem-c-document-list__item--highlight" if item[:highlight] %>
|
@@ -3,9 +3,11 @@
|
|
3
3
|
|
4
4
|
emergency_banner ||= nil
|
5
5
|
full_width ||= false
|
6
|
+
blue_bar ||= local_assigns.include?(:blue_bar) ? local_assigns[:blue_bar] : !full_width
|
6
7
|
global_bar ||= nil
|
7
8
|
html_lang ||= "en"
|
8
9
|
layout_helper = GovukPublishingComponents::Presenters::PublicLayoutHelper.new(local_assigns)
|
10
|
+
blue_bar_background_colour = layout_helper.blue_bar_background_colours.include?(blue_bar_background_colour) ? blue_bar_background_colour : nil
|
9
11
|
logo_link ||= "/"
|
10
12
|
navigation_items ||= []
|
11
13
|
omit_feedback_form ||= false
|
@@ -44,6 +46,9 @@
|
|
44
46
|
blue_bar_dedupe = !full_width && global_bar.present?
|
45
47
|
body_css_classes = %w(gem-c-layout-for-public govuk-template__body)
|
46
48
|
body_css_classes << "draft" if draft_watermark
|
49
|
+
|
50
|
+
blue_bar_wrapper_classes = %w()
|
51
|
+
blue_bar_wrapper_classes << "gem-c-layout-for-public__blue-bar-wrapper--#{blue_bar_background_colour}" if blue_bar_background_colour
|
47
52
|
-%>
|
48
53
|
<!DOCTYPE html>
|
49
54
|
<!--[if lt IE 9]><html class="lte-ie8 govuk-template" lang="<%= html_lang %>"><![endif]-->
|
@@ -117,8 +122,10 @@
|
|
117
122
|
|
118
123
|
<%= raw(emergency_banner) %>
|
119
124
|
|
120
|
-
<%
|
121
|
-
|
125
|
+
<% if (blue_bar && !global_bar.present?) || (blue_bar_dedupe) %>
|
126
|
+
<%= content_tag(:div, class: blue_bar_wrapper_classes) do %>
|
127
|
+
<div class="gem-c-layout-for-public__blue-bar govuk-width-container"></div>
|
128
|
+
<% end %>
|
122
129
|
<% end %>
|
123
130
|
|
124
131
|
<% if global_bar.present? %>
|
@@ -20,6 +20,11 @@
|
|
20
20
|
classes << shared_helper.get_margin_bottom if local_assigns[:margin_bottom]
|
21
21
|
|
22
22
|
ga4_tracking ||= false
|
23
|
+
ga4_object = {
|
24
|
+
event_name: "navigation",
|
25
|
+
type: "content",
|
26
|
+
section: "Top"
|
27
|
+
}.to_json
|
23
28
|
%>
|
24
29
|
<%= content_tag :div, class: classes, data: { module: "gem-toggle metadata" } do %>
|
25
30
|
<dl class="gem-c-metadata__list" data-module="gem-track-click">
|
@@ -48,19 +53,15 @@
|
|
48
53
|
<dd class="gem-c-metadata__definition">
|
49
54
|
<%= last_updated %>
|
50
55
|
<% if local_assigns.include?(:see_updates_link) %>
|
51
|
-
— <a href="#full-publication-update-history"
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
section: "Top"
|
61
|
-
}.to_json %>"
|
62
|
-
<% end%>
|
63
|
-
>
|
56
|
+
— <a href="#full-publication-update-history"
|
57
|
+
class="gem-c-metadata__definition-link govuk-!-display-none-print js-see-all-updates-link"
|
58
|
+
data-track-category="content-history"
|
59
|
+
data-track-action="see-all-updates-link-clicked"
|
60
|
+
data-track-label="history"
|
61
|
+
<% if ga4_tracking %>
|
62
|
+
data-module="ga4-link-tracker"
|
63
|
+
data-ga4-link="<%= ga4_object %>"
|
64
|
+
<% end%>>
|
64
65
|
<%= t("components.metadata.see_all_updates") %>
|
65
66
|
</a>
|
66
67
|
<% end %>
|
@@ -74,7 +75,12 @@
|
|
74
75
|
%>
|
75
76
|
<% if definition.any? %>
|
76
77
|
<dt class="gem-c-metadata__term"><%= title %>:</dt>
|
77
|
-
<dd class="gem-c-metadata__definition"
|
78
|
+
<dd class="gem-c-metadata__definition"
|
79
|
+
<% if ga4_tracking %>
|
80
|
+
data-module="ga4-link-tracker"
|
81
|
+
data-ga4-track-links-only
|
82
|
+
data-ga4-link="<%= ga4_object %>"
|
83
|
+
<% end%>>
|
78
84
|
<%= render 'govuk_publishing_components/components/metadata/sentence', items: definition, toggle_id: "#{index}-#{SecureRandom.hex(4)}" %>
|
79
85
|
</dd>
|
80
86
|
<% end %>
|
data/app/views/govuk_publishing_components/components/_single_page_notification_button.html.erb
CHANGED
@@ -1,25 +1,37 @@
|
|
1
1
|
<%
|
2
2
|
add_gem_component_stylesheet("single-page-notification-button")
|
3
3
|
|
4
|
-
|
4
|
+
spnb_helper = GovukPublishingComponents::Presenters::SinglePageNotificationButtonHelper.new(local_assigns)
|
5
5
|
shared_helper = GovukPublishingComponents::Presenters::SharedHelper.new(local_assigns)
|
6
|
+
component_helper = GovukPublishingComponents::Presenters::ComponentWrapperHelper.new(local_assigns)
|
6
7
|
|
7
8
|
wrapper_classes = %w(govuk-!-display-none-print)
|
8
9
|
wrapper_classes << shared_helper.get_margin_bottom
|
10
|
+
|
11
|
+
ga4_data_attributes = ga4_data_attributes ||= nil
|
12
|
+
ga4_link_data_attributes = ga4_data_attributes[:ga4_link] if ga4_data_attributes
|
13
|
+
ga4_link_data_attributes[:url] = spnb_helper.form_action if ga4_link_data_attributes
|
14
|
+
|
15
|
+
component_helper.add_class(wrapper_classes.join(" "))
|
16
|
+
component_helper.add_data_attribute({ module: "gem-track-click" })
|
17
|
+
component_helper.add_data_attribute({ module: ga4_data_attributes[:module] }) if ga4_data_attributes
|
9
18
|
%>
|
10
19
|
<% button_text = capture do %>
|
11
|
-
<svg class="gem-c-single-page-notification-button__icon" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" height="18" width="18" viewBox="0 0 459.334 459.334"><path fill="currentColor" d="M177.216 404.514c-.001.12-.009.239-.009.359 0 30.078 24.383 54.461 54.461 54.461s54.461-24.383 54.461-54.461c0-.12-.008-.239-.009-.359H175.216zM403.549 336.438l-49.015-72.002v-89.83c0-60.581-43.144-111.079-100.381-122.459V24.485C254.152 10.963 243.19 0 229.667 0s-24.485 10.963-24.485 24.485v27.663c-57.237 11.381-100.381 61.879-100.381 122.459v89.83l-49.015 72.002a24.76 24.76 0 0 0 20.468 38.693H383.08a24.761 24.761 0 0 0 20.469-38.694z"/></svg><span class="gem-c-single-page-notication-button__text"><%=
|
20
|
+
<svg class="gem-c-single-page-notification-button__icon" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" height="18" width="18" viewBox="0 0 459.334 459.334"><path fill="currentColor" d="M177.216 404.514c-.001.12-.009.239-.009.359 0 30.078 24.383 54.461 54.461 54.461s54.461-24.383 54.461-54.461c0-.12-.008-.239-.009-.359H175.216zM403.549 336.438l-49.015-72.002v-89.83c0-60.581-43.144-111.079-100.381-122.459V24.485C254.152 10.963 243.19 0 229.667 0s-24.485 10.963-24.485 24.485v27.663c-57.237 11.381-100.381 61.879-100.381 122.459v89.83l-49.015 72.002a24.76 24.76 0 0 0 20.468 38.693H383.08a24.761 24.761 0 0 0 20.469-38.694z"/></svg><span class="gem-c-single-page-notication-button__text"><%= spnb_helper.button_text %></span>
|
12
21
|
<% end %>
|
13
|
-
<%= tag.div
|
14
|
-
<%= tag.form class:
|
15
|
-
<input type="hidden" name="base_path" value="<%=
|
16
|
-
<% if
|
17
|
-
<input type="hidden" name="<%=
|
18
|
-
<input type="hidden" name="link" value="<%=
|
22
|
+
<%= tag.div(**component_helper.all_attributes) do %>
|
23
|
+
<%= tag.form class: spnb_helper.classes, action: spnb_helper.form_action, method: "POST", data: spnb_helper.data do %>
|
24
|
+
<input type="hidden" name="base_path" value="<%= spnb_helper.base_path %>">
|
25
|
+
<% if spnb_helper.skip_the_gov_uk_account? %>
|
26
|
+
<input type="hidden" name="<%= spnb_helper.skip_account_param %>" value="true">
|
27
|
+
<input type="hidden" name="link" value="<%= spnb_helper.base_path %>">
|
19
28
|
<% end %>
|
20
29
|
<%= content_tag(:button, button_text, {
|
21
30
|
class: "govuk-body-s gem-c-single-page-notification-button__submit",
|
22
31
|
type: "submit",
|
32
|
+
data: {
|
33
|
+
ga4_link: ga4_link_data_attributes
|
34
|
+
}
|
23
35
|
}) %>
|
24
36
|
<% end %>
|
25
|
-
<% end if
|
37
|
+
<% end if spnb_helper.base_path %>
|
@@ -26,7 +26,7 @@
|
|
26
26
|
<% if ga4_tracking
|
27
27
|
ga4_attributes = {
|
28
28
|
event_name: "navigation",
|
29
|
-
type: "
|
29
|
+
type: "part of",
|
30
30
|
index:{
|
31
31
|
"index_link": "1"
|
32
32
|
},
|
@@ -56,7 +56,7 @@
|
|
56
56
|
<% if ga4_tracking
|
57
57
|
ga4_attributes = {
|
58
58
|
event_name: "navigation",
|
59
|
-
type: "
|
59
|
+
type: "part of",
|
60
60
|
index:{
|
61
61
|
"index_link": (index + 1).to_s
|
62
62
|
},
|
@@ -37,6 +37,23 @@ examples:
|
|
37
37
|
metadata:
|
38
38
|
public_updated_at: 2016-09-05 16:48:27
|
39
39
|
document_type: 'Statutory guidance'
|
40
|
+
with_margin:
|
41
|
+
description: The component accepts a number for margin bottom from `0` to `9` (`0px` to `60px`) using the [GOV.UK Frontend spacing scale](https://design-system.service.gov.uk/styles/spacing/#the-responsive-spacing-scale). It defaults to having a margin bottom of 5 (25px).
|
42
|
+
data:
|
43
|
+
margin_bottom: 9
|
44
|
+
items:
|
45
|
+
- link:
|
46
|
+
text: 'Alternative provision'
|
47
|
+
path: '/government/publications/alternative-provision'
|
48
|
+
metadata:
|
49
|
+
public_updated_at: 2016-06-27 10:29:44
|
50
|
+
document_type: 'Statutory guidance'
|
51
|
+
- link:
|
52
|
+
text: 'Behaviour and discipline in schools: guide for governing bodies'
|
53
|
+
path: '/government/publications/behaviour-and-discipline-in-schools-guidance-for-governing-bodies'
|
54
|
+
metadata:
|
55
|
+
public_updated_at: 2015-09-24 16:42:48
|
56
|
+
document_type: 'Statutory guidance'
|
40
57
|
without_links:
|
41
58
|
data:
|
42
59
|
items:
|
@@ -27,6 +27,12 @@ examples:
|
|
27
27
|
description: This allows the header to be omitted which is currently used when rendering CSV previews from Whitehall
|
28
28
|
data:
|
29
29
|
omit_header: true
|
30
|
+
blue_bar_background:
|
31
|
+
description: For use when a page has a heading component with a background colour.
|
32
|
+
data:
|
33
|
+
full_width: true
|
34
|
+
blue_bar: true
|
35
|
+
blue_bar_background_colour: "no"
|
30
36
|
omit_feedback:
|
31
37
|
description: This allows the feedback form to be omitted
|
32
38
|
data:
|
@@ -35,7 +35,7 @@ examples:
|
|
35
35
|
title: 'Advisory Committee on Novel Foods and Processes has a <a href="http://www.food.gov.uk/acnfp">separate website</a>'
|
36
36
|
without_title:
|
37
37
|
data:
|
38
|
-
description_govspeak: '<p>Scheduled to publish at 8am on 25 April 2019
|
38
|
+
description_govspeak: '<p>Scheduled to publish at 8am on 25 April 2019</p><ul><li><a href="change-date">Change date</a></li><li><a href="stop-scheduled-publishing">Stop scheduled publishing</a></li></ul>'
|
39
39
|
with_aria_live:
|
40
40
|
description: Passing the aria live flag to the notice component will read the notice out to users if the notice changes, e.g on form submission the notice may go from hidden to visible.
|
41
41
|
data:
|
data/app/views/govuk_publishing_components/components/docs/single_page_notification_button.yml
CHANGED
@@ -25,6 +25,19 @@ examples:
|
|
25
25
|
base_path: '/current-page-path'
|
26
26
|
data_attributes:
|
27
27
|
test_attribute: "testing"
|
28
|
+
with_ga4_tracking:
|
29
|
+
description: To add GA4 tracking, pass a `ga4_data_attributes` object with the necessary properties to the component. For example:-
|
30
|
+
data:
|
31
|
+
base_path: '/current-page-path'
|
32
|
+
ga4_data_attributes:
|
33
|
+
module: "ga4-link-tracker"
|
34
|
+
ga4_link:
|
35
|
+
event_name: "navigation"
|
36
|
+
type: "subscribe"
|
37
|
+
index:
|
38
|
+
index_link: 1
|
39
|
+
index_total: 1
|
40
|
+
section: "Top"
|
28
41
|
with_margin_bottom:
|
29
42
|
description: |
|
30
43
|
The component accepts a number for margin bottom from `0` to `9` (`0px` to `60px`) using the [GOV.UK Frontend spacing scale](https://design-system.service.gov.uk/styles/spacing/#the-responsive-spacing-scale). It defaults to having a margin bottom of 15px.
|
@@ -1,6 +1,7 @@
|
|
1
1
|
module GovukPublishingComponents
|
2
2
|
module Presenters
|
3
3
|
class PublicLayoutHelper
|
4
|
+
BLUE_BAR_BACKGROUND_COLOURS = %w[browse].freeze
|
4
5
|
FOOTER_NAVIGATION_COLUMNS = [2, 1].freeze
|
5
6
|
FOOTER_TRACK_ACTIONS = %w[topicsLink governmentactivityLink].freeze
|
6
7
|
FOOTER_META = {
|
@@ -69,6 +70,10 @@ module GovukPublishingComponents
|
|
69
70
|
FOOTER_TRACK_ACTIONS
|
70
71
|
end
|
71
72
|
|
73
|
+
def blue_bar_background_colours
|
74
|
+
BLUE_BAR_BACKGROUND_COLOURS
|
75
|
+
end
|
76
|
+
|
72
77
|
def generate_data_attribute(link, track_action)
|
73
78
|
{
|
74
79
|
track_category: "footerClicked",
|
@@ -61,7 +61,11 @@ module GovukPublishingComponents
|
|
61
61
|
end
|
62
62
|
|
63
63
|
def form_action
|
64
|
-
|
64
|
+
if skip_the_gov_uk_account?
|
65
|
+
email_alert_frontend_endpoint_no_account
|
66
|
+
else
|
67
|
+
email_alert_frontend_endpoint_enforce_account
|
68
|
+
end
|
65
69
|
end
|
66
70
|
|
67
71
|
def email_alert_frontend_endpoint_enforce_account
|
@@ -75,6 +79,10 @@ module GovukPublishingComponents
|
|
75
79
|
def skip_account_param
|
76
80
|
"single_page_subscription"
|
77
81
|
end
|
82
|
+
|
83
|
+
def skip_the_gov_uk_account?
|
84
|
+
@skip_account == "true"
|
85
|
+
end
|
78
86
|
end
|
79
87
|
end
|
80
88
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: govuk_publishing_components
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 35.
|
4
|
+
version: 35.9.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- GOV.UK Dev
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-
|
11
|
+
date: 2023-07-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: govuk_app_config
|
@@ -1455,7 +1455,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
1455
1455
|
- !ruby/object:Gem::Version
|
1456
1456
|
version: '0'
|
1457
1457
|
requirements: []
|
1458
|
-
rubygems_version: 3.4.
|
1458
|
+
rubygems_version: 3.4.15
|
1459
1459
|
signing_key:
|
1460
1460
|
specification_version: 4
|
1461
1461
|
summary: A gem to document components in GOV.UK frontend applications
|