govuk_publishing_components 32.1.0 → 33.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (145) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/javascripts/component_guide/accessibility-test.js +0 -1
  3. data/app/assets/javascripts/govuk_publishing_components/analytics-ga4/ga4-core.js +175 -0
  4. data/app/assets/javascripts/govuk_publishing_components/analytics-ga4/ga4-ecommerce-tracker.js +4 -4
  5. data/app/assets/javascripts/govuk_publishing_components/analytics-ga4/ga4-event-tracker.js +5 -13
  6. data/app/assets/javascripts/govuk_publishing_components/analytics-ga4/ga4-link-tracker.js +80 -309
  7. data/app/assets/javascripts/govuk_publishing_components/analytics-ga4/ga4-page-views.js +2 -2
  8. data/app/assets/javascripts/govuk_publishing_components/analytics-ga4/ga4-specialist-link-tracker.js +140 -0
  9. data/app/assets/javascripts/govuk_publishing_components/analytics-ga4/init-ga4.js +3 -0
  10. data/app/assets/javascripts/govuk_publishing_components/analytics-ga4.js +1 -0
  11. data/app/assets/javascripts/govuk_publishing_components/components/accordion.js +12 -1
  12. data/app/assets/javascripts/govuk_publishing_components/components/single-page-notification-button.js +24 -8
  13. data/app/assets/javascripts/govuk_publishing_components/components/step-by-step-nav.js +22 -1
  14. data/app/assets/javascripts/govuk_publishing_components/vendor/lux/lux-reporter.js +140 -191
  15. data/app/assets/stylesheets/govuk_publishing_components/components/_big-number.scss +2 -5
  16. data/app/assets/stylesheets/govuk_publishing_components/components/_image-card.scss +1 -5
  17. data/app/assets/stylesheets/govuk_publishing_components/components/_input.scss +3 -5
  18. data/app/assets/stylesheets/govuk_publishing_components/components/_layout-super-navigation-header.scss +10 -30
  19. data/app/assets/stylesheets/govuk_publishing_components/components/_search.scss +0 -7
  20. data/app/views/govuk_publishing_components/components/_accordion.html.erb +14 -1
  21. data/app/views/govuk_publishing_components/components/_error_summary.html.erb +27 -26
  22. data/app/views/govuk_publishing_components/components/_layout_super_navigation_header.html.erb +2 -2
  23. data/app/views/govuk_publishing_components/components/_phase_banner.html.erb +1 -1
  24. data/app/views/govuk_publishing_components/components/_share_links.html.erb +11 -13
  25. data/app/views/govuk_publishing_components/components/_single_page_notification_button.html.erb +1 -1
  26. data/app/views/govuk_publishing_components/components/_step_by_step_nav.html.erb +4 -1
  27. data/app/views/govuk_publishing_components/components/docs/accordion.yml +15 -3
  28. data/app/views/govuk_publishing_components/components/docs/button.yml +10 -0
  29. data/app/views/govuk_publishing_components/components/docs/share_links.yml +59 -30
  30. data/app/views/govuk_publishing_components/components/docs/single_page_notification_button.yml +10 -1
  31. data/app/views/govuk_publishing_components/components/docs/step_by_step_nav.yml +34 -0
  32. data/app/views/govuk_publishing_components/components/feedback/_problem_form.html.erb +1 -1
  33. data/app/views/govuk_publishing_components/components/feedback/_survey_signup_form.html.erb +1 -1
  34. data/app/views/govuk_publishing_components/components/feedback/_yes_no_banner.html.erb +3 -3
  35. data/lib/govuk_publishing_components/presenters/button_helper.rb +9 -2
  36. data/lib/govuk_publishing_components/presenters/single_page_notification_button_helper.rb +25 -1
  37. data/lib/govuk_publishing_components/version.rb +1 -1
  38. data/node_modules/axe-core/axe.js +4559 -4673
  39. data/node_modules/axe-core/axe.min.js +2 -2
  40. data/node_modules/axe-core/package.json +2 -2
  41. data/node_modules/axe-core/sri-history.json +4 -0
  42. data/node_modules/govuk-frontend/README.md +1 -2
  43. data/node_modules/govuk-frontend/govuk/all.js +1398 -273
  44. data/node_modules/govuk-frontend/govuk/common/closest-attribute-value.js +70 -0
  45. data/node_modules/govuk-frontend/govuk/common/index.js +172 -0
  46. data/node_modules/govuk-frontend/govuk/common/normalise-dataset.js +373 -0
  47. data/node_modules/govuk-frontend/govuk/common.js +138 -3
  48. data/node_modules/govuk-frontend/govuk/components/accordion/accordion.js +753 -25
  49. data/node_modules/govuk-frontend/govuk/components/accordion/fixtures.json +54 -22
  50. data/node_modules/govuk-frontend/govuk/components/accordion/macro-options.json +36 -0
  51. data/node_modules/govuk-frontend/govuk/components/accordion/template.njk +7 -1
  52. data/node_modules/govuk-frontend/govuk/components/back-link/fixtures.json +12 -12
  53. data/node_modules/govuk-frontend/govuk/components/breadcrumbs/fixtures.json +22 -22
  54. data/node_modules/govuk-frontend/govuk/components/button/_index.scss +23 -5
  55. data/node_modules/govuk-frontend/govuk/components/button/button.js +365 -107
  56. data/node_modules/govuk-frontend/govuk/components/button/fixtures.json +85 -66
  57. data/node_modules/govuk-frontend/govuk/components/button/template.njk +1 -1
  58. data/node_modules/govuk-frontend/govuk/components/character-count/_index.scss +9 -0
  59. data/node_modules/govuk-frontend/govuk/components/character-count/character-count.js +1033 -121
  60. data/node_modules/govuk-frontend/govuk/components/character-count/fixtures.json +112 -36
  61. data/node_modules/govuk-frontend/govuk/components/character-count/macro-options.json +42 -0
  62. data/node_modules/govuk-frontend/govuk/components/character-count/template.njk +27 -3
  63. data/node_modules/govuk-frontend/govuk/components/checkboxes/checkboxes.js +30 -2
  64. data/node_modules/govuk-frontend/govuk/components/checkboxes/fixtures.json +96 -93
  65. data/node_modules/govuk-frontend/govuk/components/cookie-banner/fixtures.json +46 -46
  66. data/node_modules/govuk-frontend/govuk/components/date-input/fixtures.json +50 -50
  67. data/node_modules/govuk-frontend/govuk/components/details/details.js +43 -13
  68. data/node_modules/govuk-frontend/govuk/components/details/fixtures.json +20 -20
  69. data/node_modules/govuk-frontend/govuk/components/error-message/fixtures.json +20 -20
  70. data/node_modules/govuk-frontend/govuk/components/error-summary/error-summary.js +268 -6
  71. data/node_modules/govuk-frontend/govuk/components/error-summary/fixtures.json +44 -35
  72. data/node_modules/govuk-frontend/govuk/components/error-summary/template.njk +25 -21
  73. data/node_modules/govuk-frontend/govuk/components/fieldset/fixtures.json +51 -39
  74. data/node_modules/govuk-frontend/govuk/components/file-upload/fixtures.json +26 -26
  75. data/node_modules/govuk-frontend/govuk/components/footer/_index.scss +1 -1
  76. data/node_modules/govuk-frontend/govuk/components/footer/fixtures.json +46 -46
  77. data/node_modules/govuk-frontend/govuk/components/footer/macro-options.json +2 -2
  78. data/node_modules/govuk-frontend/govuk/components/header/fixtures.json +93 -38
  79. data/node_modules/govuk-frontend/govuk/components/header/header.js +6 -0
  80. data/node_modules/govuk-frontend/govuk/components/header/macro-options.json +8 -2
  81. data/node_modules/govuk-frontend/govuk/components/header/template.njk +4 -2
  82. data/node_modules/govuk-frontend/govuk/components/hint/fixtures.json +12 -12
  83. data/node_modules/govuk-frontend/govuk/components/input/fixtures.json +80 -80
  84. data/node_modules/govuk-frontend/govuk/components/inset-text/fixtures.json +12 -12
  85. data/node_modules/govuk-frontend/govuk/components/label/fixtures.json +34 -34
  86. data/node_modules/govuk-frontend/govuk/components/notification-banner/fixtures.json +56 -46
  87. data/node_modules/govuk-frontend/govuk/components/notification-banner/notification-banner.js +252 -2
  88. data/node_modules/govuk-frontend/govuk/components/notification-banner/template.njk +1 -1
  89. data/node_modules/govuk-frontend/govuk/components/pagination/_index.scss +10 -7
  90. data/node_modules/govuk-frontend/govuk/components/pagination/fixtures.json +33 -26
  91. data/node_modules/govuk-frontend/govuk/components/panel/fixtures.json +18 -18
  92. data/node_modules/govuk-frontend/govuk/components/phase-banner/fixtures.json +14 -14
  93. data/node_modules/govuk-frontend/govuk/components/radios/fixtures.json +94 -91
  94. data/node_modules/govuk-frontend/govuk/components/radios/radios.js +30 -2
  95. data/node_modules/govuk-frontend/govuk/components/select/fixtures.json +32 -32
  96. data/node_modules/govuk-frontend/govuk/components/skip-link/fixtures.json +22 -20
  97. data/node_modules/govuk-frontend/govuk/components/skip-link/skip-link.js +10 -4
  98. data/node_modules/govuk-frontend/govuk/components/summary-list/fixtures.json +50 -50
  99. data/node_modules/govuk-frontend/govuk/components/table/_index.scss +1 -1
  100. data/node_modules/govuk-frontend/govuk/components/table/fixtures.json +40 -40
  101. data/node_modules/govuk-frontend/govuk/components/tabs/fixtures.json +29 -29
  102. data/node_modules/govuk-frontend/govuk/components/tabs/tabs.js +28 -0
  103. data/node_modules/govuk-frontend/govuk/components/tag/fixtures.json +28 -28
  104. data/node_modules/govuk-frontend/govuk/components/textarea/fixtures.json +34 -34
  105. data/node_modules/govuk-frontend/govuk/components/warning-text/fixtures.json +14 -14
  106. data/node_modules/govuk-frontend/govuk/core/_section-break.scss +1 -1
  107. data/node_modules/govuk-frontend/govuk/helpers/_colour.scss +2 -2
  108. data/node_modules/govuk-frontend/govuk/helpers/_links.scss +6 -6
  109. data/node_modules/govuk-frontend/govuk/i18n.js +390 -0
  110. data/node_modules/govuk-frontend/govuk/macros/i18n.njk +15 -0
  111. data/node_modules/govuk-frontend/govuk/settings/_all.scss +1 -0
  112. data/node_modules/govuk-frontend/govuk/settings/_colours-palette.scss +12 -0
  113. data/node_modules/govuk-frontend/govuk/settings/_compatibility.scss +26 -0
  114. data/node_modules/govuk-frontend/govuk/settings/_typography-font.scss +23 -0
  115. data/node_modules/govuk-frontend/govuk/settings/_typography-responsive.scss +12 -0
  116. data/node_modules/govuk-frontend/govuk/settings/_warnings.scss +53 -0
  117. data/node_modules/govuk-frontend/govuk/tools/_compatibility.scss +20 -6
  118. data/node_modules/govuk-frontend/govuk/vendor/polyfills/Date/now.js +21 -0
  119. data/node_modules/govuk-frontend/govuk/vendor/polyfills/Element/prototype/dataset.js +300 -0
  120. data/node_modules/govuk-frontend/govuk/vendor/polyfills/String/prototype/trim.js +21 -0
  121. data/node_modules/govuk-frontend/govuk-esm/all.mjs +50 -27
  122. data/node_modules/govuk-frontend/govuk-esm/common/closest-attribute-value.mjs +15 -0
  123. data/node_modules/govuk-frontend/govuk-esm/common/index.mjs +159 -0
  124. data/node_modules/govuk-frontend/govuk-esm/common/normalise-dataset.mjs +58 -0
  125. data/node_modules/govuk-frontend/govuk-esm/common.mjs +6 -28
  126. data/node_modules/govuk-frontend/govuk-esm/components/accordion/accordion.mjs +113 -43
  127. data/node_modules/govuk-frontend/govuk-esm/components/button/button.mjs +67 -30
  128. data/node_modules/govuk-frontend/govuk-esm/components/character-count/character-count.mjs +325 -123
  129. data/node_modules/govuk-frontend/govuk-esm/components/checkboxes/checkboxes.mjs +9 -3
  130. data/node_modules/govuk-frontend/govuk-esm/components/details/details.mjs +22 -8
  131. data/node_modules/govuk-frontend/govuk-esm/components/error-summary/error-summary.mjs +48 -6
  132. data/node_modules/govuk-frontend/govuk-esm/components/header/header.mjs +6 -0
  133. data/node_modules/govuk-frontend/govuk-esm/components/notification-banner/notification-banner.mjs +32 -2
  134. data/node_modules/govuk-frontend/govuk-esm/components/radios/radios.mjs +9 -3
  135. data/node_modules/govuk-frontend/govuk-esm/components/skip-link/skip-link.mjs +10 -4
  136. data/node_modules/govuk-frontend/govuk-esm/components/tabs/tabs.mjs +8 -2
  137. data/node_modules/govuk-frontend/govuk-esm/i18n.mjs +380 -0
  138. data/node_modules/govuk-frontend/govuk-esm/vendor/polyfills/Date/now.mjs +13 -0
  139. data/node_modules/govuk-frontend/govuk-esm/vendor/polyfills/Element/prototype/dataset.mjs +68 -0
  140. data/node_modules/govuk-frontend/govuk-esm/vendor/polyfills/String/prototype/trim.mjs +13 -0
  141. data/node_modules/govuk-frontend/govuk-prototype-kit/init.js +7 -0
  142. data/node_modules/govuk-frontend/govuk-prototype-kit/init.scss +12 -0
  143. data/node_modules/govuk-frontend/govuk-prototype-kit.config.json +138 -7
  144. data/node_modules/govuk-frontend/package.json +1 -1
  145. metadata +22 -3
@@ -36,6 +36,9 @@ window.GOVUK.Modules = window.GOVUK.Modules || {};
36
36
 
37
37
  this.$module.uniqueId = this.$module.getAttribute('data-id') || false
38
38
 
39
+ this.$module.dataModule = this.$module.getAttribute('data-module')
40
+ this.$module.isGa4Enabled = this.$module.dataModule ? this.$module.dataModule.indexOf('ga4-event-tracker') !== -1 : false
41
+
39
42
  if (this.$module.uniqueId) {
40
43
  this.$module.sessionStoreLink = this.$module.sessionStoreLink + '_' + this.$module.uniqueId
41
44
  }
@@ -78,6 +81,12 @@ window.GOVUK.Modules = window.GOVUK.Modules || {};
78
81
 
79
82
  this.$module.insertBefore(showAll, steps)
80
83
  this.$module.showOrHideAllButton = this.$module.querySelectorAll('.js-step-controls-button')[0]
84
+
85
+ // if GA4 is enabled, set attributes on 'show all sections' for tracking using ga4-event-tracker
86
+ if (this.$module.isGa4Enabled) {
87
+ var showAllAttributesGa4 = { event_name: 'select_content', type: 'step by step', index: 0, index_total: this.$module.totalSteps }
88
+ this.$module.showOrHideAllButton.setAttribute('data-ga4-event', JSON.stringify(showAllAttributesGa4))
89
+ }
81
90
  }
82
91
 
83
92
  Gemstepnav.prototype.addShowHideToggle = function () {
@@ -169,12 +178,24 @@ window.GOVUK.Modules = window.GOVUK.Modules || {};
169
178
  var title = thisel.querySelectorAll('.js-step-title')[0]
170
179
  var contentId = thisel.querySelectorAll('.js-panel')[0].getAttribute('id')
171
180
  var titleText = title.textContent || title.innerText // IE8 fallback
181
+ var ga4Data = ''
182
+
183
+ if (this.$module.isGa4Enabled) {
184
+ var ga4JSON = {
185
+ event_name: 'select_content',
186
+ type: 'step by step',
187
+ text: titleText.trim(),
188
+ index: i + 1,
189
+ index_total: this.$module.totalSteps
190
+ }
191
+ ga4Data = "data-ga4-event='" + JSON.stringify(ga4JSON) + "'" // Construct GA4 data-attributes for ga4-event-tracker.
192
+ }
172
193
 
173
194
  title.outerHTML =
174
195
  '<span class="js-step-title">' +
175
196
  '<button ' +
176
197
  'class="gem-c-step-nav__button gem-c-step-nav__button--title js-step-title-button" ' +
177
- 'aria-expanded="false" aria-controls="' + contentId + '">' +
198
+ 'aria-expanded="false" aria-controls="' + contentId + '" ' + ga4Data + '>' +
178
199
  '<span class="gem-c-step-nav____title-text-focus">' +
179
200
  '<span class="gem-c-step-nav__title-text js-step-title-text">' + titleText + '</span>' +
180
201
  '<span class="govuk-visually-hidden gem-c-step-nav__section-heading-divider">, </span>' +
@@ -38,6 +38,8 @@
38
38
  errorBeaconUrl: getProperty(obj, "errorBeaconUrl", "https://lux.speedcurve.com/error/"),
39
39
  jspagelabel: getProperty(obj, "jspagelabel", undefined),
40
40
  label: getProperty(obj, "label", undefined),
41
+ maxBeaconUrlLength: getProperty(obj, "maxBeaconUrlLength", 8190),
42
+ maxBeaconUTEntries: getProperty(obj, "maxBeaconUTEntries", 20),
41
43
  maxErrors: getProperty(obj, "maxErrors", 5),
42
44
  maxMeasureTime: getProperty(obj, "maxMeasureTime", 60000),
43
45
  measureUntil: getProperty(obj, "measureUntil", "onload"),
@@ -133,11 +135,8 @@
133
135
  }
134
136
 
135
137
  /**
136
- * Get the interaction attribution name for an element
137
- *
138
- * @param {HTMLElement} el
139
- * @returns string
140
- */
138
+ * Get the interaction attribution name for an element
139
+ */
141
140
  function interactionAttributionForElement(el) {
142
141
  // Our first preference is to use the data-sctrack attribute from anywhere in the tree
143
142
  var trackId = getClosestScTrackAttribute(el);
@@ -183,10 +182,10 @@
183
182
  // prevent having to make regular typeof checks.
184
183
  var performance = window.performance || {};
185
184
  var timing = performance.timing || {
186
- // If performance.timing isn't available, we attempt to polyfill the navigationStart value.
187
- // Our first attempt is from LUX.ns, which is the time that the snippet execution began. If this
188
- // is not available, we fall back to the time that the current script execution began.
189
- navigationStart: ((_a = window.LUX) === null || _a === void 0 ? void 0 : _a.ns) || scriptStartTime,
185
+ // If performance.timing isn't available, we attempt to polyfill the navigationStart value.
186
+ // Our first attempt is from LUX.ns, which is the time that the snippet execution began. If this
187
+ // is not available, we fall back to the time that the current script execution began.
188
+ navigationStart: ((_a = window.LUX) === null || _a === void 0 ? void 0 : _a.ns) || scriptStartTime,
190
189
  };
191
190
  function msSinceNavigationStart() {
192
191
  if (performance.now) {
@@ -195,10 +194,10 @@
195
194
  return now() - timing.navigationStart;
196
195
  }
197
196
  /**
198
- * Simple wrapper around performance.getEntriesByType to provide fallbacks for
199
- * legacy browsers, and work around edge cases where undefined is returned instead
200
- * of an empty PerformanceEntryList.
201
- */
197
+ * Simple wrapper around performance.getEntriesByType to provide fallbacks for
198
+ * legacy browsers, and work around edge cases where undefined is returned instead
199
+ * of an empty PerformanceEntryList.
200
+ */
202
201
  function getEntriesByType(type) {
203
202
  if (typeof performance.getEntriesByType === "function") {
204
203
  var entries = performance.getEntriesByType(type);
@@ -210,74 +209,92 @@
210
209
  }
211
210
 
212
211
  var Matching = /** @class */ (function () {
213
- function Matching() {
212
+ function Matching() {
213
+ }
214
+ Matching.isMatching = function (pattern, url) {
215
+ var regexp = Matching.createRegexpFromPattern(pattern);
216
+ return url.match(regexp) ? true : false;
217
+ };
218
+ /**
219
+ * Converts string pattern to RegExp object
220
+ * @return RegExp
221
+ */
222
+ Matching.createRegexpFromPattern = function (pattern) {
223
+ var regexp;
224
+ if (pattern == "/") {
225
+ regexp = this.getRegexpForHostnameRoot();
214
226
  }
215
- Matching.isMatching = function (pattern, url) {
216
- var regexp = Matching.createRegexpFromPattern(pattern);
217
- return url.match(regexp) ? true : false;
218
- };
219
- /**
220
- * Converts string pattern to RegExp object
221
- * @return RegExp
222
- */
223
- Matching.createRegexpFromPattern = function (pattern) {
224
- var regexp;
225
- if (pattern == "/") {
226
- regexp = this.getRegexpForHostnameRoot();
227
- }
228
- else if (!pattern.includes(Matching.wildcard)) {
229
- regexp = this.getRegexpForExactString(pattern);
230
- }
231
- else if (pattern.charAt(0) == "/") {
232
- regexp = this.createRegexpFromPathname(pattern);
233
- }
234
- else {
235
- regexp = this.createRegexpFromPathname(pattern, false);
236
- }
237
- return regexp;
238
- };
239
- /**
240
- * Converts URL pathname string pattern to RegExp object
241
- * Multile wildcards (*) are supported
242
- * @return RegExp
243
- */
244
- Matching.createRegexpFromPathname = function (pattern, anyDomain) {
245
- if (anyDomain === void 0) { anyDomain = true; }
246
- pattern = this.escapeStringForRegexp(pattern);
247
- var expression = "^" +
248
- (anyDomain ? Matching.domainExpression : "") +
249
- pattern.replaceAll(Matching.wildcard, ".*?") +
250
- "$";
251
- return new RegExp(expression, "i");
252
- };
253
- /**
254
- * Matches hostname root (e.g. "/", "somedomain.com/", "www.somedomain.co.nz/")
255
- * Trailing slash is mandatory
256
- * @return RegExp
257
- */
258
- Matching.getRegexpForHostnameRoot = function () {
259
- return new RegExp("^" + Matching.domainExpression + "/$", "i");
260
- };
261
- /**
262
- * Matches exact string (no wildcard provided)
263
- * @return RegExp
264
- */
265
- Matching.getRegexpForExactString = function (string) {
266
- return new RegExp("^" + this.escapeStringForRegexp(string) + "/?$", "i");
267
- };
268
- /**
269
- * Escape special symbols in regexp string
270
- * @param string
271
- */
272
- Matching.escapeStringForRegexp = function (string) {
273
- // we don't escape * because it's our own special symbol!
274
- return string.replace(/[-/\\^$+?.()|[\]{}]/g, "\\$&");
275
- };
276
- Matching.wildcard = "*";
277
- Matching.domainExpression = "[a-zA-Z0-9-.]{1,61}[a-zA-Z0-9]\\.[a-zA-Z]{2,}";
278
- return Matching;
227
+ else if (!pattern.includes(Matching.wildcard)) {
228
+ regexp = this.getRegexpForExactString(pattern);
229
+ }
230
+ else {
231
+ regexp = this.createRegexpFromPathname(pattern);
232
+ }
233
+ return regexp;
234
+ };
235
+ /**
236
+ * Converts URL pathname string pattern to RegExp object
237
+ * Multile wildcards (*) are supported
238
+ * @return RegExp
239
+ */
240
+ Matching.createRegexpFromPathname = function (pattern) {
241
+ var anyDomain = pattern.charAt(0) == "/";
242
+ pattern = this.escapeStringForRegexp(pattern);
243
+ var expression = "^" +
244
+ (anyDomain ? Matching.domainExpression : "") +
245
+ pattern.replaceAll(Matching.wildcard, ".*?") +
246
+ "$";
247
+ return new RegExp(expression, "i");
248
+ };
249
+ /**
250
+ * Matches hostname root (e.g. "/", "somedomain.com/", "www.somedomain.co.nz/")
251
+ * Trailing slash is mandatory
252
+ * @return RegExp
253
+ */
254
+ Matching.getRegexpForHostnameRoot = function () {
255
+ return new RegExp("^" + Matching.domainExpression + "/$", "i");
256
+ };
257
+ /**
258
+ * Matches exact string (no wildcard provided)
259
+ * @return RegExp
260
+ */
261
+ Matching.getRegexpForExactString = function (string) {
262
+ var anyDomain = string.charAt(0) == "/";
263
+ return new RegExp("^" +
264
+ (anyDomain ? Matching.domainExpression : "") +
265
+ this.escapeStringForRegexp(string) +
266
+ "/?$", "i");
267
+ };
268
+ /**
269
+ * Escape special symbols in regexp string
270
+ * @param string
271
+ */
272
+ Matching.escapeStringForRegexp = function (string) {
273
+ // we don't escape * because it's our own special symbol!
274
+ return string.replace(/[-/\\^$+?.()|[\]{}]/g, "\\$&");
275
+ };
276
+ Matching.wildcard = "*";
277
+ Matching.domainExpression = "[a-zA-Z0-9-.]{1,61}[a-zA-Z0-9]\\.[a-zA-Z]{2,}";
278
+ return Matching;
279
279
  }());
280
280
 
281
+ /**
282
+ * Fit an array of user timing delimited strings into a URL and return both the entries that fit and
283
+ * the remaining entries that didn't fit.
284
+ */
285
+ function fitUserTimingEntries(utValues, config, url) {
286
+ // Start with the maximum allowed UT entries per beacon
287
+ var beaconUtValues = utValues.slice(0, config.maxBeaconUTEntries);
288
+ var remainingUtValues = utValues.slice(config.maxBeaconUTEntries);
289
+ // Trim UT entries until they fit within the maximum URL length, ensuring at least one UT entry
290
+ // is included.
291
+ while ((url + "&UT=" + beaconUtValues.join(",")).length > config.maxBeaconUrlLength &&
292
+ beaconUtValues.length > 1) {
293
+ remainingUtValues.unshift(beaconUtValues.pop());
294
+ }
295
+ return [beaconUtValues, remainingUtValues];
296
+ }
297
+
281
298
  var LUX = window.LUX || {};
282
299
  var scriptEndTime = scriptStartTime;
283
300
  LUX = (function () {
@@ -290,7 +307,7 @@
290
307
  /// End
291
308
  // -------------------------------------------------------------------------
292
309
 
293
- var SCRIPT_VERSION = "302";
310
+ var SCRIPT_VERSION = "305";
294
311
  var logger = new Logger();
295
312
  var globalConfig = fromObject(LUX);
296
313
  logger.logEvent(LogEvent.EvaluationStart, [SCRIPT_VERSION]);
@@ -384,7 +401,6 @@
384
401
  var gUid = refreshUniqueId(gSyncId); // cookie for this session ("Unique ID")
385
402
  var gCustomerDataTimeout; // setTimeout timer for sending a Customer Data beacon after onload
386
403
  var gMaxMeasureTimeout; // setTimeout timer for sending the beacon after a maximum measurement time
387
- var gMaxQuerystring = 8190; // split the beacon querystring if it gets longer than this
388
404
  if (_sample()) {
389
405
  logger.logEvent(LogEvent.SessionIsSampled, [globalConfig.samplerate]);
390
406
  }
@@ -703,7 +719,7 @@
703
719
  }
704
720
  aUT.push(utParts.join("|"));
705
721
  }
706
- return aUT.join(",");
722
+ return aUT;
707
723
  }
708
724
  // Return a string of Element Timing Metrics formatted for beacon querystring.
709
725
  function elementTimingValues() {
@@ -787,8 +803,8 @@
787
803
  ",x|" +
788
804
  hStats["max"] +
789
805
  (0 === hStats["fci"] ? "" : ",i|" + hStats["fci"]); // only add FCI if it is non-zero
790
- sCPU += "s|" + hCPU[jsType] + sStats + hCPUDetails[jsType];
791
- return sCPU;
806
+ sCPU += "s|" + hCPU[jsType] + sStats + hCPUDetails[jsType];
807
+ return sCPU;
792
808
  }
793
809
  // Return a hash of "stats" about the CPU details incl. count, max, and median.
794
810
  function cpuStats(sDetails) {
@@ -1408,8 +1424,28 @@
1408
1424
  clearTimeout(gMaxMeasureTimeout);
1409
1425
  }
1410
1426
  }
1427
+ function _getBeaconUrl() {
1428
+ var queryParams = [
1429
+ "v=" + SCRIPT_VERSION,
1430
+ "id=" + getCustomerId(),
1431
+ "sid=" + gSyncId,
1432
+ "uid=" + gUid,
1433
+ "l=" + encodeURIComponent(_getPageLabel()),
1434
+ "HN=" + encodeURIComponent(document.location.hostname),
1435
+ "PN=" + encodeURIComponent(document.location.pathname),
1436
+ ];
1437
+ if (gFlags) {
1438
+ queryParams.push("fl=" + gFlags);
1439
+ }
1440
+ var customerData = customerDataValues();
1441
+ if (customerData) {
1442
+ queryParams.push("CD=" + customerData);
1443
+ }
1444
+ return globalConfig.beaconUrl + "?" + queryParams.join("&");
1445
+ }
1411
1446
  // Beacon back the LUX data.
1412
1447
  function _sendLux() {
1448
+ var _a;
1413
1449
  clearMaxMeasureTimeout();
1414
1450
  var customerid = getCustomerId();
1415
1451
  if (!customerid ||
@@ -1427,9 +1463,7 @@
1427
1463
  // with LUX.markLoadTime()
1428
1464
  _markLoadTime();
1429
1465
  }
1430
- var sUT = userTimingValues(); // User Timing data
1431
1466
  var sET = elementTimingValues(); // Element Timing data
1432
- var sCustomerData = customerDataValues(); // customer data
1433
1467
  var sIx = ""; // Interaction Metrics
1434
1468
  if (!gbIxSent) {
1435
1469
  // It is possible for the IX beacon to be sent BEFORE the "main" window.onload LUX beacon.
@@ -1444,21 +1478,10 @@
1444
1478
  }
1445
1479
  // We want ALL beacons to have ALL the data used for query filters (geo, pagelabel, browser, & customerdata).
1446
1480
  // So we create a base URL that has all the necessary information:
1447
- var baseUrl = globalConfig.beaconUrl +
1448
- "?v=" +
1449
- SCRIPT_VERSION +
1450
- "&id=" +
1451
- customerid +
1452
- "&sid=" +
1453
- gSyncId +
1454
- "&uid=" +
1455
- gUid +
1456
- (sCustomerData ? "&CD=" + sCustomerData : "") +
1457
- "&l=" +
1458
- encodeURIComponent(_getPageLabel());
1481
+ var baseUrl = _getBeaconUrl();
1459
1482
  var is = inlineTagSize("script");
1460
1483
  var ic = inlineTagSize("style");
1461
- var querystring =
1484
+ var metricsQueryString =
1462
1485
  // only send Nav Timing and lux.js metrics on initial pageload (not for SPA page views)
1463
1486
  (gbNavSent ? "" : "&NT=" + getNavTiming()) +
1464
1487
  (gbFirstPV ? "&LJS=" + sLuxjs : "") +
@@ -1499,31 +1522,15 @@
1499
1522
  (sIx ? "&IX=" + sIx : "") +
1500
1523
  (typeof gFirstInputDelay !== "undefined" ? "&FID=" + gFirstInputDelay : "") +
1501
1524
  (sCPU ? "&CPU=" + sCPU : "") +
1502
- (gFlags ? "&fl=" + gFlags : "") +
1503
1525
  (sET ? "&ET=" + sET : "") + // element timing
1504
- "&HN=" +
1505
- encodeURIComponent(document.location.hostname) +
1506
- (DCLS !== false ? "&CLS=" + DCLS : "") +
1507
- "&PN=" +
1508
- encodeURIComponent(document.location.pathname);
1509
- // User Timing marks & measures
1510
- var sUT_remainder = "";
1511
- if (sUT) {
1512
- var curLen = baseUrl.length + querystring.length;
1513
- if (curLen + sUT.length <= gMaxQuerystring) {
1514
- // Add all User Timing
1515
- querystring += "&UT=" + sUT;
1516
- }
1517
- else {
1518
- // Only add a substring of User Timing
1519
- var avail_1 = gMaxQuerystring - curLen; // how much room is left in the querystring
1520
- var iComma = sUT.lastIndexOf(",", avail_1); // as many UT tuples as possible
1521
- querystring += "&UT=" + sUT.substring(0, iComma);
1522
- sUT_remainder = sUT.substring(iComma + 1);
1523
- }
1524
- }
1526
+ (DCLS !== false ? "&CLS=" + DCLS : "");
1527
+ // We add the user timing entries last so that we can split them to reduce the URL size if necessary.
1528
+ var utValues = userTimingValues();
1529
+ var _b = fitUserTimingEntries(utValues, globalConfig, baseUrl + metricsQueryString), beaconUtValues = _b[0], remainingUtValues = _b[1];
1525
1530
  // Send the MAIN LUX beacon.
1526
- var mainBeaconUrl = baseUrl + querystring;
1531
+ var mainBeaconUrl = baseUrl +
1532
+ metricsQueryString +
1533
+ (beaconUtValues.length > 0 ? "&UT=" + beaconUtValues.join(",") : "");
1527
1534
  logger.logEvent(LogEvent.MainBeaconSent, [mainBeaconUrl]);
1528
1535
  _sendBeacon(mainBeaconUrl);
1529
1536
  // Set some states.
@@ -1531,34 +1538,9 @@
1531
1538
  gbNavSent = 1;
1532
1539
  gbIxSent = sIx ? 1 : 0;
1533
1540
  // Send other beacons for JUST User Timing.
1534
- var avail = gMaxQuerystring - baseUrl.length;
1535
- while (sUT_remainder) {
1536
- var sUT_cur = "";
1537
- if (sUT_remainder.length <= avail) {
1538
- // We can fit ALL the remaining UT params.
1539
- sUT_cur = sUT_remainder;
1540
- sUT_remainder = "";
1541
- }
1542
- else {
1543
- // We have to take a subset of the remaining UT params.
1544
- var iComma = sUT_remainder.lastIndexOf(",", avail); // as many UT tuples as possible
1545
- if (-1 === iComma) {
1546
- // Trouble: we have SO LITTLE available space we can not fit the first UT tuple.
1547
- // Try it anyway but find it by searching from the front.
1548
- iComma = sUT_remainder.indexOf(",");
1549
- }
1550
- if (-1 === iComma) {
1551
- // The is only one UT tuple left, but it is bigger than the available space.
1552
- // Take the whole tuple even tho it is too big.
1553
- sUT_cur = sUT_remainder;
1554
- sUT_remainder = "";
1555
- }
1556
- else {
1557
- sUT_cur = sUT_remainder.substring(0, iComma);
1558
- sUT_remainder = sUT_remainder.substring(iComma + 1);
1559
- }
1560
- }
1561
- var utBeaconUrl = baseUrl + "&UT=" + sUT_cur;
1541
+ while (remainingUtValues.length) {
1542
+ _a = fitUserTimingEntries(remainingUtValues, globalConfig, baseUrl), beaconUtValues = _a[0], remainingUtValues = _a[1];
1543
+ var utBeaconUrl = baseUrl + "&UT=" + beaconUtValues.join(",");
1562
1544
  logger.logEvent(LogEvent.UserTimingBeaconSent, [utBeaconUrl]);
1563
1545
  _sendBeacon(utBeaconUrl);
1564
1546
  }
@@ -1576,26 +1558,10 @@
1576
1558
  }
1577
1559
  var sIx = ixValues(); // Interaction Metrics
1578
1560
  if (sIx) {
1579
- var sCustomerData = customerDataValues(); // customer data
1580
- var querystring = "?v=" +
1581
- SCRIPT_VERSION +
1582
- "&id=" +
1583
- customerid +
1584
- "&sid=" +
1585
- gSyncId +
1586
- "&uid=" +
1587
- gUid +
1588
- (sCustomerData ? "&CD=" + sCustomerData : "") +
1589
- "&l=" +
1590
- encodeURIComponent(_getPageLabel()) +
1591
- "&IX=" +
1592
- sIx +
1593
- (gFirstInputDelay ? "&FID=" + gFirstInputDelay : "") +
1594
- "&HN=" +
1595
- encodeURIComponent(document.location.hostname) +
1596
- "&PN=" +
1597
- encodeURIComponent(document.location.pathname);
1598
- var beaconUrl = globalConfig.beaconUrl + querystring;
1561
+ var beaconUrl = _getBeaconUrl() +
1562
+ "&IX=" +
1563
+ sIx +
1564
+ (typeof gFirstInputDelay !== "undefined" ? "&FID=" + gFirstInputDelay : "");
1599
1565
  logger.logEvent(LogEvent.InteractionBeaconSent, [beaconUrl]);
1600
1566
  _sendBeacon(beaconUrl);
1601
1567
  gbIxSent = 1;
@@ -1614,23 +1580,7 @@
1614
1580
  }
1615
1581
  var sCustomerData = customerDataValues(); // customer data
1616
1582
  if (sCustomerData) {
1617
- var querystring = "?v=" +
1618
- SCRIPT_VERSION +
1619
- "&id=" +
1620
- customerid +
1621
- "&sid=" +
1622
- gSyncId +
1623
- "&uid=" +
1624
- gUid +
1625
- "&CD=" +
1626
- sCustomerData +
1627
- "&l=" +
1628
- encodeURIComponent(_getPageLabel()) +
1629
- "&HN=" +
1630
- encodeURIComponent(document.location.hostname) +
1631
- "&PN=" +
1632
- encodeURIComponent(document.location.pathname);
1633
- var beaconUrl = globalConfig.beaconUrl + querystring;
1583
+ var beaconUrl = _getBeaconUrl();
1634
1584
  logger.logEvent(LogEvent.CustomDataBeaconSent, [beaconUrl]);
1635
1585
  _sendBeacon(beaconUrl);
1636
1586
  }
@@ -1657,7 +1607,7 @@
1657
1607
  _removeIxHandlers();
1658
1608
  if (typeof ghIx["k"] === "undefined") {
1659
1609
  ghIx["k"] = Math.round(_now());
1660
- if (e && e.target) {
1610
+ if (e && e.target instanceof Element) {
1661
1611
  var trackId = interactionAttributionForElement(e.target);
1662
1612
  if (trackId) {
1663
1613
  ghIx["ki"] = trackId;
@@ -1670,16 +1620,15 @@
1670
1620
  _removeIxHandlers();
1671
1621
  if (typeof ghIx["c"] === "undefined") {
1672
1622
  ghIx["c"] = Math.round(_now());
1673
- var target = null;
1623
+ var target = void 0;
1674
1624
  try {
1675
1625
  // Seeing "Permission denied" errors, so do a simple try-catch.
1676
- if (e && e.target) {
1626
+ if (e && e.target instanceof Element) {
1677
1627
  target = e.target;
1678
1628
  }
1679
1629
  }
1680
1630
  catch (e) {
1681
1631
  logger.logEvent(LogEvent.EventTargetAccessError);
1682
- target = null;
1683
1632
  }
1684
1633
  if (target) {
1685
1634
  if (e.clientX) {
@@ -1687,7 +1636,7 @@
1687
1636
  ghIx["cx"] = e.clientX;
1688
1637
  ghIx["cy"] = e.clientY;
1689
1638
  }
1690
- var trackId = interactionAttributionForElement(e.target);
1639
+ var trackId = interactionAttributionForElement(target);
1691
1640
  if (trackId) {
1692
1641
  ghIx["ci"] = trackId;
1693
1642
  }
@@ -5,12 +5,9 @@
5
5
 
6
6
  .gem-c-big-number__value {
7
7
  @include govuk-font($size: false, $weight: bold);
8
- font-size: 80px;
9
8
  line-height: 1;
10
-
11
- @if $govuk-typography-use-rem {
12
- font-size: govuk-px-to-rem(80px);
13
- }
9
+ font-size: 80px;
10
+ font-size: govuk-px-to-rem(80px);
14
11
  }
15
12
 
16
13
  .gem-c-big-number__label {
@@ -107,11 +107,7 @@
107
107
  .gem-c-image-card__metadata {
108
108
  @include govuk-font($size: false);
109
109
  font-size: 16px;
110
-
111
- @if $govuk-typography-use-rem {
112
- font-size: govuk-px-to-rem(16px);
113
- }
114
-
110
+ font-size: govuk-px-to-rem(16px);
115
111
  margin: 0 0 (govuk-spacing(3) / 2);
116
112
  color: govuk-colour("dark-grey", $legacy: "grey-1");
117
113
 
@@ -4,14 +4,12 @@ $search-icon-size: 40px;
4
4
  .gem-c-input__search-icon {
5
5
  display: block;
6
6
  position: relative;
7
- margin-bottom: -$search-icon-size;
8
7
  z-index: 1;
8
+ margin-bottom: -$search-icon-size;
9
+ margin-bottom: -(govuk-px-to-rem($search-icon-size));
9
10
  width: $search-icon-size;
10
11
  height: $search-icon-size;
11
- @if $govuk-typography-use-rem {
12
- margin-bottom: -(govuk-px-to-rem($search-icon-size));
13
- height: govuk-px-to-rem($search-icon-size);
14
- }
12
+ height: govuk-px-to-rem($search-icon-size);
15
13
  background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 36 36' width='40' height='40'%3E%3Cpath d='M25.7 24.8L21.9 21c.7-1 1.1-2.2 1.1-3.5 0-3.6-2.9-6.5-6.5-6.5S10 13.9 10 17.5s2.9 6.5 6.5 6.5c1.6 0 3-.6 4.1-1.5l3.7 3.7 1.4-1.4zM12 17.5c0-2.5 2-4.5 4.5-4.5s4.5 2 4.5 4.5-2 4.5-4.5 4.5-4.5-2-4.5-4.5z' fill='currentColor'%3E%3C/path%3E%3C/svg%3E") no-repeat -3px center;
16
14
  }
17
15