govuk_publishing_components 35.22.0 → 36.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 (38) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/config/govuk_publishing_components_manifest.js +1 -0
  3. data/app/assets/javascripts/govuk_publishing_components/analytics-ga4/ga4-auto-tracker.js +1 -5
  4. data/app/assets/javascripts/govuk_publishing_components/analytics-ga4/ga4-core.js +29 -41
  5. data/app/assets/javascripts/govuk_publishing_components/analytics-ga4/ga4-event-tracker.js +6 -10
  6. data/app/assets/javascripts/govuk_publishing_components/analytics-ga4/ga4-form-tracker.js +1 -4
  7. data/app/assets/javascripts/govuk_publishing_components/analytics-ga4/ga4-link-tracker.js +1 -5
  8. data/app/assets/javascripts/govuk_publishing_components/analytics-ga4/ga4-page-views.js +6 -17
  9. data/app/assets/javascripts/govuk_publishing_components/analytics-ga4/ga4-print-intent-tracker.js +1 -3
  10. data/app/assets/javascripts/govuk_publishing_components/analytics-ga4/ga4-schemas.js +4 -20
  11. data/app/assets/javascripts/govuk_publishing_components/analytics-ga4/ga4-scroll-tracker.js +1 -3
  12. data/app/assets/javascripts/govuk_publishing_components/analytics-ga4/ga4-specialist-link-tracker.js +1 -5
  13. data/app/assets/javascripts/govuk_publishing_components/analytics-ga4/ga4-video-tracker.js +1 -4
  14. data/app/assets/javascripts/govuk_publishing_components/analytics-ga4/pii-remover.js +22 -4
  15. data/app/assets/javascripts/govuk_publishing_components/components/cross-service-header.js +78 -0
  16. data/app/assets/stylesheets/govuk_publishing_components/_all_components.scss +1 -0
  17. data/app/assets/stylesheets/govuk_publishing_components/components/_action-link.scss +3 -79
  18. data/app/assets/stylesheets/govuk_publishing_components/components/_cross-service-header.scss +430 -0
  19. data/app/views/govuk_publishing_components/components/_action_link.html.erb +2 -19
  20. data/app/views/govuk_publishing_components/components/_cross_service_header.html.erb +19 -0
  21. data/app/views/govuk_publishing_components/components/_layout_for_public.html.erb +9 -0
  22. data/app/views/govuk_publishing_components/components/cross_service_header/_one_login_header.html.erb +97 -0
  23. data/app/views/govuk_publishing_components/components/cross_service_header/_service_header.html.erb +49 -0
  24. data/app/views/govuk_publishing_components/components/docs/action_link.yml +1 -52
  25. data/app/views/govuk_publishing_components/components/docs/cross_service_header.yml +64 -0
  26. data/lib/govuk_publishing_components/app_helpers/asset_helper.rb +1 -0
  27. data/lib/govuk_publishing_components/presenters/component_wrapper_helper.rb +1 -1
  28. data/lib/govuk_publishing_components/presenters/meta_tags.rb +21 -0
  29. data/lib/govuk_publishing_components/version.rb +1 -1
  30. metadata +8 -10
  31. data/app/assets/images/govuk_publishing_components/action-link--nhs.png +0 -0
  32. data/app/assets/images/govuk_publishing_components/action-link--nhs.svg +0 -1
  33. data/app/assets/images/govuk_publishing_components/action-link-arrow--blue.png +0 -0
  34. data/app/assets/images/govuk_publishing_components/action-link-arrow--blue.svg +0 -9
  35. data/app/assets/images/govuk_publishing_components/action-link-arrow--brexit.svg +0 -3
  36. data/app/assets/images/govuk_publishing_components/action-link-arrow--transparent.svg +0 -1
  37. data/app/assets/images/govuk_publishing_components/action-link-arrow--white.png +0 -0
  38. data/app/assets/images/govuk_publishing_components/action-link-arrow--white.svg +0 -1
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b44a8215911c2a260e0b80134c14d3f974a4ee0bb91cdf7eb23dc081e61ee9d9
4
- data.tar.gz: 4262f87d3ce863db103a0f24e3936b69e2219b0794ad83d142abb115bf7fe66a
3
+ metadata.gz: 773208000d7b04127bf634415ed17bbfd977ba73ab9a45e2eca5742f19eacbc6
4
+ data.tar.gz: c2b77952558ca4fd34c22e87088721dffe9d55346cc1cd9a5ac8ee3f64ff2087
5
5
  SHA512:
6
- metadata.gz: 4deebaa45c7bb16f6acbbc0ae2b916222a6e8b3c9efb05581f3fefbf8e4b87b3ee772025b81399055e3bbedceb6162d1cd9df56b7e22f6ad1f6637523dea307c
7
- data.tar.gz: 1fef3fd8a3ab99df0359cfd7d2787ba7d0d62ee50e12e455acb64fad1c51fbb47bc657b4f3ef784767c9c2fb95967678be14d168efb9db789ce28b618118e2bc
6
+ metadata.gz: 5d2efbb677bc763e54375000098c7419ccec70d70d4ad49093e6fda016788ec22ef989d8c7a480e5e9fa00d4dba4c6ac10672bb683baa67d129a3a49da80e460
7
+ data.tar.gz: 5e34040e64f3863838db6c24a5d8e2c0f0d423d62f24f6841adb204e0071899699796c07740130b6ec06205a87cffdcfed80814a177f7eb6aa93cd7112e55e1a
@@ -30,6 +30,7 @@
30
30
  //= link govuk_publishing_components/components/_contextual-sidebar.css
31
31
  //= link govuk_publishing_components/components/_cookie-banner.css
32
32
  //= link govuk_publishing_components/components/_copy-to-clipboard.css
33
+ //= link govuk_publishing_components/components/_cross-service-header.css
33
34
  //= link govuk_publishing_components/components/_date-input.css
34
35
  //= link govuk_publishing_components/components/_details.css
35
36
  //= link govuk_publishing_components/components/_devolved-nations.css
@@ -35,12 +35,8 @@ window.GOVUK.Modules = window.GOVUK.Modules || {};
35
35
  console.error('GA4 configuration error: ' + e.message, window.location)
36
36
  return
37
37
  }
38
-
39
38
  data.text = this.PIIRemover.stripPIIWithOverride(data.text, true, true)
40
- var schemas = new window.GOVUK.analyticsGa4.Schemas()
41
- var schema = schemas.mergeProperties(data, 'event_data')
42
-
43
- window.GOVUK.analyticsGa4.core.sendData(schema)
39
+ window.GOVUK.analyticsGa4.core.applySchemaAndSendData(data, 'event_data')
44
40
  }
45
41
  }
46
42
 
@@ -35,20 +35,35 @@ window.GOVUK.analyticsGa4 = window.GOVUK.analyticsGa4 || {};
35
35
  },
36
36
 
37
37
  sendData: function (data) {
38
- // Prevent any GA4 data being sent during Smokey tests
39
- if (this.getUserAgent() === 'Smokey Test / Ruby') {
40
- return
41
- }
42
-
43
38
  data.govuk_gem_version = this.getGemVersion()
44
39
  // set this in the console as a debugging aid
45
40
  if (window.GOVUK.analyticsGa4.showDebug) {
46
- data.event_data = this.sortEventData(data.event_data)
41
+ if (data.event_data) {
42
+ data.event_data = this.sortEventData(data.event_data)
43
+ } else if (data.page_view) {
44
+ data.page_view = this.sortEventData(data.page_view)
45
+ } else if (data.search_results) {
46
+ data.search_results = this.sortEventData(data.search_results)
47
+ }
47
48
  console.info(JSON.stringify(data, null, ' '))
48
49
  }
50
+
51
+ // Send GA4 data to a fake dataLayer if smokey_cachebust or disable_ga4 is in the query string. Used to prevent Smokey/other tests from spamming our analytics.
52
+ if (this.trackFunctions.getSearch().match(/[?&](disable_ga4|smokey_cachebust){1}/)) {
53
+ window.fakeDataLayer = window.fakeDataLayer || []
54
+ window.fakeDataLayer.push(data)
55
+ return
56
+ }
57
+
49
58
  window.dataLayer.push(data)
50
59
  },
51
60
 
61
+ applySchemaAndSendData: function (data, name) {
62
+ var schemas = new window.GOVUK.analyticsGa4.Schemas()
63
+ var schema = schemas.mergeProperties(data, name)
64
+ this.sendData(schema)
65
+ },
66
+
52
67
  getGemVersion: function () {
53
68
  return window.GOVUK.analyticsGa4.vars.gem_version || 'not found'
54
69
  },
@@ -74,6 +89,10 @@ window.GOVUK.analyticsGa4 = window.GOVUK.analyticsGa4 || {};
74
89
  return /^(http:||https:)?(\/\/)([^\/]*)/ // eslint-disable-line no-useless-escape
75
90
  },
76
91
 
92
+ getSearch: function () {
93
+ return window.location.search
94
+ },
95
+
77
96
  findTrackingAttributes: function (clicked, trackingTrigger) {
78
97
  if (clicked.hasAttribute('[' + trackingTrigger + ']')) {
79
98
  return clicked
@@ -82,39 +101,6 @@ window.GOVUK.analyticsGa4 = window.GOVUK.analyticsGa4 || {};
82
101
  }
83
102
  },
84
103
 
85
- // create an object to split up long URLs and get around the 100 character limit on GTM data
86
- // this gets reassembled in GA4
87
- populateLinkPathParts: function (href) {
88
- var path = ''
89
- if (this.hrefIsRelative(href) || this.isMailToLink(href)) {
90
- path = href
91
- } else {
92
- // This regex matches a protocol and domain name at the start of a string such as https://www.gov.uk, http://gov.uk, //gov.uk
93
- path = href.replace(/^(http:||https:)?(\/\/)([^\/]*)/, '') // eslint-disable-line no-useless-escape
94
- }
95
-
96
- if (path === '/' || path.length === 0) {
97
- return
98
- }
99
-
100
- return this.splitStringIntoParts(path)
101
- },
102
-
103
- splitStringIntoParts: function (string) {
104
- /*
105
- This will create an object with 5 keys that are indexes ("1", "2", etc.)
106
- The values will be each part of the string split every 100 characters, or undefined.
107
- For example: {"1": "/hello/world/etc...", "2": "/more/path/text...", "3": undefined, "4": undefined, "5": undefined}
108
- Undefined values are needed to override the persistent object in GTM so that any values from old pushes are overwritten.
109
- */
110
- var parts = string.match(/.{1,100}/g)
111
- var obj = {}
112
- for (var i = 0; i < 5; i++) {
113
- obj[(i + 1).toString()] = parts[i]
114
- }
115
- return obj
116
- },
117
-
118
104
  hrefIsRelative: function (href) {
119
105
  // Checks that a href is relative by the lack of http:, https:// or // at the start of the href.
120
106
  var domain = this.getDomainRegex().exec(href)
@@ -135,6 +121,8 @@ window.GOVUK.analyticsGa4 = window.GOVUK.analyticsGa4 || {};
135
121
  return 'command/win click'
136
122
  } else if (event.shiftKey) {
137
123
  return 'shift click'
124
+ } else if (event.altKey) {
125
+ return 'alt/option click'
138
126
  } else {
139
127
  return 'primary click'
140
128
  }
@@ -259,8 +247,8 @@ window.GOVUK.analyticsGa4 = window.GOVUK.analyticsGa4 || {};
259
247
  var totalLinks = 0
260
248
  for (var i = 0; i < links.length; i++) {
261
249
  var link = links[i]
262
- // Only index links that are not search results or do not have a data-ga4-do-not-index attribute
263
- if (link.getAttribute('data-ga4-ecommerce-path') || link.getAttribute('data-ga4-do-not-index') !== null) {
250
+ // Ignore links that don't have a href, have a data-ga4-do-not-index attribute on them, or are search result links.
251
+ if (!link.getAttribute('href') || link.getAttribute('data-ga4-ecommerce-path') || link.getAttribute('data-ga4-do-not-index') !== null) {
264
252
  continue
265
253
  }
266
254
  totalLinks++
@@ -43,9 +43,6 @@ window.GOVUK.Modules = window.GOVUK.Modules || {};
43
43
  var text = data.text || event.target.textContent
44
44
  data.text = window.GOVUK.analyticsGa4.core.trackFunctions.removeLinesAndExtraSpaces(text)
45
45
 
46
- var schemas = new window.GOVUK.analyticsGa4.Schemas()
47
- var schema = schemas.mergeProperties(data, 'event_data')
48
-
49
46
  /* Ensure it only tracks aria-expanded in an element with data-ga4-expandable on it. */
50
47
  if (target.closest('[data-ga4-expandable]')) {
51
48
  var ariaExpanded = this.getClosestAttribute(target, 'aria-expanded')
@@ -59,12 +56,12 @@ window.GOVUK.Modules = window.GOVUK.Modules || {};
59
56
  var detailsElement = target.closest('details')
60
57
 
61
58
  if (ariaExpanded) {
62
- schema.event_data.text = data.text || target.innerText
63
- schema.event_data.action = (ariaExpanded === 'false') ? 'opened' : 'closed'
59
+ data.text = data.text || target.innerText
60
+ data.action = (ariaExpanded === 'false') ? 'opened' : 'closed'
64
61
  } else if (detailsElement) {
65
- schema.event_data.text = data.text || detailsElement.textContent
62
+ data.text = data.text || detailsElement.textContent
66
63
  var openAttribute = detailsElement.getAttribute('open')
67
- schema.event_data.action = (openAttribute == null) ? 'opened' : 'closed'
64
+ data.action = (openAttribute == null) ? 'opened' : 'closed'
68
65
  }
69
66
 
70
67
  /* If a tab was clicked, grab the href of the clicked tab (usually an anchor # link) */
@@ -74,12 +71,11 @@ window.GOVUK.Modules = window.GOVUK.Modules || {};
74
71
  if (aTag) {
75
72
  var href = aTag.getAttribute('href')
76
73
  if (href) {
77
- schema.event_data.url = window.GOVUK.analyticsGa4.core.trackFunctions.appendPathToAnchorLinks(href)
74
+ data.url = window.GOVUK.analyticsGa4.core.trackFunctions.appendPathToAnchorLinks(href)
78
75
  }
79
76
  }
80
77
  }
81
-
82
- window.GOVUK.analyticsGa4.core.sendData(schema)
78
+ window.GOVUK.analyticsGa4.core.applySchemaAndSendData(data, 'event_data')
83
79
  }
84
80
  }
85
81
 
@@ -50,10 +50,7 @@ window.GOVUK.Modules = window.GOVUK.Modules || {};
50
50
  data.text = data.text.toLowerCase()
51
51
  data.text = window.GOVUK.analyticsGa4.core.trackFunctions.removeLinesAndExtraSpaces(data.text)
52
52
  }
53
-
54
- var schemas = new window.GOVUK.analyticsGa4.Schemas()
55
- var schema = schemas.mergeProperties(data, 'event_data')
56
- window.GOVUK.analyticsGa4.core.sendData(schema)
53
+ window.GOVUK.analyticsGa4.core.applySchemaAndSendData(data, 'event_data')
57
54
  }
58
55
  }
59
56
 
@@ -90,7 +90,6 @@ window.GOVUK.Modules = window.GOVUK.Modules || {};
90
90
  data.url = trackFunctions.applyRedactionIfRequired(this.PIIRemover, element, data.url)
91
91
  data.url = trackFunctions.appendPathToAnchorLinks(data.url)
92
92
  data.link_domain = trackFunctions.populateLinkDomain(data.url)
93
- data.link_path_parts = trackFunctions.populateLinkPathParts(data.url)
94
93
  data.method = trackFunctions.getClickType(event)
95
94
  data.external = trackFunctions.isExternalLink(data.url) ? 'true' : 'false'
96
95
  data.index = this.setIndex(data.index, event.target)
@@ -106,10 +105,7 @@ window.GOVUK.Modules = window.GOVUK.Modules || {};
106
105
  if (data.type === 'smart answer' && data.action === 'change response') {
107
106
  data.section = this.PIIRemover.stripPIIWithOverride(data.section, true, true)
108
107
  }
109
-
110
- var schemas = new window.GOVUK.analyticsGa4.Schemas()
111
- var schema = schemas.mergeProperties(data, 'event_data')
112
- window.GOVUK.analyticsGa4.core.sendData(schema)
108
+ window.GOVUK.analyticsGa4.core.applySchemaAndSendData(data, 'event_data')
113
109
  }
114
110
  }
115
111
 
@@ -36,8 +36,8 @@ window.GOVUK.analyticsGa4.analyticsModules = window.GOVUK.analyticsGa4.analytics
36
36
  taxonomy_level1: this.getMetaContent('themes'),
37
37
  taxonomy_main: this.getMetaContent('taxon-slug'),
38
38
  taxonomy_main_id: this.getMetaContent('taxon-id'),
39
- taxonomy_all: this.splitLongMetaContent('taxon-slugs'),
40
- taxonomy_all_ids: this.splitLongMetaContent('taxon-ids'),
39
+ taxonomy_all: this.getMetaContent('taxon-slugs'),
40
+ taxonomy_all_ids: this.getMetaContent('taxon-ids'),
41
41
 
42
42
  language: this.getLanguage(),
43
43
  history: this.getHistory(),
@@ -45,8 +45,8 @@ window.GOVUK.analyticsGa4.analyticsModules = window.GOVUK.analyticsGa4.analytics
45
45
  first_published_at: this.stripTimeFrom(this.getMetaContent('first-published-at')),
46
46
  updated_at: this.stripTimeFrom(this.getMetaContent('updated-at')),
47
47
  public_updated_at: this.stripTimeFrom(this.getMetaContent('public-updated-at')),
48
- publishing_government: this.getMetaContent('publishing-government'),
49
- political_status: this.getMetaContent('political-status'),
48
+ publishing_government: this.getMetaContent('publishing-government') || this.getMetaContent('ga4-publishing-government'),
49
+ political_status: this.getMetaContent('political-status') || this.getMetaContent('ga4-political-status'),
50
50
  primary_publishing_organisation: this.getMetaContent('primary-publishing-organisation'),
51
51
  organisations: this.getMetaContent('analytics:organisations'),
52
52
  world_locations: this.getMetaContent('analytics:world-locations'),
@@ -73,12 +73,8 @@ window.GOVUK.analyticsGa4.analyticsModules = window.GOVUK.analyticsGa4.analytics
73
73
  return this.PIIRemover.stripPIIWithOverride(this.stripGaParam(document.location.href), true, true)
74
74
  },
75
75
 
76
- getSearch: function () {
77
- return window.location.search
78
- },
79
-
80
76
  getSearchTerm: function () {
81
- var queryString = this.getSearch()
77
+ var queryString = window.GOVUK.analyticsGa4.core.trackFunctions.getSearch()
82
78
 
83
79
  if (!queryString) {
84
80
  return undefined
@@ -97,7 +93,7 @@ window.GOVUK.analyticsGa4.analyticsModules = window.GOVUK.analyticsGa4.analytics
97
93
  },
98
94
 
99
95
  getQueryString: function () {
100
- var queryString = this.getSearch()
96
+ var queryString = window.GOVUK.analyticsGa4.core.trackFunctions.getSearch()
101
97
  if (queryString) {
102
98
  queryString = this.stripGaParam(queryString)
103
99
  queryString = this.PIIRemover.stripPIIWithOverride(queryString, true, true)
@@ -200,13 +196,6 @@ window.GOVUK.analyticsGa4.analyticsModules = window.GOVUK.analyticsGa4.analytics
200
196
  return undefined
201
197
  },
202
198
 
203
- splitLongMetaContent: function (metatag) {
204
- var tag = this.getMetaContent(metatag)
205
- if (tag) {
206
- return window.GOVUK.analyticsGa4.core.trackFunctions.splitStringIntoParts(tag)
207
- }
208
- },
209
-
210
199
  // return only the date from given timestamps of the form
211
200
  // 2022-03-28T19:11:00.000+00:00
212
201
  stripTimeFrom: function (value) {
@@ -13,9 +13,7 @@ window.GOVUK.analyticsGa4.analyticsModules = window.GOVUK.analyticsGa4.analytics
13
13
  type: 'print page',
14
14
  method: 'browser print'
15
15
  }
16
- var schema = new window.GOVUK.analyticsGa4.Schemas()
17
- schema = schema.mergeProperties(data, 'event_data')
18
- window.GOVUK.analyticsGa4.core.sendData(schema)
16
+ window.GOVUK.analyticsGa4.core.applySchemaAndSendData(data, 'event_data')
19
17
  })
20
18
  }
21
19
  }
@@ -27,7 +27,6 @@
27
27
  external: this.undefined,
28
28
  method: this.undefined,
29
29
  link_domain: this.undefined,
30
- link_path_parts: this.undefined,
31
30
  tool_name: this.undefined,
32
31
  percent_scrolled: this.undefined,
33
32
  video_current_time: this.undefined,
@@ -53,48 +52,33 @@
53
52
  }
54
53
  }
55
54
 
56
- // merge data attributes data into the event schema
57
- // only allow it if it already exists in the schema
55
+ // merge allowed data attributes into the event schema
58
56
  Schemas.prototype.mergeProperties = function (data, eventAttribute) {
59
57
  var schema = this.eventSchema()
60
58
  schema.event = eventAttribute
61
- // exceptions should be inserted without checking for sub parameters
62
- // exceptions should only come from code, not directly from data attributes
63
- // e.g. link_path_parts is generated by JS and contains potentially non-unique
64
- // sub parameter names i.e. '1', '2'
65
- var exceptions = ['link_path_parts']
66
59
 
67
60
  for (var property in data) {
68
61
  // some passed data might be undefined, don't want it to overwrite e.g. the index sub parameters
69
62
  if (data[property] !== undefined) {
70
- if (exceptions.indexOf(property) >= 0 || !this.isAnObject(data[property])) {
71
- schema.event_data = this.addToObject(schema.event_data, property, data[property])
72
- } else {
73
- // we check for one level of nesting in the data attributes data
74
- // this check can be removed once nesting is removed from all data attributes
75
- for (var subproperty in data[property]) {
76
- schema.event_data = this.addToObject(schema.event_data, subproperty, data[property][subproperty])
77
- }
78
- }
63
+ schema.event_data = this.addToObject(schema.event_data, property, data[property])
79
64
  }
80
65
  }
81
66
  return schema
82
67
  }
83
68
 
84
- // might be easier to check if it's not a string or a number?
85
69
  Schemas.prototype.isAnObject = function (item) {
86
70
  if (typeof item === 'object' && !Array.isArray(item) && item !== null) {
87
71
  return true
88
72
  }
89
73
  }
90
74
 
91
- // given an object and a key, insert a value into that object for that key
92
- // we check for one level of nesting in the object
75
+ // given an object and a key, insert a value into object[key] if it exists
93
76
  Schemas.prototype.addToObject = function (obj, key, value) {
94
77
  if (key in obj) {
95
78
  obj[key] = value
96
79
  return obj
97
80
  } else {
81
+ // check for one level of nesting in the object
98
82
  for (var property in obj) {
99
83
  if (this.isAnObject(obj[property])) {
100
84
  if (key in obj[property]) {
@@ -123,9 +123,7 @@ window.GOVUK.Modules = window.GOVUK.Modules || {};
123
123
  // following will be undefined if tracking headings
124
124
  data.percent_scrolled = node.eventData.percent_scrolled
125
125
 
126
- var schemas = new window.GOVUK.analyticsGa4.Schemas()
127
- var schema = schemas.mergeProperties(data, 'event_data')
128
- window.GOVUK.analyticsGa4.core.sendData(schema)
126
+ window.GOVUK.analyticsGa4.core.applySchemaAndSendData(data, 'event_data')
129
127
  }
130
128
  }
131
129
  }
@@ -72,7 +72,6 @@ window.GOVUK.analyticsGa4.analyticsModules = window.GOVUK.analyticsGa4.analytics
72
72
  if (data.url) {
73
73
  data.url = window.GOVUK.analyticsGa4.core.trackFunctions.removeCrossDomainParams(data.url)
74
74
  data.link_domain = window.GOVUK.analyticsGa4.core.trackFunctions.populateLinkDomain(data.url)
75
- data.link_path_parts = window.GOVUK.analyticsGa4.core.trackFunctions.populateLinkPathParts(data.url)
76
75
  }
77
76
 
78
77
  data.text = window.GOVUK.analyticsGa4.core.trackFunctions.removeLinesAndExtraSpaces(element.textContent)
@@ -81,10 +80,7 @@ window.GOVUK.analyticsGa4.analyticsModules = window.GOVUK.analyticsGa4.analytics
81
80
  data.text = 'image'
82
81
  }
83
82
  data.method = window.GOVUK.analyticsGa4.core.trackFunctions.getClickType(event)
84
-
85
- var schemas = new window.GOVUK.analyticsGa4.Schemas()
86
- var schema = schemas.mergeProperties(data, 'event_data')
87
- window.GOVUK.analyticsGa4.core.sendData(schema)
83
+ window.GOVUK.analyticsGa4.core.applySchemaAndSendData(data, 'event_data')
88
84
  }
89
85
  },
90
86
 
@@ -81,10 +81,7 @@ window.GOVUK.analyticsGa4.analyticsModules = window.GOVUK.analyticsGa4.analytics
81
81
  data.video_duration = this.handlers['video-' + player.id + '-duration']
82
82
  data.video_percent = position
83
83
 
84
- var schemas = new window.GOVUK.analyticsGa4.Schemas()
85
- var schema = schemas.mergeProperties(data, 'event_data')
86
-
87
- window.GOVUK.analyticsGa4.core.sendData(schema)
84
+ window.GOVUK.analyticsGa4.core.applySchemaAndSendData(data, 'event_data')
88
85
  },
89
86
 
90
87
  cleanVideoUrl: function (url) {
@@ -4,8 +4,22 @@
4
4
  var GOVUK = global.GOVUK || {}
5
5
  var EMAIL_PATTERN = /[^\s=/?&#+]+(?:@|%40)[^\s=/?&+]+/g
6
6
  var POSTCODE_PATTERN = /\b[A-PR-UWYZ][A-HJ-Z]?[0-9][0-9A-HJKMNPR-Y]?(?:[\s+]|%20)*[0-9](?!refund)[ABD-HJLNPQ-Z]{2,3}\b/gi
7
- var DATE_PATTERN_NUMERIC = /\d{4}(-?)\d{2}(-?)\d{2}/g
8
- var DATE_PATTERN_STRING = /\d{1,2}\s(January|February|March|April|May|June|July|August|September|October|November|December)\s\d{4}/g
7
+
8
+ // e.g. 01/01/1990 or 01-01-1990 or 1-1-1990 or 1/1/1990 or 01\01\1990 or 1\1\1990
9
+ var DATE_PATTERN_NUMERIC_1 = /\d{1,2}([-\/\\])\d{1,2}([-\/\\])\d{4}/g // eslint-disable-line no-useless-escape
10
+
11
+ // e.g. 1990/01/01 or 1990-01-01 or 1990-1-1 or 1990/1/1 or 1990\1\1 or 1990\01\01
12
+ var DATE_PATTERN_NUMERIC_2 = /\d{4}([-\/\\])\d{1,2}([-\/\\])\d{1,2}/g // eslint-disable-line no-useless-escape
13
+
14
+ // e.g. 12345678 (This originated from the UA PII Remover)
15
+ var DATE_PATTERN_NUMERIC_3 = /[0-9]{8}/g
16
+
17
+ // e.g. 1(st) (of) Jan(uary) 1990 (or 90 or '90) - where the bracketed characters are optional parts that can be matched
18
+ var DATE_PATTERN_STRING_1 = /\d{1,2}(?:st|nd|rd|th)?\s(?:of\s)?(Jan(?:uary)?|Feb(?:ruary)?|Mar(?:ch)?|Apr(?:il)?|May|Jun(?:e)?|Jul(?:y)?|Aug(?:ust)?|Sep(?:t)?(?:ember)?|Oct(?:ober)?|Nov(?:ember)?|Dec(?:ember)?)\s(?:')?(\d{4}|\d{2})/gi
19
+
20
+ // e.g. Jan(uary) 1(st) 1990 (or 90 or '90) - where the bracketed characters are optional parts that can be matched
21
+ var DATE_PATTERN_STRING_2 = /(Jan(?:uary)?|Feb(?:ruary)?|Mar(?:ch)?|Apr(?:il)?|May|Jun(?:e)?|Jul(?:y)?|Aug(?:ust)?|Sep(?:t)?(?:ember)?|Oct(?:ober)?|Nov(?:ember)?|Dec(?:ember)?)\s\d{1,2}?(?:st|nd|rd|th)?\s(?:')?(\d{4}|\d{2})/gi
22
+
9
23
  var ESCAPE_REGEX_PATTERN = /[|\\{}()[\]^$+*?.]/g
10
24
 
11
25
  // specific URL parameters to be redacted from accounts URLs
@@ -86,8 +100,12 @@
86
100
  stripped = this.stripQueryStringParameters(stripped)
87
101
 
88
102
  if (this.stripDatePII === true) {
89
- stripped = stripped.replace(DATE_PATTERN_NUMERIC, '[date]')
90
- stripped = stripped.replace(DATE_PATTERN_STRING, '[date]')
103
+ var DATE_REDACTION_STRING = '[date]'
104
+ stripped = stripped.replace(DATE_PATTERN_NUMERIC_1, DATE_REDACTION_STRING)
105
+ stripped = stripped.replace(DATE_PATTERN_NUMERIC_2, DATE_REDACTION_STRING)
106
+ stripped = stripped.replace(DATE_PATTERN_NUMERIC_3, DATE_REDACTION_STRING)
107
+ stripped = stripped.replace(DATE_PATTERN_STRING_1, DATE_REDACTION_STRING)
108
+ stripped = stripped.replace(DATE_PATTERN_STRING_2, DATE_REDACTION_STRING)
91
109
  }
92
110
  if (this.stripPostcodePII === true) {
93
111
  stripped = stripped.replace(POSTCODE_PATTERN, '[postcode]')
@@ -0,0 +1,78 @@
1
+ window.GOVUK = window.GOVUK || {}
2
+ window.GOVUK.Modules = window.GOVUK.Modules || {};
3
+
4
+ (function (Modules) {
5
+ /**
6
+ * A modified adaptation of the Design System header script
7
+ * To initialise the One Login header, run:
8
+ * new window.CrossServiceHeader(document.querySelector("[data-module='one-login-header']")).init();
9
+ */
10
+ function CrossServiceHeader ($module) {
11
+ this.$header = $module
12
+ this.$navigation = $module && $module.querySelectorAll('[data-one-login-header-nav]')
13
+ this.$numberOfNavs = this.$navigation && this.$navigation.length
14
+ if (this.$header) {
15
+ this.$header.classList.add('js-enabled')
16
+ }
17
+ }
18
+ /**
19
+ * Initialise header
20
+ *
21
+ * Check for the presence of the header, menu and menu button – if any are
22
+ * missing then there's nothing to do so return early.
23
+ */
24
+ CrossServiceHeader.prototype.init = function () {
25
+ if (!this.$header && !this.$numberOfNavs) {
26
+ return
27
+ }
28
+ /**
29
+ * The header can render with one or two navigation elements which collapse
30
+ * into dropdowns on the mobile variation. This initialises the dropdown
31
+ * functionality for all navs that have a menu button which has:
32
+ * 1. a class of .js-x-header-toggle
33
+ * 2. an aria-controls attribute which can be mapped to the ID of the element
34
+ * that should be hidden on mobile
35
+ */
36
+ for (var i = 0; i < this.$numberOfNavs; i++) {
37
+ var $nav = this.$navigation[i]
38
+ $nav.$menuButton = $nav.querySelector('.js-x-header-toggle')
39
+
40
+ $nav.$menu = $nav.$menuButton && $nav.querySelector(
41
+ '#' + $nav.$menuButton.getAttribute('aria-controls')
42
+ )
43
+ if (!$nav.$menuButton || !$nav.$menu) {
44
+ return
45
+ }
46
+ $nav.$menuOpenClass = $nav.$menu && $nav.$menu.dataset.openClass
47
+ $nav.$menuButtonOpenClass = $nav.$menuButton && $nav.$menuButton.dataset.openClass
48
+ $nav.$menuButtonOpenLabel = $nav.$menuButton && $nav.$menuButton.dataset.labelForShow
49
+ $nav.$menuButtonCloseLabel = $nav.$menuButton && $nav.$menuButton.dataset.labelForHide
50
+ $nav.$menuButtonOpenText = $nav.$menuButton && $nav.$menuButton.dataset.textForShow
51
+ $nav.$menuButtonCloseText = $nav.$menuButton && $nav.$menuButton.dataset.textForHide
52
+ $nav.isOpen = false
53
+
54
+ $nav.$menuButton.addEventListener('click', this.handleMenuButtonClick.bind($nav))
55
+ }
56
+ }
57
+
58
+ /**
59
+ * Handle menu button click
60
+ *
61
+ * When the menu button is clicked, change the visibility of the menu and then
62
+ * sync the accessibility state and menu button state
63
+ */
64
+ CrossServiceHeader.prototype.handleMenuButtonClick = function () {
65
+ this.isOpen = !this.isOpen
66
+ this.$menuOpenClass && this.$menu.classList.toggle(this.$menuOpenClass, this.isOpen)
67
+ this.$menuButtonOpenClass && this.$menuButton.classList.toggle(this.$menuButtonOpenClass, this.isOpen)
68
+ this.$menuButton.setAttribute('aria-expanded', this.isOpen)
69
+ if (this.$menuButtonCloseLabel && this.$menuButtonOpenLabel) {
70
+ this.$menuButton.setAttribute('aria-label', (this.isOpen ? this.$menuButtonCloseLabel : this.$menuButtonOpenLabel))
71
+ }
72
+ if (this.$menuButtonCloseText && this.$menuButtonOpenText) {
73
+ this.$menuButton.innerHTML = this.isOpen ? this.$menuButtonCloseText : this.$menuButtonOpenText
74
+ }
75
+ }
76
+
77
+ Modules.CrossServiceHeader = CrossServiceHeader
78
+ })(window.GOVUK.Modules)
@@ -27,6 +27,7 @@ $govuk-new-link-styles: true;
27
27
  @import "components/contextual-sidebar";
28
28
  @import "components/cookie-banner";
29
29
  @import "components/copy-to-clipboard";
30
+ @import "components/cross-service-header";
30
31
  @import "components/date-input";
31
32
  @import "components/details";
32
33
  @import "components/devolved-nations";
@@ -94,31 +94,6 @@
94
94
  }
95
95
  }
96
96
 
97
- .gem-c-action-link--white-arrow {
98
- &::before {
99
- background-image: image-url("govuk_publishing_components/action-link-arrow--white.png");
100
- background-image: image-url("govuk_publishing_components/action-link-arrow--white.svg"), linear-gradient(transparent, transparent);
101
- }
102
- }
103
-
104
- .gem-c-action-link--blue-arrow {
105
- &::before {
106
- width: 36px;
107
- height: 28px;
108
- background: image-url("govuk_publishing_components/action-link-arrow--blue.png");
109
- background: image-url("govuk_publishing_components/action-link-arrow--blue.svg"), linear-gradient(transparent, transparent);
110
- background-repeat: no-repeat;
111
- background-size: 28px auto;
112
- background-position: 0 0;
113
-
114
- @include govuk-media-query($from: tablet) {
115
- width: 45px;
116
- height: 35px;
117
- background-size: 35px auto;
118
- }
119
- }
120
- }
121
-
122
97
  .gem-c-action-link--simple {
123
98
  &::before {
124
99
  width: 30px;
@@ -143,13 +118,6 @@
143
118
  }
144
119
  }
145
120
 
146
- .gem-c-action-link--dark-icon {
147
- &::before {
148
- background: image-url("govuk_publishing_components/action-link-arrow--dark.png");
149
- background: image-url("govuk_publishing_components/action-link-arrow--dark.svg"), linear-gradient(transparent, transparent);
150
- }
151
- }
152
-
153
121
  .gem-c-action-link--dark-large-icon {
154
122
  &::before {
155
123
  background: image-url("govuk_publishing_components/action-link-arrow--dark.png");
@@ -184,8 +152,7 @@
184
152
  }
185
153
  }
186
154
 
187
- .gem-c-action-link--dark-icon,
188
- .gem-c-action-link--small-icon {
155
+ .gem-c-action-link--dark-icon {
189
156
  max-width: none;
190
157
 
191
158
  @include govuk-media-query($until: tablet) {
@@ -195,57 +162,14 @@
195
162
  &::before {
196
163
  height: 30px;
197
164
  width: 35px;
165
+ background: image-url("govuk_publishing_components/action-link-arrow--dark.png");
166
+ background: image-url("govuk_publishing_components/action-link-arrow--dark.svg"), linear-gradient(transparent, transparent);
198
167
  background-repeat: no-repeat;
199
168
  background-size: 25px auto;
200
169
  background-position: 0 2px;
201
170
  }
202
171
  }
203
172
 
204
- .gem-c-action-link--transparent-icon {
205
- &::before {
206
- background-image: image-url("govuk_publishing_components/action-link-arrow--transparent.svg");
207
- }
208
- }
209
-
210
- .gem-c-action-link--brexit {
211
- max-width: none;
212
-
213
- &::before {
214
- height: 30px;
215
- width: 30px;
216
- background-image: image-url("govuk_publishing_components/action-link-arrow--brexit.svg");
217
- background-repeat: no-repeat;
218
- background-size: 18px auto;
219
- background-position: 0 2px;
220
- }
221
-
222
- @include govuk-media-query($until: tablet) {
223
- margin-bottom: govuk-spacing(2);
224
- }
225
-
226
- @include govuk-media-query($from: tablet) {
227
- margin-bottom: govuk-spacing(2);
228
-
229
- &::before {
230
- width: 35px;
231
- background-position: 0 4px;
232
- background-size: 25px auto;
233
- }
234
- }
235
- }
236
-
237
- .gem-c-action-link--nhs {
238
- &::before {
239
- width: 80px;
240
- height: 70px;
241
- background: image-url("govuk_publishing_components/action-link--nhs.png");
242
- background: image-url("govuk_publishing_components/action-link--nhs.svg"), linear-gradient(transparent, transparent);
243
- background-repeat: no-repeat;
244
- background-size: 85% auto;
245
- background-position: 0 50%;
246
- }
247
- }
248
-
249
173
  .gem-c-action-link--light-text {
250
174
  color: govuk-colour("white");
251
175