govuk_publishing_components 32.0.0 → 33.0.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.
Files changed (206) 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 +1 -1
  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/layout-super-navigation-header.js +13 -4
  13. data/app/assets/javascripts/govuk_publishing_components/components/single-page-notification-button.js +24 -8
  14. data/app/assets/javascripts/govuk_publishing_components/vendor/lux/lux-reporter.js +83 -86
  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/assets/stylesheets/govuk_publishing_components/components/_share-links.scss +0 -6
  21. data/app/views/govuk_publishing_components/components/_accordion.html.erb +14 -1
  22. data/app/views/govuk_publishing_components/components/_error_summary.html.erb +27 -26
  23. data/app/views/govuk_publishing_components/components/_layout_super_navigation_header.html.erb +2 -2
  24. data/app/views/govuk_publishing_components/components/_phase_banner.html.erb +1 -1
  25. data/app/views/govuk_publishing_components/components/_share_links.html.erb +18 -15
  26. data/app/views/govuk_publishing_components/components/_single_page_notification_button.html.erb +1 -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/feedback/_yes_no_banner.html.erb +3 -3
  32. data/config/locales/ar.yml +4 -1
  33. data/config/locales/az.yml +4 -1
  34. data/config/locales/be.yml +4 -1
  35. data/config/locales/bg.yml +4 -1
  36. data/config/locales/bn.yml +4 -1
  37. data/config/locales/cs.yml +4 -1
  38. data/config/locales/cy.yml +4 -1
  39. data/config/locales/da.yml +4 -1
  40. data/config/locales/de.yml +4 -1
  41. data/config/locales/dr.yml +4 -1
  42. data/config/locales/el.yml +4 -1
  43. data/config/locales/en.yml +20 -17
  44. data/config/locales/es-419.yml +4 -1
  45. data/config/locales/es.yml +4 -1
  46. data/config/locales/et.yml +4 -1
  47. data/config/locales/fa.yml +4 -1
  48. data/config/locales/fi.yml +4 -1
  49. data/config/locales/fr.yml +4 -1
  50. data/config/locales/gd.yml +4 -1
  51. data/config/locales/gu.yml +4 -1
  52. data/config/locales/he.yml +4 -1
  53. data/config/locales/hi.yml +4 -1
  54. data/config/locales/hr.yml +4 -1
  55. data/config/locales/hu.yml +4 -1
  56. data/config/locales/hy.yml +4 -1
  57. data/config/locales/id.yml +4 -1
  58. data/config/locales/is.yml +4 -1
  59. data/config/locales/it.yml +4 -1
  60. data/config/locales/ja.yml +4 -1
  61. data/config/locales/ka.yml +4 -1
  62. data/config/locales/kk.yml +4 -1
  63. data/config/locales/ko.yml +4 -1
  64. data/config/locales/lt.yml +4 -1
  65. data/config/locales/lv.yml +4 -1
  66. data/config/locales/ms.yml +4 -1
  67. data/config/locales/mt.yml +4 -1
  68. data/config/locales/nl.yml +4 -1
  69. data/config/locales/no.yml +4 -1
  70. data/config/locales/pa-pk.yml +4 -1
  71. data/config/locales/pa.yml +4 -1
  72. data/config/locales/pl.yml +4 -1
  73. data/config/locales/ps.yml +4 -1
  74. data/config/locales/pt.yml +4 -1
  75. data/config/locales/ro.yml +4 -1
  76. data/config/locales/ru.yml +4 -1
  77. data/config/locales/si.yml +4 -1
  78. data/config/locales/sk.yml +4 -1
  79. data/config/locales/sl.yml +4 -1
  80. data/config/locales/so.yml +4 -1
  81. data/config/locales/sq.yml +4 -1
  82. data/config/locales/sr.yml +4 -1
  83. data/config/locales/sv.yml +4 -1
  84. data/config/locales/sw.yml +4 -1
  85. data/config/locales/ta.yml +4 -1
  86. data/config/locales/th.yml +4 -1
  87. data/config/locales/tk.yml +4 -1
  88. data/config/locales/tr.yml +4 -1
  89. data/config/locales/uk.yml +4 -1
  90. data/config/locales/ur.yml +4 -1
  91. data/config/locales/uz.yml +4 -1
  92. data/config/locales/vi.yml +4 -1
  93. data/config/locales/zh-hk.yml +4 -1
  94. data/config/locales/zh-tw.yml +4 -1
  95. data/config/locales/zh.yml +4 -1
  96. data/lib/govuk_publishing_components/presenters/button_helper.rb +7 -1
  97. data/lib/govuk_publishing_components/presenters/single_page_notification_button_helper.rb +25 -1
  98. data/lib/govuk_publishing_components/version.rb +1 -1
  99. data/node_modules/axe-core/axe.js +4567 -4678
  100. data/node_modules/axe-core/axe.min.js +2 -2
  101. data/node_modules/axe-core/package.json +2 -2
  102. data/node_modules/axe-core/sri-history.json +8 -0
  103. data/node_modules/govuk-frontend/README.md +1 -2
  104. data/node_modules/govuk-frontend/govuk/all.js +1398 -273
  105. data/node_modules/govuk-frontend/govuk/common/closest-attribute-value.js +70 -0
  106. data/node_modules/govuk-frontend/govuk/common/index.js +172 -0
  107. data/node_modules/govuk-frontend/govuk/common/normalise-dataset.js +373 -0
  108. data/node_modules/govuk-frontend/govuk/common.js +138 -3
  109. data/node_modules/govuk-frontend/govuk/components/accordion/accordion.js +753 -25
  110. data/node_modules/govuk-frontend/govuk/components/accordion/fixtures.json +54 -22
  111. data/node_modules/govuk-frontend/govuk/components/accordion/macro-options.json +36 -0
  112. data/node_modules/govuk-frontend/govuk/components/accordion/template.njk +7 -1
  113. data/node_modules/govuk-frontend/govuk/components/back-link/fixtures.json +12 -12
  114. data/node_modules/govuk-frontend/govuk/components/breadcrumbs/fixtures.json +22 -22
  115. data/node_modules/govuk-frontend/govuk/components/button/_index.scss +23 -5
  116. data/node_modules/govuk-frontend/govuk/components/button/button.js +365 -107
  117. data/node_modules/govuk-frontend/govuk/components/button/fixtures.json +85 -66
  118. data/node_modules/govuk-frontend/govuk/components/button/template.njk +1 -1
  119. data/node_modules/govuk-frontend/govuk/components/character-count/_index.scss +9 -0
  120. data/node_modules/govuk-frontend/govuk/components/character-count/character-count.js +1033 -121
  121. data/node_modules/govuk-frontend/govuk/components/character-count/fixtures.json +112 -36
  122. data/node_modules/govuk-frontend/govuk/components/character-count/macro-options.json +42 -0
  123. data/node_modules/govuk-frontend/govuk/components/character-count/template.njk +27 -3
  124. data/node_modules/govuk-frontend/govuk/components/checkboxes/checkboxes.js +30 -2
  125. data/node_modules/govuk-frontend/govuk/components/checkboxes/fixtures.json +96 -93
  126. data/node_modules/govuk-frontend/govuk/components/cookie-banner/fixtures.json +46 -46
  127. data/node_modules/govuk-frontend/govuk/components/date-input/fixtures.json +50 -50
  128. data/node_modules/govuk-frontend/govuk/components/details/details.js +43 -13
  129. data/node_modules/govuk-frontend/govuk/components/details/fixtures.json +20 -20
  130. data/node_modules/govuk-frontend/govuk/components/error-message/fixtures.json +20 -20
  131. data/node_modules/govuk-frontend/govuk/components/error-summary/error-summary.js +268 -6
  132. data/node_modules/govuk-frontend/govuk/components/error-summary/fixtures.json +44 -35
  133. data/node_modules/govuk-frontend/govuk/components/error-summary/template.njk +25 -21
  134. data/node_modules/govuk-frontend/govuk/components/fieldset/fixtures.json +51 -39
  135. data/node_modules/govuk-frontend/govuk/components/file-upload/fixtures.json +26 -26
  136. data/node_modules/govuk-frontend/govuk/components/footer/_index.scss +1 -1
  137. data/node_modules/govuk-frontend/govuk/components/footer/fixtures.json +46 -46
  138. data/node_modules/govuk-frontend/govuk/components/footer/macro-options.json +2 -2
  139. data/node_modules/govuk-frontend/govuk/components/header/fixtures.json +93 -38
  140. data/node_modules/govuk-frontend/govuk/components/header/header.js +6 -0
  141. data/node_modules/govuk-frontend/govuk/components/header/macro-options.json +8 -2
  142. data/node_modules/govuk-frontend/govuk/components/header/template.njk +4 -2
  143. data/node_modules/govuk-frontend/govuk/components/hint/fixtures.json +12 -12
  144. data/node_modules/govuk-frontend/govuk/components/input/fixtures.json +80 -80
  145. data/node_modules/govuk-frontend/govuk/components/inset-text/fixtures.json +12 -12
  146. data/node_modules/govuk-frontend/govuk/components/label/fixtures.json +34 -34
  147. data/node_modules/govuk-frontend/govuk/components/notification-banner/fixtures.json +56 -46
  148. data/node_modules/govuk-frontend/govuk/components/notification-banner/notification-banner.js +252 -2
  149. data/node_modules/govuk-frontend/govuk/components/notification-banner/template.njk +1 -1
  150. data/node_modules/govuk-frontend/govuk/components/pagination/_index.scss +10 -7
  151. data/node_modules/govuk-frontend/govuk/components/pagination/fixtures.json +33 -26
  152. data/node_modules/govuk-frontend/govuk/components/panel/fixtures.json +18 -18
  153. data/node_modules/govuk-frontend/govuk/components/phase-banner/fixtures.json +14 -14
  154. data/node_modules/govuk-frontend/govuk/components/radios/fixtures.json +94 -91
  155. data/node_modules/govuk-frontend/govuk/components/radios/radios.js +30 -2
  156. data/node_modules/govuk-frontend/govuk/components/select/fixtures.json +32 -32
  157. data/node_modules/govuk-frontend/govuk/components/skip-link/fixtures.json +22 -20
  158. data/node_modules/govuk-frontend/govuk/components/skip-link/skip-link.js +10 -4
  159. data/node_modules/govuk-frontend/govuk/components/summary-list/fixtures.json +50 -50
  160. data/node_modules/govuk-frontend/govuk/components/table/_index.scss +1 -1
  161. data/node_modules/govuk-frontend/govuk/components/table/fixtures.json +40 -40
  162. data/node_modules/govuk-frontend/govuk/components/tabs/fixtures.json +29 -29
  163. data/node_modules/govuk-frontend/govuk/components/tabs/tabs.js +28 -0
  164. data/node_modules/govuk-frontend/govuk/components/tag/fixtures.json +28 -28
  165. data/node_modules/govuk-frontend/govuk/components/textarea/fixtures.json +34 -34
  166. data/node_modules/govuk-frontend/govuk/components/warning-text/fixtures.json +14 -14
  167. data/node_modules/govuk-frontend/govuk/core/_section-break.scss +1 -1
  168. data/node_modules/govuk-frontend/govuk/helpers/_colour.scss +2 -2
  169. data/node_modules/govuk-frontend/govuk/helpers/_links.scss +6 -6
  170. data/node_modules/govuk-frontend/govuk/i18n.js +390 -0
  171. data/node_modules/govuk-frontend/govuk/macros/i18n.njk +15 -0
  172. data/node_modules/govuk-frontend/govuk/settings/_all.scss +1 -0
  173. data/node_modules/govuk-frontend/govuk/settings/_colours-palette.scss +12 -0
  174. data/node_modules/govuk-frontend/govuk/settings/_compatibility.scss +26 -0
  175. data/node_modules/govuk-frontend/govuk/settings/_typography-font.scss +23 -0
  176. data/node_modules/govuk-frontend/govuk/settings/_typography-responsive.scss +12 -0
  177. data/node_modules/govuk-frontend/govuk/settings/_warnings.scss +53 -0
  178. data/node_modules/govuk-frontend/govuk/tools/_compatibility.scss +20 -6
  179. data/node_modules/govuk-frontend/govuk/vendor/polyfills/Date/now.js +21 -0
  180. data/node_modules/govuk-frontend/govuk/vendor/polyfills/Element/prototype/dataset.js +300 -0
  181. data/node_modules/govuk-frontend/govuk/vendor/polyfills/String/prototype/trim.js +21 -0
  182. data/node_modules/govuk-frontend/govuk-esm/all.mjs +50 -27
  183. data/node_modules/govuk-frontend/govuk-esm/common/closest-attribute-value.mjs +15 -0
  184. data/node_modules/govuk-frontend/govuk-esm/common/index.mjs +159 -0
  185. data/node_modules/govuk-frontend/govuk-esm/common/normalise-dataset.mjs +58 -0
  186. data/node_modules/govuk-frontend/govuk-esm/common.mjs +6 -28
  187. data/node_modules/govuk-frontend/govuk-esm/components/accordion/accordion.mjs +113 -43
  188. data/node_modules/govuk-frontend/govuk-esm/components/button/button.mjs +67 -30
  189. data/node_modules/govuk-frontend/govuk-esm/components/character-count/character-count.mjs +325 -123
  190. data/node_modules/govuk-frontend/govuk-esm/components/checkboxes/checkboxes.mjs +9 -3
  191. data/node_modules/govuk-frontend/govuk-esm/components/details/details.mjs +22 -8
  192. data/node_modules/govuk-frontend/govuk-esm/components/error-summary/error-summary.mjs +48 -6
  193. data/node_modules/govuk-frontend/govuk-esm/components/header/header.mjs +6 -0
  194. data/node_modules/govuk-frontend/govuk-esm/components/notification-banner/notification-banner.mjs +32 -2
  195. data/node_modules/govuk-frontend/govuk-esm/components/radios/radios.mjs +9 -3
  196. data/node_modules/govuk-frontend/govuk-esm/components/skip-link/skip-link.mjs +10 -4
  197. data/node_modules/govuk-frontend/govuk-esm/components/tabs/tabs.mjs +8 -2
  198. data/node_modules/govuk-frontend/govuk-esm/i18n.mjs +380 -0
  199. data/node_modules/govuk-frontend/govuk-esm/vendor/polyfills/Date/now.mjs +13 -0
  200. data/node_modules/govuk-frontend/govuk-esm/vendor/polyfills/Element/prototype/dataset.mjs +68 -0
  201. data/node_modules/govuk-frontend/govuk-esm/vendor/polyfills/String/prototype/trim.mjs +13 -0
  202. data/node_modules/govuk-frontend/govuk-prototype-kit/init.js +7 -0
  203. data/node_modules/govuk-frontend/govuk-prototype-kit/init.scss +12 -0
  204. data/node_modules/govuk-frontend/govuk-prototype-kit.config.json +138 -7
  205. data/node_modules/govuk-frontend/package.json +1 -1
  206. metadata +22 -3
@@ -27,10 +27,10 @@ window.GOVUK.analyticsGa4.analyticsModules = window.GOVUK.analyticsGa4.analytics
27
27
  schema_name: this.getMetaContent('schema-name'),
28
28
  content_id: this.getMetaContent('content-id'),
29
29
 
30
- section: this.getMetaContent('section'),
30
+ browse_topic: this.getMetaContent('section'),
31
31
  taxon_slug: this.getMetaContent('taxon-slug'),
32
32
  taxon_id: this.getMetaContent('taxon-id'),
33
- themes: this.getMetaContent('themes'),
33
+ taxonomy_level1: this.getMetaContent('themes'),
34
34
  taxon_slugs: this.getMetaContent('taxon-slugs'),
35
35
  taxon_ids: this.getMetaContent('taxon-ids'),
36
36
 
@@ -0,0 +1,140 @@
1
+ // = require govuk/vendor/polyfills/Element/prototype/closest.js
2
+ window.GOVUK = window.GOVUK || {}
3
+ window.GOVUK.analyticsGa4 = window.GOVUK.analyticsGa4 || {}
4
+ window.GOVUK.analyticsGa4.analyticsModules = window.GOVUK.analyticsGa4.analyticsModules || {};
5
+
6
+ (function (analyticsModules) {
7
+ 'use strict'
8
+
9
+ var Ga4SpecialistLinkTracker = {
10
+ init: function (config) {
11
+ if (window.dataLayer) {
12
+ config = config || {}
13
+ this.internalDownloadPaths = config.internalDownloadPaths || ['/government/uploads/']
14
+ this.dedicatedDownloadDomains = config.dedicatedDownloadDomains || ['assets.publishing.service.gov.uk']
15
+ window.GOVUK.analyticsGa4.core.trackFunctions.appendDomainsWithoutWWW(this.dedicatedDownloadDomains)
16
+ this.handleClick = this.handleClick.bind(this)
17
+ this.handleMousedown = this.handleMousedown.bind(this)
18
+
19
+ document.querySelector('body').addEventListener('click', this.handleClick)
20
+ document.querySelector('body').addEventListener('contextmenu', this.handleClick)
21
+ document.querySelector('body').addEventListener('mousedown', this.handleMousedown)
22
+ }
23
+ },
24
+
25
+ stopTracking: function () {
26
+ document.querySelector('body').removeEventListener('click', this.handleClick)
27
+ document.querySelector('body').removeEventListener('contextmenu', this.handleClick)
28
+ document.querySelector('body').removeEventListener('mousedown', this.handleMousedown)
29
+ },
30
+
31
+ handleClick: function (event) {
32
+ var element = event.target
33
+
34
+ if (element.tagName !== 'A') {
35
+ element = element.closest('a')
36
+ }
37
+
38
+ if (!element) {
39
+ return
40
+ }
41
+
42
+ // don't track this link if it's already being tracked by the other link tracker
43
+ if (element.closest('[data-ga4-link]')) {
44
+ return
45
+ }
46
+
47
+ var href = element.getAttribute('href')
48
+
49
+ if (!href) {
50
+ return
51
+ }
52
+ var clickData = {}
53
+ if (window.GOVUK.analyticsGa4.core.trackFunctions.isMailToLink(href)) {
54
+ clickData.event_name = 'navigation'
55
+ clickData.type = 'email'
56
+ clickData.external = 'true'
57
+ } else if (this.isDownloadLink(href)) {
58
+ clickData.event_name = 'file_download'
59
+ clickData.type = this.isPreviewLink(href) ? 'preview' : 'generic download'
60
+ clickData.external = window.GOVUK.analyticsGa4.core.trackFunctions.isExternalLink(href) ? 'true' : 'false'
61
+ } else if (window.GOVUK.analyticsGa4.core.trackFunctions.isExternalLink(href)) {
62
+ clickData.event_name = 'navigation'
63
+ clickData.type = 'generic link'
64
+ clickData.external = 'true'
65
+ }
66
+
67
+ if (Object.keys(clickData).length > 0) {
68
+ clickData.url = href
69
+ if (clickData.url) {
70
+ clickData.url = window.GOVUK.analyticsGa4.core.trackFunctions.removeCrossDomainParams(clickData.url)
71
+ clickData.link_domain = window.GOVUK.analyticsGa4.core.trackFunctions.populateLinkDomain(clickData.url)
72
+ clickData.link_path_parts = window.GOVUK.analyticsGa4.core.trackFunctions.populateLinkPathParts(clickData.url)
73
+ }
74
+
75
+ clickData.text = window.GOVUK.analyticsGa4.core.trackFunctions.removeLinesAndExtraSpaces(element.textContent)
76
+ clickData.method = window.GOVUK.analyticsGa4.core.trackFunctions.getClickType(event)
77
+
78
+ var schema = new window.GOVUK.analyticsGa4.Schemas().eventSchema()
79
+ schema.event = 'event_data'
80
+
81
+ // get attributes from the clickData object to send to GA
82
+ // only allow it if it already exists in the schema
83
+ for (var property in clickData) {
84
+ if (property in schema.event_data) {
85
+ schema.event_data[property] = clickData[property]
86
+ }
87
+ }
88
+
89
+ window.GOVUK.analyticsGa4.core.sendData(schema)
90
+ }
91
+ },
92
+
93
+ handleMousedown: function (event) {
94
+ // 1 = middle mouse button
95
+ if (event.button === 1) {
96
+ this.handleClick(event)
97
+ }
98
+ },
99
+
100
+ isDownloadLink: function (href) {
101
+ if (window.GOVUK.analyticsGa4.core.trackFunctions.isInternalLink(href) && this.hrefPointsToDownloadPath(href)) {
102
+ return true
103
+ }
104
+
105
+ var result = false
106
+ for (var i = 0; i < this.dedicatedDownloadDomains.length; i++) {
107
+ var downloadDomain = this.dedicatedDownloadDomains[i]
108
+ if (window.GOVUK.analyticsGa4.core.trackFunctions.hrefPointsToDomain(href, downloadDomain)) {
109
+ result = true
110
+ }
111
+ }
112
+ return result
113
+ },
114
+
115
+ isPreviewLink: function (href) {
116
+ /* Regex looks for:
117
+ 1. The file extension period (the character '.')
118
+ 2. any alphanumeric characters (so we can match any file type such as jpg, pdf, mp4.)
119
+ 3. the presence of '/preview'.
120
+ For example, .csv/preview or .mp4/preview will be matched.
121
+ Regex is used over JS string methods as this should work with anchor links, query string parameters and files that may have 'preview' in their name.
122
+ */
123
+ var previewRegex = /\.\w+\/preview/i
124
+ return previewRegex.test(href)
125
+ },
126
+
127
+ hrefPointsToDownloadPath: function (href) {
128
+ var result = false
129
+ for (var i = 0; i < this.internalDownloadPaths.length; i++) {
130
+ var internalDownloadPath = this.internalDownloadPaths[i]
131
+ if (href.indexOf(internalDownloadPath) !== -1) {
132
+ result = true
133
+ }
134
+ }
135
+ return result
136
+ }
137
+ }
138
+
139
+ analyticsModules.Ga4SpecialistLinkTracker = Ga4SpecialistLinkTracker
140
+ })(window.GOVUK.analyticsGa4.analyticsModules)
@@ -7,6 +7,9 @@ var initFunction = function () {
7
7
  var consentCookie = window.GOVUK.getConsentCookie()
8
8
 
9
9
  if (consentCookie && consentCookie.usage) {
10
+ window.GOVUK.analyticsGa4.vars.internalDomains = []
11
+ window.GOVUK.analyticsGa4.vars.internalDomains.push(window.GOVUK.analyticsGa4.core.trackFunctions.getHostname())
12
+ window.GOVUK.analyticsGa4.core.trackFunctions.appendDomainsWithoutWWW(window.GOVUK.analyticsGa4.vars.internalDomains)
10
13
  window.GOVUK.analyticsGa4.core.load()
11
14
 
12
15
  var analyticsModules = window.GOVUK.analyticsGa4.analyticsModules
@@ -3,6 +3,7 @@
3
3
  //= require ./analytics-ga4/ga4-schemas
4
4
  //= require ./analytics-ga4/pii-remover
5
5
  //= require ./analytics-ga4/ga4-page-views
6
+ //= require ./analytics-ga4/ga4-specialist-link-tracker
6
7
  //= require ./analytics-ga4/ga4-link-tracker
7
8
  //= require ./analytics-ga4/ga4-event-tracker
8
9
  //= require ./analytics-ga4/ga4-ecommerce-tracker
@@ -43,9 +43,10 @@ window.GOVUK.Modules.GovukAccordion = window.GOVUKFrontend.Accordion;
43
43
 
44
44
  // look for data attributes to put onto the 'show/hide all' link
45
45
  var showAllAttributes = this.$module.getAttribute('data-show-all-attributes')
46
+ var showAll
46
47
  if (showAllAttributes) {
47
48
  try {
48
- var showAll = this.$module.querySelector(this.showAllControls)
49
+ showAll = this.$module.querySelector(this.showAllControls)
49
50
  var values = JSON.parse(showAllAttributes)
50
51
  var keys = Object.keys(values)
51
52
  for (var i = 0; i < keys.length; i++) {
@@ -55,6 +56,16 @@ window.GOVUK.Modules.GovukAccordion = window.GOVUKFrontend.Accordion;
55
56
  console.error('Could not read accordion data attributes error: ' + e.message, window.location)
56
57
  }
57
58
  }
59
+
60
+ // if GA4 is enabled, set attributes on 'show all sections' for tracking using ga4-event-tracker
61
+ var dataModule = this.$module.getAttribute('data-module')
62
+ var isGa4Enabled = dataModule ? dataModule.indexOf('ga4-event-tracker') !== -1 : false
63
+ if (isGa4Enabled) {
64
+ var indexTotal = this.$module.querySelectorAll('.govuk-accordion__section').length
65
+ var showAllAttributesGa4 = { event_name: 'select_content', type: 'accordion', index: 0, index_total: indexTotal }
66
+ showAll = this.$module.querySelector(this.showAllControls)
67
+ showAll.setAttribute('data-ga4-event', JSON.stringify(showAllAttributesGa4))
68
+ }
58
69
  }
59
70
 
60
71
  // Navigate to and open accordions with anchored content on page load if a hash is present
@@ -98,13 +98,22 @@ window.GOVUK.Modules = window.GOVUK.Modules || {};
98
98
  return $menu.querySelectorAll('button[aria-expanded="true"]').length > 0
99
99
  }
100
100
 
101
- // Returns what screen size the window is currently. Returns a string of
102
- // either `desktop` or `mobile` so it can be interpolated to access the
101
+ // Detect the current viewport width. Return the string `desktop` or `mobile` so it can be interpolated to access the
103
102
  // `data-toggle-{desktop|mobile}-group` attribute.
103
+ //
104
+ // Use `matchedia` which mitigates issues in modern browsers when scrollbars are forced in MacOS (using `document.documentElement.clientWidth`
105
+ // for viewport width detection has issues in Chrome and Firefox, and `window.innerWidth` has issues in Safari).
106
+ //
107
+ // Fall back to `document.documentElement.clientWidth` for legacy browsers.
104
108
  var windowSize = function () {
105
- return document.documentElement.clientWidth >= SETTINGS.breakpoint.desktop ? 'desktop' : 'mobile'
109
+ var viewport = false
110
+ if (typeof window.matchMedia === 'function') {
111
+ viewport = window.matchMedia('(min-width:' + SETTINGS.breakpoint.desktop + 'px)').matches
112
+ } else {
113
+ viewport = document.documentElement.clientWidth >= SETTINGS.breakpoint.desktop
114
+ }
115
+ return viewport ? 'desktop' : 'mobile'
106
116
  }
107
-
108
117
  function SuperNavigationMegaMenu ($module) {
109
118
  this.$module = $module
110
119
  this.$navigationToggle = this.$module.querySelector('#super-navigation-menu-toggle')
@@ -28,15 +28,31 @@ window.GOVUK.Modules = window.GOVUK.Modules || {};
28
28
  if (xhr.readyState === 4) {
29
29
  if (xhr.status === 200) {
30
30
  var responseText = xhr.responseText
31
- // if response text exists and is JSON parse-able, parse the response and get the button html
31
+ // if response text exists and is JSON parse-able, parse the response and update the button html
32
32
  if (responseText && this.responseIsJSON(responseText)) {
33
- var newButton = JSON.parse(responseText).button_html
34
- var html = document.createElement('div')
35
- html.innerHTML = newButton
36
- // test that the html returned contains the button component; if yes, swap the button for the updated version
37
- var responseButtonContainer = html.querySelector('form.gem-c-single-page-notification-button')
38
- if (responseButtonContainer) {
39
- this.$module.parentNode.replaceChild(responseButtonContainer, this.$module)
33
+ var active = JSON.parse(responseText).active
34
+
35
+ var customSubscribeText = this.$module.getAttribute('data-button-text-subscribe')
36
+ var customUnsubscribeText = this.$module.getAttribute('data-button-text-unsubscribe')
37
+ // Only set custom button text if both text items are provided
38
+ var customText = customSubscribeText && customUnsubscribeText
39
+
40
+ // Append '-[button-location]' to the tracking data attribute value if data-button-location is set
41
+ var optionalButtonLocation = this.$module.getAttribute('data-button-location') ? '-' + this.$module.getAttribute('data-button-location') : ''
42
+
43
+ // If response returns active, user has subscribed to notifications
44
+ if (active === true) {
45
+ this.$module.setAttribute('data-track-action', 'Unsubscribe-button' + optionalButtonLocation)
46
+
47
+ if (customText) {
48
+ this.$module.querySelector('.gem-c-single-page-notication-button__text').textContent = customUnsubscribeText
49
+ }
50
+ } else {
51
+ this.$module.setAttribute('data-track-action', 'Subscribe-button' + optionalButtonLocation)
52
+
53
+ if (customText) {
54
+ this.$module.querySelector('.gem-c-single-page-notication-button__text').textContent = customSubscribeText
55
+ }
40
56
  }
41
57
  }
42
58
  }
@@ -133,11 +133,8 @@
133
133
  }
134
134
 
135
135
  /**
136
- * Get the interaction attribution name for an element
137
- *
138
- * @param {HTMLElement} el
139
- * @returns string
140
- */
136
+ * Get the interaction attribution name for an element
137
+ */
141
138
  function interactionAttributionForElement(el) {
142
139
  // Our first preference is to use the data-sctrack attribute from anywhere in the tree
143
140
  var trackId = getClosestScTrackAttribute(el);
@@ -183,10 +180,10 @@
183
180
  // prevent having to make regular typeof checks.
184
181
  var performance = window.performance || {};
185
182
  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,
183
+ // If performance.timing isn't available, we attempt to polyfill the navigationStart value.
184
+ // Our first attempt is from LUX.ns, which is the time that the snippet execution began. If this
185
+ // is not available, we fall back to the time that the current script execution began.
186
+ navigationStart: ((_a = window.LUX) === null || _a === void 0 ? void 0 : _a.ns) || scriptStartTime,
190
187
  };
191
188
  function msSinceNavigationStart() {
192
189
  if (performance.now) {
@@ -195,10 +192,10 @@
195
192
  return now() - timing.navigationStart;
196
193
  }
197
194
  /**
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
- */
195
+ * Simple wrapper around performance.getEntriesByType to provide fallbacks for
196
+ * legacy browsers, and work around edge cases where undefined is returned instead
197
+ * of an empty PerformanceEntryList.
198
+ */
202
199
  function getEntriesByType(type) {
203
200
  if (typeof performance.getEntriesByType === "function") {
204
201
  var entries = performance.getEntriesByType(type);
@@ -210,72 +207,73 @@
210
207
  }
211
208
 
212
209
  var Matching = /** @class */ (function () {
213
- function Matching() {
210
+ function Matching() {
211
+ }
212
+ Matching.isMatching = function (pattern, url) {
213
+ var regexp = Matching.createRegexpFromPattern(pattern);
214
+ return url.match(regexp) ? true : false;
215
+ };
216
+ /**
217
+ * Converts string pattern to RegExp object
218
+ * @return RegExp
219
+ */
220
+ Matching.createRegexpFromPattern = function (pattern) {
221
+ var regexp;
222
+ if (pattern == "/") {
223
+ regexp = this.getRegexpForHostnameRoot();
214
224
  }
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;
225
+ else if (!pattern.includes(Matching.wildcard)) {
226
+ regexp = this.getRegexpForExactString(pattern);
227
+ }
228
+ else {
229
+ regexp = this.createRegexpFromPathname(pattern);
230
+ }
231
+ return regexp;
232
+ };
233
+ /**
234
+ * Converts URL pathname string pattern to RegExp object
235
+ * Multile wildcards (*) are supported
236
+ * @return RegExp
237
+ */
238
+ Matching.createRegexpFromPathname = function (pattern) {
239
+ var anyDomain = pattern.charAt(0) == "/";
240
+ pattern = this.escapeStringForRegexp(pattern);
241
+ var expression = "^" +
242
+ (anyDomain ? Matching.domainExpression : "") +
243
+ pattern.replaceAll(Matching.wildcard, ".*?") +
244
+ "$";
245
+ return new RegExp(expression, "i");
246
+ };
247
+ /**
248
+ * Matches hostname root (e.g. "/", "somedomain.com/", "www.somedomain.co.nz/")
249
+ * Trailing slash is mandatory
250
+ * @return RegExp
251
+ */
252
+ Matching.getRegexpForHostnameRoot = function () {
253
+ return new RegExp("^" + Matching.domainExpression + "/$", "i");
254
+ };
255
+ /**
256
+ * Matches exact string (no wildcard provided)
257
+ * @return RegExp
258
+ */
259
+ Matching.getRegexpForExactString = function (string) {
260
+ var anyDomain = string.charAt(0) == "/";
261
+ return new RegExp("^" +
262
+ (anyDomain ? Matching.domainExpression : "") +
263
+ this.escapeStringForRegexp(string) +
264
+ "/?$", "i");
265
+ };
266
+ /**
267
+ * Escape special symbols in regexp string
268
+ * @param string
269
+ */
270
+ Matching.escapeStringForRegexp = function (string) {
271
+ // we don't escape * because it's our own special symbol!
272
+ return string.replace(/[-/\\^$+?.()|[\]{}]/g, "\\$&");
273
+ };
274
+ Matching.wildcard = "*";
275
+ Matching.domainExpression = "[a-zA-Z0-9-.]{1,61}[a-zA-Z0-9]\\.[a-zA-Z]{2,}";
276
+ return Matching;
279
277
  }());
280
278
 
281
279
  var LUX = window.LUX || {};
@@ -290,7 +288,7 @@
290
288
  /// End
291
289
  // -------------------------------------------------------------------------
292
290
 
293
- var SCRIPT_VERSION = "302";
291
+ var SCRIPT_VERSION = "304";
294
292
  var logger = new Logger();
295
293
  var globalConfig = fromObject(LUX);
296
294
  logger.logEvent(LogEvent.EvaluationStart, [SCRIPT_VERSION]);
@@ -787,8 +785,8 @@
787
785
  ",x|" +
788
786
  hStats["max"] +
789
787
  (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;
788
+ sCPU += "s|" + hCPU[jsType] + sStats + hCPUDetails[jsType];
789
+ return sCPU;
792
790
  }
793
791
  // Return a hash of "stats" about the CPU details incl. count, max, and median.
794
792
  function cpuStats(sDetails) {
@@ -1657,7 +1655,7 @@
1657
1655
  _removeIxHandlers();
1658
1656
  if (typeof ghIx["k"] === "undefined") {
1659
1657
  ghIx["k"] = Math.round(_now());
1660
- if (e && e.target) {
1658
+ if (e && e.target instanceof Element) {
1661
1659
  var trackId = interactionAttributionForElement(e.target);
1662
1660
  if (trackId) {
1663
1661
  ghIx["ki"] = trackId;
@@ -1670,16 +1668,15 @@
1670
1668
  _removeIxHandlers();
1671
1669
  if (typeof ghIx["c"] === "undefined") {
1672
1670
  ghIx["c"] = Math.round(_now());
1673
- var target = null;
1671
+ var target = void 0;
1674
1672
  try {
1675
1673
  // Seeing "Permission denied" errors, so do a simple try-catch.
1676
- if (e && e.target) {
1674
+ if (e && e.target instanceof Element) {
1677
1675
  target = e.target;
1678
1676
  }
1679
1677
  }
1680
1678
  catch (e) {
1681
1679
  logger.logEvent(LogEvent.EventTargetAccessError);
1682
- target = null;
1683
1680
  }
1684
1681
  if (target) {
1685
1682
  if (e.clientX) {
@@ -1687,7 +1684,7 @@
1687
1684
  ghIx["cx"] = e.clientX;
1688
1685
  ghIx["cy"] = e.clientY;
1689
1686
  }
1690
- var trackId = interactionAttributionForElement(e.target);
1687
+ var trackId = interactionAttributionForElement(target);
1691
1688
  if (trackId) {
1692
1689
  ghIx["ci"] = trackId;
1693
1690
  }
@@ -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
 
@@ -201,9 +201,7 @@ $after-button-padding-left: govuk-spacing(5);
201
201
 
202
202
  display: inline-block;
203
203
  font-size: 19px;
204
- @if $govuk-typography-use-rem {
205
- font-size: govuk-px-to-rem(19px);
206
- }
204
+ font-size: govuk-px-to-rem(19px);
207
205
  font-weight: bold;
208
206
  margin: govuk-spacing(3) 0;
209
207
 
@@ -242,14 +240,10 @@ $after-button-padding-left: govuk-spacing(5);
242
240
  }
243
241
 
244
242
  @include govuk-media-query($from: "desktop") {
243
+ // stylelint-disable max-nesting-depth
245
244
  float: left;
246
245
  font-size: 16px;
247
-
248
- // stylelint-disable max-nesting-depth
249
- @if $govuk-typography-use-rem {
250
- font-size: govuk-px-to-rem(16px);
251
- }
252
-
246
+ font-size: govuk-px-to-rem(16px);
253
247
  height: govuk-spacing(4);
254
248
  position: relative;
255
249
 
@@ -394,9 +388,7 @@ $after-button-padding-left: govuk-spacing(5);
394
388
  color: govuk-colour("white");
395
389
  float: left;
396
390
  font-size: 16px;
397
- @if $govuk-typography-use-rem {
398
- font-size: govuk-px-to-rem(16px);
399
- }
391
+ font-size: govuk-px-to-rem(16px);
400
392
  height: $black-bar-height;
401
393
  position: relative;
402
394
  text-decoration: none;
@@ -604,9 +596,7 @@ $after-button-padding-left: govuk-spacing(5);
604
596
  @include govuk-link-style-no-underline;
605
597
 
606
598
  font-size: 16px;
607
- @if $govuk-typography-use-rem {
608
- font-size: govuk-px-to-rem(16px);
609
- }
599
+ font-size: govuk-px-to-rem(16px);
610
600
  font-weight: 700;
611
601
  background: govuk-colour("black");
612
602
  border: 0;
@@ -878,9 +868,7 @@ $after-button-padding-left: govuk-spacing(5);
878
868
 
879
869
  .gem-c-layout-super-navigation-header__navigation-second-item-link {
880
870
  font-size: 16px;
881
- @if $govuk-typography-use-rem {
882
- font-size: govuk-px-to-rem(16px);
883
- }
871
+ font-size: govuk-px-to-rem(16px);
884
872
 
885
873
  &:after {
886
874
  @include make-selectable-area-bigger;
@@ -898,9 +886,7 @@ $after-button-padding-left: govuk-spacing(5);
898
886
 
899
887
  .gem-c-layout-super-navigation-header__navigation-second-item-link--with-description {
900
888
  font-size: 16px;
901
- @if $govuk-typography-use-rem {
902
- font-size: govuk-px-to-rem(16px);
903
- }
889
+ font-size: govuk-px-to-rem(16px);
904
890
  font-weight: bold;
905
891
  }
906
892
 
@@ -934,9 +920,7 @@ $after-button-padding-left: govuk-spacing(5);
934
920
  .gem-c-layout-super-navigation-header__navigation-second-footer-link {
935
921
  display: inline-block;
936
922
  font-size: 16px;
937
- @if $govuk-typography-use-rem {
938
- font-size: govuk-px-to-rem(16px);
939
- }
923
+ font-size: govuk-px-to-rem(16px);
940
924
  margin: govuk-spacing(1) 0;
941
925
 
942
926
  &:after {
@@ -956,9 +940,7 @@ $after-button-padding-left: govuk-spacing(5);
956
940
  .gem-c-layout-super-navigation-header__navigation-second-item-description {
957
941
  @include govuk-typography-common;
958
942
  font-size: 16px;
959
- @if $govuk-typography-use-rem {
960
- font-size: govuk-px-to-rem(16px);
961
- }
943
+ font-size: govuk-px-to-rem(16px);
962
944
  font-weight: normal;
963
945
  margin: govuk-spacing(1) 0 0 0;
964
946
  }
@@ -996,9 +978,7 @@ $after-button-padding-left: govuk-spacing(5);
996
978
  .gem-c-layout-super-navigation-header__popular-link {
997
979
  display: inline-block;
998
980
  font-size: 16px;
999
- @if $govuk-typography-use-rem {
1000
- font-size: govuk-px-to-rem(16px);
1001
- }
981
+ font-size: govuk-px-to-rem(16px);
1002
982
  padding: 0;
1003
983
 
1004
984
  &:after {