govuk_publishing_components 32.0.0 → 33.0.0

Sign up to get free protection for your applications and to get access to all the features.
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 {