govuk_publishing_components 35.3.5 → 35.4.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/javascripts/component_guide/audit-filter.js +81 -0
- data/app/assets/javascripts/govuk_publishing_components/analytics-ga4/ga4-link-tracker.js +4 -3
- data/app/assets/javascripts/govuk_publishing_components/analytics-ga4/ga4-specialist-link-tracker.js +5 -1
- data/app/assets/javascripts/govuk_publishing_components/components/step-by-step-nav.js +1 -1
- data/app/assets/javascripts/govuk_publishing_components/vendor/lux/lux-reporter.js +245 -176
- data/app/assets/stylesheets/component_guide/application.scss +16 -0
- data/app/assets/stylesheets/govuk_publishing_components/components/_layout-super-navigation-header.scss +0 -5
- data/app/assets/stylesheets/govuk_publishing_components/components/_search.scss +0 -12
- data/app/assets/stylesheets/govuk_publishing_components/components/govspeak/_attachment.scss +0 -11
- data/app/models/govuk_publishing_components/audit_applications.rb +14 -0
- data/app/models/govuk_publishing_components/audit_comparer.rb +14 -0
- data/app/models/govuk_publishing_components/audit_components.rb +34 -32
- data/app/views/govuk_publishing_components/audit/_applications.html.erb +40 -32
- data/app/views/govuk_publishing_components/audit/_component_contents.html.erb +56 -12
- data/app/views/govuk_publishing_components/audit/_components.html.erb +9 -7
- data/app/views/govuk_publishing_components/audit/show.html.erb +5 -1
- data/app/views/govuk_publishing_components/components/_hint.html.erb +5 -1
- data/app/views/govuk_publishing_components/components/_label.html.erb +6 -6
- data/app/views/govuk_publishing_components/components/docs/hint.yml +1 -1
- data/lib/generators/govuk_publishing_components/component_generator.rb +2 -2
- data/lib/govuk_publishing_components/presenters/related_navigation_helper.rb +8 -8
- data/lib/govuk_publishing_components/version.rb +1 -1
- data/node_modules/axe-core/README.md +1 -3
- data/node_modules/axe-core/axe.js +4385 -1157
- data/node_modules/axe-core/axe.min.js +2 -2
- data/node_modules/axe-core/locales/_template.json +12 -0
- data/node_modules/axe-core/package.json +2 -1
- data/node_modules/axe-core/sri-history.json +4 -0
- metadata +3 -2
|
@@ -42,9 +42,10 @@
|
|
|
42
42
|
var autoMode = getProperty(obj, "auto", true);
|
|
43
43
|
return {
|
|
44
44
|
auto: autoMode,
|
|
45
|
+
autoWhenHidden: getProperty(obj, "autoWhenHidden", false),
|
|
45
46
|
beaconUrl: getProperty(obj, "beaconUrl", "https://lux.speedcurve.com/lux/"),
|
|
47
|
+
conversions: getProperty(obj, "conversions", undefined),
|
|
46
48
|
customerid: getProperty(obj, "customerid", undefined),
|
|
47
|
-
debug: getProperty(obj, "debug", false),
|
|
48
49
|
errorBeaconUrl: getProperty(obj, "errorBeaconUrl", "https://lux.speedcurve.com/error/"),
|
|
49
50
|
jspagelabel: getProperty(obj, "jspagelabel", undefined),
|
|
50
51
|
label: getProperty(obj, "label", undefined),
|
|
@@ -52,7 +53,6 @@
|
|
|
52
53
|
maxBeaconUTEntries: getProperty(obj, "maxBeaconUTEntries", 20),
|
|
53
54
|
maxErrors: getProperty(obj, "maxErrors", 5),
|
|
54
55
|
maxMeasureTime: getProperty(obj, "maxMeasureTime", 60000),
|
|
55
|
-
measureUntil: getProperty(obj, "measureUntil", "onload"),
|
|
56
56
|
minMeasureTime: getProperty(obj, "minMeasureTime", 0),
|
|
57
57
|
samplerate: getProperty(obj, "samplerate", 100),
|
|
58
58
|
sendBeaconOnPageHidden: getProperty(obj, "sendBeaconOnPageHidden", autoMode),
|
|
@@ -69,6 +69,7 @@
|
|
|
69
69
|
|
|
70
70
|
var START_MARK = "LUX_start";
|
|
71
71
|
var END_MARK = "LUX_end";
|
|
72
|
+
var BOOLEAN_TRUE = "true";
|
|
72
73
|
|
|
73
74
|
var customDataValues = {};
|
|
74
75
|
var updatedCustomData = {};
|
|
@@ -111,6 +112,104 @@
|
|
|
111
112
|
return encodeURIComponent(strings.join(","));
|
|
112
113
|
}
|
|
113
114
|
|
|
115
|
+
function floor(x) {
|
|
116
|
+
return Math.floor(x);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
function now() {
|
|
120
|
+
return Date.now ? Date.now() : +new Date();
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
var scriptStartTime = now();
|
|
124
|
+
|
|
125
|
+
var _a;
|
|
126
|
+
// If the various performance APIs aren't available, we export an empty object to
|
|
127
|
+
// prevent having to make regular typeof checks.
|
|
128
|
+
var performance = window.performance || {};
|
|
129
|
+
var timing = performance.timing || {
|
|
130
|
+
// If performance.timing isn't available, we attempt to polyfill the navigationStart value.
|
|
131
|
+
// Our first attempt is from LUX.ns, which is the time that the snippet execution began. If this
|
|
132
|
+
// is not available, we fall back to the time that the current script execution began.
|
|
133
|
+
navigationStart: ((_a = window.LUX) === null || _a === void 0 ? void 0 : _a.ns) || scriptStartTime,
|
|
134
|
+
};
|
|
135
|
+
function msSinceNavigationStart() {
|
|
136
|
+
if (performance.now) {
|
|
137
|
+
return floor(performance.now());
|
|
138
|
+
}
|
|
139
|
+
return now() - timing.navigationStart;
|
|
140
|
+
}
|
|
141
|
+
function navigationType() {
|
|
142
|
+
if (performance.navigation && typeof performance.navigation.type !== "undefined") {
|
|
143
|
+
return performance.navigation.type;
|
|
144
|
+
}
|
|
145
|
+
return "";
|
|
146
|
+
}
|
|
147
|
+
function getNavigationEntry() {
|
|
148
|
+
var navEntries = getEntriesByType("navigation");
|
|
149
|
+
if (navEntries.length) {
|
|
150
|
+
var entry_1 = navEntries[0];
|
|
151
|
+
entry_1.navigationStart = 0;
|
|
152
|
+
if (typeof entry_1.activationStart === "undefined") {
|
|
153
|
+
entry_1.activationStart = 0;
|
|
154
|
+
}
|
|
155
|
+
return entry_1;
|
|
156
|
+
}
|
|
157
|
+
var navType = navigationType();
|
|
158
|
+
var entry = {
|
|
159
|
+
navigationStart: 0,
|
|
160
|
+
activationStart: 0,
|
|
161
|
+
startTime: 0,
|
|
162
|
+
type: navType == 2 ? "back_forward" : navType === 1 ? "reload" : "navigate",
|
|
163
|
+
};
|
|
164
|
+
if (__ENABLE_POLYFILLS) {
|
|
165
|
+
for (var key in timing) {
|
|
166
|
+
if (typeof timing[key] === "number" && key !== "navigationStart") {
|
|
167
|
+
entry[key] = Math.max(0, timing[key] - timing.navigationStart);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
return entry;
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Simple wrapper around performance.getEntriesByType to provide fallbacks for
|
|
175
|
+
* legacy browsers, and work around edge cases where undefined is returned instead
|
|
176
|
+
* of an empty PerformanceEntryList.
|
|
177
|
+
*/
|
|
178
|
+
function getEntriesByType(type) {
|
|
179
|
+
if (typeof performance.getEntriesByType === "function") {
|
|
180
|
+
var entries = performance.getEntriesByType(type);
|
|
181
|
+
if (entries && entries.length) {
|
|
182
|
+
return entries;
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
return [];
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
function isVisible() {
|
|
189
|
+
if (document.visibilityState) {
|
|
190
|
+
return document.visibilityState === "visible";
|
|
191
|
+
}
|
|
192
|
+
// For browsers that don't support document.visibilityState, we assume the page is visible.
|
|
193
|
+
return true;
|
|
194
|
+
}
|
|
195
|
+
function onVisible(cb) {
|
|
196
|
+
if (isVisible()) {
|
|
197
|
+
cb();
|
|
198
|
+
}
|
|
199
|
+
else {
|
|
200
|
+
var onVisibleCallback_1 = function () {
|
|
201
|
+
if (isVisible()) {
|
|
202
|
+
cb();
|
|
203
|
+
removeEventListener("visibilitychange", onVisibleCallback_1);
|
|
204
|
+
}
|
|
205
|
+
};
|
|
206
|
+
addEventListener("visibilitychange", onVisibleCallback_1, true);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
function wasPrerendered() {
|
|
210
|
+
return document.prerendering || getNavigationEntry().activationStart > 0;
|
|
211
|
+
}
|
|
212
|
+
|
|
114
213
|
var Flags = {
|
|
115
214
|
InitCalled: 1 << 0,
|
|
116
215
|
NavTimingNotSupported: 1 << 1,
|
|
@@ -122,6 +221,7 @@
|
|
|
122
221
|
PageLabelFromLabelProp: 1 << 7,
|
|
123
222
|
PageLabelFromGlobalVariable: 1 << 8,
|
|
124
223
|
PageLabelFromPagegroup: 1 << 9,
|
|
224
|
+
PageWasPrerendered: 1 << 10,
|
|
125
225
|
};
|
|
126
226
|
function addFlag(flags, flag) {
|
|
127
227
|
return flags | flag;
|
|
@@ -177,10 +277,6 @@
|
|
|
177
277
|
return null;
|
|
178
278
|
}
|
|
179
279
|
|
|
180
|
-
function now() {
|
|
181
|
-
return Date.now ? Date.now() : +new Date();
|
|
182
|
-
}
|
|
183
|
-
|
|
184
280
|
var LogEvent = {
|
|
185
281
|
// Internal events
|
|
186
282
|
EvaluationStart: 1,
|
|
@@ -254,65 +350,6 @@
|
|
|
254
350
|
return sessionValue;
|
|
255
351
|
}
|
|
256
352
|
|
|
257
|
-
var scriptStartTime = now();
|
|
258
|
-
|
|
259
|
-
var _a;
|
|
260
|
-
// If the various performance APIs aren't available, we export an empty object to
|
|
261
|
-
// prevent having to make regular typeof checks.
|
|
262
|
-
var performance = window.performance || {};
|
|
263
|
-
var timing = performance.timing || {
|
|
264
|
-
// If performance.timing isn't available, we attempt to polyfill the navigationStart value.
|
|
265
|
-
// Our first attempt is from LUX.ns, which is the time that the snippet execution began. If this
|
|
266
|
-
// is not available, we fall back to the time that the current script execution began.
|
|
267
|
-
navigationStart: ((_a = window.LUX) === null || _a === void 0 ? void 0 : _a.ns) || scriptStartTime,
|
|
268
|
-
};
|
|
269
|
-
function msSinceNavigationStart() {
|
|
270
|
-
if (performance.now) {
|
|
271
|
-
return performance.now();
|
|
272
|
-
}
|
|
273
|
-
return now() - timing.navigationStart;
|
|
274
|
-
}
|
|
275
|
-
function navigationType() {
|
|
276
|
-
if (performance.navigation && typeof performance.navigation.type !== "undefined") {
|
|
277
|
-
return performance.navigation.type;
|
|
278
|
-
}
|
|
279
|
-
return "";
|
|
280
|
-
}
|
|
281
|
-
function getNavigationEntry() {
|
|
282
|
-
var navEntries = getEntriesByType("navigation");
|
|
283
|
-
if (navEntries.length) {
|
|
284
|
-
return navEntries[0];
|
|
285
|
-
}
|
|
286
|
-
var navType = navigationType();
|
|
287
|
-
var entry = {
|
|
288
|
-
activationStart: 0,
|
|
289
|
-
startTime: 0,
|
|
290
|
-
type: navType == 2 ? "back_forward" : navType === 1 ? "reload" : "navigate",
|
|
291
|
-
};
|
|
292
|
-
if (__ENABLE_POLYFILLS) {
|
|
293
|
-
for (var key in timing) {
|
|
294
|
-
if (typeof timing[key] === "number" && key !== "navigationStart") {
|
|
295
|
-
entry[key] = Math.max(0, timing[key] - timing.navigationStart);
|
|
296
|
-
}
|
|
297
|
-
}
|
|
298
|
-
}
|
|
299
|
-
return entry;
|
|
300
|
-
}
|
|
301
|
-
/**
|
|
302
|
-
* Simple wrapper around performance.getEntriesByType to provide fallbacks for
|
|
303
|
-
* legacy browsers, and work around edge cases where undefined is returned instead
|
|
304
|
-
* of an empty PerformanceEntryList.
|
|
305
|
-
*/
|
|
306
|
-
function getEntriesByType(type) {
|
|
307
|
-
if (typeof performance.getEntriesByType === "function") {
|
|
308
|
-
var entries = performance.getEntriesByType(type);
|
|
309
|
-
if (entries && entries.length) {
|
|
310
|
-
return entries;
|
|
311
|
-
}
|
|
312
|
-
}
|
|
313
|
-
return [];
|
|
314
|
-
}
|
|
315
|
-
|
|
316
353
|
/**
|
|
317
354
|
* This implementation is based on the web-vitals implementation, however it is stripped back to the
|
|
318
355
|
* bare minimum required to measure just the INP value and does not store the actual event entries.
|
|
@@ -342,7 +379,7 @@
|
|
|
342
379
|
slowestEntriesMap[interactionId] = { duration: duration, interactionId: interactionId, startTime: startTime };
|
|
343
380
|
slowestEntries.push(slowestEntriesMap[interactionId]);
|
|
344
381
|
}
|
|
345
|
-
|
|
382
|
+
// Only store the longest <MAX_INTERACTIONS> interactions
|
|
346
383
|
slowestEntries.sort(function (a, b) { return b.duration - a.duration; });
|
|
347
384
|
slowestEntries.splice(MAX_INTERACTIONS).forEach(function (entry) {
|
|
348
385
|
delete slowestEntriesMap[entry.interactionId];
|
|
@@ -368,6 +405,18 @@
|
|
|
368
405
|
return interactionCountEstimate;
|
|
369
406
|
}
|
|
370
407
|
|
|
408
|
+
/**
|
|
409
|
+
* Get the number of milliseconds between navigationStart and the given PerformanceNavigationTiming key
|
|
410
|
+
*/
|
|
411
|
+
function getNavTimingValue(key) {
|
|
412
|
+
var navEntry = getNavigationEntry();
|
|
413
|
+
var relativeTo = key === "activationStart" ? 0 : navEntry.activationStart;
|
|
414
|
+
if (typeof navEntry[key] === "number") {
|
|
415
|
+
return Math.max(0, navEntry[key] - relativeTo);
|
|
416
|
+
}
|
|
417
|
+
return undefined;
|
|
418
|
+
}
|
|
419
|
+
|
|
371
420
|
/******************************************************************************
|
|
372
421
|
Copyright (c) Microsoft Corporation.
|
|
373
422
|
|
|
@@ -416,6 +465,27 @@
|
|
|
416
465
|
ALL_ENTRIES.splice(0);
|
|
417
466
|
}
|
|
418
467
|
|
|
468
|
+
function getMatchesFromPatternMap(patternMap, hostname, pathname, firstOnly) {
|
|
469
|
+
var matches = [];
|
|
470
|
+
for (var key in patternMap) {
|
|
471
|
+
var patterns = patternMap[key];
|
|
472
|
+
if (Array.isArray(patterns)) {
|
|
473
|
+
for (var i in patterns) {
|
|
474
|
+
var pattern = patterns[i];
|
|
475
|
+
if (patternMatchesUrl(pattern, hostname, pathname)) {
|
|
476
|
+
if (firstOnly) {
|
|
477
|
+
return key;
|
|
478
|
+
}
|
|
479
|
+
matches.push(key);
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
if (firstOnly) {
|
|
485
|
+
return undefined;
|
|
486
|
+
}
|
|
487
|
+
return matches;
|
|
488
|
+
}
|
|
419
489
|
function patternMatchesUrl(pattern, hostname, pathname) {
|
|
420
490
|
var regex = createRegExpFromPattern(pattern);
|
|
421
491
|
if (pattern.charAt(0) === "/") {
|
|
@@ -444,7 +514,7 @@
|
|
|
444
514
|
// -------------------------------------------------------------------------
|
|
445
515
|
/// End
|
|
446
516
|
// -------------------------------------------------------------------------
|
|
447
|
-
var SCRIPT_VERSION = "
|
|
517
|
+
var SCRIPT_VERSION = "308";
|
|
448
518
|
var logger = new Logger();
|
|
449
519
|
var globalConfig = fromObject(LUX);
|
|
450
520
|
logger.logEvent(LogEvent.EvaluationStart, [SCRIPT_VERSION]);
|
|
@@ -542,6 +612,7 @@
|
|
|
542
612
|
var gUid = refreshUniqueId(gSyncId); // cookie for this session ("Unique ID")
|
|
543
613
|
var gCustomerDataTimeout; // setTimeout timer for sending a Customer Data beacon after onload
|
|
544
614
|
var gMaxMeasureTimeout; // setTimeout timer for sending the beacon after a maximum measurement time
|
|
615
|
+
var navEntry = getNavigationEntry();
|
|
545
616
|
if (_sample()) {
|
|
546
617
|
logger.logEvent(LogEvent.SessionIsSampled, [globalConfig.samplerate]);
|
|
547
618
|
}
|
|
@@ -564,7 +635,7 @@
|
|
|
564
635
|
// Record the FIRST input delay.
|
|
565
636
|
function recordDelay(delay) {
|
|
566
637
|
if (!gFirstInputDelay) {
|
|
567
|
-
gFirstInputDelay =
|
|
638
|
+
gFirstInputDelay = delay;
|
|
568
639
|
// remove event listeners
|
|
569
640
|
gaEventTypes.forEach(function (eventType) {
|
|
570
641
|
removeEventListener(eventType, onInput, ghListenerOptions);
|
|
@@ -631,12 +702,12 @@
|
|
|
631
702
|
});
|
|
632
703
|
////////////////////// FID END
|
|
633
704
|
/**
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
705
|
+
* Returns the time elapsed (in ms) since navigationStart. For SPAs, returns
|
|
706
|
+
* the time elapsed since the last LUX.init call.
|
|
707
|
+
*
|
|
708
|
+
* When `absolute = true` the time is always relative to navigationStart, even
|
|
709
|
+
* in SPAs.
|
|
710
|
+
*/
|
|
640
711
|
function _now(absolute) {
|
|
641
712
|
var sinceNavigationStart = msSinceNavigationStart();
|
|
642
713
|
var startMark = _getMark(START_MARK);
|
|
@@ -737,9 +808,9 @@
|
|
|
737
808
|
if (startMark) {
|
|
738
809
|
startTime = startMark.startTime;
|
|
739
810
|
}
|
|
740
|
-
else if (
|
|
811
|
+
else if (typeof navEntry[startMarkName] === "number") {
|
|
741
812
|
// the mark name can also be a property from Navigation Timing
|
|
742
|
-
startTime =
|
|
813
|
+
startTime = navEntry[startMarkName];
|
|
743
814
|
}
|
|
744
815
|
else {
|
|
745
816
|
throwError(startMarkName);
|
|
@@ -750,15 +821,15 @@
|
|
|
750
821
|
if (endMark) {
|
|
751
822
|
endTime = endMark.startTime;
|
|
752
823
|
}
|
|
753
|
-
else if (
|
|
824
|
+
else if (typeof navEntry[endMarkName] === "number") {
|
|
754
825
|
// the mark name can also be a property from Navigation Timing
|
|
755
|
-
endTime =
|
|
826
|
+
endTime = navEntry[endMarkName];
|
|
756
827
|
}
|
|
757
828
|
else {
|
|
758
829
|
throwError(endMarkName);
|
|
759
830
|
}
|
|
760
831
|
}
|
|
761
|
-
var duration =
|
|
832
|
+
var duration = endTime - startTime;
|
|
762
833
|
var detail = null;
|
|
763
834
|
if (options) {
|
|
764
835
|
if (options.duration) {
|
|
@@ -826,7 +897,7 @@
|
|
|
826
897
|
// Don't include the internal marks in the beacon
|
|
827
898
|
return;
|
|
828
899
|
}
|
|
829
|
-
var startTime =
|
|
900
|
+
var startTime = floor(mark.startTime - tZero);
|
|
830
901
|
if (startTime < 0) {
|
|
831
902
|
// Exclude marks that were taken before the current SPA page view
|
|
832
903
|
return;
|
|
@@ -845,8 +916,8 @@
|
|
|
845
916
|
return;
|
|
846
917
|
}
|
|
847
918
|
var name = measure.name;
|
|
848
|
-
var startTime =
|
|
849
|
-
var duration =
|
|
919
|
+
var startTime = floor(measure.startTime - tZero);
|
|
920
|
+
var duration = floor(measure.duration);
|
|
850
921
|
if (typeof hUT[name] === "undefined" || startTime > hUT[name].startTime) {
|
|
851
922
|
hUT[name] = { startTime: startTime, duration: duration };
|
|
852
923
|
}
|
|
@@ -872,7 +943,7 @@
|
|
|
872
943
|
getEntries("element").forEach(function (entry) {
|
|
873
944
|
if (entry.identifier && entry.startTime) {
|
|
874
945
|
logger.logEvent(LogEvent.PerformanceEntryProcessed, [entry]);
|
|
875
|
-
aET.push(entry.identifier + "|" +
|
|
946
|
+
aET.push(entry.identifier + "|" + floor(entry.startTime - tZero));
|
|
876
947
|
}
|
|
877
948
|
});
|
|
878
949
|
return aET.join(",");
|
|
@@ -904,7 +975,7 @@
|
|
|
904
975
|
}
|
|
905
976
|
}
|
|
906
977
|
longTaskEntries.forEach(function (entry) {
|
|
907
|
-
var dur =
|
|
978
|
+
var dur = floor(entry.duration);
|
|
908
979
|
if (entry.startTime < tZero_1) {
|
|
909
980
|
// In a SPA it is possible that we were in the middle of a Long Task when
|
|
910
981
|
// LUX.init() was called. If so, only include the duration after tZero.
|
|
@@ -924,7 +995,7 @@
|
|
|
924
995
|
}
|
|
925
996
|
hCPU[type] += dur;
|
|
926
997
|
// Send back the raw startTime and duration, as well as the adjusted duration.
|
|
927
|
-
hCPUDetails[type] += "," +
|
|
998
|
+
hCPUDetails[type] += "," + floor(entry.startTime) + "|" + dur;
|
|
928
999
|
});
|
|
929
1000
|
}
|
|
930
1001
|
// TODO - Add more types if/when they become available.
|
|
@@ -942,7 +1013,7 @@
|
|
|
942
1013
|
",x|" +
|
|
943
1014
|
hStats["max"] +
|
|
944
1015
|
(0 === hStats["fci"] ? "" : ",i|" + hStats["fci"]); // only add FCI if it is non-zero
|
|
945
|
-
|
|
1016
|
+
sCPU += "s|" + hCPU[jsType] + sStats + hCPUDetails[jsType];
|
|
946
1017
|
return sCPU;
|
|
947
1018
|
}
|
|
948
1019
|
// Return a hash of "stats" about the CPU details incl. count, max, and median.
|
|
@@ -995,7 +1066,7 @@
|
|
|
995
1066
|
if (0 === aValues.length) {
|
|
996
1067
|
return 0;
|
|
997
1068
|
}
|
|
998
|
-
var half =
|
|
1069
|
+
var half = floor(aValues.length / 2);
|
|
999
1070
|
aValues.sort(function (a, b) {
|
|
1000
1071
|
return a - b;
|
|
1001
1072
|
});
|
|
@@ -1020,10 +1091,10 @@
|
|
|
1020
1091
|
var r = aResources[0];
|
|
1021
1092
|
// DO NOT USE DURATION!!!!!
|
|
1022
1093
|
// See https://www.stevesouders.com/blog/2014/11/25/serious-confusion-with-resource-timing/
|
|
1023
|
-
var dns =
|
|
1024
|
-
var tcp =
|
|
1025
|
-
var fb =
|
|
1026
|
-
var content =
|
|
1094
|
+
var dns = floor(r.domainLookupEnd - r.domainLookupStart);
|
|
1095
|
+
var tcp = floor(r.connectEnd - r.connectStart);
|
|
1096
|
+
var fb = floor(r.responseStart - r.requestStart);
|
|
1097
|
+
var content = floor(r.responseEnd - r.responseStart);
|
|
1027
1098
|
var networkDuration = dns + tcp + fb + content;
|
|
1028
1099
|
var parseEval = scriptEndTime - scriptStartTime;
|
|
1029
1100
|
var transferSize = r.encodedBodySize ? r.encodedBodySize : 0;
|
|
@@ -1149,8 +1220,8 @@
|
|
|
1149
1220
|
!e.async &&
|
|
1150
1221
|
!e.defer &&
|
|
1151
1222
|
0 !== (e.compareDocumentPosition(lastViewportElem) & 4)) {
|
|
1152
|
-
|
|
1153
|
-
|
|
1223
|
+
// If the script has a SRC and async is false and it occurs BEFORE the last viewport element,
|
|
1224
|
+
// then increment the counter.
|
|
1154
1225
|
num++;
|
|
1155
1226
|
}
|
|
1156
1227
|
}
|
|
@@ -1236,9 +1307,9 @@
|
|
|
1236
1307
|
var endMark = _getMark(END_MARK);
|
|
1237
1308
|
if (startMark && endMark) {
|
|
1238
1309
|
// This is a SPA page view, so send the SPA marks & measures instead of Nav Timing.
|
|
1239
|
-
var start =
|
|
1310
|
+
var start = floor(startMark.startTime); // the start mark is "zero"
|
|
1240
1311
|
ns += start; // "navigationStart" for a SPA is the real navigationStart plus the start mark
|
|
1241
|
-
var end =
|
|
1312
|
+
var end = floor(endMark.startTime) - start; // delta from start mark
|
|
1242
1313
|
s =
|
|
1243
1314
|
ns +
|
|
1244
1315
|
"fs" +
|
|
@@ -1251,38 +1322,44 @@
|
|
|
1251
1322
|
}
|
|
1252
1323
|
else if (performance.timing) {
|
|
1253
1324
|
// Return the real Nav Timing metrics because this is the "main" page view (not a SPA)
|
|
1254
|
-
var
|
|
1255
|
-
var
|
|
1256
|
-
var
|
|
1257
|
-
var
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
(
|
|
1267
|
-
(
|
|
1268
|
-
(
|
|
1269
|
-
(
|
|
1270
|
-
(
|
|
1271
|
-
(
|
|
1272
|
-
(
|
|
1273
|
-
(
|
|
1274
|
-
(
|
|
1275
|
-
(
|
|
1276
|
-
(
|
|
1277
|
-
(
|
|
1278
|
-
(
|
|
1279
|
-
(
|
|
1280
|
-
(
|
|
1281
|
-
""
|
|
1325
|
+
var startRender = getStartRender();
|
|
1326
|
+
var fcp = getFcp();
|
|
1327
|
+
var lcp = getLcp();
|
|
1328
|
+
var prefixNTValue = function (key, prefix) {
|
|
1329
|
+
var value = getNavTimingValue(key);
|
|
1330
|
+
if (typeof value === "undefined") {
|
|
1331
|
+
return "";
|
|
1332
|
+
}
|
|
1333
|
+
return prefix + value;
|
|
1334
|
+
};
|
|
1335
|
+
s = [
|
|
1336
|
+
ns,
|
|
1337
|
+
prefixNTValue("activationStart", "as"),
|
|
1338
|
+
prefixNTValue("redirectStart", "rs"),
|
|
1339
|
+
prefixNTValue("redirectEnd", "re"),
|
|
1340
|
+
prefixNTValue("fetchStart", "fs"),
|
|
1341
|
+
prefixNTValue("domainLookupStart", "ds"),
|
|
1342
|
+
prefixNTValue("domainLookupEnd", "de"),
|
|
1343
|
+
prefixNTValue("connectStart", "cs"),
|
|
1344
|
+
prefixNTValue("secureConnectionStart", "sc"),
|
|
1345
|
+
prefixNTValue("connectEnd", "ce"),
|
|
1346
|
+
prefixNTValue("requestStart", "qs"),
|
|
1347
|
+
prefixNTValue("responseStart", "bs"),
|
|
1348
|
+
prefixNTValue("responseEnd", "be"),
|
|
1349
|
+
prefixNTValue("domInteractive", "oi"),
|
|
1350
|
+
prefixNTValue("domContentLoadedEventStart", "os"),
|
|
1351
|
+
prefixNTValue("domContentLoadedEventEnd", "oe"),
|
|
1352
|
+
prefixNTValue("domComplete", "oc"),
|
|
1353
|
+
prefixNTValue("loadEventStart", "ls"),
|
|
1354
|
+
prefixNTValue("loadEventEnd", "le"),
|
|
1355
|
+
typeof startRender !== "undefined" ? "sr" + startRender : "",
|
|
1356
|
+
typeof fcp !== "undefined" ? "fc" + fcp : "",
|
|
1357
|
+
typeof lcp !== "undefined" ? "lc" + lcp : "",
|
|
1358
|
+
].join("");
|
|
1282
1359
|
}
|
|
1283
1360
|
else if (endMark) {
|
|
1284
1361
|
// This is a "main" page view that does NOT support Navigation Timing - strange.
|
|
1285
|
-
var end =
|
|
1362
|
+
var end = floor(endMark.startTime);
|
|
1286
1363
|
s =
|
|
1287
1364
|
ns +
|
|
1288
1365
|
"fs" +
|
|
@@ -1301,7 +1378,7 @@
|
|
|
1301
1378
|
for (var i = 0; i < paintEntries.length; i++) {
|
|
1302
1379
|
var entry = paintEntries[i];
|
|
1303
1380
|
if (entry.name === "first-contentful-paint") {
|
|
1304
|
-
return
|
|
1381
|
+
return floor(entry.startTime);
|
|
1305
1382
|
}
|
|
1306
1383
|
}
|
|
1307
1384
|
return undefined;
|
|
@@ -1312,7 +1389,7 @@
|
|
|
1312
1389
|
if (lcpEntries.length) {
|
|
1313
1390
|
var lastEntry = lcpEntries[lcpEntries.length - 1];
|
|
1314
1391
|
logger.logEvent(LogEvent.PerformanceEntryProcessed, [lastEntry]);
|
|
1315
|
-
return
|
|
1392
|
+
return floor(lastEntry.startTime);
|
|
1316
1393
|
}
|
|
1317
1394
|
return undefined;
|
|
1318
1395
|
}
|
|
@@ -1320,22 +1397,18 @@
|
|
|
1320
1397
|
// Mostly works on just Chrome and IE.
|
|
1321
1398
|
// Return undefined if not supported.
|
|
1322
1399
|
function getStartRender() {
|
|
1323
|
-
if (
|
|
1400
|
+
if ("PerformancePaintTiming" in self) {
|
|
1324
1401
|
var paintEntries = getEntriesByType("paint");
|
|
1325
1402
|
if (paintEntries.length) {
|
|
1326
|
-
// If Paint Timing API is supported, use
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
if (entry.name === "first-paint") {
|
|
1330
|
-
return Math.round(entry.startTime);
|
|
1331
|
-
}
|
|
1332
|
-
}
|
|
1333
|
-
}
|
|
1334
|
-
else if (timing.msFirstPaint && __ENABLE_POLYFILLS) {
|
|
1335
|
-
// If IE/Edge, use the prefixed `msFirstPaint` property (see http://msdn.microsoft.com/ff974719).
|
|
1336
|
-
return Math.round(timing.msFirstPaint - timing.navigationStart);
|
|
1403
|
+
// If the Paint Timing API is supported, use the value of the first paint event
|
|
1404
|
+
var paintValues = paintEntries.map(function (entry) { return entry.startTime; });
|
|
1405
|
+
return floor(Math.min.apply(null, paintValues));
|
|
1337
1406
|
}
|
|
1338
1407
|
}
|
|
1408
|
+
if (performance.timing && timing.msFirstPaint && __ENABLE_POLYFILLS) {
|
|
1409
|
+
// If IE/Edge, use the prefixed `msFirstPaint` property (see http://msdn.microsoft.com/ff974719).
|
|
1410
|
+
return floor(timing.msFirstPaint - timing.navigationStart);
|
|
1411
|
+
}
|
|
1339
1412
|
logger.logEvent(LogEvent.PaintTimingNotSupported);
|
|
1340
1413
|
return undefined;
|
|
1341
1414
|
}
|
|
@@ -1411,7 +1484,7 @@
|
|
|
1411
1484
|
}
|
|
1412
1485
|
// Return the main HTML document transfer size (in bytes).
|
|
1413
1486
|
function docSize() {
|
|
1414
|
-
return
|
|
1487
|
+
return navEntry.encodedBodySize || 0;
|
|
1415
1488
|
}
|
|
1416
1489
|
// Return the connection type based on Network Information API.
|
|
1417
1490
|
// Note this API is in flux.
|
|
@@ -1576,7 +1649,7 @@
|
|
|
1576
1649
|
if (!gbIxSent) {
|
|
1577
1650
|
sIx = ixValues();
|
|
1578
1651
|
if (sIx === "") {
|
|
1579
|
-
|
|
1652
|
+
// If there are no interaction metrics, we
|
|
1580
1653
|
INP = undefined;
|
|
1581
1654
|
}
|
|
1582
1655
|
}
|
|
@@ -1584,9 +1657,17 @@
|
|
|
1584
1657
|
var sCPU = cpuTimes();
|
|
1585
1658
|
var CLS = getCLS$1();
|
|
1586
1659
|
var sLuxjs = selfLoading();
|
|
1587
|
-
if (
|
|
1660
|
+
if (!isVisible()) {
|
|
1588
1661
|
gFlags = addFlag(gFlags, Flags.VisibilityStateNotVisible);
|
|
1589
1662
|
}
|
|
1663
|
+
if (wasPrerendered()) {
|
|
1664
|
+
gFlags = addFlag(gFlags, Flags.PageWasPrerendered);
|
|
1665
|
+
}
|
|
1666
|
+
if (LUX.conversions) {
|
|
1667
|
+
getMatchesFromPatternMap(LUX.conversions, location.hostname, location.pathname).forEach(function (conversion) {
|
|
1668
|
+
LUX.addData(conversion, BOOLEAN_TRUE);
|
|
1669
|
+
});
|
|
1670
|
+
}
|
|
1590
1671
|
// We want ALL beacons to have ALL the data used for query filters (geo, pagelabel, browser, & customerdata).
|
|
1591
1672
|
// So we create a base URL that has all the necessary information:
|
|
1592
1673
|
var baseUrl = _getBeaconUrl(getAllCustomData());
|
|
@@ -1676,7 +1757,7 @@
|
|
|
1676
1757
|
var sIx = ixValues(); // Interaction Metrics
|
|
1677
1758
|
var INP = getINP();
|
|
1678
1759
|
if (sIx) {
|
|
1679
|
-
|
|
1760
|
+
var beaconUrl = _getBeaconUrl(getUpdatedCustomData()) +
|
|
1680
1761
|
"&IX=" +
|
|
1681
1762
|
sIx +
|
|
1682
1763
|
(typeof gFirstInputDelay !== "undefined" ? "&FID=" + gFirstInputDelay : "") +
|
|
@@ -1718,13 +1799,13 @@
|
|
|
1718
1799
|
// Note for scroll input we don't remove the handlers or send the IX beacon because we want to
|
|
1719
1800
|
// capture click and key events as well, since these are typically more important than scrolls.
|
|
1720
1801
|
if (typeof ghIx["s"] === "undefined") {
|
|
1721
|
-
ghIx["s"] =
|
|
1802
|
+
ghIx["s"] = _now();
|
|
1722
1803
|
}
|
|
1723
1804
|
}
|
|
1724
1805
|
function _keyHandler(e) {
|
|
1725
1806
|
_removeIxHandlers();
|
|
1726
1807
|
if (typeof ghIx["k"] === "undefined") {
|
|
1727
|
-
ghIx["k"] =
|
|
1808
|
+
ghIx["k"] = _now();
|
|
1728
1809
|
if (e && e.target instanceof Element) {
|
|
1729
1810
|
var trackId = interactionAttributionForElement(e.target);
|
|
1730
1811
|
if (trackId) {
|
|
@@ -1737,7 +1818,7 @@
|
|
|
1737
1818
|
function _clickHandler(e) {
|
|
1738
1819
|
_removeIxHandlers();
|
|
1739
1820
|
if (typeof ghIx["c"] === "undefined") {
|
|
1740
|
-
ghIx["c"] =
|
|
1821
|
+
ghIx["c"] = _now();
|
|
1741
1822
|
var target = void 0;
|
|
1742
1823
|
try {
|
|
1743
1824
|
// Seeing "Permission denied" errors, so do a simple try-catch.
|
|
@@ -1865,30 +1946,11 @@
|
|
|
1865
1946
|
gFlags = addFlag(gFlags, Flags.PageLabelFromLabelProp);
|
|
1866
1947
|
return LUX.label;
|
|
1867
1948
|
}
|
|
1868
|
-
|
|
1869
|
-
var
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
|
|
1873
|
-
if (Array.isArray(rules)) {
|
|
1874
|
-
rules.every(function (rule) {
|
|
1875
|
-
if (patternMatchesUrl(rule, document.location.hostname, document.location.pathname)) {
|
|
1876
|
-
label_1 = pagegroup;
|
|
1877
|
-
return false; // stop when first match is found
|
|
1878
|
-
}
|
|
1879
|
-
return true;
|
|
1880
|
-
});
|
|
1881
|
-
}
|
|
1882
|
-
// exits loop when first match is found
|
|
1883
|
-
if (label_1) {
|
|
1884
|
-
gFlags = addFlag(gFlags, Flags.PageLabelFromPagegroup);
|
|
1885
|
-
return { value: label_1 };
|
|
1886
|
-
}
|
|
1887
|
-
};
|
|
1888
|
-
for (var pagegroup in pagegroups) {
|
|
1889
|
-
var state_1 = _loop_1(pagegroup);
|
|
1890
|
-
if (typeof state_1 === "object")
|
|
1891
|
-
return state_1.value;
|
|
1949
|
+
if (typeof LUX.pagegroups !== "undefined") {
|
|
1950
|
+
var label = getMatchesFromPatternMap(LUX.pagegroups, location.hostname, location.pathname, true);
|
|
1951
|
+
if (label) {
|
|
1952
|
+
gFlags = addFlag(gFlags, Flags.PageLabelFromPagegroup);
|
|
1953
|
+
return label;
|
|
1892
1954
|
}
|
|
1893
1955
|
}
|
|
1894
1956
|
if (typeof LUX.jspagelabel !== "undefined") {
|
|
@@ -1969,9 +2031,16 @@
|
|
|
1969
2031
|
setTimeout(sendBeaconAfterMinimumMeasureTime_1, timeRemaining);
|
|
1970
2032
|
}
|
|
1971
2033
|
};
|
|
1972
|
-
|
|
2034
|
+
if (globalConfig.autoWhenHidden) {
|
|
2035
|
+
// The autoWhenHidden config forces the beacon to be sent even when the page is not visible.
|
|
2036
|
+
sendBeaconAfterMinimumMeasureTime_1();
|
|
2037
|
+
}
|
|
2038
|
+
else {
|
|
2039
|
+
// Otherwise we only send the beacon when the page is visible.
|
|
2040
|
+
onVisible(sendBeaconAfterMinimumMeasureTime_1);
|
|
2041
|
+
}
|
|
1973
2042
|
}
|
|
1974
|
-
// Add the unload handlers
|
|
2043
|
+
// Add the unload handlers when sendBeaconOnPageHidden is enabled
|
|
1975
2044
|
if (globalConfig.sendBeaconOnPageHidden) {
|
|
1976
2045
|
_addUnloadHandlers();
|
|
1977
2046
|
}
|
|
@@ -1980,9 +2049,9 @@
|
|
|
1980
2049
|
// Set the maximum measurement timer
|
|
1981
2050
|
createMaxMeasureTimeout();
|
|
1982
2051
|
/**
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
|
|
2052
|
+
* LUX functions and properties must be attached to the existing global object to ensure that
|
|
2053
|
+
* changes made to the global object are reflected in the "internal" LUX object, and vice versa.
|
|
2054
|
+
*/
|
|
1986
2055
|
var globalLux = globalConfig;
|
|
1987
2056
|
// Functions
|
|
1988
2057
|
globalLux.mark = _mark;
|
|
@@ -2007,8 +2076,8 @@
|
|
|
2007
2076
|
// Public properties
|
|
2008
2077
|
globalLux.version = SCRIPT_VERSION;
|
|
2009
2078
|
/**
|
|
2010
|
-
|
|
2011
|
-
|
|
2079
|
+
* Run a command from the command queue
|
|
2080
|
+
*/
|
|
2012
2081
|
function _runCommand(_a) {
|
|
2013
2082
|
var fn = _a[0], args = _a.slice(1);
|
|
2014
2083
|
if (typeof globalLux[fn] === "function") {
|