govuk_publishing_components 29.8.0 → 29.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/vendor/lux/lux-measurer.js +18 -9
- data/app/assets/javascripts/govuk_publishing_components/vendor/lux/lux-reporter.js +166 -142
- data/app/views/govuk_publishing_components/components/_summary_list.html.erb +4 -5
- 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: d0d30bd1a2b86ab711560f26438e2ba7907402831cc617b752d3e1fb05c2e6cc
|
4
|
+
data.tar.gz: e13d38616b71e39a1e3e23df2999eb88f9824a668dc8347a4b914a58e86bf2bb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d91d69b91a14c9f6acaf230a32c9c75385f54cd7c2ff924860f87e3578ea32f58726d16e0de1d5ccbfbeb808da0ceba804adc9827cd5ae2370dae3b6b478090b
|
7
|
+
data.tar.gz: 036b79310b2cef0189a2536eab0d70bdf0d293cd079533da198f666c00ee04ddc7f34a22468ad4b853d2875fe1d44ec8ec305157c115ea19e0b2760e21ccd401
|
@@ -171,16 +171,25 @@ if (
|
|
171
171
|
// `DOMContentReady` event before we can see what the HTTP version is.
|
172
172
|
//
|
173
173
|
// [1]: https://github.com/alphagov/govuk-rfcs/pull/148
|
174
|
-
try {
|
175
|
-
if (typeof performance !== 'undefined') {
|
176
|
-
document.addEventListener('DOMContentLoaded', function () {
|
177
|
-
var getEntriesByType = performance.getEntriesByType('navigation')
|
178
174
|
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
175
|
+
var measureHTTPProtocol = function () {
|
176
|
+
var getEntriesByType = performance.getEntriesByType('navigation')
|
177
|
+
|
178
|
+
if (getEntriesByType.length > 0) {
|
179
|
+
var httpProtocol = JSON.parse(JSON.stringify(performance.getEntriesByType('navigation')[0].nextHopProtocol))
|
180
|
+
LUX.addData("http-protocol", httpProtocol)
|
181
|
+
}
|
182
|
+
}
|
183
|
+
|
184
|
+
try {
|
185
|
+
if (typeof performance !== 'undefined' && typeof performance.getEntriesByType !== 'undefined') {
|
186
|
+
if (document.readyState === 'complete') {
|
187
|
+
measureHTTPProtocol()
|
188
|
+
} else {
|
189
|
+
window.addEventListener('load', function() {
|
190
|
+
measureHTTPProtocol()
|
191
|
+
})
|
192
|
+
}
|
184
193
|
}
|
185
194
|
} catch (e) {
|
186
195
|
console.error('Error in LUX reporting the HTTP protocol (' + window.location + '):', e)
|
@@ -41,6 +41,7 @@
|
|
41
41
|
maxErrors: getProperty(obj, "maxErrors", 5),
|
42
42
|
maxMeasureTime: getProperty(obj, "maxMeasureTime", 60000),
|
43
43
|
measureUntil: getProperty(obj, "measureUntil", "onload"),
|
44
|
+
minMeasureTime: getProperty(obj, "minMeasureTime", 0),
|
44
45
|
samplerate: getProperty(obj, "samplerate", 100),
|
45
46
|
sendBeaconOnPageHidden: getProperty(obj, "sendBeaconOnPageHidden", autoMode),
|
46
47
|
trackErrors: getProperty(obj, "trackErrors", true),
|
@@ -63,6 +64,9 @@
|
|
63
64
|
AddDataCalled: 6,
|
64
65
|
SendCalled: 7,
|
65
66
|
ForceSampleCalled: 8,
|
67
|
+
DataCollectionStart: 9,
|
68
|
+
UnloadHandlerTriggered: 10,
|
69
|
+
OnloadHandlerTriggered: 11,
|
66
70
|
// Data collection events
|
67
71
|
SessionIsSampled: 21,
|
68
72
|
SessionIsNotSampled: 22,
|
@@ -70,6 +74,10 @@
|
|
70
74
|
UserTimingBeaconSent: 24,
|
71
75
|
InteractionBeaconSent: 25,
|
72
76
|
CustomDataBeaconSent: 26,
|
77
|
+
// Metric information
|
78
|
+
NavigationStart: 41,
|
79
|
+
PerformanceEntryReceived: 42,
|
80
|
+
PerformanceEntryProcessed: 43,
|
73
81
|
// Errors
|
74
82
|
PerformanceObserverError: 51,
|
75
83
|
InputEventPermissionError: 52,
|
@@ -82,7 +90,7 @@
|
|
82
90
|
NavTimingNotSupported: 71,
|
83
91
|
PaintTimingNotSupported: 72,
|
84
92
|
};
|
85
|
-
var Logger = (function () {
|
93
|
+
var Logger = /** @class */ (function () {
|
86
94
|
function Logger() {
|
87
95
|
this.events = [];
|
88
96
|
}
|
@@ -90,7 +98,7 @@
|
|
90
98
|
if (args === void 0) {
|
91
99
|
args = [];
|
92
100
|
}
|
93
|
-
this.events.push([
|
101
|
+
this.events.push([now(), event, args]);
|
94
102
|
};
|
95
103
|
Logger.prototype.getEvents = function () {
|
96
104
|
return this.events;
|
@@ -113,7 +121,34 @@
|
|
113
121
|
return flags | flag;
|
114
122
|
}
|
115
123
|
|
124
|
+
// If the various performance APIs aren't available, we export an empty object to
|
125
|
+
// prevent having to make regular typeof checks.
|
126
|
+
var performance = window.performance || {};
|
127
|
+
var timing = performance.timing || {};
|
128
|
+
/**
|
129
|
+
* Simple wrapper around performance.getEntriesByType to provide fallbacks for
|
130
|
+
* legacy browsers, and work around edge cases where undefined is returned instead
|
131
|
+
* of an empty PerformanceEntryList.
|
132
|
+
*/
|
133
|
+
function getEntriesByType(type) {
|
134
|
+
if (typeof performance.getEntriesByType === "function") {
|
135
|
+
var entries = performance.getEntriesByType(type);
|
136
|
+
if (entries && entries.length) {
|
137
|
+
return entries;
|
138
|
+
}
|
139
|
+
} else if (typeof performance.webkitGetEntriesByType === "function") {
|
140
|
+
var entries = performance.webkitGetEntriesByType(type);
|
141
|
+
if (entries && entries.length) {
|
142
|
+
return entries;
|
143
|
+
}
|
144
|
+
}
|
145
|
+
return [];
|
146
|
+
}
|
147
|
+
|
116
148
|
var LUX = window.LUX || {};
|
149
|
+
// Get a timestamp as close to navigationStart as possible.
|
150
|
+
var _navigationStart = LUX.ns ? LUX.ns : now();
|
151
|
+
var LUX_t_end = LUX_t_start;
|
117
152
|
LUX = (function () {
|
118
153
|
// -------------------------------------------------------------------------
|
119
154
|
// Settings
|
@@ -124,7 +159,7 @@
|
|
124
159
|
/// End
|
125
160
|
// -------------------------------------------------------------------------
|
126
161
|
|
127
|
-
var SCRIPT_VERSION = "
|
162
|
+
var SCRIPT_VERSION = "301";
|
128
163
|
var logger = new Logger();
|
129
164
|
var userConfig = fromObject(LUX);
|
130
165
|
logger.logEvent(LogEvent.EvaluationStart, [SCRIPT_VERSION]);
|
@@ -137,17 +172,13 @@
|
|
137
172
|
nErrors++;
|
138
173
|
if (
|
139
174
|
e &&
|
140
|
-
|
141
|
-
|
175
|
+
typeof e.filename !== "undefined" &&
|
176
|
+
typeof e.message !== "undefined"
|
142
177
|
) {
|
143
|
-
//
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
(nErrors <= userConfig.maxErrors &&
|
148
|
-
"function" === typeof _sample &&
|
149
|
-
_sample())
|
150
|
-
) {
|
178
|
+
// Always send LUX errors
|
179
|
+
var isLuxError =
|
180
|
+
e.filename.indexOf("/lux.js?") > -1 || e.message.indexOf("LUX") > -1;
|
181
|
+
if (isLuxError || (nErrors <= userConfig.maxErrors && _sample())) {
|
151
182
|
// Sample & limit other errors.
|
152
183
|
// Send the error beacon.
|
153
184
|
new Image().src =
|
@@ -184,8 +215,8 @@
|
|
184
215
|
var gaPerfEntries = gaSnippetLongTasks.slice(); // array of Long Tasks (prefer the array from the snippet)
|
185
216
|
if (typeof PerformanceObserver === "function") {
|
186
217
|
var perfObserver = new PerformanceObserver(function (list) {
|
187
|
-
// Keep an array of perf objects to process later.
|
188
218
|
list.getEntries().forEach(function (entry) {
|
219
|
+
logger.logEvent(LogEvent.PerformanceEntryReceived, [entry]);
|
189
220
|
// Only record long tasks that weren't already recorded by the PerformanceObserver in the snippet
|
190
221
|
if (
|
191
222
|
entry.entryType !== "longtask" ||
|
@@ -237,24 +268,23 @@
|
|
237
268
|
var gSyncId = createSyncId(); // if we send multiple beacons, use this to sync them (eg, LUX & IX) (also called "luxid")
|
238
269
|
var gUid = refreshUniqueId(gSyncId); // cookie for this session ("Unique ID")
|
239
270
|
var gCustomerDataTimeout; // setTimeout timer for sending a Customer Data beacon after onload
|
240
|
-
var
|
271
|
+
var gMaxMeasureTimeout; // setTimeout timer for sending the beacon after a maximum measurement time
|
241
272
|
var gMaxQuerystring = 8190; // split the beacon querystring if it gets longer than this
|
242
273
|
if (_sample()) {
|
243
274
|
logger.logEvent(LogEvent.SessionIsSampled, [userConfig.samplerate]);
|
244
275
|
} else {
|
245
276
|
logger.logEvent(LogEvent.SessionIsNotSampled, [userConfig.samplerate]);
|
246
277
|
}
|
247
|
-
// Get a timestamp as close to navigationStart as possible.
|
248
|
-
var _navigationStart = LUX.ns ? LUX.ns : now(); // create a _navigationStart
|
249
278
|
var gLuxSnippetStart = 0;
|
250
|
-
if (
|
251
|
-
_navigationStart =
|
279
|
+
if (timing.navigationStart) {
|
280
|
+
_navigationStart = timing.navigationStart;
|
252
281
|
// Record when the LUX snippet was evaluated relative to navigationStart.
|
253
282
|
gLuxSnippetStart = LUX.ns ? LUX.ns - _navigationStart : 0;
|
254
283
|
} else {
|
255
284
|
logger.logEvent(LogEvent.NavTimingNotSupported);
|
256
285
|
gFlags = addFlag(gFlags, Flags.NavTimingNotSupported);
|
257
286
|
}
|
287
|
+
logger.logEvent(LogEvent.NavigationStart, [_navigationStart]);
|
258
288
|
////////////////////// FID BEGIN
|
259
289
|
// FIRST INPUT DELAY (FID)
|
260
290
|
// The basic idea behind FID is to attach various input event listeners and measure the time
|
@@ -351,16 +381,15 @@
|
|
351
381
|
* in SPAs.
|
352
382
|
*/
|
353
383
|
function _now(absolute) {
|
354
|
-
var
|
355
|
-
var msSinceNavigationStart = currentTimestamp - _navigationStart;
|
384
|
+
var msSinceNavigationStart = now() - _navigationStart;
|
356
385
|
var startMark = _getMark(gStartMark);
|
357
386
|
// For SPA page views, we use our internal mark as a reference point
|
358
387
|
if (startMark && !absolute) {
|
359
388
|
return msSinceNavigationStart - startMark.startTime;
|
360
389
|
}
|
361
390
|
// For "regular" page views, we can use performance.now() if it's available...
|
362
|
-
if (
|
363
|
-
return
|
391
|
+
if (performance.now) {
|
392
|
+
return performance.now();
|
364
393
|
}
|
365
394
|
// ... or we can use navigationStart as a reference point
|
366
395
|
return msSinceNavigationStart;
|
@@ -369,12 +398,10 @@
|
|
369
398
|
// NOTE: It's possible to set multiple marks with the same name.
|
370
399
|
function _mark(name) {
|
371
400
|
logger.logEvent(LogEvent.MarkCalled, [name]);
|
372
|
-
if (
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
return perf.webkitMark(name);
|
377
|
-
}
|
401
|
+
if (performance.mark) {
|
402
|
+
return performance.mark(name);
|
403
|
+
} else if (performance.webkitMark) {
|
404
|
+
return performance.webkitMark(name);
|
378
405
|
}
|
379
406
|
gFlags = addFlag(gFlags, Flags.UserTimingNotSupported);
|
380
407
|
// Shim
|
@@ -395,26 +422,24 @@
|
|
395
422
|
startMarkName,
|
396
423
|
endMarkName,
|
397
424
|
]);
|
398
|
-
if ("undefined"
|
425
|
+
if (typeof startMarkName === "undefined" && _getMark(gStartMark)) {
|
399
426
|
// If a start mark is not specified, but the user has called _init() to set a new start,
|
400
427
|
// then use the new start base time (similar to navigationStart) as the start mark.
|
401
428
|
startMarkName = gStartMark;
|
402
429
|
}
|
403
|
-
if (
|
404
|
-
|
405
|
-
|
406
|
-
if (
|
407
|
-
|
408
|
-
return perf.measure(name, startMarkName, endMarkName);
|
409
|
-
} else {
|
410
|
-
return perf.measure(name, startMarkName);
|
411
|
-
}
|
430
|
+
if (performance.measure) {
|
431
|
+
// IE 11 does not handle null and undefined correctly
|
432
|
+
if (startMarkName) {
|
433
|
+
if (endMarkName) {
|
434
|
+
return performance.measure(name, startMarkName, endMarkName);
|
412
435
|
} else {
|
413
|
-
return
|
436
|
+
return performance.measure(name, startMarkName);
|
414
437
|
}
|
415
|
-
} else
|
416
|
-
return
|
438
|
+
} else {
|
439
|
+
return performance.measure(name);
|
417
440
|
}
|
441
|
+
} else if (performance.webkitMeasure) {
|
442
|
+
return performance.webkitMeasure(name, startMarkName, endMarkName);
|
418
443
|
}
|
419
444
|
// shim:
|
420
445
|
var startTime = 0,
|
@@ -423,9 +448,9 @@
|
|
423
448
|
var startMark = _getMark(startMarkName);
|
424
449
|
if (startMark) {
|
425
450
|
startTime = startMark.startTime;
|
426
|
-
} else if (
|
451
|
+
} else if (timing[startMarkName]) {
|
427
452
|
// the mark name can also be a property from Navigation Timing
|
428
|
-
startTime =
|
453
|
+
startTime = timing[startMarkName] - timing.navigationStart;
|
429
454
|
} else {
|
430
455
|
throw new DOMException(
|
431
456
|
"Failed to execute 'measure' on 'Performance': The mark '".concat(
|
@@ -439,9 +464,9 @@
|
|
439
464
|
var endMark = _getMark(endMarkName);
|
440
465
|
if (endMark) {
|
441
466
|
endTime = endMark.startTime;
|
442
|
-
} else if (
|
467
|
+
} else if (timing[endMarkName]) {
|
443
468
|
// the mark name can also be a property from Navigation Timing
|
444
|
-
endTime =
|
469
|
+
endTime = timing[endMarkName] - timing.navigationStart;
|
445
470
|
} else {
|
446
471
|
throw new DOMException(
|
447
472
|
"Failed to execute 'measure' on 'Performance': The mark '".concat(
|
@@ -479,23 +504,17 @@
|
|
479
504
|
}
|
480
505
|
// Return an array of marks.
|
481
506
|
function _getMarks() {
|
482
|
-
|
483
|
-
|
484
|
-
|
485
|
-
} else if (perf.webkitGetEntriesByType) {
|
486
|
-
return perf.webkitGetEntriesByType("mark");
|
487
|
-
}
|
507
|
+
var marks = getEntriesByType("mark");
|
508
|
+
if (marks.length) {
|
509
|
+
return marks;
|
488
510
|
}
|
489
511
|
return gaMarks;
|
490
512
|
}
|
491
513
|
// Return an array of measures.
|
492
514
|
function _getMeasures() {
|
493
|
-
|
494
|
-
|
495
|
-
|
496
|
-
} else if (perf.webkitGetEntriesByType) {
|
497
|
-
return perf.webkitGetEntriesByType("measure");
|
498
|
-
}
|
515
|
+
var measures = getEntriesByType("measure");
|
516
|
+
if (measures.length) {
|
517
|
+
return measures;
|
499
518
|
}
|
500
519
|
return gaMeasures;
|
501
520
|
}
|
@@ -568,6 +587,7 @@
|
|
568
587
|
for (var i = 0; i < gaPerfEntries.length; i++) {
|
569
588
|
var pe = gaPerfEntries[i];
|
570
589
|
if ("element" === pe.entryType && pe.identifier && pe.startTime) {
|
590
|
+
logger.logEvent(LogEvent.PerformanceEntryProcessed, [pe]);
|
571
591
|
aET.push(pe.identifier + "|" + Math.round(pe.startTime));
|
572
592
|
}
|
573
593
|
}
|
@@ -576,7 +596,7 @@
|
|
576
596
|
}
|
577
597
|
// Return a string of CPU times formatted for beacon querystring.
|
578
598
|
function cpuTimes() {
|
579
|
-
if ("function"
|
599
|
+
if (typeof PerformanceLongTaskTiming !== "function") {
|
580
600
|
// Do not return any CPU metrics if Long Tasks API is not supported.
|
581
601
|
return "";
|
582
602
|
}
|
@@ -591,7 +611,7 @@
|
|
591
611
|
var tZero = startMark ? startMark.startTime : 0;
|
592
612
|
// Do not include Long Tasks that start after the page is done.
|
593
613
|
// For full page loads, "done" is loadEventEnd.
|
594
|
-
var tEnd =
|
614
|
+
var tEnd = timing.loadEventEnd - timing.navigationStart;
|
595
615
|
if (startMark) {
|
596
616
|
// For SPA page loads (determined by the presence of a start mark), "done" is gEndMark.
|
597
617
|
var endMark = _getMark(gEndMark);
|
@@ -614,6 +634,7 @@
|
|
614
634
|
// callback from setTimeout(200) happened. Do not include anything that started after tEnd.
|
615
635
|
continue;
|
616
636
|
}
|
637
|
+
logger.logEvent(LogEvent.PerformanceEntryProcessed, [p]);
|
617
638
|
var type = p.attribution[0].name; // TODO - is there ever more than 1 attribution???
|
618
639
|
if (!hCPU[type]) {
|
619
640
|
// initialize this category
|
@@ -626,8 +647,8 @@
|
|
626
647
|
}
|
627
648
|
}
|
628
649
|
// TODO - Add more types if/when they become available.
|
629
|
-
var jsType =
|
630
|
-
if (
|
650
|
+
var jsType = typeof hCPU["script"] !== "undefined" ? "script" : "unknown"; // spec changed from "script" to "unknown" Nov 2018
|
651
|
+
if (typeof hCPU[jsType] === "undefined") {
|
631
652
|
// Initialize default values for pages that have *no Long Tasks*.
|
632
653
|
hCPU[jsType] = 0;
|
633
654
|
hCPUDetails[jsType] = "";
|
@@ -681,7 +702,7 @@
|
|
681
702
|
return { count: count, median: median, max: max, fci: fci };
|
682
703
|
}
|
683
704
|
function calculateDCLS() {
|
684
|
-
if ("function"
|
705
|
+
if (typeof LayoutShift !== "function") {
|
685
706
|
return false;
|
686
707
|
}
|
687
708
|
var DCLS = 0;
|
@@ -690,6 +711,7 @@
|
|
690
711
|
if ("layout-shift" !== p.entryType || p.hadRecentInput) {
|
691
712
|
continue;
|
692
713
|
}
|
714
|
+
logger.logEvent(LogEvent.PerformanceEntryProcessed, [p]);
|
693
715
|
DCLS += p.value;
|
694
716
|
}
|
695
717
|
// The DCL column in Redshift is REAL (FLOAT4) which stores a maximum
|
@@ -716,11 +738,11 @@
|
|
716
738
|
// Track how long it took lux.js to load via Resource Timing.
|
717
739
|
function selfLoading() {
|
718
740
|
var sLuxjs = "";
|
719
|
-
if (
|
741
|
+
if (performance.getEntriesByName) {
|
720
742
|
// Get the lux script URL (including querystring params).
|
721
743
|
var luxScript = getScriptElement("/js/lux.js");
|
722
744
|
if (luxScript) {
|
723
|
-
var aResources =
|
745
|
+
var aResources = performance.getEntriesByName(luxScript.src);
|
724
746
|
if (aResources && aResources.length) {
|
725
747
|
var r = aResources[0];
|
726
748
|
// DO NOT USE DURATION!!!!!
|
@@ -799,8 +821,8 @@
|
|
799
821
|
// Return true if beacons for this page should be sampled.
|
800
822
|
function _sample() {
|
801
823
|
if (
|
802
|
-
"undefined"
|
803
|
-
|
824
|
+
typeof gUid === "undefined" ||
|
825
|
+
typeof userConfig.samplerate === "undefined"
|
804
826
|
) {
|
805
827
|
return false; // bail
|
806
828
|
}
|
@@ -851,6 +873,8 @@
|
|
851
873
|
gFlags = addFlag(gFlags, Flags.InitCalled);
|
852
874
|
// Mark the "navigationStart" for this SPA page.
|
853
875
|
_mark(gStartMark);
|
876
|
+
// Reset the maximum measure timeout
|
877
|
+
createMaxMeasureTimeout();
|
854
878
|
}
|
855
879
|
// Return the number of blocking (synchronous) external scripts in the page.
|
856
880
|
function blockingScripts() {
|
@@ -891,7 +915,7 @@
|
|
891
915
|
e.onloadcssdefined ||
|
892
916
|
"print" === e.media ||
|
893
917
|
"style" === e.as ||
|
894
|
-
(
|
918
|
+
(typeof e.onload === "function" && e.media === "all")
|
895
919
|
);
|
896
920
|
else {
|
897
921
|
nBlocking++;
|
@@ -971,9 +995,9 @@
|
|
971
995
|
"le" +
|
972
996
|
end +
|
973
997
|
"";
|
974
|
-
} else if (
|
998
|
+
} else if (performance.timing) {
|
975
999
|
// Return the real Nav Timing metrics because this is the "main" page view (not a SPA)
|
976
|
-
var t =
|
1000
|
+
var t = timing;
|
977
1001
|
var startRender = getStartRender(); // first paint
|
978
1002
|
var fcp = getFcp(); // first contentful paint
|
979
1003
|
var lcp = getLcp(); // largest contentful paint
|
@@ -1024,20 +1048,11 @@
|
|
1024
1048
|
}
|
1025
1049
|
// Return First Contentful Paint or zero if not supported.
|
1026
1050
|
function getFcp() {
|
1027
|
-
|
1028
|
-
|
1029
|
-
|
1030
|
-
|
1031
|
-
|
1032
|
-
for (
|
1033
|
-
var arr = perf.getEntriesByType("paint"), i = 0;
|
1034
|
-
i < arr.length;
|
1035
|
-
i++
|
1036
|
-
) {
|
1037
|
-
var ppt = arr[i]; // PerformancePaintTiming object
|
1038
|
-
if ("first-contentful-paint" === ppt.name) {
|
1039
|
-
return Math.round(ppt.startTime);
|
1040
|
-
}
|
1051
|
+
var paintEntries = getEntriesByType("paint");
|
1052
|
+
for (var i = 0; i < paintEntries.length; i++) {
|
1053
|
+
var entry = paintEntries[i];
|
1054
|
+
if (entry.name === "first-contentful-paint") {
|
1055
|
+
return Math.round(entry.startTime);
|
1041
1056
|
}
|
1042
1057
|
}
|
1043
1058
|
return 0;
|
@@ -1049,6 +1064,7 @@
|
|
1049
1064
|
for (var i = gaPerfEntries.length - 1; i >= 0; i--) {
|
1050
1065
|
var pe = gaPerfEntries[i];
|
1051
1066
|
if ("largest-contentful-paint" === pe.entryType) {
|
1067
|
+
logger.logEvent(LogEvent.PerformanceEntryProcessed, [pe]);
|
1052
1068
|
return Math.round(pe.startTime);
|
1053
1069
|
}
|
1054
1070
|
}
|
@@ -1059,31 +1075,24 @@
|
|
1059
1075
|
// Mostly works on just Chrome and IE.
|
1060
1076
|
// Return null if not supported.
|
1061
1077
|
function getStartRender() {
|
1062
|
-
if (
|
1063
|
-
var t =
|
1078
|
+
if (performance.timing) {
|
1079
|
+
var t = timing;
|
1064
1080
|
var ns = t.navigationStart;
|
1065
1081
|
var startRender = void 0;
|
1066
1082
|
if (ns) {
|
1067
|
-
|
1068
|
-
|
1069
|
-
perf.getEntriesByType &&
|
1070
|
-
perf.getEntriesByType("paint").length
|
1071
|
-
) {
|
1083
|
+
var paintEntries = getEntriesByType("paint");
|
1084
|
+
if (paintEntries.length) {
|
1072
1085
|
// If Paint Timing API is supported, use it.
|
1073
|
-
for (
|
1074
|
-
var
|
1075
|
-
|
1076
|
-
|
1077
|
-
) {
|
1078
|
-
var ppt = arr[i]; // PerformancePaintTiming object
|
1079
|
-
if ("first-paint" === ppt.name) {
|
1080
|
-
startRender = Math.round(ppt.startTime);
|
1086
|
+
for (var i = 0; i < paintEntries.length; i++) {
|
1087
|
+
var entry = paintEntries[i];
|
1088
|
+
if (entry.name === "first-paint") {
|
1089
|
+
startRender = Math.round(entry.startTime);
|
1081
1090
|
break;
|
1082
1091
|
}
|
1083
1092
|
}
|
1084
1093
|
} else if (
|
1085
1094
|
window.chrome &&
|
1086
|
-
|
1095
|
+
typeof window.chrome.loadTimes === "function"
|
1087
1096
|
) {
|
1088
1097
|
// If chrome, get first paint time from `chrome.loadTimes`. Need extra error handling.
|
1089
1098
|
var loadTimes = window.chrome.loadTimes();
|
@@ -1094,9 +1103,9 @@
|
|
1094
1103
|
// If IE/Edge, use the prefixed `msFirstPaint` property (see http://msdn.microsoft.com/ff974719).
|
1095
1104
|
startRender = Math.round(t.msFirstPaint - ns);
|
1096
1105
|
}
|
1097
|
-
|
1098
|
-
|
1099
|
-
|
1106
|
+
}
|
1107
|
+
if (startRender) {
|
1108
|
+
return startRender;
|
1100
1109
|
}
|
1101
1110
|
}
|
1102
1111
|
logger.logEvent(LogEvent.PaintTimingNotSupported);
|
@@ -1185,15 +1194,9 @@
|
|
1185
1194
|
}
|
1186
1195
|
// Return the main HTML document transfer size (in bytes).
|
1187
1196
|
function docSize() {
|
1188
|
-
|
1189
|
-
|
1190
|
-
|
1191
|
-
perf.getEntriesByType("navigation").length
|
1192
|
-
) {
|
1193
|
-
var aEntries = performance.getEntriesByType("navigation");
|
1194
|
-
if (aEntries && aEntries.length > 0 && aEntries[0]["encodedBodySize"]) {
|
1195
|
-
return aEntries[0]["encodedBodySize"];
|
1196
|
-
}
|
1197
|
+
var aEntries = getEntriesByType("navigation");
|
1198
|
+
if (aEntries.length && aEntries[0]["encodedBodySize"]) {
|
1199
|
+
return aEntries[0]["encodedBodySize"];
|
1197
1200
|
}
|
1198
1201
|
return 0; // ERROR - NOT FOUND
|
1199
1202
|
}
|
@@ -1201,11 +1204,10 @@
|
|
1201
1204
|
// Return empty string if not available.
|
1202
1205
|
function navigationType() {
|
1203
1206
|
if (
|
1204
|
-
|
1205
|
-
|
1206
|
-
"undefined" != typeof perf.navigation.type
|
1207
|
+
performance.navigation &&
|
1208
|
+
typeof performance.navigation.type !== "undefined"
|
1207
1209
|
) {
|
1208
|
-
return
|
1210
|
+
return performance.navigation.type;
|
1209
1211
|
}
|
1210
1212
|
return "";
|
1211
1213
|
}
|
@@ -1310,19 +1312,31 @@
|
|
1310
1312
|
function _markLoadTime() {
|
1311
1313
|
_mark(gEndMark);
|
1312
1314
|
}
|
1315
|
+
function createMaxMeasureTimeout() {
|
1316
|
+
clearMaxMeasureTimeout();
|
1317
|
+
gMaxMeasureTimeout = window.setTimeout(function () {
|
1318
|
+
gFlags = addFlag(gFlags, Flags.BeaconSentAfterTimeout);
|
1319
|
+
_sendLux();
|
1320
|
+
}, userConfig.maxMeasureTime - _now());
|
1321
|
+
}
|
1322
|
+
function clearMaxMeasureTimeout() {
|
1323
|
+
if (gMaxMeasureTimeout) {
|
1324
|
+
clearTimeout(gMaxMeasureTimeout);
|
1325
|
+
}
|
1326
|
+
}
|
1313
1327
|
// Beacon back the LUX data.
|
1314
1328
|
function _sendLux() {
|
1315
|
-
|
1329
|
+
clearMaxMeasureTimeout();
|
1316
1330
|
var customerid = getCustomerId();
|
1317
1331
|
if (
|
1318
1332
|
!customerid ||
|
1319
1333
|
!gSyncId ||
|
1320
|
-
!validDomain() ||
|
1321
1334
|
!_sample() || // OUTSIDE the sampled range
|
1322
1335
|
gbLuxSent // LUX data already sent
|
1323
1336
|
) {
|
1324
1337
|
return;
|
1325
1338
|
}
|
1339
|
+
logger.logEvent(LogEvent.DataCollectionStart);
|
1326
1340
|
var startMark = _getMark(gStartMark);
|
1327
1341
|
var endMark = _getMark(gEndMark);
|
1328
1342
|
if (!startMark || (endMark && endMark.startTime < startMark.startTime)) {
|
@@ -1472,7 +1486,6 @@
|
|
1472
1486
|
if (
|
1473
1487
|
!customerid ||
|
1474
1488
|
!gSyncId ||
|
1475
|
-
!validDomain() ||
|
1476
1489
|
!_sample() || // OUTSIDE the sampled range
|
1477
1490
|
gbIxSent || // IX data already sent
|
1478
1491
|
!gbLuxSent // LUX has NOT been sent yet, so wait to include it there
|
@@ -1514,7 +1527,6 @@
|
|
1514
1527
|
if (
|
1515
1528
|
!customerid ||
|
1516
1529
|
!gSyncId ||
|
1517
|
-
!validDomain() ||
|
1518
1530
|
!_sample() || // OUTSIDE the sampled range
|
1519
1531
|
!gbLuxSent // LUX has NOT been sent yet, so wait to include it there
|
1520
1532
|
) {
|
@@ -1599,14 +1611,14 @@
|
|
1599
1611
|
function _scrollHandler() {
|
1600
1612
|
// Leave handlers IN PLACE so we can track which ID is clicked/keyed.
|
1601
1613
|
// _removeIxHandlers();
|
1602
|
-
if (
|
1614
|
+
if (typeof ghIx["s"] === "undefined") {
|
1603
1615
|
ghIx["s"] = Math.round(_now());
|
1604
1616
|
// _sendIx(); // wait for key or click to send the IX beacon
|
1605
1617
|
}
|
1606
1618
|
}
|
1607
1619
|
function _keyHandler(e) {
|
1608
1620
|
_removeIxHandlers();
|
1609
|
-
if (
|
1621
|
+
if (typeof ghIx["k"] === "undefined") {
|
1610
1622
|
ghIx["k"] = Math.round(_now());
|
1611
1623
|
if (e && e.target) {
|
1612
1624
|
var trackId = interactionAttributionForElement(e.target);
|
@@ -1619,7 +1631,7 @@
|
|
1619
1631
|
}
|
1620
1632
|
function _clickHandler(e) {
|
1621
1633
|
_removeIxHandlers();
|
1622
|
-
if (
|
1634
|
+
if (typeof ghIx["c"] === "undefined") {
|
1623
1635
|
ghIx["c"] = Math.round(_now());
|
1624
1636
|
var target = null;
|
1625
1637
|
try {
|
@@ -1672,6 +1684,7 @@
|
|
1672
1684
|
function _addUnloadHandlers() {
|
1673
1685
|
var onunload = function () {
|
1674
1686
|
gFlags = addFlag(gFlags, Flags.BeaconSentFromUnloadHandler);
|
1687
|
+
logger.logEvent(LogEvent.UnloadHandlerTriggered);
|
1675
1688
|
_sendLux();
|
1676
1689
|
_sendIx();
|
1677
1690
|
};
|
@@ -1775,14 +1788,6 @@
|
|
1775
1788
|
gFlags = addFlag(gFlags, Flags.PageLabelFromDocumentTitle);
|
1776
1789
|
return document.title;
|
1777
1790
|
}
|
1778
|
-
// Return true if the hostname of the current page is one of the listed domains.
|
1779
|
-
function validDomain() {
|
1780
|
-
// Our signup process is such that a customer almost always deploys lux.js BEFORE we
|
1781
|
-
// enable LUX for their account. In which case, the list of domains is empty and no
|
1782
|
-
// beacons will be sent. Further, that version of lux.js will be cached at the CDN
|
1783
|
-
// and browser for a week. Instead, do the domain validation on the backend in VCL.
|
1784
|
-
return true;
|
1785
|
-
}
|
1786
1791
|
function _getCookie(name) {
|
1787
1792
|
try {
|
1788
1793
|
// Seeing "Permission denied" errors, so do a simple try-catch.
|
@@ -1818,15 +1823,29 @@
|
|
1818
1823
|
// Set "LUX.auto=false" to disable send results automatically and
|
1819
1824
|
// instead you must call LUX.send() explicitly.
|
1820
1825
|
if (userConfig.auto) {
|
1821
|
-
|
1822
|
-
|
1823
|
-
|
1824
|
-
|
1825
|
-
|
1826
|
-
|
1827
|
-
|
1828
|
-
|
1829
|
-
|
1826
|
+
var sendBeaconAfterMinimumMeasureTime_1 = function () {
|
1827
|
+
var elapsedTime = _now();
|
1828
|
+
var timeRemaining = userConfig.minMeasureTime - elapsedTime;
|
1829
|
+
if (timeRemaining <= 0) {
|
1830
|
+
logger.logEvent(LogEvent.OnloadHandlerTriggered, [
|
1831
|
+
elapsedTime,
|
1832
|
+
userConfig.minMeasureTime,
|
1833
|
+
]);
|
1834
|
+
if (document.readyState === "complete") {
|
1835
|
+
// If onload has already passed, send the beacon now.
|
1836
|
+
_sendLux();
|
1837
|
+
} else {
|
1838
|
+
// Ow, send the beacon slightly after window.onload.
|
1839
|
+
addListener("load", function () {
|
1840
|
+
setTimeout(_sendLux, 200);
|
1841
|
+
});
|
1842
|
+
}
|
1843
|
+
} else {
|
1844
|
+
// Try again after the minimum measurement time has elapsed
|
1845
|
+
setTimeout(sendBeaconAfterMinimumMeasureTime_1, timeRemaining);
|
1846
|
+
}
|
1847
|
+
};
|
1848
|
+
sendBeaconAfterMinimumMeasureTime_1();
|
1830
1849
|
}
|
1831
1850
|
// Add the unload handlers for auto mode, or when LUX.measureUntil is "pagehidden"
|
1832
1851
|
if (userConfig.sendBeaconOnPageHidden) {
|
@@ -1834,6 +1853,8 @@
|
|
1834
1853
|
}
|
1835
1854
|
// Regardless of userConfig.auto, we need to register the IX handlers immediately.
|
1836
1855
|
_addIxHandlers();
|
1856
|
+
// Set the maximum measurement timer
|
1857
|
+
createMaxMeasureTimeout();
|
1837
1858
|
// This is the public API.
|
1838
1859
|
var _LUX = userConfig;
|
1839
1860
|
// Functions
|
@@ -1841,7 +1862,10 @@
|
|
1841
1862
|
_LUX.measure = _measure;
|
1842
1863
|
_LUX.init = _init;
|
1843
1864
|
_LUX.markLoadTime = _markLoadTime;
|
1844
|
-
_LUX.send =
|
1865
|
+
_LUX.send = function () {
|
1866
|
+
logger.logEvent(LogEvent.SendCalled);
|
1867
|
+
_sendLux();
|
1868
|
+
};
|
1845
1869
|
_LUX.addData = _addData;
|
1846
1870
|
_LUX.getSessionId = _getUniqueId; // so customers can do their own sampling
|
1847
1871
|
_LUX.getDebug = function () {
|
@@ -1883,7 +1907,7 @@
|
|
1883
1907
|
return _LUX;
|
1884
1908
|
})();
|
1885
1909
|
window.LUX = LUX;
|
1886
|
-
|
1910
|
+
LUX_t_end = now();
|
1887
1911
|
|
1888
1912
|
// ---------------------------------------------------------------------------
|
1889
1913
|
// More settings
|
@@ -107,20 +107,19 @@
|
|
107
107
|
<% if edit_link && delete_link %>
|
108
108
|
<%= tag.dd class: "govuk-summary-list__actions" do %>
|
109
109
|
<%= tag.ul class: "govuk-summary-list__actions-list" do %>
|
110
|
-
<% if
|
110
|
+
<% if edit_link %>
|
111
111
|
<%= tag.li class: "govuk-summary-list__actions-list-item" do %>
|
112
112
|
<%= edit_link %>
|
113
113
|
<% end %>
|
114
114
|
<% end %>
|
115
|
-
<% if
|
115
|
+
<% if delete_link %>
|
116
116
|
<%= tag.li class: "govuk-summary-list__actions-list-item" do %>
|
117
117
|
<%= delete_link %>
|
118
118
|
<% end %>
|
119
119
|
<% end %>
|
120
120
|
<% end %>
|
121
121
|
<% end %>
|
122
|
-
<%
|
123
|
-
<% if edit_link || delete_link %>
|
122
|
+
<% elsif edit_link || delete_link %>
|
124
123
|
<%= tag.dd class: "govuk-summary-list__actions" do %>
|
125
124
|
<%= edit_link %>
|
126
125
|
<%= delete_link %>
|
@@ -130,7 +129,7 @@
|
|
130
129
|
<% end %>
|
131
130
|
<% end %>
|
132
131
|
<% end %>
|
133
|
-
|
132
|
+
|
134
133
|
<%= tag.div block, class: "gem-c-summary__block" if block %>
|
135
134
|
<% end %>
|
136
135
|
<% 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: 29.
|
4
|
+
version: 29.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: 2022-05-
|
11
|
+
date: 2022-05-19 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: govuk_app_config
|
@@ -1893,7 +1893,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
1893
1893
|
- !ruby/object:Gem::Version
|
1894
1894
|
version: '0'
|
1895
1895
|
requirements: []
|
1896
|
-
rubygems_version: 3.3.
|
1896
|
+
rubygems_version: 3.3.14
|
1897
1897
|
signing_key:
|
1898
1898
|
specification_version: 4
|
1899
1899
|
summary: A gem to document components in GOV.UK frontend applications
|