govuk_publishing_components 38.1.0 → 38.2.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.
- checksums.yaml +4 -4
- data/app/assets/images/govuk_publishing_components/crests/no10_crest_18px_x2.png +0 -0
- data/app/assets/javascripts/govuk_publishing_components/analytics-ga4/ga4-core.js +14 -7
- data/app/assets/javascripts/govuk_publishing_components/vendor/lux/lux-measurer.js +1 -1
- data/app/assets/javascripts/govuk_publishing_components/vendor/lux/lux-reporter.js +143 -84
- data/app/assets/stylesheets/govuk_publishing_components/components/_organisation-logo.scss +4 -0
- data/app/views/govuk_publishing_components/components/_layout_for_admin.html.erb +4 -2
- data/app/views/govuk_publishing_components/components/_layout_for_public.html.erb +5 -0
- data/app/views/govuk_publishing_components/components/docs/layout_for_admin.yml +18 -0
- data/app/views/govuk_publishing_components/components/docs/layout_for_public.yml +16 -0
- data/app/views/govuk_publishing_components/components/docs/organisation_logo.yml +9 -2
- data/lib/govuk_publishing_components/version.rb +1 -1
- metadata +4 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: '0386f2759bb8457478930df490b0744905dd8b044daffbdc9f4074e44c11f7a2'
|
4
|
+
data.tar.gz: b2892a04b8af279fc386deace44cde4adeea7119cd53d6276ca62b13bcdf01e4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 790aa1333fddc398174f120f056b8b3860e1eed354478b09dcae609c67330f0eecc567d39e94b12cdb349575360ccd0b8e535c53e26c54436057715615febb8c
|
7
|
+
data.tar.gz: 3b3759b84cb3b936f169494694fd4cd47db0ab834e60168dabfb286b3dae8e9139ff4d8cbe81aa9449ada1857943e9022ffc9025044dda3ca1ac84b20f0c0917
|
@@ -371,11 +371,6 @@ window.GOVUK.analyticsGa4 = window.GOVUK.analyticsGa4 || {};
|
|
371
371
|
}
|
372
372
|
} else {
|
373
373
|
for (var i = 0; i < items.length; i++) {
|
374
|
-
// GA4 limits us to 200 items, so we should limit the array to this size.
|
375
|
-
if (i === 200) {
|
376
|
-
break
|
377
|
-
}
|
378
|
-
|
379
374
|
var item = items[i]
|
380
375
|
var path = item.getAttribute('data-ga4-ecommerce-path')
|
381
376
|
|
@@ -385,16 +380,28 @@ window.GOVUK.analyticsGa4 = window.GOVUK.analyticsGa4 || {};
|
|
385
380
|
item.setAttribute('data-ga4-ecommerce-index', i + 1)
|
386
381
|
}
|
387
382
|
|
388
|
-
|
383
|
+
var nextItem = {
|
389
384
|
item_id: path,
|
390
385
|
item_content_id: item.getAttribute('data-ga4-ecommerce-content-id') || undefined,
|
391
386
|
item_list_name: listTitle,
|
392
387
|
index: window.GOVUK.analyticsGa4.core.ecommerceHelperFunctions.getIndex(item, startPosition)
|
393
|
-
}
|
388
|
+
}
|
389
|
+
|
390
|
+
// GA4 has a max payload, so ensure this array doesn't exceed 15,000 UTF-16 code units.
|
391
|
+
if ((this.getArraySize(ecommerceSchema.search_results.ecommerce.items) + this.getArraySize(nextItem)) >= 15000) {
|
392
|
+
break
|
393
|
+
}
|
394
|
+
|
395
|
+
ecommerceSchema.search_results.ecommerce.items.push(nextItem)
|
394
396
|
}
|
395
397
|
}
|
396
398
|
|
397
399
|
return ecommerceSchema
|
400
|
+
},
|
401
|
+
|
402
|
+
getArraySize: function (array) {
|
403
|
+
// .length represents the number of UTF-16 code units in a string, so we can stringify the array then grab the length of the string to get an 'accurate enough' number representing the size.
|
404
|
+
return JSON.stringify(array).length
|
398
405
|
}
|
399
406
|
}
|
400
407
|
}
|
@@ -46,6 +46,7 @@
|
|
46
46
|
auto: autoMode,
|
47
47
|
beaconUrl: getProperty(obj, "beaconUrl", luxOrigin + "/lux/"),
|
48
48
|
conversions: getProperty(obj, "conversions"),
|
49
|
+
cookieDomain: getProperty(obj, "cookieDomain"),
|
49
50
|
customerid: getProperty(obj, "customerid"),
|
50
51
|
errorBeaconUrl: getProperty(obj, "errorBeaconUrl", luxOrigin + "/error/"),
|
51
52
|
jspagelabel: getProperty(obj, "jspagelabel"),
|
@@ -120,6 +121,7 @@
|
|
120
121
|
return Math.floor(x);
|
121
122
|
}
|
122
123
|
var max = Math.max;
|
124
|
+
var round = Math.round;
|
123
125
|
/**
|
124
126
|
* Clamp a number so that it is never less than 0
|
125
127
|
*/
|
@@ -178,7 +180,7 @@
|
|
178
180
|
startTime: 0,
|
179
181
|
type: navType == 2 ? "back_forward" : navType === 1 ? "reload" : "navigate",
|
180
182
|
};
|
181
|
-
{
|
183
|
+
if (true) {
|
182
184
|
for (var key in timing) {
|
183
185
|
if (typeof timing[key] === "number" && key !== "navigationStart") {
|
184
186
|
entry[key] = floor(timing[key] - timing.navigationStart);
|
@@ -240,6 +242,66 @@
|
|
240
242
|
return getNavigationEntry().redirectCount > 0 || timing.redirectEnd > 0;
|
241
243
|
}
|
242
244
|
|
245
|
+
function getClosestScTrackAttribute(el) {
|
246
|
+
var _a;
|
247
|
+
if (el.hasAttribute("data-sctrack")) {
|
248
|
+
var trackId = (_a = el.getAttribute("data-sctrack")) === null || _a === void 0 ? void 0 : _a.trim();
|
249
|
+
if (trackId) {
|
250
|
+
return trackId;
|
251
|
+
}
|
252
|
+
}
|
253
|
+
if (hasParentNode(el)) {
|
254
|
+
return getClosestScTrackAttribute(el.parentNode);
|
255
|
+
}
|
256
|
+
return null;
|
257
|
+
}
|
258
|
+
|
259
|
+
function hasParentNode(el) {
|
260
|
+
if (el.parentNode && el.parentNode.tagName) {
|
261
|
+
return true;
|
262
|
+
}
|
263
|
+
return false;
|
264
|
+
}
|
265
|
+
var MAX_SELECTOR_LENGTH = 100;
|
266
|
+
function getNodeSelector(node, selector) {
|
267
|
+
if (selector === void 0) {
|
268
|
+
selector = "";
|
269
|
+
}
|
270
|
+
try {
|
271
|
+
if (selector && (node.nodeType === 9 || selector.length > MAX_SELECTOR_LENGTH || !node.parentNode)) {
|
272
|
+
// Final selector.
|
273
|
+
return selector;
|
274
|
+
}
|
275
|
+
var el = node;
|
276
|
+
// Our first preference is to use the data-sctrack attribute from anywhere in the tree
|
277
|
+
var trackId = getClosestScTrackAttribute(el);
|
278
|
+
if (trackId) {
|
279
|
+
return trackId;
|
280
|
+
}
|
281
|
+
if (el.id) {
|
282
|
+
// Once we've found an element with ID we return the selector.
|
283
|
+
return "#" + el.id + (selector ? ">" + selector : "");
|
284
|
+
}
|
285
|
+
else {
|
286
|
+
// Otherwise attempt to get parent elements recursively
|
287
|
+
var name_1 = el.nodeType === 1 ? el.nodeName.toLowerCase() : el.nodeName.toUpperCase();
|
288
|
+
var classes = el.className ? "." + el.className.replace(/\s+/g, ".") : "";
|
289
|
+
var currentSelector = name_1 + classes + (selector ? ">" + selector : "");
|
290
|
+
if (el.parentNode) {
|
291
|
+
var selectorWithParent = getNodeSelector(el.parentNode, currentSelector);
|
292
|
+
if (selectorWithParent.length < MAX_SELECTOR_LENGTH) {
|
293
|
+
return selectorWithParent;
|
294
|
+
}
|
295
|
+
}
|
296
|
+
return currentSelector;
|
297
|
+
}
|
298
|
+
}
|
299
|
+
catch (error) {
|
300
|
+
// Do nothing.
|
301
|
+
}
|
302
|
+
return selector;
|
303
|
+
}
|
304
|
+
|
243
305
|
var Flags = {
|
244
306
|
InitCalled: 1 << 0,
|
245
307
|
NavTimingNotSupported: 1 << 1,
|
@@ -258,56 +320,6 @@
|
|
258
320
|
return flags | flag;
|
259
321
|
}
|
260
322
|
|
261
|
-
function hasParentNode(el) {
|
262
|
-
if (el.parentNode && el.parentNode.tagName) {
|
263
|
-
return true;
|
264
|
-
}
|
265
|
-
return false;
|
266
|
-
}
|
267
|
-
|
268
|
-
/**
|
269
|
-
* Get the interaction attribution name for an element
|
270
|
-
*/
|
271
|
-
function interactionAttributionForElement(el) {
|
272
|
-
// Our first preference is to use the data-sctrack attribute from anywhere in the tree
|
273
|
-
var trackId = getClosestScTrackAttribute(el);
|
274
|
-
if (trackId) {
|
275
|
-
return trackId;
|
276
|
-
}
|
277
|
-
// The second preference is to use the element's ID
|
278
|
-
if (el.id) {
|
279
|
-
return el.id;
|
280
|
-
}
|
281
|
-
// The third preference is to use the text content of a button or link
|
282
|
-
var isSubmitInput = el.tagName === "INPUT" && el.type === "submit";
|
283
|
-
var isButton = el.tagName === "BUTTON";
|
284
|
-
var isLink = el.tagName === "A";
|
285
|
-
if (isSubmitInput && el.value) {
|
286
|
-
return el.value;
|
287
|
-
}
|
288
|
-
if ((isButton || isLink) && el.innerText) {
|
289
|
-
return el.innerText;
|
290
|
-
}
|
291
|
-
if (hasParentNode(el)) {
|
292
|
-
return interactionAttributionForElement(el.parentNode);
|
293
|
-
}
|
294
|
-
// No suitable attribute was found
|
295
|
-
return "";
|
296
|
-
}
|
297
|
-
function getClosestScTrackAttribute(el) {
|
298
|
-
var _a;
|
299
|
-
if (el.hasAttribute("data-sctrack")) {
|
300
|
-
var trackId = (_a = el.getAttribute("data-sctrack")) === null || _a === void 0 ? void 0 : _a.trim();
|
301
|
-
if (trackId) {
|
302
|
-
return trackId;
|
303
|
-
}
|
304
|
-
}
|
305
|
-
if (hasParentNode(el)) {
|
306
|
-
return getClosestScTrackAttribute(el.parentNode);
|
307
|
-
}
|
308
|
-
return null;
|
309
|
-
}
|
310
|
-
|
311
323
|
var LogEvent = {
|
312
324
|
// Internal events
|
313
325
|
EvaluationStart: 1,
|
@@ -358,7 +370,7 @@
|
|
358
370
|
return this.events;
|
359
371
|
};
|
360
372
|
return Logger;
|
361
|
-
}()
|
373
|
+
})();
|
362
374
|
|
363
375
|
var sessionValue = 0;
|
364
376
|
var sessionEntries = [];
|
@@ -406,14 +418,33 @@
|
|
406
418
|
}
|
407
419
|
function addEntry$1(entry) {
|
408
420
|
if (entry.interactionId || (entry.entryType === "first-input" && !entryExists(entry))) {
|
409
|
-
var duration = entry.duration,
|
421
|
+
var duration = entry.duration,
|
422
|
+
startTime = entry.startTime,
|
423
|
+
interactionId = entry.interactionId,
|
424
|
+
processingStart = entry.processingStart,
|
425
|
+
processingEnd = entry.processingEnd,
|
426
|
+
target = entry.target;
|
410
427
|
var existingEntry = slowestEntriesMap[interactionId];
|
428
|
+
var selector = target ? getNodeSelector(target) : null;
|
411
429
|
if (existingEntry) {
|
412
|
-
existingEntry.duration
|
430
|
+
if (existingEntry.duration < duration) {
|
431
|
+
existingEntry.duration = duration;
|
432
|
+
existingEntry.startTime = startTime;
|
433
|
+
existingEntry.processingStart = processingStart;
|
434
|
+
existingEntry.processingEnd = processingEnd;
|
435
|
+
existingEntry.selector = selector;
|
436
|
+
}
|
413
437
|
}
|
414
438
|
else {
|
415
439
|
interactionCountEstimate++;
|
416
|
-
slowestEntriesMap[interactionId] = {
|
440
|
+
slowestEntriesMap[interactionId] = {
|
441
|
+
duration: duration,
|
442
|
+
interactionId: interactionId,
|
443
|
+
startTime: startTime,
|
444
|
+
processingStart: processingStart,
|
445
|
+
processingEnd: processingEnd,
|
446
|
+
selector: selector,
|
447
|
+
};
|
417
448
|
slowestEntries.push(slowestEntriesMap[interactionId]);
|
418
449
|
}
|
419
450
|
// Only store the longest <MAX_INTERACTIONS> interactions
|
@@ -430,10 +461,9 @@
|
|
430
461
|
* Returns an estimated high percentile INP value based on the total number of interactions on the
|
431
462
|
* current page.
|
432
463
|
*/
|
433
|
-
function
|
434
|
-
var _a;
|
464
|
+
function getHighPercentileInteraction() {
|
435
465
|
var index = Math.min(slowestEntries.length - 1, Math.floor(getInteractionCount() / 50));
|
436
|
-
return
|
466
|
+
return slowestEntries[index];
|
437
467
|
}
|
438
468
|
function getInteractionCount() {
|
439
469
|
if ("interactionCount" in performance) {
|
@@ -547,7 +577,7 @@
|
|
547
577
|
// -------------------------------------------------------------------------
|
548
578
|
/// End
|
549
579
|
// -------------------------------------------------------------------------
|
550
|
-
var SCRIPT_VERSION = "
|
580
|
+
var SCRIPT_VERSION = "314";
|
551
581
|
var logger = new Logger();
|
552
582
|
var globalConfig = fromObject(LUX);
|
553
583
|
logger.logEvent(LogEvent.EvaluationStart, [SCRIPT_VERSION, globalConfig]);
|
@@ -661,7 +691,7 @@
|
|
661
691
|
*/
|
662
692
|
var getZeroTime = function () {
|
663
693
|
var _a;
|
664
|
-
return
|
694
|
+
return max(pageRestoreTime || 0, getNavigationEntry().activationStart, ((_a = _getMark(START_MARK)) === null || _a === void 0 ? void 0 : _a.startTime) || 0);
|
665
695
|
};
|
666
696
|
/**
|
667
697
|
* Most time-based metrics that LUX reports should be relative to the "zero" marker, rounded down
|
@@ -792,7 +822,7 @@
|
|
792
822
|
return performance.mark.apply(performance, args);
|
793
823
|
}
|
794
824
|
// ...Otherwise provide a polyfill
|
795
|
-
{
|
825
|
+
if (true) {
|
796
826
|
var name_1 = args[0];
|
797
827
|
var detail = ((_a = args[1]) === null || _a === void 0 ? void 0 : _a.detail) || null;
|
798
828
|
var startTime = ((_b = args[1]) === null || _b === void 0 ? void 0 : _b.startTime) || _now();
|
@@ -855,7 +885,7 @@
|
|
855
885
|
return performance.measure.apply(performance, args);
|
856
886
|
}
|
857
887
|
// ...Otherwise provide a polyfill
|
858
|
-
{
|
888
|
+
if (true) {
|
859
889
|
var navEntry = getNavigationEntry();
|
860
890
|
var startTime = typeof startMarkName === "number" ? startMarkName : 0;
|
861
891
|
var endTime = typeof endMarkName === "number" ? endMarkName : _now();
|
@@ -1123,7 +1153,7 @@
|
|
1123
1153
|
}
|
1124
1154
|
else {
|
1125
1155
|
// Return the average of the two middle values.
|
1126
|
-
return
|
1156
|
+
return round((aValues[half - 1] + aValues[half]) / 2.0);
|
1127
1157
|
}
|
1128
1158
|
}
|
1129
1159
|
// Track how long it took lux.js to load via Resource Timing.
|
@@ -1176,7 +1206,7 @@
|
|
1176
1206
|
function ixValues() {
|
1177
1207
|
var aIx = [];
|
1178
1208
|
for (var key in ghIx) {
|
1179
|
-
aIx.push(key + "|" + ghIx[key]);
|
1209
|
+
aIx.push(key + "|" + encodeURIComponent(ghIx[key]));
|
1180
1210
|
}
|
1181
1211
|
return aIx.join(",");
|
1182
1212
|
}
|
@@ -1288,7 +1318,7 @@
|
|
1288
1318
|
e.onloadcssdefined ||
|
1289
1319
|
"print" === e.media ||
|
1290
1320
|
"style" === e.as ||
|
1291
|
-
(typeof e.onload === "function" && e.media === "all"))
|
1321
|
+
(typeof e.onload === "function" && e.media === "all"));
|
1292
1322
|
else {
|
1293
1323
|
nBlocking++;
|
1294
1324
|
}
|
@@ -1492,11 +1522,31 @@
|
|
1492
1522
|
logger.logEvent(LogEvent.PaintTimingNotSupported);
|
1493
1523
|
return undefined;
|
1494
1524
|
}
|
1495
|
-
function
|
1525
|
+
function getINPDetails() {
|
1496
1526
|
if (!("PerformanceEventTiming" in self)) {
|
1497
1527
|
return undefined;
|
1498
1528
|
}
|
1499
|
-
return
|
1529
|
+
return getHighPercentileInteraction();
|
1530
|
+
}
|
1531
|
+
/**
|
1532
|
+
* Build the query string for the INP parameters:
|
1533
|
+
*
|
1534
|
+
* - INP: The duration of the P98 interaction
|
1535
|
+
* - INPs: The selector of the P98 interaction element
|
1536
|
+
* - INPt: The timestamp of the P98 interaction start time
|
1537
|
+
* - INPi: The input delay subpart of the P98 interaction
|
1538
|
+
* - INPp: The processing time subpart of the P98 interaction
|
1539
|
+
* - INPd: The presentation delay subpart of the P98 interaction
|
1540
|
+
*/
|
1541
|
+
function getINPString(details) {
|
1542
|
+
return [
|
1543
|
+
"&INP=" + details.duration,
|
1544
|
+
details.selector ? "&INPs=" + encodeURIComponent(details.selector) : "",
|
1545
|
+
"&INPt=" + clamp(floor(details.startTime)),
|
1546
|
+
"&INPi=" + clamp(floor(details.processingStart - details.startTime)),
|
1547
|
+
"&INPp=" + clamp(floor(details.processingEnd - details.processingStart)),
|
1548
|
+
"&INPd=" + clamp(floor(details.startTime + details.duration - details.processingEnd)),
|
1549
|
+
].join("");
|
1500
1550
|
}
|
1501
1551
|
function getCustomerId() {
|
1502
1552
|
return LUX.customerid || "";
|
@@ -1508,7 +1558,7 @@
|
|
1508
1558
|
while (i--) {
|
1509
1559
|
totalParents += numParents(aElems[i]);
|
1510
1560
|
}
|
1511
|
-
var average =
|
1561
|
+
var average = round(totalParents / aElems.length);
|
1512
1562
|
return average;
|
1513
1563
|
}
|
1514
1564
|
function numParents(elem) {
|
@@ -1607,7 +1657,7 @@
|
|
1607
1657
|
var vw = document.documentElement.clientWidth;
|
1608
1658
|
// Return true if the top-left corner is in the viewport and it has width & height.
|
1609
1659
|
var lt = findPos(e);
|
1610
|
-
return
|
1660
|
+
return lt[0] >= 0 && lt[1] >= 0 && lt[0] < vw && lt[1] < vh && e.offsetWidth > 0 && e.offsetHeight > 0;
|
1611
1661
|
}
|
1612
1662
|
// Return an array containing the top & left coordinates of the element.
|
1613
1663
|
// from http://www.quirksmode.org/js/findpos.html
|
@@ -1689,14 +1739,14 @@
|
|
1689
1739
|
_markLoadTime();
|
1690
1740
|
}
|
1691
1741
|
var sIx = "";
|
1692
|
-
var INP =
|
1693
|
-
//
|
1694
|
-
//
|
1695
|
-
// has not been sent.
|
1742
|
+
var INP = getINPDetails();
|
1743
|
+
// If we haven't already sent an interaction beacon, check for interaction metrics and include
|
1744
|
+
// them in the main beacon.
|
1696
1745
|
if (!gbIxSent) {
|
1697
1746
|
sIx = ixValues();
|
1698
1747
|
if (sIx === "") {
|
1699
|
-
// If there are no interaction metrics, we
|
1748
|
+
// If there are no interaction metrics, we wait to send INP with the IX beacon to increase
|
1749
|
+
// the chance that we capture a valid INP.
|
1700
1750
|
INP = undefined;
|
1701
1751
|
}
|
1702
1752
|
}
|
@@ -1766,13 +1816,14 @@
|
|
1766
1816
|
nErrors +
|
1767
1817
|
"nt" +
|
1768
1818
|
navigationType() +
|
1769
|
-
(navigator.deviceMemory ? "dm" +
|
1819
|
+
(navigator.deviceMemory ? "dm" + round(navigator.deviceMemory) : "") + // device memory (GB)
|
1770
1820
|
(sIx ? "&IX=" + sIx : "") +
|
1771
1821
|
(typeof gFirstInputDelay !== "undefined" ? "&FID=" + gFirstInputDelay : "") +
|
1772
1822
|
(sCPU ? "&CPU=" + sCPU : "") +
|
1773
1823
|
(sET ? "&ET=" + sET : "") + // element timing
|
1774
1824
|
(typeof CLS !== "undefined" ? "&CLS=" + CLS : "") +
|
1775
|
-
|
1825
|
+
// INP and sub-parts
|
1826
|
+
(typeof INP !== "undefined" ? getINPString(INP) : "");
|
1776
1827
|
// We add the user timing entries last so that we can split them to reduce the URL size if necessary.
|
1777
1828
|
var utValues = userTimingValues();
|
1778
1829
|
var _b = fitUserTimingEntries(utValues, globalConfig, baseUrl + metricsQueryString), beaconUtValues = _b[0], remainingUtValues = _b[1];
|
@@ -1788,7 +1839,7 @@
|
|
1788
1839
|
gbIxSent = sIx ? 1 : 0;
|
1789
1840
|
// Send other beacons for JUST User Timing.
|
1790
1841
|
while (remainingUtValues.length) {
|
1791
|
-
_a = fitUserTimingEntries(remainingUtValues, globalConfig, baseUrl), beaconUtValues = _a[0], remainingUtValues = _a[1];
|
1842
|
+
(_a = fitUserTimingEntries(remainingUtValues, globalConfig, baseUrl)), (beaconUtValues = _a[0]), (remainingUtValues = _a[1]);
|
1792
1843
|
var utBeaconUrl = baseUrl + "&UT=" + beaconUtValues.join(",");
|
1793
1844
|
logger.logEvent(LogEvent.UserTimingBeaconSent, [utBeaconUrl]);
|
1794
1845
|
_sendBeacon(utBeaconUrl);
|
@@ -1811,13 +1862,13 @@
|
|
1811
1862
|
return;
|
1812
1863
|
}
|
1813
1864
|
var sIx = ixValues(); // Interaction Metrics
|
1814
|
-
var INP =
|
1865
|
+
var INP = getINPDetails();
|
1815
1866
|
if (sIx) {
|
1816
1867
|
var beaconUrl = _getBeaconUrl(getUpdatedCustomData()) +
|
1817
1868
|
"&IX=" +
|
1818
1869
|
sIx +
|
1819
1870
|
(typeof gFirstInputDelay !== "undefined" ? "&FID=" + gFirstInputDelay : "") +
|
1820
|
-
(typeof INP !== "undefined" ?
|
1871
|
+
(typeof INP !== "undefined" ? getINPString(INP) : "");
|
1821
1872
|
logger.logEvent(LogEvent.InteractionBeaconSent, [beaconUrl]);
|
1822
1873
|
_sendBeacon(beaconUrl);
|
1823
1874
|
gbIxSent = 1;
|
@@ -1872,22 +1923,27 @@
|
|
1872
1923
|
if (keyCode === 16 || keyCode === 17 || keyCode === 18 || keyCode === 20 || keyCode === 224) {
|
1873
1924
|
return;
|
1874
1925
|
}
|
1875
|
-
_removeIxHandlers();
|
1876
1926
|
if (typeof ghIx["k"] === "undefined") {
|
1877
1927
|
ghIx["k"] = _now();
|
1878
1928
|
if (e && e.target instanceof Element) {
|
1879
|
-
var trackId =
|
1929
|
+
var trackId = getNodeSelector(e.target);
|
1880
1930
|
if (trackId) {
|
1881
1931
|
ghIx["ki"] = trackId;
|
1882
1932
|
}
|
1883
1933
|
}
|
1934
|
+
// Only one interaction type is recorded. Scrolls are considered less important, so delete
|
1935
|
+
// any scroll times if they exist.
|
1936
|
+
delete ghIx["s"];
|
1884
1937
|
_sendIxAfterDelay();
|
1885
1938
|
}
|
1939
|
+
_removeIxHandlers();
|
1886
1940
|
}
|
1887
1941
|
function _clickHandler(e) {
|
1888
|
-
_removeIxHandlers();
|
1889
1942
|
if (typeof ghIx["c"] === "undefined") {
|
1890
1943
|
ghIx["c"] = _now();
|
1944
|
+
// Only one interaction type is recorded. Scrolls are considered less important, so delete
|
1945
|
+
// any scroll times if they exist.
|
1946
|
+
delete ghIx["s"];
|
1891
1947
|
var target = void 0;
|
1892
1948
|
try {
|
1893
1949
|
// Seeing "Permission denied" errors, so do a simple try-catch.
|
@@ -1904,13 +1960,14 @@
|
|
1904
1960
|
ghIx["cx"] = e.clientX;
|
1905
1961
|
ghIx["cy"] = e.clientY;
|
1906
1962
|
}
|
1907
|
-
var trackId =
|
1963
|
+
var trackId = getNodeSelector(target);
|
1908
1964
|
if (trackId) {
|
1909
1965
|
ghIx["ci"] = trackId;
|
1910
1966
|
}
|
1911
1967
|
}
|
1912
1968
|
_sendIxAfterDelay();
|
1913
1969
|
}
|
1970
|
+
_removeIxHandlers();
|
1914
1971
|
}
|
1915
1972
|
// Wrapper to support older browsers (<= IE8)
|
1916
1973
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
@@ -1976,7 +2033,7 @@
|
|
1976
2033
|
// "00" matches all sample rates
|
1977
2034
|
return Number(new Date()) + "00000";
|
1978
2035
|
}
|
1979
|
-
return Number(new Date()) + _padLeft(String(
|
2036
|
+
return Number(new Date()) + _padLeft(String(round(100000 * Math.random())), "00000");
|
1980
2037
|
}
|
1981
2038
|
// Unique ID (also known as Session ID)
|
1982
2039
|
// We use this to track all the page views in a single user session.
|
@@ -2063,6 +2120,8 @@
|
|
2063
2120
|
"=" +
|
2064
2121
|
escape(value) +
|
2065
2122
|
(seconds ? "; max-age=" + seconds : "") +
|
2123
|
+
(globalConfig.cookieDomain ? "; domain=" +
|
2124
|
+
globalConfig.cookieDomain : "") +
|
2066
2125
|
"; path=/; SameSite=Lax";
|
2067
2126
|
}
|
2068
2127
|
catch (e) {
|
@@ -104,6 +104,10 @@
|
|
104
104
|
@include tall-crest;
|
105
105
|
}
|
106
106
|
|
107
|
+
.gem-c-organisation-logo__crest--no10 {
|
108
|
+
@include crest("no10_crest", $xpos: 8px);
|
109
|
+
}
|
110
|
+
|
107
111
|
.gem-c-organisation-logo__crest--single-identity,
|
108
112
|
.gem-c-organisation-logo__crest--eo,
|
109
113
|
.gem-c-organisation-logo__crest--org {
|
@@ -1,5 +1,7 @@
|
|
1
1
|
<%
|
2
2
|
add_gem_component_stylesheet("layout-for-admin")
|
3
|
+
js_filename ||= "application"
|
4
|
+
css_filename ||= "application"
|
3
5
|
|
4
6
|
product_name ||= "Publishing"
|
5
7
|
%>
|
@@ -13,7 +15,7 @@
|
|
13
15
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
14
16
|
<%= csrf_meta_tags %>
|
15
17
|
<%= favicon_link_tag "govuk_publishing_components/favicon-#{environment}.png" %>
|
16
|
-
<%= stylesheet_link_tag
|
18
|
+
<%= stylesheet_link_tag css_filename, media: "all" %>
|
17
19
|
<%= javascript_include_tag "govuk_publishing_components/vendor/modernizr" %>
|
18
20
|
<%= yield :head %>
|
19
21
|
</head>
|
@@ -22,6 +24,6 @@
|
|
22
24
|
document.body.className += ' js-enabled' + ('noModule' in HTMLScriptElement.prototype ? ' govuk-frontend-supported' : '');
|
23
25
|
<% end -%>
|
24
26
|
<%= yield %>
|
25
|
-
<%= javascript_include_tag
|
27
|
+
<%= javascript_include_tag js_filename %>
|
26
28
|
</body>
|
27
29
|
</html>
|
@@ -17,6 +17,7 @@
|
|
17
17
|
omit_footer_navigation ||= false
|
18
18
|
omit_footer_border ||= false
|
19
19
|
omit_header ||= false
|
20
|
+
custom_layout ||= false
|
20
21
|
product_name ||= nil
|
21
22
|
show_explore_header ||= false
|
22
23
|
show_cross_service_header ||= false
|
@@ -120,6 +121,8 @@
|
|
120
121
|
service_navigation_items: service_navigation_items,
|
121
122
|
product_name: product_name,
|
122
123
|
} %>
|
124
|
+
<% elsif content_for?(:custom_header) %>
|
125
|
+
<%= yield :custom_header %>
|
123
126
|
<% else %>
|
124
127
|
<%= render "govuk_publishing_components/components/layout_header", {
|
125
128
|
search: show_search,
|
@@ -159,6 +162,8 @@
|
|
159
162
|
<%= yield :before_content %>
|
160
163
|
<%= yield %>
|
161
164
|
<% end %>
|
165
|
+
<% elsif custom_layout %>
|
166
|
+
<%= yield %>
|
162
167
|
<% else %>
|
163
168
|
<div id="wrapper" class="<%= "govuk-width-container" unless full_width %>">
|
164
169
|
<%= yield :before_content %>
|
@@ -23,3 +23,21 @@ examples:
|
|
23
23
|
browser_title: 'A page title'
|
24
24
|
block: |
|
25
25
|
<!-- You probably want to use the header, main & footer components here -->
|
26
|
+
with_custom_js_filename:
|
27
|
+
description: An alternative JS filename can be used in place of the default `application.js` if required (note that this cannot easily be demonstrated here).
|
28
|
+
data:
|
29
|
+
environment: production
|
30
|
+
product_name: Publishing
|
31
|
+
browser_title: 'A page title'
|
32
|
+
js_filename: "application"
|
33
|
+
block: |
|
34
|
+
<!-- You probably want to use the header, main & footer components here -->
|
35
|
+
with_custom_css_filename:
|
36
|
+
description: An alternative JS filename can be used in place of the default `application.scss` if required (note that this cannot easily be demonstrated here).
|
37
|
+
data:
|
38
|
+
environment: production
|
39
|
+
product_name: Publishing
|
40
|
+
browser_title: 'A page title'
|
41
|
+
css_filename: "application"
|
42
|
+
block: |
|
43
|
+
<!-- You probably want to use the header, main & footer components here -->
|
@@ -123,3 +123,19 @@ examples:
|
|
123
123
|
cookie_preferences:
|
124
124
|
text: How GOV.UK accounts use cookies
|
125
125
|
href: https://www.gov.uk/government/publications/govuk-accounts-trial-full-privacy-notice-and-accessibility-statement
|
126
|
+
with_custom_layout:
|
127
|
+
description: Yields a custom layout for the content.
|
128
|
+
data:
|
129
|
+
custom_layout: true
|
130
|
+
block: |
|
131
|
+
<main id="custom-layout">
|
132
|
+
<h1>This is a custom layout</h1>
|
133
|
+
</main>
|
134
|
+
with_custom_header:
|
135
|
+
description: Allows the header to be replaced with HTML injected by the calling application in a `content_for` tag named `:custom_header`.
|
136
|
+
embed: |
|
137
|
+
<% content_for(:custom_header) do %>
|
138
|
+
<header id="custom-header">I'm a custom header</header>
|
139
|
+
<% end %>
|
140
|
+
<%= render "govuk_publishing_components/components/layout_for_public", {
|
141
|
+
} %>
|
@@ -51,8 +51,8 @@ examples:
|
|
51
51
|
executive_office:
|
52
52
|
data:
|
53
53
|
organisation:
|
54
|
-
name:
|
55
|
-
url: '/government/organisations/
|
54
|
+
name: Example
|
55
|
+
url: '/government/organisations/'
|
56
56
|
brand: 'executive-office'
|
57
57
|
crest: 'eo'
|
58
58
|
home_office:
|
@@ -69,6 +69,13 @@ examples:
|
|
69
69
|
url: '/government/organisations/ministry-of-defence'
|
70
70
|
brand: 'ministry-of-defence'
|
71
71
|
crest: 'mod'
|
72
|
+
prime_ministers_office_10_downing_street:
|
73
|
+
data:
|
74
|
+
organisation:
|
75
|
+
name: "Prime Minister's Office,<br>10 Downing Street"
|
76
|
+
url: '/government/organisations/prime-ministers-office-10-downing-street'
|
77
|
+
brand: 'prime-ministers-office-10-downing-street'
|
78
|
+
crest: 'no10'
|
72
79
|
office_of_the_advocate_general_for_scotland:
|
73
80
|
data:
|
74
81
|
organisation:
|
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: 38.
|
4
|
+
version: 38.2.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: 2024-
|
11
|
+
date: 2024-05-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: govuk_app_config
|
@@ -373,6 +373,7 @@ files:
|
|
373
373
|
- app/assets/images/govuk_publishing_components/crests/hmrc_crest_18px_x2.png
|
374
374
|
- app/assets/images/govuk_publishing_components/crests/ho_crest_18px_x2.png
|
375
375
|
- app/assets/images/govuk_publishing_components/crests/mod_crest_18px_x2.png
|
376
|
+
- app/assets/images/govuk_publishing_components/crests/no10_crest_18px_x2.png
|
376
377
|
- app/assets/images/govuk_publishing_components/crests/org_crest_18px_x2.png
|
377
378
|
- app/assets/images/govuk_publishing_components/crests/portcullis_18px_x2.png
|
378
379
|
- app/assets/images/govuk_publishing_components/crests/so_crest_18px_x2.png
|
@@ -1599,7 +1600,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
1599
1600
|
- !ruby/object:Gem::Version
|
1600
1601
|
version: '0'
|
1601
1602
|
requirements: []
|
1602
|
-
rubygems_version: 3.5.
|
1603
|
+
rubygems_version: 3.5.10
|
1603
1604
|
signing_key:
|
1604
1605
|
specification_version: 4
|
1605
1606
|
summary: A gem to document components in GOV.UK frontend applications
|