govuk_publishing_components 35.15.0 → 35.15.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.
- checksums.yaml +4 -4
- data/app/assets/javascripts/govuk_publishing_components/vendor/lux/lux-reporter.js +327 -321
- data/app/assets/stylesheets/govuk_publishing_components/components/_accordion.scss +6 -0
- data/app/assets/stylesheets/govuk_publishing_components/components/_govspeak.scss +6 -0
- data/app/views/govuk_publishing_components/components/_attachment.html.erb +2 -1
- data/app/views/govuk_publishing_components/components/layout_for_public/_account-layout.html.erb +1 -0
- data/lib/govuk_publishing_components/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5edbe2c7a347d6bc8069704f3434dc4c41de45b3286f7640893f7ff8f62c25a8
|
4
|
+
data.tar.gz: d17f853fdf1a5598b808a69fdec621da35aa8662bc911d5c951715cc53bfb6a0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0f5f8a3a9706d98e11ce756987eb9dc442dce2c3701eeb2dbfe8ff2ad48c6c48d27c0c8f056b9e3f851d53d4c6cfb1712c042f9699a658fad94618d679b6c974
|
7
|
+
data.tar.gz: fc1469502870ba2a479cde17f7d8edc652270a3ce98efd2aa6128797634e484bf6448cb54712f4c12c116a4f9275d345cb39ffdf13901bde137fc80321769657
|
@@ -21,33 +21,34 @@
|
|
21
21
|
|
22
22
|
(function () {
|
23
23
|
'use strict';
|
24
|
+
|
24
25
|
/**
|
25
|
-
|
26
|
-
|
27
|
-
|
26
|
+
* Fit an array of user timing delimited strings into a URL and return both the entries that fit and
|
27
|
+
* the remaining entries that didn't fit.
|
28
|
+
*/
|
28
29
|
function fitUserTimingEntries(utValues, config, url) {
|
29
30
|
// Start with the maximum allowed UT entries per beacon
|
30
31
|
var beaconUtValues = utValues.slice(0, config.maxBeaconUTEntries);
|
31
32
|
var remainingUtValues = utValues.slice(config.maxBeaconUTEntries);
|
32
33
|
// Trim UT entries until they fit within the maximum URL length, ensuring at least one UT entry
|
33
34
|
// is included.
|
34
|
-
while ((url + "&UT=" + beaconUtValues.join(",")).length > config.maxBeaconUrlLength &&
|
35
|
-
beaconUtValues.length > 1) {
|
35
|
+
while ((url + "&UT=" + beaconUtValues.join(",")).length > config.maxBeaconUrlLength && beaconUtValues.length > 1) {
|
36
36
|
remainingUtValues.unshift(beaconUtValues.pop());
|
37
37
|
}
|
38
38
|
return [beaconUtValues, remainingUtValues];
|
39
39
|
}
|
40
40
|
|
41
|
+
var luxOrigin = "https://lux.speedcurve.com";
|
41
42
|
function fromObject(obj) {
|
42
43
|
var autoMode = getProperty(obj, "auto", true);
|
43
44
|
return {
|
44
45
|
auto: autoMode,
|
45
|
-
beaconUrl: getProperty(obj, "beaconUrl", "
|
46
|
-
conversions: getProperty(obj, "conversions"
|
47
|
-
customerid: getProperty(obj, "customerid"
|
48
|
-
errorBeaconUrl: getProperty(obj, "errorBeaconUrl", "
|
49
|
-
jspagelabel: getProperty(obj, "jspagelabel"
|
50
|
-
label: getProperty(obj, "label"
|
46
|
+
beaconUrl: getProperty(obj, "beaconUrl", luxOrigin + "/lux/"),
|
47
|
+
conversions: getProperty(obj, "conversions"),
|
48
|
+
customerid: getProperty(obj, "customerid"),
|
49
|
+
errorBeaconUrl: getProperty(obj, "errorBeaconUrl", luxOrigin + "/error/"),
|
50
|
+
jspagelabel: getProperty(obj, "jspagelabel"),
|
51
|
+
label: getProperty(obj, "label"),
|
51
52
|
maxBeaconUrlLength: getProperty(obj, "maxBeaconUrlLength", 8190),
|
52
53
|
maxBeaconUTEntries: getProperty(obj, "maxBeaconUTEntries", 20),
|
53
54
|
maxErrors: getProperty(obj, "maxErrors", 5),
|
@@ -56,10 +57,10 @@
|
|
56
57
|
newBeaconOnPageShow: getProperty(obj, "newBeaconOnPageShow", false),
|
57
58
|
samplerate: getProperty(obj, "samplerate", 100),
|
58
59
|
sendBeaconOnPageHidden: getProperty(obj, "sendBeaconOnPageHidden", autoMode),
|
59
|
-
serverTiming: getProperty(obj, "serverTiming"
|
60
|
+
serverTiming: getProperty(obj, "serverTiming"),
|
60
61
|
trackErrors: getProperty(obj, "trackErrors", true),
|
61
62
|
trackHiddenPages: getProperty(obj, "trackHiddenPages", false),
|
62
|
-
pagegroups: getProperty(obj, "pagegroups"
|
63
|
+
pagegroups: getProperty(obj, "pagegroups"),
|
63
64
|
};
|
64
65
|
}
|
65
66
|
function getProperty(obj, key, defaultValue) {
|
@@ -99,8 +100,8 @@
|
|
99
100
|
updatedCustomData = {};
|
100
101
|
}
|
101
102
|
/**
|
102
|
-
|
103
|
-
|
103
|
+
* Convert a set of custom data values to the string format expected by the backend.
|
104
|
+
*/
|
104
105
|
function valuesToString(values) {
|
105
106
|
var strings = [];
|
106
107
|
for (var key in values) {
|
@@ -119,11 +120,14 @@
|
|
119
120
|
}
|
120
121
|
var max = Math.max;
|
121
122
|
/**
|
122
|
-
|
123
|
-
|
123
|
+
* Clamp a number so that it is never less than 0
|
124
|
+
*/
|
124
125
|
function clamp(x) {
|
125
126
|
return max(0, x);
|
126
127
|
}
|
128
|
+
function sortNumeric(a, b) {
|
129
|
+
return a - b;
|
130
|
+
}
|
127
131
|
|
128
132
|
function now() {
|
129
133
|
return Date.now ? Date.now() : +new Date();
|
@@ -173,7 +177,7 @@
|
|
173
177
|
startTime: 0,
|
174
178
|
type: navType == 2 ? "back_forward" : navType === 1 ? "reload" : "navigate",
|
175
179
|
};
|
176
|
-
|
180
|
+
{
|
177
181
|
for (var key in timing) {
|
178
182
|
if (typeof timing[key] === "number" && key !== "navigationStart") {
|
179
183
|
entry[key] = floor(timing[key] - timing.navigationStart);
|
@@ -183,10 +187,10 @@
|
|
183
187
|
return entry;
|
184
188
|
}
|
185
189
|
/**
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
+
* Simple wrapper around performance.getEntriesByType to provide fallbacks for
|
191
|
+
* legacy browsers, and work around edge cases where undefined is returned instead
|
192
|
+
* of an empty PerformanceEntryList.
|
193
|
+
*/
|
190
194
|
function getEntriesByType(type) {
|
191
195
|
if (typeof performance.getEntriesByType === "function") {
|
192
196
|
var entries = performance.getEntriesByType(type);
|
@@ -245,7 +249,7 @@
|
|
245
249
|
PageLabelFromDocumentTitle: 1 << 6,
|
246
250
|
PageLabelFromLabelProp: 1 << 7,
|
247
251
|
PageLabelFromGlobalVariable: 1 << 8,
|
248
|
-
|
252
|
+
PageLabelFromUrlPattern: 1 << 9,
|
249
253
|
PageWasPrerendered: 1 << 10,
|
250
254
|
PageWasBfCacheRestored: 1 << 11,
|
251
255
|
};
|
@@ -261,8 +265,8 @@
|
|
261
265
|
}
|
262
266
|
|
263
267
|
/**
|
264
|
-
|
265
|
-
|
268
|
+
* Get the interaction attribution name for an element
|
269
|
+
*/
|
266
270
|
function interactionAttributionForElement(el) {
|
267
271
|
// Our first preference is to use the data-sctrack attribute from anywhere in the tree
|
268
272
|
var trackId = getClosestScTrackAttribute(el);
|
@@ -354,6 +358,7 @@
|
|
354
358
|
};
|
355
359
|
return Logger;
|
356
360
|
}());
|
361
|
+
|
357
362
|
var sessionValue = 0;
|
358
363
|
var sessionEntries = [];
|
359
364
|
var maximumSessionValue = 0;
|
@@ -363,9 +368,9 @@
|
|
363
368
|
var latestEntry = sessionEntries[sessionEntries.length - 1];
|
364
369
|
if (sessionEntries.length &&
|
365
370
|
(entry.startTime - latestEntry.startTime >= 1000 ||
|
366
|
-
|
367
|
-
|
368
|
-
|
371
|
+
entry.startTime - firstEntry.startTime >= 5000)) {
|
372
|
+
sessionValue = entry.value;
|
373
|
+
sessionEntries = [entry];
|
369
374
|
}
|
370
375
|
else {
|
371
376
|
sessionValue += entry.value;
|
@@ -384,9 +389,9 @@
|
|
384
389
|
}
|
385
390
|
|
386
391
|
/**
|
387
|
-
|
388
|
-
|
389
|
-
|
392
|
+
* This implementation is based on the web-vitals implementation, however it is stripped back to the
|
393
|
+
* bare minimum required to measure just the INP value and does not store the actual event entries.
|
394
|
+
*/
|
390
395
|
// The maximum number of interactions to store
|
391
396
|
var MAX_INTERACTIONS = 10;
|
392
397
|
// A list of the slowest interactions
|
@@ -423,9 +428,9 @@
|
|
423
428
|
return slowestEntries.some(function (e2) { return e1.startTime === e2.startTime && e1.duration === e2.duration; });
|
424
429
|
}
|
425
430
|
/**
|
426
|
-
|
427
|
-
|
428
|
-
|
431
|
+
* Returns an estimated high percentile INP value based on the total number of interactions on the
|
432
|
+
* current page.
|
433
|
+
*/
|
429
434
|
function getHighPercentileINP() {
|
430
435
|
var _a;
|
431
436
|
var index = Math.min(slowestEntries.length - 1, Math.floor(getInteractionCount() / 50));
|
@@ -440,8 +445,7 @@
|
|
440
445
|
|
441
446
|
var ALL_ENTRIES = [];
|
442
447
|
function observe(type, callback, options) {
|
443
|
-
if (typeof PerformanceObserver === "function" &&
|
444
|
-
PerformanceObserver.supportedEntryTypes.includes(type)) {
|
448
|
+
if (typeof PerformanceObserver === "function" && PerformanceObserver.supportedEntryTypes.includes(type)) {
|
445
449
|
var po = new PerformanceObserver(function (list) {
|
446
450
|
list.getEntries().forEach(function (entry) { return callback(entry); });
|
447
451
|
});
|
@@ -456,17 +460,14 @@
|
|
456
460
|
function addEntry(entry) {
|
457
461
|
ALL_ENTRIES.push(entry);
|
458
462
|
}
|
459
|
-
function clearEntries() {
|
460
|
-
ALL_ENTRIES.splice(0);
|
461
|
-
}
|
462
463
|
|
463
464
|
/**
|
464
|
-
|
465
|
-
|
465
|
+
* A server timing metric that has its value set to the duration field
|
466
|
+
*/
|
466
467
|
var TYPE_DURATION = "r";
|
467
468
|
/**
|
468
|
-
|
469
|
-
|
469
|
+
* When a description metric has no value, we consider it to be a boolean and set it to this value.
|
470
|
+
*/
|
470
471
|
var BOOLEAN_TRUE_VALUE = "true";
|
471
472
|
function getKeyValuePairs(config, serverTiming) {
|
472
473
|
var pairs = {};
|
@@ -500,7 +501,7 @@
|
|
500
501
|
if (Array.isArray(patterns)) {
|
501
502
|
for (var i in patterns) {
|
502
503
|
var pattern = patterns[i];
|
503
|
-
if (patternMatchesUrl(pattern, hostname, pathname)) {
|
504
|
+
if (typeof pattern === "string" && patternMatchesUrl(pattern, hostname, pathname)) {
|
504
505
|
if (firstOnly) {
|
505
506
|
return key;
|
506
507
|
}
|
@@ -542,10 +543,18 @@
|
|
542
543
|
// -------------------------------------------------------------------------
|
543
544
|
/// End
|
544
545
|
// -------------------------------------------------------------------------
|
545
|
-
var SCRIPT_VERSION = "
|
546
|
+
var SCRIPT_VERSION = "311";
|
546
547
|
var logger = new Logger();
|
547
548
|
var globalConfig = fromObject(LUX);
|
548
549
|
logger.logEvent(LogEvent.EvaluationStart, [SCRIPT_VERSION]);
|
550
|
+
// Variable aliases that allow the minifier to reduce file size.
|
551
|
+
var document = window.document;
|
552
|
+
var addEventListener = window.addEventListener;
|
553
|
+
var removeEventListener = window.removeEventListener;
|
554
|
+
var setTimeout = window.setTimeout;
|
555
|
+
var clearTimeout = window.clearTimeout;
|
556
|
+
var encodeURIComponent = window.encodeURIComponent;
|
557
|
+
var thisScript = document.currentScript || {};
|
549
558
|
// Log JS errors.
|
550
559
|
var nErrors = 0;
|
551
560
|
function errorHandler(e) {
|
@@ -560,30 +569,30 @@
|
|
560
569
|
// Sample & limit other errors.
|
561
570
|
// Send the error beacon.
|
562
571
|
new Image().src =
|
563
|
-
|
564
|
-
|
565
|
-
|
566
|
-
|
567
|
-
|
568
|
-
|
569
|
-
|
570
|
-
|
571
|
-
|
572
|
-
|
573
|
-
|
574
|
-
|
575
|
-
|
576
|
-
|
577
|
-
|
578
|
-
|
579
|
-
|
580
|
-
|
581
|
-
|
582
|
-
|
583
|
-
}
|
584
|
-
}
|
585
|
-
}
|
586
|
-
|
572
|
+
globalConfig.errorBeaconUrl +
|
573
|
+
"?v=" +
|
574
|
+
SCRIPT_VERSION +
|
575
|
+
"&id=" +
|
576
|
+
getCustomerId() +
|
577
|
+
"&fn=" +
|
578
|
+
encodeURIComponent(e.filename) +
|
579
|
+
"&ln=" +
|
580
|
+
e.lineno +
|
581
|
+
"&cn=" +
|
582
|
+
e.colno +
|
583
|
+
"&msg=" +
|
584
|
+
encodeURIComponent(e.message) +
|
585
|
+
"&l=" +
|
586
|
+
encodeURIComponent(_getPageLabel()) +
|
587
|
+
(connectionType() ? "&ct=" + connectionType() : "") +
|
588
|
+
"&HN=" +
|
589
|
+
encodeURIComponent(document.location.hostname) +
|
590
|
+
"&PN=" +
|
591
|
+
encodeURIComponent(document.location.pathname);
|
592
|
+
}
|
593
|
+
}
|
594
|
+
}
|
595
|
+
addEventListener("error", errorHandler);
|
587
596
|
var logEntry = function (entry) {
|
588
597
|
logger.logEvent(LogEvent.PerformanceEntryReceived, [entry]);
|
589
598
|
};
|
@@ -611,9 +620,9 @@
|
|
611
620
|
logEntry(entry);
|
612
621
|
});
|
613
622
|
observe("first-input", function (entry) {
|
614
|
-
var
|
615
|
-
if (!gFirstInputDelay || gFirstInputDelay <
|
616
|
-
gFirstInputDelay = floor(
|
623
|
+
var entryTime = entry.processingStart - entry.startTime;
|
624
|
+
if (!gFirstInputDelay || gFirstInputDelay < entryTime) {
|
625
|
+
gFirstInputDelay = floor(entryTime);
|
617
626
|
}
|
618
627
|
// Allow first-input events to be considered for INP
|
619
628
|
addEntry$1(entry);
|
@@ -642,11 +651,24 @@
|
|
642
651
|
var gMaxMeasureTimeout; // setTimeout timer for sending the beacon after a maximum measurement time
|
643
652
|
var pageRestoreTime; // ms since navigationStart representing when the page was restored from the bfcache
|
644
653
|
/**
|
645
|
-
|
646
|
-
|
647
|
-
|
648
|
-
|
649
|
-
var getZeroTime = function () {
|
654
|
+
* To measure the way a user experienced a metric, we measure metrics relative to the time the user
|
655
|
+
* started viewing the page. On prerendered pages, this is activationStart. On bfcache restores, this
|
656
|
+
* is the page restore time. On all other pages this value will be zero.
|
657
|
+
*/
|
658
|
+
var getZeroTime = function () {
|
659
|
+
var _a;
|
660
|
+
return Math.max(pageRestoreTime || 0, getNavigationEntry().activationStart, ((_a = _getMark(START_MARK)) === null || _a === void 0 ? void 0 : _a.startTime) || 0);
|
661
|
+
};
|
662
|
+
/**
|
663
|
+
* Most time-based metrics that LUX reports should be relative to the "zero" marker, rounded down
|
664
|
+
* to the nearest unit so as not to report times in the future, and clamped to zero.
|
665
|
+
*/
|
666
|
+
var processTimeMetric = function (value) { return clamp(floor(value - getZeroTime())); };
|
667
|
+
/**
|
668
|
+
* Some values should only be reported if they are non-zero. The exception to this is when the page
|
669
|
+
* was prerendered or restored from BF cache
|
670
|
+
*/
|
671
|
+
var shouldReportValue = function (value) { return value > 0 || pageRestoreTime || wasPrerendered(); };
|
650
672
|
if (_sample()) {
|
651
673
|
logger.logEvent(LogEvent.SessionIsSampled, [globalConfig.samplerate]);
|
652
674
|
}
|
@@ -688,11 +710,11 @@
|
|
688
710
|
removeListeners();
|
689
711
|
}
|
690
712
|
function removeListeners() {
|
691
|
-
|
692
|
-
|
713
|
+
removeEventListener("pointerup", onPointerUp, ghListenerOptions);
|
714
|
+
removeEventListener("pointercancel", onPointerCancel, ghListenerOptions);
|
693
715
|
}
|
694
|
-
|
695
|
-
|
716
|
+
addEventListener("pointerup", onPointerUp, ghListenerOptions);
|
717
|
+
addEventListener("pointercancel", onPointerCancel, ghListenerOptions);
|
696
718
|
}
|
697
719
|
// Record FID as the delta between when the event happened and when the
|
698
720
|
// listener was able to execute.
|
@@ -732,16 +754,16 @@
|
|
732
754
|
}
|
733
755
|
// Attach event listener to input events.
|
734
756
|
gaEventTypes.forEach(function (eventType) {
|
735
|
-
|
757
|
+
addEventListener(eventType, onInput, ghListenerOptions);
|
736
758
|
});
|
737
759
|
////////////////////// FID END
|
738
760
|
/**
|
739
|
-
|
740
|
-
|
741
|
-
|
742
|
-
|
743
|
-
|
744
|
-
|
761
|
+
* Returns the time elapsed (in ms) since navigationStart. For SPAs, returns
|
762
|
+
* the time elapsed since the last LUX.init call.
|
763
|
+
*
|
764
|
+
* When `absolute = true` the time is always relative to navigationStart, even
|
765
|
+
* in SPAs.
|
766
|
+
*/
|
745
767
|
function _now(absolute) {
|
746
768
|
var sinceNavigationStart = msSinceNavigationStart();
|
747
769
|
var startMark = _getMark(START_MARK);
|
@@ -766,7 +788,7 @@
|
|
766
788
|
return performance.mark.apply(performance, args);
|
767
789
|
}
|
768
790
|
// ...Otherwise provide a polyfill
|
769
|
-
|
791
|
+
{
|
770
792
|
var name_1 = args[0];
|
771
793
|
var detail = ((_a = args[1]) === null || _a === void 0 ? void 0 : _a.detail) || null;
|
772
794
|
var startTime = ((_b = args[1]) === null || _b === void 0 ? void 0 : _b.startTime) || _now();
|
@@ -829,14 +851,14 @@
|
|
829
851
|
return performance.measure.apply(performance, args);
|
830
852
|
}
|
831
853
|
// ...Otherwise provide a polyfill
|
832
|
-
|
854
|
+
{
|
833
855
|
var navEntry = getNavigationEntry();
|
834
856
|
var startTime = typeof startMarkName === "number" ? startMarkName : 0;
|
835
857
|
var endTime = typeof endMarkName === "number" ? endMarkName : _now();
|
836
858
|
var throwError = function (missingMark) {
|
837
859
|
throw new DOMException("Failed to execute 'measure' on 'Performance': The mark '" +
|
838
|
-
|
839
|
-
|
860
|
+
missingMark +
|
861
|
+
"' does not exist");
|
840
862
|
};
|
841
863
|
if (typeof startMarkName === "string") {
|
842
864
|
var startMark = _getMark(startMarkName);
|
@@ -924,7 +946,7 @@
|
|
924
946
|
var startMark = _getMark(START_MARK);
|
925
947
|
// For user timing values taken in a SPA page load, we need to adjust them
|
926
948
|
// so that they're zeroed against the last LUX.init() call.
|
927
|
-
var tZero =
|
949
|
+
var tZero = getZeroTime();
|
928
950
|
// marks
|
929
951
|
_getMarks().forEach(function (mark) {
|
930
952
|
var name = mark.name;
|
@@ -973,12 +995,13 @@
|
|
973
995
|
// Return a string of Element Timing Metrics formatted for beacon querystring.
|
974
996
|
function elementTimingValues() {
|
975
997
|
var aET = [];
|
976
|
-
var startMark = _getMark(START_MARK);
|
977
|
-
var tZero = startMark ? startMark.startTime : getZeroTime();
|
978
998
|
getEntries("element").forEach(function (entry) {
|
979
999
|
if (entry.identifier && entry.startTime) {
|
980
|
-
|
981
|
-
|
1000
|
+
var value = processTimeMetric(entry.startTime);
|
1001
|
+
if (shouldReportValue(value)) {
|
1002
|
+
logger.logEvent(LogEvent.PerformanceEntryProcessed, [entry]);
|
1003
|
+
aET.push(entry.identifier + "|" + value);
|
1004
|
+
}
|
982
1005
|
}
|
983
1006
|
});
|
984
1007
|
return aET.join(",");
|
@@ -995,20 +1018,7 @@
|
|
995
1018
|
var longTaskEntries = getEntries("longtask");
|
996
1019
|
// Add up totals for each "type" of long task
|
997
1020
|
if (longTaskEntries.length) {
|
998
|
-
|
999
|
-
// But if it is a SPA then the relative start time is gStartMark.
|
1000
|
-
var startMark = _getMark(START_MARK);
|
1001
|
-
var tZero_1 = startMark ? startMark.startTime : 0;
|
1002
|
-
// Do not include Long Tasks that start after the page is done.
|
1003
|
-
// For full page loads, "done" is loadEventEnd.
|
1004
|
-
var tEnd_1 = timing.loadEventEnd - timing.navigationStart;
|
1005
|
-
if (startMark) {
|
1006
|
-
// For SPA page loads (determined by the presence of a start mark), "done" is gEndMark.
|
1007
|
-
var endMark = _getMark(END_MARK);
|
1008
|
-
if (endMark) {
|
1009
|
-
tEnd_1 = endMark.startTime;
|
1010
|
-
}
|
1011
|
-
}
|
1021
|
+
var tZero_1 = getZeroTime();
|
1012
1022
|
longTaskEntries.forEach(function (entry) {
|
1013
1023
|
var dur = floor(entry.duration);
|
1014
1024
|
if (entry.startTime < tZero_1) {
|
@@ -1016,21 +1026,18 @@
|
|
1016
1026
|
// LUX.init() was called. If so, only include the duration after tZero.
|
1017
1027
|
dur -= tZero_1 - entry.startTime;
|
1018
1028
|
}
|
1019
|
-
|
1020
|
-
|
1021
|
-
|
1022
|
-
|
1023
|
-
|
1024
|
-
|
1025
|
-
|
1026
|
-
|
1027
|
-
|
1028
|
-
|
1029
|
-
hCPUDetails[type]
|
1029
|
+
// Only process entries that we calculated to have a valid duration
|
1030
|
+
if (dur > 0) {
|
1031
|
+
logger.logEvent(LogEvent.PerformanceEntryProcessed, [entry]);
|
1032
|
+
var type = entry.attribution[0].name;
|
1033
|
+
if (!hCPU[type]) {
|
1034
|
+
hCPU[type] = 0;
|
1035
|
+
hCPUDetails[type] = "";
|
1036
|
+
}
|
1037
|
+
hCPU[type] += dur;
|
1038
|
+
// Send back the raw startTime and duration, as well as the adjusted duration.
|
1039
|
+
hCPUDetails[type] += "," + floor(entry.startTime) + "|" + dur;
|
1030
1040
|
}
|
1031
|
-
hCPU[type] += dur;
|
1032
|
-
// Send back the raw startTime and duration, as well as the adjusted duration.
|
1033
|
-
hCPUDetails[type] += "," + floor(entry.startTime) + "|" + dur;
|
1034
1041
|
});
|
1035
1042
|
}
|
1036
1043
|
// TODO - Add more types if/when they become available.
|
@@ -1042,12 +1049,12 @@
|
|
1042
1049
|
}
|
1043
1050
|
var hStats = cpuStats(hCPUDetails[jsType]);
|
1044
1051
|
var sStats = ",n|" +
|
1045
|
-
|
1046
|
-
|
1047
|
-
|
1048
|
-
|
1049
|
-
|
1050
|
-
|
1052
|
+
hStats.count +
|
1053
|
+
",d|" +
|
1054
|
+
hStats.median +
|
1055
|
+
",x|" +
|
1056
|
+
hStats.max +
|
1057
|
+
(typeof hStats.fci === "undefined" ? "" : ",i|" + hStats.fci);
|
1051
1058
|
sCPU += "s|" + hCPU[jsType] + sStats + hCPUDetails[jsType];
|
1052
1059
|
return sCPU;
|
1053
1060
|
}
|
@@ -1055,11 +1062,11 @@
|
|
1055
1062
|
function cpuStats(sDetails) {
|
1056
1063
|
// tuples of starttime|duration, eg: ,456|250,789|250,1012|250
|
1057
1064
|
var max = 0;
|
1058
|
-
|
1059
|
-
|
1060
|
-
|
1061
|
-
//
|
1062
|
-
var bFoundFci =
|
1065
|
+
// FCI is beginning of 5 second window of no Long Tasks _after_ first contentful paint
|
1066
|
+
var fcp = getFcp();
|
1067
|
+
var fci = fcp || 0;
|
1068
|
+
// If FCP is not supported, we can't calculate a valid FCI.
|
1069
|
+
var bFoundFci = typeof fcp === "undefined";
|
1063
1070
|
var aValues = [];
|
1064
1071
|
var aTuples = sDetails.split(",");
|
1065
1072
|
for (var i = 0; i < aTuples.length; i++) {
|
@@ -1079,7 +1086,10 @@
|
|
1079
1086
|
}
|
1080
1087
|
else {
|
1081
1088
|
// Less than 5 seconds of inactivity
|
1082
|
-
|
1089
|
+
var val = processTimeMetric(start + dur);
|
1090
|
+
if (shouldReportValue(val)) {
|
1091
|
+
fci = val; // FCI is now the end of this Long Task
|
1092
|
+
}
|
1083
1093
|
}
|
1084
1094
|
}
|
1085
1095
|
}
|
@@ -1102,9 +1112,7 @@
|
|
1102
1112
|
return 0;
|
1103
1113
|
}
|
1104
1114
|
var half = floor(aValues.length / 2);
|
1105
|
-
aValues.sort(
|
1106
|
-
return a - b;
|
1107
|
-
});
|
1115
|
+
aValues.sort(sortNumeric);
|
1108
1116
|
if (aValues.length % 2) {
|
1109
1117
|
// Return the middle value.
|
1110
1118
|
return aValues[half];
|
@@ -1119,42 +1127,39 @@
|
|
1119
1127
|
var sLuxjs = "";
|
1120
1128
|
if (performance.getEntriesByName) {
|
1121
1129
|
// Get the lux script URL (including querystring params).
|
1122
|
-
var
|
1123
|
-
if (
|
1124
|
-
var
|
1125
|
-
|
1126
|
-
|
1127
|
-
|
1128
|
-
|
1129
|
-
|
1130
|
-
|
1131
|
-
|
1132
|
-
|
1133
|
-
|
1134
|
-
|
1135
|
-
|
1136
|
-
|
1137
|
-
|
1138
|
-
|
1139
|
-
|
1140
|
-
|
1141
|
-
|
1142
|
-
|
1143
|
-
|
1144
|
-
|
1145
|
-
|
1146
|
-
|
1147
|
-
|
1148
|
-
|
1149
|
-
|
1150
|
-
|
1151
|
-
|
1152
|
-
|
1153
|
-
|
1154
|
-
|
1155
|
-
(scriptStartTime - timing.navigationStart) + // when lux.js started getting evaluated relative to navigationStart
|
1156
|
-
"";
|
1157
|
-
}
|
1130
|
+
var aResources = performance.getEntriesByName(thisScript.src);
|
1131
|
+
if (aResources && aResources.length) {
|
1132
|
+
var r = aResources[0];
|
1133
|
+
// DO NOT USE DURATION!!!!!
|
1134
|
+
// See https://www.stevesouders.com/blog/2014/11/25/serious-confusion-with-resource-timing/
|
1135
|
+
var dns = floor(r.domainLookupEnd - r.domainLookupStart);
|
1136
|
+
var tcp = floor(r.connectEnd - r.connectStart);
|
1137
|
+
var fb = floor(r.responseStart - r.requestStart);
|
1138
|
+
var content = floor(r.responseEnd - r.responseStart);
|
1139
|
+
var networkDuration = dns + tcp + fb + content;
|
1140
|
+
var parseEval = scriptEndTime - scriptStartTime;
|
1141
|
+
var transferSize = r.encodedBodySize ? r.encodedBodySize : 0;
|
1142
|
+
// Instead of a delimiter use a 1-letter abbreviation as a separator.
|
1143
|
+
sLuxjs =
|
1144
|
+
"d" +
|
1145
|
+
dns +
|
1146
|
+
"t" +
|
1147
|
+
tcp +
|
1148
|
+
"f" +
|
1149
|
+
fb +
|
1150
|
+
"c" +
|
1151
|
+
content +
|
1152
|
+
"n" +
|
1153
|
+
networkDuration +
|
1154
|
+
"e" +
|
1155
|
+
parseEval +
|
1156
|
+
"r" +
|
1157
|
+
globalConfig.samplerate + // sample rate
|
1158
|
+
(typeof transferSize === "number" ? "x" + transferSize : "") +
|
1159
|
+
(typeof gLuxSnippetStart === "number" ? "l" + gLuxSnippetStart : "") +
|
1160
|
+
"s" +
|
1161
|
+
(scriptStartTime - timing.navigationStart) + // when lux.js started getting evaluated relative to navigationStart
|
1162
|
+
"";
|
1158
1163
|
}
|
1159
1164
|
}
|
1160
1165
|
return sLuxjs;
|
@@ -1185,9 +1190,9 @@
|
|
1185
1190
|
if (gCustomerDataTimeout) {
|
1186
1191
|
// Cancel the timer for any previous beacons so that if they have not
|
1187
1192
|
// yet been sent we can combine all the data in a new beacon.
|
1188
|
-
|
1193
|
+
clearTimeout(gCustomerDataTimeout);
|
1189
1194
|
}
|
1190
|
-
gCustomerDataTimeout =
|
1195
|
+
gCustomerDataTimeout = setTimeout(_sendCustomerData, 100);
|
1191
1196
|
}
|
1192
1197
|
}
|
1193
1198
|
// _sample()
|
@@ -1200,9 +1205,9 @@
|
|
1200
1205
|
return parseInt(nThis) < globalConfig.samplerate;
|
1201
1206
|
}
|
1202
1207
|
/**
|
1203
|
-
|
1204
|
-
|
1205
|
-
|
1208
|
+
* Re-initialize lux.js to start a new "page". This is typically called within a SPA at the
|
1209
|
+
* beginning of a page transition, but is also called internally when the BF cache is restored.
|
1210
|
+
*/
|
1206
1211
|
function _init(startTime) {
|
1207
1212
|
// Some customers (incorrectly) call LUX.init on the very first page load of a SPA. This would
|
1208
1213
|
// cause some first-page-only data (like paint metrics) to be lost. To prevent this, we silently
|
@@ -1232,7 +1237,6 @@
|
|
1232
1237
|
gbFirstPV = 0;
|
1233
1238
|
gSyncId = createSyncId();
|
1234
1239
|
gUid = refreshUniqueId(gSyncId);
|
1235
|
-
clearEntries();
|
1236
1240
|
reset$1();
|
1237
1241
|
reset();
|
1238
1242
|
nErrors = 0;
|
@@ -1353,14 +1357,17 @@
|
|
1353
1357
|
ns += start; // "navigationStart" for a SPA is the real navigationStart plus the start mark
|
1354
1358
|
var end = floor(endMark.startTime) - start; // delta from start mark
|
1355
1359
|
s =
|
1356
|
-
|
1357
|
-
|
1358
|
-
|
1359
|
-
|
1360
|
-
|
1361
|
-
|
1362
|
-
|
1363
|
-
|
1360
|
+
ns +
|
1361
|
+
// fetchStart and activationStart are the same as navigationStart for a SPA
|
1362
|
+
"as" +
|
1363
|
+
0 +
|
1364
|
+
"fs" +
|
1365
|
+
0 +
|
1366
|
+
"ls" +
|
1367
|
+
end +
|
1368
|
+
"le" +
|
1369
|
+
end +
|
1370
|
+
"";
|
1364
1371
|
}
|
1365
1372
|
else if (performance.timing) {
|
1366
1373
|
// Return the real Nav Timing metrics because this is the "main" page view (not a SPA)
|
@@ -1368,17 +1375,20 @@
|
|
1368
1375
|
var startRender = getStartRender();
|
1369
1376
|
var fcp = getFcp();
|
1370
1377
|
var lcp = getLcp();
|
1371
|
-
var prefixNTValue = function (key, prefix) {
|
1372
|
-
// activationStart is always absolute. Other values are relative to activationStart.
|
1373
|
-
var zero = key === "activationStart" ? 0 : getZeroTime();
|
1378
|
+
var prefixNTValue = function (key, prefix, ignoreZero) {
|
1374
1379
|
if (typeof navEntry_1[key] === "number") {
|
1375
|
-
var value =
|
1376
|
-
|
1380
|
+
var value = navEntry_1[key];
|
1381
|
+
// We allow zero values for most navigation timing metrics, but for some metrics we want
|
1382
|
+
// to ignore zeroes. The exceptions are that all metrics can be zero if the page was either
|
1383
|
+
// prerendered or restored from the BF cache.
|
1384
|
+
if (shouldReportValue(value) || !ignoreZero) {
|
1385
|
+
return prefix + processTimeMetric(value);
|
1386
|
+
}
|
1377
1387
|
}
|
1378
1388
|
return "";
|
1379
1389
|
};
|
1380
|
-
var loadEventStartStr = prefixNTValue("loadEventStart", "ls");
|
1381
|
-
var loadEventEndStr = prefixNTValue("loadEventEnd", "le");
|
1390
|
+
var loadEventStartStr = prefixNTValue("loadEventStart", "ls", true);
|
1391
|
+
var loadEventEndStr = prefixNTValue("loadEventEnd", "le", true);
|
1382
1392
|
if (pageRestoreTime && startMark && endMark) {
|
1383
1393
|
// For bfcache restores, we set the load time to the time it took for the page to be restored.
|
1384
1394
|
var loadTime = floor(endMark.startTime - startMark.startTime);
|
@@ -1386,43 +1396,44 @@
|
|
1386
1396
|
loadEventEndStr = "le" + loadTime;
|
1387
1397
|
}
|
1388
1398
|
var redirect = wasRedirected();
|
1399
|
+
var isSecure = document.location.protocol === "https:";
|
1389
1400
|
s = [
|
1390
1401
|
ns,
|
1391
|
-
|
1392
|
-
redirect ? prefixNTValue("redirectStart", "rs") : "",
|
1393
|
-
redirect ? prefixNTValue("redirectEnd", "re") : "",
|
1402
|
+
"as" + clamp(navEntry_1.activationStart),
|
1403
|
+
redirect && !pageRestoreTime ? prefixNTValue("redirectStart", "rs") : "",
|
1404
|
+
redirect && !pageRestoreTime ? prefixNTValue("redirectEnd", "re") : "",
|
1394
1405
|
prefixNTValue("fetchStart", "fs"),
|
1395
1406
|
prefixNTValue("domainLookupStart", "ds"),
|
1396
1407
|
prefixNTValue("domainLookupEnd", "de"),
|
1397
1408
|
prefixNTValue("connectStart", "cs"),
|
1398
|
-
prefixNTValue("secureConnectionStart", "sc"),
|
1409
|
+
isSecure ? prefixNTValue("secureConnectionStart", "sc") : "",
|
1399
1410
|
prefixNTValue("connectEnd", "ce"),
|
1400
1411
|
prefixNTValue("requestStart", "qs"),
|
1401
1412
|
prefixNTValue("responseStart", "bs"),
|
1402
1413
|
prefixNTValue("responseEnd", "be"),
|
1403
|
-
prefixNTValue("domInteractive", "oi"),
|
1404
|
-
prefixNTValue("domContentLoadedEventStart", "os"),
|
1405
|
-
prefixNTValue("domContentLoadedEventEnd", "oe"),
|
1406
|
-
prefixNTValue("domComplete", "oc"),
|
1414
|
+
prefixNTValue("domInteractive", "oi", true),
|
1415
|
+
prefixNTValue("domContentLoadedEventStart", "os", true),
|
1416
|
+
prefixNTValue("domContentLoadedEventEnd", "oe", true),
|
1417
|
+
prefixNTValue("domComplete", "oc", true),
|
1407
1418
|
loadEventStartStr,
|
1408
1419
|
loadEventEndStr,
|
1409
|
-
typeof startRender !== "undefined" ? "sr" +
|
1410
|
-
typeof fcp !== "undefined" ? "fc" +
|
1411
|
-
typeof lcp !== "undefined" ? "lc" +
|
1420
|
+
typeof startRender !== "undefined" ? "sr" + startRender : "",
|
1421
|
+
typeof fcp !== "undefined" ? "fc" + fcp : "",
|
1422
|
+
typeof lcp !== "undefined" ? "lc" + lcp : "",
|
1412
1423
|
].join("");
|
1413
1424
|
}
|
1414
1425
|
else if (endMark) {
|
1415
1426
|
// This is a "main" page view that does NOT support Navigation Timing - strange.
|
1416
1427
|
var end = floor(endMark.startTime);
|
1417
1428
|
s =
|
1418
|
-
|
1419
|
-
|
1420
|
-
|
1421
|
-
|
1422
|
-
|
1423
|
-
|
1424
|
-
|
1425
|
-
|
1429
|
+
ns +
|
1430
|
+
"fs" +
|
1431
|
+
0 + // fetchStart is the same as navigationStart
|
1432
|
+
"ls" +
|
1433
|
+
end +
|
1434
|
+
"le" +
|
1435
|
+
end +
|
1436
|
+
"";
|
1426
1437
|
}
|
1427
1438
|
return s;
|
1428
1439
|
}
|
@@ -1432,7 +1443,10 @@
|
|
1432
1443
|
for (var i = 0; i < paintEntries.length; i++) {
|
1433
1444
|
var entry = paintEntries[i];
|
1434
1445
|
if (entry.name === "first-contentful-paint") {
|
1435
|
-
|
1446
|
+
var value = processTimeMetric(entry.startTime);
|
1447
|
+
if (shouldReportValue(value)) {
|
1448
|
+
return value;
|
1449
|
+
}
|
1436
1450
|
}
|
1437
1451
|
}
|
1438
1452
|
return undefined;
|
@@ -1442,8 +1456,11 @@
|
|
1442
1456
|
var lcpEntries = getEntries("largest-contentful-paint");
|
1443
1457
|
if (lcpEntries.length) {
|
1444
1458
|
var lastEntry = lcpEntries[lcpEntries.length - 1];
|
1445
|
-
|
1446
|
-
|
1459
|
+
var value = processTimeMetric(lastEntry.startTime);
|
1460
|
+
if (shouldReportValue(value)) {
|
1461
|
+
logger.logEvent(LogEvent.PerformanceEntryProcessed, [lastEntry]);
|
1462
|
+
return value;
|
1463
|
+
}
|
1447
1464
|
}
|
1448
1465
|
return undefined;
|
1449
1466
|
}
|
@@ -1454,12 +1471,17 @@
|
|
1454
1471
|
if ("PerformancePaintTiming" in self) {
|
1455
1472
|
var paintEntries = getEntriesByType("paint");
|
1456
1473
|
if (paintEntries.length) {
|
1457
|
-
|
1458
|
-
|
1459
|
-
|
1474
|
+
var paintValues = paintEntries.map(function (entry) { return entry.startTime; }).sort(sortNumeric);
|
1475
|
+
// Use the earliest valid paint entry as the start render time.
|
1476
|
+
for (var i = 0; i < paintValues.length; i++) {
|
1477
|
+
var value = processTimeMetric(paintValues[i]);
|
1478
|
+
if (shouldReportValue(value)) {
|
1479
|
+
return value;
|
1480
|
+
}
|
1481
|
+
}
|
1460
1482
|
}
|
1461
1483
|
}
|
1462
|
-
if (performance.timing && timing.msFirstPaint &&
|
1484
|
+
if (performance.timing && timing.msFirstPaint && true) {
|
1463
1485
|
// If IE/Edge, use the prefixed `msFirstPaint` property (see http://msdn.microsoft.com/ff974719).
|
1464
1486
|
return floor(timing.msFirstPaint - timing.navigationStart);
|
1465
1487
|
}
|
@@ -1473,40 +1495,11 @@
|
|
1473
1495
|
return getHighPercentileINP();
|
1474
1496
|
}
|
1475
1497
|
function getCustomerId() {
|
1476
|
-
if (
|
1477
|
-
|
1478
|
-
var luxScript = getScriptElement("/js/lux.js");
|
1479
|
-
if (luxScript) {
|
1480
|
-
LUX.customerid = getQuerystringParam(luxScript.src, "id");
|
1481
|
-
}
|
1498
|
+
if (!LUX.customerid) {
|
1499
|
+
LUX.customerid = thisScript.src.match(/id=(\d+)/).pop();
|
1482
1500
|
}
|
1483
1501
|
return LUX.customerid || "";
|
1484
1502
|
}
|
1485
|
-
// Return the SCRIPT DOM element whose SRC contains the URL snippet.
|
1486
|
-
// This is used to find the LUX script element.
|
1487
|
-
function getScriptElement(urlsnippet) {
|
1488
|
-
var aScripts = document.getElementsByTagName("script");
|
1489
|
-
for (var i = 0, len = aScripts.length; i < len; i++) {
|
1490
|
-
var script = aScripts[i];
|
1491
|
-
if (script.src && -1 !== script.src.indexOf(urlsnippet)) {
|
1492
|
-
return script;
|
1493
|
-
}
|
1494
|
-
}
|
1495
|
-
return undefined;
|
1496
|
-
}
|
1497
|
-
function getQuerystringParam(url, name) {
|
1498
|
-
var qs = url.split("?")[1];
|
1499
|
-
var aTuples = qs.split("&");
|
1500
|
-
for (var i = 0, len = aTuples.length; i < len; i++) {
|
1501
|
-
var tuple = aTuples[i];
|
1502
|
-
var aTuple = tuple.split("=");
|
1503
|
-
var key = aTuple[0];
|
1504
|
-
if (name === key) {
|
1505
|
-
return aTuple[1];
|
1506
|
-
}
|
1507
|
-
}
|
1508
|
-
return undefined;
|
1509
|
-
}
|
1510
1503
|
function avgDomDepth() {
|
1511
1504
|
var aElems = document.getElementsByTagName("*");
|
1512
1505
|
var i = aElems.length;
|
@@ -1645,14 +1638,14 @@
|
|
1645
1638
|
}
|
1646
1639
|
function createMaxMeasureTimeout() {
|
1647
1640
|
clearMaxMeasureTimeout();
|
1648
|
-
gMaxMeasureTimeout =
|
1641
|
+
gMaxMeasureTimeout = setTimeout(function () {
|
1649
1642
|
gFlags = addFlag(gFlags, Flags.BeaconSentAfterTimeout);
|
1650
1643
|
_sendLux();
|
1651
1644
|
}, globalConfig.maxMeasureTime - _now());
|
1652
1645
|
}
|
1653
1646
|
function clearMaxMeasureTimeout() {
|
1654
1647
|
if (gMaxMeasureTimeout) {
|
1655
|
-
|
1648
|
+
clearTimeout(gMaxMeasureTimeout);
|
1656
1649
|
}
|
1657
1650
|
}
|
1658
1651
|
function _getBeaconUrl(customData) {
|
@@ -1688,7 +1681,7 @@
|
|
1688
1681
|
!gSyncId ||
|
1689
1682
|
!_sample() || // OUTSIDE the sampled range
|
1690
1683
|
gbLuxSent // LUX data already sent
|
1691
|
-
|
1684
|
+
) {
|
1692
1685
|
return;
|
1693
1686
|
}
|
1694
1687
|
logger.logEvent(LogEvent.DataCollectionStart);
|
@@ -1741,49 +1734,49 @@
|
|
1741
1734
|
var is = inlineTagSize("script");
|
1742
1735
|
var ic = inlineTagSize("style");
|
1743
1736
|
var metricsQueryString =
|
1744
|
-
|
1745
|
-
|
1746
|
-
|
1747
|
-
|
1748
|
-
|
1749
|
-
|
1750
|
-
|
1751
|
-
|
1752
|
-
|
1753
|
-
|
1754
|
-
|
1755
|
-
|
1756
|
-
|
1757
|
-
|
1758
|
-
|
1759
|
-
|
1760
|
-
|
1761
|
-
|
1762
|
-
|
1763
|
-
|
1764
|
-
|
1765
|
-
|
1766
|
-
|
1767
|
-
|
1768
|
-
|
1769
|
-
|
1770
|
-
|
1771
|
-
|
1772
|
-
|
1773
|
-
|
1774
|
-
|
1775
|
-
|
1776
|
-
|
1777
|
-
|
1778
|
-
|
1779
|
-
|
1780
|
-
|
1781
|
-
|
1782
|
-
|
1783
|
-
|
1784
|
-
|
1785
|
-
|
1786
|
-
|
1737
|
+
// only send Nav Timing and lux.js metrics on initial pageload (not for SPA page views)
|
1738
|
+
(gbNavSent ? "" : "&NT=" + getNavTiming()) +
|
1739
|
+
(gbFirstPV ? "&LJS=" + sLuxjs : "") +
|
1740
|
+
// Page Stats
|
1741
|
+
"&PS=ns" +
|
1742
|
+
numScripts() +
|
1743
|
+
"bs" +
|
1744
|
+
blockingScripts() +
|
1745
|
+
(is > -1 ? "is" + is : "") +
|
1746
|
+
"ss" +
|
1747
|
+
numStylesheets() +
|
1748
|
+
"bc" +
|
1749
|
+
blockingStylesheets() +
|
1750
|
+
(ic > -1 ? "ic" + ic : "") +
|
1751
|
+
"ia" +
|
1752
|
+
imagesATF().length +
|
1753
|
+
"it" +
|
1754
|
+
document.getElementsByTagName("img").length + // total number of images
|
1755
|
+
"dd" +
|
1756
|
+
avgDomDepth() +
|
1757
|
+
"nd" +
|
1758
|
+
document.getElementsByTagName("*").length + // numdomelements
|
1759
|
+
"vh" +
|
1760
|
+
document.documentElement.clientHeight + // see http://www.quirksmode.org/mobile/viewports.html
|
1761
|
+
"vw" +
|
1762
|
+
document.documentElement.clientWidth +
|
1763
|
+
"dh" +
|
1764
|
+
docHeight(document) +
|
1765
|
+
"dw" +
|
1766
|
+
docWidth(document) +
|
1767
|
+
(docSize() ? "ds" + docSize() : "") + // document HTTP transfer size (bytes)
|
1768
|
+
(connectionType() ? "ct" + connectionType() + "_" : "") + // delimit with "_" since values can be non-numeric so need a way to extract with regex in VCL
|
1769
|
+
"er" +
|
1770
|
+
nErrors +
|
1771
|
+
"nt" +
|
1772
|
+
navigationType() +
|
1773
|
+
(navigator.deviceMemory ? "dm" + Math.round(navigator.deviceMemory) : "") + // device memory (GB)
|
1774
|
+
(sIx ? "&IX=" + sIx : "") +
|
1775
|
+
(typeof gFirstInputDelay !== "undefined" ? "&FID=" + gFirstInputDelay : "") +
|
1776
|
+
(sCPU ? "&CPU=" + sCPU : "") +
|
1777
|
+
(sET ? "&ET=" + sET : "") + // element timing
|
1778
|
+
(typeof CLS !== "undefined" ? "&CLS=" + CLS : "") +
|
1779
|
+
(typeof INP !== "undefined" ? "&INP=" + INP : "");
|
1787
1780
|
// We add the user timing entries last so that we can split them to reduce the URL size if necessary.
|
1788
1781
|
var utValues = userTimingValues();
|
1789
1782
|
var _b = fitUserTimingEntries(utValues, globalConfig, baseUrl + metricsQueryString), beaconUtValues = _b[0], remainingUtValues = _b[1];
|
@@ -1807,8 +1800,8 @@
|
|
1807
1800
|
}
|
1808
1801
|
var ixTimerId;
|
1809
1802
|
function _sendIxAfterDelay() {
|
1810
|
-
|
1811
|
-
ixTimerId =
|
1803
|
+
clearTimeout(ixTimerId);
|
1804
|
+
ixTimerId = setTimeout(_sendIx, 100);
|
1812
1805
|
}
|
1813
1806
|
// Beacon back the IX data separately (need to sync with LUX beacon on the backend).
|
1814
1807
|
function _sendIx() {
|
@@ -1842,7 +1835,7 @@
|
|
1842
1835
|
!gSyncId ||
|
1843
1836
|
!_sample() || // OUTSIDE the sampled range
|
1844
1837
|
!gbLuxSent // LUX has NOT been sent yet, so wait to include it there
|
1845
|
-
|
1838
|
+
) {
|
1846
1839
|
return;
|
1847
1840
|
}
|
1848
1841
|
var sCustomerData = valuesToString(getUpdatedCustomData());
|
@@ -1870,6 +1863,19 @@
|
|
1870
1863
|
}
|
1871
1864
|
}
|
1872
1865
|
function _keyHandler(e) {
|
1866
|
+
var keyCode = e.keyCode;
|
1867
|
+
/**
|
1868
|
+
* Ignore modifier keys
|
1869
|
+
*
|
1870
|
+
* 16 = Shift
|
1871
|
+
* 17 = Control
|
1872
|
+
* 18 = Alt
|
1873
|
+
* 20 = Caps Lock
|
1874
|
+
* 224 = Meta/Command
|
1875
|
+
*/
|
1876
|
+
if (keyCode === 16 || keyCode === 17 || keyCode === 18 || keyCode === 20 || keyCode === 224) {
|
1877
|
+
return;
|
1878
|
+
}
|
1873
1879
|
_removeIxHandlers();
|
1874
1880
|
if (typeof ghIx["k"] === "undefined") {
|
1875
1881
|
ghIx["k"] = _now();
|
@@ -1914,10 +1920,10 @@
|
|
1914
1920
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
1915
1921
|
function addListener(type, callback, useCapture) {
|
1916
1922
|
if (useCapture === void 0) { useCapture = false; }
|
1917
|
-
if (
|
1918
|
-
|
1923
|
+
if (addEventListener) {
|
1924
|
+
addEventListener(type, callback, useCapture);
|
1919
1925
|
}
|
1920
|
-
else if (window.attachEvent &&
|
1926
|
+
else if (window.attachEvent && true) {
|
1921
1927
|
window.attachEvent("on" + type, callback);
|
1922
1928
|
}
|
1923
1929
|
}
|
@@ -1925,10 +1931,10 @@
|
|
1925
1931
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
1926
1932
|
function removeListener(type, callback, useCapture) {
|
1927
1933
|
if (useCapture === void 0) { useCapture = false; }
|
1928
|
-
if (
|
1929
|
-
|
1934
|
+
if (removeEventListener) {
|
1935
|
+
removeEventListener(type, callback, useCapture);
|
1930
1936
|
}
|
1931
|
-
else if (window.detachEvent &&
|
1937
|
+
else if (window.detachEvent && true) {
|
1932
1938
|
window.detachEvent("on" + type, callback);
|
1933
1939
|
}
|
1934
1940
|
}
|
@@ -2016,7 +2022,7 @@
|
|
2016
2022
|
if (typeof LUX.pagegroups !== "undefined") {
|
2017
2023
|
var label = getMatchesFromPatternMap(LUX.pagegroups, location.hostname, location.pathname, true);
|
2018
2024
|
if (label) {
|
2019
|
-
gFlags = addFlag(gFlags, Flags.
|
2025
|
+
gFlags = addFlag(gFlags, Flags.PageLabelFromUrlPattern);
|
2020
2026
|
return label;
|
2021
2027
|
}
|
2022
2028
|
}
|
@@ -2057,11 +2063,11 @@
|
|
2057
2063
|
function _setCookie(name, value, seconds) {
|
2058
2064
|
try {
|
2059
2065
|
document.cookie =
|
2060
|
-
|
2061
|
-
|
2062
|
-
|
2063
|
-
|
2064
|
-
|
2066
|
+
name +
|
2067
|
+
"=" +
|
2068
|
+
escape(value) +
|
2069
|
+
(seconds ? "; max-age=" + seconds : "") +
|
2070
|
+
"; path=/; SameSite=Lax";
|
2065
2071
|
}
|
2066
2072
|
catch (e) {
|
2067
2073
|
logger.logEvent(LogEvent.CookieSetError);
|
@@ -2111,7 +2117,7 @@
|
|
2111
2117
|
// bfcache. Since we have no "onload" event to hook into after a bfcache restore, we rely on the
|
2112
2118
|
// unload and maxMeasureTime handlers to send the beacon.
|
2113
2119
|
if (globalConfig.newBeaconOnPageShow) {
|
2114
|
-
|
2120
|
+
addEventListener("pageshow", function (event) {
|
2115
2121
|
if (event.persisted) {
|
2116
2122
|
// Record the timestamp of the bfcache restore
|
2117
2123
|
pageRestoreTime = event.timeStamp;
|
@@ -2141,9 +2147,9 @@
|
|
2141
2147
|
// Set the maximum measurement timer
|
2142
2148
|
createMaxMeasureTimeout();
|
2143
2149
|
/**
|
2144
|
-
|
2145
|
-
|
2146
|
-
|
2150
|
+
* LUX functions and properties must be attached to the existing global object to ensure that
|
2151
|
+
* changes made to the global object are reflected in the "internal" LUX object, and vice versa.
|
2152
|
+
*/
|
2147
2153
|
var globalLux = globalConfig;
|
2148
2154
|
// Functions
|
2149
2155
|
globalLux.mark = _mark;
|
@@ -2168,8 +2174,8 @@
|
|
2168
2174
|
// Public properties
|
2169
2175
|
globalLux.version = SCRIPT_VERSION;
|
2170
2176
|
/**
|
2171
|
-
|
2172
|
-
|
2177
|
+
* Run a command from the command queue
|
2178
|
+
*/
|
2173
2179
|
function _runCommand(_a) {
|
2174
2180
|
var fn = _a[0], args = _a.slice(1);
|
2175
2181
|
if (typeof globalLux[fn] === "function") {
|
@@ -17,6 +17,12 @@
|
|
17
17
|
display: block !important; // stylelint-disable-line declaration-no-important
|
18
18
|
}
|
19
19
|
|
20
|
+
.js-enabled .govuk-accordion__section-content[hidden] {
|
21
|
+
@supports (content-visibility: hidden) {
|
22
|
+
content-visibility: auto;
|
23
|
+
}
|
24
|
+
}
|
25
|
+
|
20
26
|
// Change the colour from the blue link colour to black.
|
21
27
|
.govuk-accordion__section-button {
|
22
28
|
color: govuk-colour("black") !important; // stylelint-disable-line declaration-no-important
|
@@ -34,6 +34,12 @@
|
|
34
34
|
// stylelint-disable max-nesting-depth
|
35
35
|
|
36
36
|
.gem-c-govspeak {
|
37
|
+
a[href^="/"]:after,a[href^="http://"]:after,a[href^="https://"]:after {
|
38
|
+
content: " (" attr(href) ")";
|
39
|
+
font-size: 90%;
|
40
|
+
word-wrap: break-word;
|
41
|
+
}
|
42
|
+
|
37
43
|
.media-player {
|
38
44
|
display: none;
|
39
45
|
}
|
@@ -54,8 +54,9 @@
|
|
54
54
|
)
|
55
55
|
end
|
56
56
|
|
57
|
+
data_attributes[:ga4_link] = ga4_link
|
57
58
|
%>
|
58
|
-
<%= tag.section class: class_names(container_class_names), data: { module: "ga4-link-tracker"
|
59
|
+
<%= tag.section class: class_names(container_class_names), data: { module: "ga4-link-tracker" } do %>
|
59
60
|
<%= tag.div class: "gem-c-attachment__thumbnail" do %>
|
60
61
|
<%= link_to attachment.url,
|
61
62
|
class: "govuk-link",
|
data/app/views/govuk_publishing_components/components/layout_for_public/_account-layout.html.erb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
<div class="govuk-width-container">
|
2
2
|
<%= render "govuk_publishing_components/components/phase_banner", {
|
3
3
|
phase: "beta",
|
4
|
+
ga4_tracking: true,
|
4
5
|
message: sanitize(t("components.layout_for_public.account_layout.feedback.banners.phase_banner_html"))
|
5
6
|
} unless omit_account_phase_banner %>
|
6
7
|
|
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.15.
|
4
|
+
version: 35.15.1
|
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-09-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: govuk_app_config
|