govuk_publishing_components 35.11.0 → 35.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/app/assets/javascripts/govuk_publishing_components/analytics-ga4/ga4-core.js +2 -48
- data/app/assets/javascripts/govuk_publishing_components/analytics-ga4/ga4-form-tracker.js +5 -0
- data/app/assets/javascripts/govuk_publishing_components/analytics-ga4/ga4-link-tracker.js +2 -2
- data/app/assets/javascripts/govuk_publishing_components/analytics-ga4/ga4-schemas.js +51 -5
- data/app/assets/javascripts/govuk_publishing_components/analytics-ga4/ga4-scroll-tracker.js +225 -0
- data/app/assets/javascripts/govuk_publishing_components/analytics-ga4/init-ga4.js +0 -5
- data/app/assets/javascripts/govuk_publishing_components/analytics-ga4.js +1 -0
- data/app/assets/stylesheets/govuk_publishing_components/components/_document-list.scss +3 -1
- data/app/assets/stylesheets/govuk_publishing_components/components/_search.scss +8 -2
- data/app/controllers/govuk_publishing_components/audit_controller.rb +3 -2
- data/app/models/govuk_publishing_components/audit_applications.rb +3 -1
- data/app/models/govuk_publishing_components/audit_comparer.rb +1 -1
- data/app/models/govuk_publishing_components/audit_components.rb +3 -2
- data/app/models/govuk_publishing_components/component_wrapper_helper_options.rb +1 -0
- data/app/views/govuk_publishing_components/audit/_applications.html.erb +1 -1
- data/app/views/govuk_publishing_components/components/_attachment.html.erb +3 -1
- data/app/views/govuk_publishing_components/components/_document_list.html.erb +29 -27
- data/app/views/govuk_publishing_components/components/_heading.html.erb +8 -5
- data/app/views/govuk_publishing_components/components/_tabs.html.erb +30 -14
- data/app/views/govuk_publishing_components/components/docs/heading.yml +1 -4
- data/app/views/govuk_publishing_components/components/docs/single_page_notification_button.yml +1 -6
- data/app/views/govuk_publishing_components/components/docs/tabs.yml +26 -3
- data/lib/govuk_publishing_components/config.rb +3 -0
- data/lib/govuk_publishing_components/presenters/component_wrapper_helper.rb +17 -1
- data/lib/govuk_publishing_components/version.rb +1 -1
- data/node_modules/govuk-frontend/govuk/all.js +406 -1
- data/node_modules/govuk-frontend/govuk/all.js.map +1 -1
- data/node_modules/govuk-frontend/govuk/common/govuk-frontend-version.js +1 -1
- data/node_modules/govuk-frontend/govuk/components/_all.scss +2 -1
- data/node_modules/govuk-frontend/govuk/components/back-link/_index.scss +8 -0
- data/node_modules/govuk-frontend/govuk/components/back-link/fixtures.json +9 -0
- data/node_modules/govuk-frontend/govuk/components/breadcrumbs/_index.scss +12 -0
- data/node_modules/govuk-frontend/govuk/components/breadcrumbs/fixtures.json +21 -0
- data/node_modules/govuk-frontend/govuk/components/button/_index.scss +41 -3
- data/node_modules/govuk-frontend/govuk/components/button/fixtures.json +44 -0
- data/node_modules/govuk-frontend/govuk/components/checkboxes/macro-options.json +9 -8
- data/node_modules/govuk-frontend/govuk/components/exit-this-page/README.md +15 -0
- data/node_modules/govuk-frontend/govuk/components/exit-this-page/_exit-this-page.scss +2 -0
- data/node_modules/govuk-frontend/govuk/components/exit-this-page/_index.scss +97 -0
- data/node_modules/govuk-frontend/govuk/components/exit-this-page/exit-this-page.js +2120 -0
- data/node_modules/govuk-frontend/govuk/components/exit-this-page/exit-this-page.js.map +1 -0
- data/node_modules/govuk-frontend/govuk/components/exit-this-page/fixtures.json +50 -0
- data/node_modules/govuk-frontend/govuk/components/exit-this-page/macro-options.json +62 -0
- data/node_modules/govuk-frontend/govuk/components/exit-this-page/macro.njk +3 -0
- data/node_modules/govuk-frontend/govuk/components/exit-this-page/template.njk +16 -0
- data/node_modules/govuk-frontend/govuk/components/radios/macro-options.json +9 -8
- data/node_modules/govuk-frontend/govuk/core/_govuk-frontend-version.scss +1 -1
- data/node_modules/govuk-frontend/govuk/helpers/_visually-hidden.scss +12 -0
- data/node_modules/govuk-frontend/govuk/objects/_template.scss +20 -0
- data/node_modules/govuk-frontend/govuk-esm/all.mjs +8 -0
- data/node_modules/govuk-frontend/govuk-esm/all.mjs.map +1 -1
- data/node_modules/govuk-frontend/govuk-esm/common/govuk-frontend-version.mjs +1 -1
- data/node_modules/govuk-frontend/govuk-esm/components/exit-this-page/exit-this-page.mjs +406 -0
- data/node_modules/govuk-frontend/govuk-esm/components/exit-this-page/exit-this-page.mjs.map +1 -0
- data/node_modules/govuk-frontend/govuk-prototype-kit.config.json +4 -0
- data/node_modules/govuk-frontend/package.json +4 -2
- metadata +14 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: b6417c1bd3d66d89500aac39c49427caa95791623fe26f1ee4844c025ef3f3c7
|
|
4
|
+
data.tar.gz: d21986e9895007dc2560b4aacd1eb28ff7f43251519029672b85d13d91211d94
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 7ca4a123db1c519256eb7ee46ff97e940d69c161f687611fb3b46915acee3454b995f2793e763ed82f5d87ae8a32d2df074b4c72587ca5c0a3c02ee858026a79
|
|
7
|
+
data.tar.gz: b1cc9c87e984de69229d5b6807d81eca27802b35a3be15caaaea249388fc0ce9934be7a4d75006e2a93c5374fc48738d9f8e8dbbc624955b2a14da78a01df8a8
|
|
@@ -30,32 +30,7 @@ window.GOVUK.analyticsGa4 = window.GOVUK.analyticsGa4 || {};
|
|
|
30
30
|
firstScript.parentNode.insertBefore(newScript, firstScript)
|
|
31
31
|
},
|
|
32
32
|
|
|
33
|
-
ensureIndexesArePopulated: function (data) {
|
|
34
|
-
if (!data.event_data) {
|
|
35
|
-
return data
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
if (!data.event_data.index) {
|
|
39
|
-
return data
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
var indexKeys = ['index_link', 'index_section', 'index_section_count']
|
|
43
|
-
|
|
44
|
-
for (var i = 0; i < indexKeys.length; i++) {
|
|
45
|
-
var indexKey = indexKeys[i]
|
|
46
|
-
|
|
47
|
-
// If the index key isn't in the object, populate it. However if it's set to 0, leave it as 0. 0 is falsy so we have to add this extra check.
|
|
48
|
-
if (!data.event_data.index[indexKey] && data.event_data.index[indexKey] !== 0) {
|
|
49
|
-
data.event_data.index[indexKey] = undefined
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
return data
|
|
54
|
-
},
|
|
55
|
-
|
|
56
33
|
sendData: function (data) {
|
|
57
|
-
data = this.ensureIndexesArePopulated(data)
|
|
58
|
-
|
|
59
34
|
data.govuk_gem_version = this.getGemVersion()
|
|
60
35
|
// set this in the console as a debugging aid
|
|
61
36
|
if (window.GOVUK.analyticsGa4.showDebug) {
|
|
@@ -274,29 +249,8 @@ window.GOVUK.analyticsGa4 = window.GOVUK.analyticsGa4 || {};
|
|
|
274
249
|
}
|
|
275
250
|
},
|
|
276
251
|
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
for (var i = 0; i < targetElements.length; i++) {
|
|
281
|
-
var element = targetElements[i]
|
|
282
|
-
|
|
283
|
-
for (var j = 0; j < dataAttributes.length; j++) {
|
|
284
|
-
var key = dataAttributes[j].key
|
|
285
|
-
var value = dataAttributes[j].value
|
|
286
|
-
|
|
287
|
-
// value must check for undefined only as it would return false on an empty string, the number 0, etc.
|
|
288
|
-
if (key && value !== undefined) {
|
|
289
|
-
var existingAttributeValue = element.getAttribute(key)
|
|
290
|
-
|
|
291
|
-
if (key === 'data-module' && existingAttributeValue) {
|
|
292
|
-
// Combines values to prevent replacing any existing data-module values.
|
|
293
|
-
element.setAttribute(key, existingAttributeValue + ' ' + value)
|
|
294
|
-
} else {
|
|
295
|
-
element.setAttribute(key, value)
|
|
296
|
-
}
|
|
297
|
-
}
|
|
298
|
-
}
|
|
299
|
-
}
|
|
252
|
+
applyRedactionIfRequired: function (PIIRemover, element, data) {
|
|
253
|
+
return element.closest('[data-ga4-do-not-redact]') ? data : PIIRemover.stripPIIWithOverride(data, true, true)
|
|
300
254
|
}
|
|
301
255
|
},
|
|
302
256
|
|
|
@@ -45,6 +45,11 @@ window.GOVUK.Modules = window.GOVUK.Modules || {};
|
|
|
45
45
|
var formData = this.getInputValues(formInputs)
|
|
46
46
|
data.text = data.text || (this.combineGivenAnswers(formData) || 'No answer given')
|
|
47
47
|
|
|
48
|
+
if (data.action === 'search') {
|
|
49
|
+
data.text = data.text.toLowerCase()
|
|
50
|
+
data.text = window.GOVUK.analyticsGa4.core.trackFunctions.removeLinesAndExtraSpaces(data.text)
|
|
51
|
+
}
|
|
52
|
+
|
|
48
53
|
var schemas = new window.GOVUK.analyticsGa4.Schemas()
|
|
49
54
|
var schema = schemas.mergeProperties(data, 'event_data')
|
|
50
55
|
window.GOVUK.analyticsGa4.core.sendData(schema)
|
|
@@ -81,12 +81,12 @@ window.GOVUK.Modules = window.GOVUK.Modules || {};
|
|
|
81
81
|
|
|
82
82
|
var text = data.text || event.target.textContent
|
|
83
83
|
data.text = window.GOVUK.analyticsGa4.core.trackFunctions.removeLinesAndExtraSpaces(text)
|
|
84
|
-
data.text =
|
|
84
|
+
data.text = window.GOVUK.analyticsGa4.core.trackFunctions.applyRedactionIfRequired(this.PIIRemover, element, data.text)
|
|
85
85
|
if (!data.text && (element.querySelector('img') || element.querySelector('svg') || element.tagName === 'IMG' || element.closest('svg'))) {
|
|
86
86
|
data.text = 'image'
|
|
87
87
|
}
|
|
88
88
|
var url = data.url || this.findLink(event.target).getAttribute('href')
|
|
89
|
-
data.url = window.GOVUK.analyticsGa4.core.trackFunctions.
|
|
89
|
+
data.url = window.GOVUK.analyticsGa4.core.trackFunctions.applyRedactionIfRequired(this.PIIRemover, element, window.GOVUK.analyticsGa4.core.trackFunctions.removeCrossDomainParams(url))
|
|
90
90
|
data.link_domain = window.GOVUK.analyticsGa4.core.trackFunctions.populateLinkDomain(data.url)
|
|
91
91
|
data.link_path_parts = window.GOVUK.analyticsGa4.core.trackFunctions.populateLinkPathParts(data.url)
|
|
92
92
|
data.method = window.GOVUK.analyticsGa4.core.trackFunctions.getClickType(event)
|
|
@@ -16,7 +16,11 @@
|
|
|
16
16
|
type: this.undefined,
|
|
17
17
|
url: this.undefined,
|
|
18
18
|
text: this.undefined,
|
|
19
|
-
index:
|
|
19
|
+
index: {
|
|
20
|
+
index_link: this.undefined,
|
|
21
|
+
index_section: this.undefined,
|
|
22
|
+
index_section_count: this.undefined
|
|
23
|
+
},
|
|
20
24
|
index_total: this.undefined,
|
|
21
25
|
section: this.undefined,
|
|
22
26
|
action: this.undefined,
|
|
@@ -24,7 +28,8 @@
|
|
|
24
28
|
method: this.undefined,
|
|
25
29
|
link_domain: this.undefined,
|
|
26
30
|
link_path_parts: this.undefined,
|
|
27
|
-
tool_name: this.undefined
|
|
31
|
+
tool_name: this.undefined,
|
|
32
|
+
percent_scrolled: this.undefined
|
|
28
33
|
}
|
|
29
34
|
}
|
|
30
35
|
}
|
|
@@ -45,19 +50,60 @@
|
|
|
45
50
|
}
|
|
46
51
|
}
|
|
47
52
|
|
|
48
|
-
//
|
|
53
|
+
// merge data attributes data into the event schema
|
|
49
54
|
// only allow it if it already exists in the schema
|
|
50
55
|
Schemas.prototype.mergeProperties = function (data, eventAttribute) {
|
|
51
56
|
var schema = this.eventSchema()
|
|
52
57
|
schema.event = eventAttribute
|
|
58
|
+
// exceptions should be inserted without checking for sub parameters
|
|
59
|
+
// exceptions should only come from code, not directly from data attributes
|
|
60
|
+
// e.g. link_path_parts is generated by JS and contains potentially non-unique
|
|
61
|
+
// sub parameter names i.e. '1', '2'
|
|
62
|
+
var exceptions = ['link_path_parts']
|
|
63
|
+
|
|
53
64
|
for (var property in data) {
|
|
54
|
-
|
|
55
|
-
|
|
65
|
+
// some passed data might be undefined, don't want it to overwrite e.g. the index sub parameters
|
|
66
|
+
if (data[property] !== undefined) {
|
|
67
|
+
if (exceptions.indexOf(property) >= 0 || !this.isAnObject(data[property])) {
|
|
68
|
+
schema.event_data = this.addToObject(schema.event_data, property, data[property])
|
|
69
|
+
} else {
|
|
70
|
+
// we check for one level of nesting in the data attributes data
|
|
71
|
+
// this check can be removed once nesting is removed from all data attributes
|
|
72
|
+
for (var subproperty in data[property]) {
|
|
73
|
+
schema.event_data = this.addToObject(schema.event_data, subproperty, data[property][subproperty])
|
|
74
|
+
}
|
|
75
|
+
}
|
|
56
76
|
}
|
|
57
77
|
}
|
|
58
78
|
return schema
|
|
59
79
|
}
|
|
60
80
|
|
|
81
|
+
// might be easier to check if it's not a string or a number?
|
|
82
|
+
Schemas.prototype.isAnObject = function (item) {
|
|
83
|
+
if (typeof item === 'object' && !Array.isArray(item) && item !== null) {
|
|
84
|
+
return true
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// given an object and a key, insert a value into that object for that key
|
|
89
|
+
// we check for one level of nesting in the object
|
|
90
|
+
Schemas.prototype.addToObject = function (obj, key, value) {
|
|
91
|
+
if (key in obj) {
|
|
92
|
+
obj[key] = value
|
|
93
|
+
return obj
|
|
94
|
+
} else {
|
|
95
|
+
for (var property in obj) {
|
|
96
|
+
if (this.isAnObject(obj[property])) {
|
|
97
|
+
if (key in obj[property]) {
|
|
98
|
+
obj[property][key] = value
|
|
99
|
+
return obj
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
return obj
|
|
105
|
+
}
|
|
106
|
+
|
|
61
107
|
GOVUK.analyticsGa4 = GOVUK.analyticsGa4 || {}
|
|
62
108
|
GOVUK.analyticsGa4.Schemas = Schemas
|
|
63
109
|
|
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
window.GOVUK = window.GOVUK || {}
|
|
2
|
+
window.GOVUK.Modules = window.GOVUK.Modules || {};
|
|
3
|
+
|
|
4
|
+
(function (Modules) {
|
|
5
|
+
function Ga4ScrollTracker ($module) {
|
|
6
|
+
this.$module = $module
|
|
7
|
+
this.pageHeight = document.querySelector('body').clientHeight
|
|
8
|
+
this.trackedNodes = []
|
|
9
|
+
this.config = {
|
|
10
|
+
allowHeadingsInside: ['main'],
|
|
11
|
+
percentages: [20, 40, 60, 80, 100],
|
|
12
|
+
scrollTimeoutDelay: 20,
|
|
13
|
+
resizeTimeoutDelay: 100,
|
|
14
|
+
pageHeightTimeoutDelay: 500,
|
|
15
|
+
markerAttribute: 'data-ga4-scroll-marker'
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
Ga4ScrollTracker.prototype.init = function () {
|
|
20
|
+
var consentCookie = window.GOVUK.getConsentCookie()
|
|
21
|
+
|
|
22
|
+
if (consentCookie && consentCookie.settings) {
|
|
23
|
+
this.startModule()
|
|
24
|
+
} else {
|
|
25
|
+
this.startModule = this.startModule.bind(this)
|
|
26
|
+
window.addEventListener('cookie-consent', this.startModule)
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
Ga4ScrollTracker.prototype.startModule = function () {
|
|
31
|
+
if (window.GOVUK.analyticsGa4.vars.scrollTrackerStarted) {
|
|
32
|
+
return
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
this.trackType = this.$module.getAttribute('data-ga4-track-type')
|
|
36
|
+
window.GOVUK.analyticsGa4.vars.scrollTrackerStarted = true
|
|
37
|
+
|
|
38
|
+
if (this.trackType === 'headings') {
|
|
39
|
+
this.track = new Ga4ScrollTracker.Heading(this.config)
|
|
40
|
+
} else if (this.trackType === 'markers') {
|
|
41
|
+
this.config.trackMarkers = true
|
|
42
|
+
this.track = new Ga4ScrollTracker.Heading(this.config)
|
|
43
|
+
} else {
|
|
44
|
+
this.track = new Ga4ScrollTracker.Percentage(this.config)
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
this.getWindowDetails()
|
|
48
|
+
// if the URL has a hash we want to prevent tracking on initial page load
|
|
49
|
+
// until the browser jumps down the page, at which point a scroll event
|
|
50
|
+
// will happen and tracking will continue normally
|
|
51
|
+
var windowHash = window.location.hash
|
|
52
|
+
var dontTrackOnLoad = windowHash && document.getElementById(windowHash.substring(1))
|
|
53
|
+
if (!dontTrackOnLoad) {
|
|
54
|
+
this.trackVisibleNodes()
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
if (this.trackedNodes.length) {
|
|
58
|
+
// store event listener functions as variables so they can be removed if needed
|
|
59
|
+
this.scrollEvent = this.onScroll.bind(this)
|
|
60
|
+
window.addEventListener('scroll', this.scrollEvent)
|
|
61
|
+
this.resizeEvent = this.onResize.bind(this)
|
|
62
|
+
window.addEventListener('resize', this.resizeEvent)
|
|
63
|
+
|
|
64
|
+
// check if the page height changes e.g. accordion opened
|
|
65
|
+
this.interval = window.setInterval(function () {
|
|
66
|
+
var pageHeight = document.querySelector('body').clientHeight
|
|
67
|
+
if (pageHeight !== this.pageHeight) {
|
|
68
|
+
this.pageHeight = pageHeight
|
|
69
|
+
this.getWindowDetails()
|
|
70
|
+
this.trackVisibleNodes()
|
|
71
|
+
}
|
|
72
|
+
}.bind(this), this.config.pageHeightTimeoutDelay)
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
Ga4ScrollTracker.prototype.onScroll = function () {
|
|
77
|
+
clearTimeout(this.scrollTimeout)
|
|
78
|
+
this.scrollTimeout = setTimeout(function () {
|
|
79
|
+
this.trackVisibleNodes()
|
|
80
|
+
}.bind(this), this.config.scrollTimeoutDelay)
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
Ga4ScrollTracker.prototype.onResize = function () {
|
|
84
|
+
clearTimeout(this.resizeTimeout)
|
|
85
|
+
this.resizeTimeout = setTimeout(function () {
|
|
86
|
+
this.getWindowDetails()
|
|
87
|
+
this.trackVisibleNodes()
|
|
88
|
+
}.bind(this), this.config.resizeTimeoutDelay)
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
Ga4ScrollTracker.prototype.getWindowDetails = function () {
|
|
92
|
+
this.pageHeight = document.querySelector('body').clientHeight
|
|
93
|
+
this.windowHeight = window.innerHeight
|
|
94
|
+
this.trackedNodes = this.track.getTrackingNodes(this.trackedNodes)
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
Ga4ScrollTracker.prototype.trackVisibleNodes = function () {
|
|
98
|
+
var data = {
|
|
99
|
+
event_name: 'scroll',
|
|
100
|
+
action: 'scroll',
|
|
101
|
+
type: this.config.type
|
|
102
|
+
}
|
|
103
|
+
for (var i = 0; i < this.trackedNodes.length; i++) {
|
|
104
|
+
var node = this.trackedNodes[i]
|
|
105
|
+
if (this.isVisible(node.top, node.bottom) && !node.alreadySeen) {
|
|
106
|
+
node.alreadySeen = true
|
|
107
|
+
// we store whether a heading has been tracked or not on the heading
|
|
108
|
+
// because if headings appear/disappear (e.g. inside an accordion)
|
|
109
|
+
// the order changes, so we can't refer to the previous trackedNodes
|
|
110
|
+
// as we do with percentages
|
|
111
|
+
if (node.element) {
|
|
112
|
+
node.element.setAttribute('data-ga4-scrolltracker-already-seen', true)
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
data.type = node.eventData.type
|
|
116
|
+
// following will be undefined if tracking percentages
|
|
117
|
+
data.text = node.eventData.text
|
|
118
|
+
data.index = node.eventData.index
|
|
119
|
+
// following will be undefined if tracking headings
|
|
120
|
+
data.percent_scrolled = node.eventData.percent_scrolled
|
|
121
|
+
|
|
122
|
+
var schemas = new window.GOVUK.analyticsGa4.Schemas()
|
|
123
|
+
var schema = schemas.mergeProperties(data, 'event_data')
|
|
124
|
+
window.GOVUK.analyticsGa4.core.sendData(schema)
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
Ga4ScrollTracker.prototype.isVisible = function (top, bottom) {
|
|
130
|
+
var scroll = window.scrollY || document.documentElement.scrollTop // IE fallback
|
|
131
|
+
return scroll <= top && (scroll + this.windowHeight) >= bottom
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
Ga4ScrollTracker.Heading = function (config) {
|
|
135
|
+
this.config = config
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
Ga4ScrollTracker.Heading.prototype.getTrackingNodes = function () {
|
|
139
|
+
var headingsDetails = []
|
|
140
|
+
var headingsFound = this.findAllowedHeadings()
|
|
141
|
+
var totalHeadings = headingsFound.length
|
|
142
|
+
|
|
143
|
+
for (var i = 0; i < totalHeadings; i++) {
|
|
144
|
+
var heading = headingsFound[i]
|
|
145
|
+
var type = this.config.trackMarkers ? 'marker' : 'heading'
|
|
146
|
+
// only track headings that are visible i.e. not inside display: none
|
|
147
|
+
if (this.visible(heading)) {
|
|
148
|
+
var pos = heading.getBoundingClientRect()
|
|
149
|
+
headingsDetails.push({
|
|
150
|
+
element: heading,
|
|
151
|
+
alreadySeen: heading.getAttribute('data-ga4-scrolltracker-already-seen'),
|
|
152
|
+
top: pos.top + document.documentElement.scrollTop,
|
|
153
|
+
bottom: pos.bottom + document.documentElement.scrollTop,
|
|
154
|
+
eventData: {
|
|
155
|
+
type: type,
|
|
156
|
+
text: heading.textContent.replace(/\s+/g, ' ').trim(),
|
|
157
|
+
index: {
|
|
158
|
+
index_section: i + 1,
|
|
159
|
+
index_section_count: totalHeadings
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
})
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
return headingsDetails
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// check heading is inside allowed elements, generally ignores everything outside of page content
|
|
169
|
+
Ga4ScrollTracker.Heading.prototype.findAllowedHeadings = function () {
|
|
170
|
+
var headingsFound = []
|
|
171
|
+
var headings = ['h1', 'h2', 'h3', 'h4', 'h5', 'h6']
|
|
172
|
+
if (this.config.trackMarkers) {
|
|
173
|
+
headings = ['[' + this.config.markerAttribute + ']']
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// this is a loop that only happens once as we currently only have one
|
|
177
|
+
// allowed element for headings to be in - 'main'
|
|
178
|
+
for (var h = 0; h < this.config.allowHeadingsInside.length; h++) {
|
|
179
|
+
var insideElements = document.querySelectorAll(this.config.allowHeadingsInside[h])
|
|
180
|
+
for (var e = 0; e < insideElements.length; e++) {
|
|
181
|
+
var found = insideElements[e].querySelectorAll(headings)
|
|
182
|
+
for (var f = 0; f < found.length; f++) {
|
|
183
|
+
headingsFound.push(found[f])
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
return headingsFound
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
// this is bit more verbose than checking offsetParent !== null but more reliable for IE10+
|
|
191
|
+
Ga4ScrollTracker.Heading.prototype.visible = function (el) {
|
|
192
|
+
return !!(el.offsetWidth || el.offsetHeight || el.getClientRects().length)
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
Ga4ScrollTracker.Percentage = function (config) {
|
|
196
|
+
this.config = config
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
Ga4ScrollTracker.Percentage.prototype.getTrackingNodes = function (trackedNodes) {
|
|
200
|
+
var body = document.body
|
|
201
|
+
var html = document.documentElement
|
|
202
|
+
// remove 20px from the calculated page height to allow for a possible horizontal scrollbar
|
|
203
|
+
var pageHeight = Math.max(body.scrollHeight, body.offsetHeight, html.clientHeight, html.scrollHeight, html.offsetHeight) - 20
|
|
204
|
+
|
|
205
|
+
var percentDetails = []
|
|
206
|
+
|
|
207
|
+
for (var i = 0; i < this.config.percentages.length; i++) {
|
|
208
|
+
var percent = this.config.percentages[i]
|
|
209
|
+
var pos = ((pageHeight / 100) * percent)
|
|
210
|
+
var alreadySeen = false
|
|
211
|
+
if (trackedNodes.length) {
|
|
212
|
+
alreadySeen = trackedNodes[i].alreadySeen
|
|
213
|
+
}
|
|
214
|
+
percentDetails.push({
|
|
215
|
+
alreadySeen: alreadySeen,
|
|
216
|
+
top: pos,
|
|
217
|
+
bottom: pos,
|
|
218
|
+
eventData: { type: 'percent', percent_scrolled: String(percent) }
|
|
219
|
+
})
|
|
220
|
+
}
|
|
221
|
+
return percentDetails
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
Modules.Ga4ScrollTracker = Ga4ScrollTracker
|
|
225
|
+
})(window.GOVUK.Modules)
|
|
@@ -8,11 +8,6 @@ var initFunction = function () {
|
|
|
8
8
|
window.GOVUK.analyticsGa4.vars.internalDomains = []
|
|
9
9
|
window.GOVUK.analyticsGa4.vars.internalDomains.push(window.GOVUK.analyticsGa4.core.trackFunctions.getHostname())
|
|
10
10
|
window.GOVUK.analyticsGa4.core.trackFunctions.appendDomainsWithoutWWW(window.GOVUK.analyticsGa4.vars.internalDomains)
|
|
11
|
-
var attachmentLinkData = [
|
|
12
|
-
{ key: 'data-module', value: 'ga4-link-tracker' },
|
|
13
|
-
{ key: 'data-ga4-track-links-only', value: '' },
|
|
14
|
-
{ key: 'data-ga4-link', value: JSON.stringify({ event_name: 'navigation', type: 'attachment' }) }]
|
|
15
|
-
window.GOVUK.analyticsGa4.core.trackFunctions.addAttributesToElements('[data-ga4-attachment-link]', attachmentLinkData)
|
|
16
11
|
window.GOVUK.analyticsGa4.core.load()
|
|
17
12
|
|
|
18
13
|
var analyticsModules = window.GOVUK.analyticsGa4.analyticsModules
|
|
@@ -110,6 +110,10 @@ $large-input-size: 50px;
|
|
|
110
110
|
border: 0;
|
|
111
111
|
cursor: pointer;
|
|
112
112
|
border-radius: 0;
|
|
113
|
+
// render a border in high contrast mode
|
|
114
|
+
outline: $govuk-border-width-form-element solid transparent;
|
|
115
|
+
// Ensure outline appears outside of the element
|
|
116
|
+
outline-offset: 0;
|
|
113
117
|
position: relative;
|
|
114
118
|
padding: 0;
|
|
115
119
|
width: $input-size;
|
|
@@ -124,8 +128,6 @@ $large-input-size: 50px;
|
|
|
124
128
|
&:focus {
|
|
125
129
|
z-index: 2;
|
|
126
130
|
outline: $govuk-focus-width solid $govuk-focus-colour;
|
|
127
|
-
// Ensure outline appears outside of the element
|
|
128
|
-
outline-offset: 0;
|
|
129
131
|
// Double the border by adding its width again. Use `box-shadow` for this // instead of changing `border-width` - this is for consistency with
|
|
130
132
|
// Also, `outline` cannot be utilised
|
|
131
133
|
// here as it is already used for the yellow focus state.
|
|
@@ -161,6 +163,10 @@ $large-input-size: 50px;
|
|
|
161
163
|
|
|
162
164
|
.gem-c-search__input {
|
|
163
165
|
border-width: 0;
|
|
166
|
+
// Render a border in high contrast mode
|
|
167
|
+
outline: $govuk-border-width-form-element solid transparent;
|
|
168
|
+
// Ensure outline appears outside of the element
|
|
169
|
+
outline-offset: 0;
|
|
164
170
|
|
|
165
171
|
// no need for black outline as there is enough contrast
|
|
166
172
|
// with the blue background
|
|
@@ -14,7 +14,6 @@ module GovukPublishingComponents
|
|
|
14
14
|
government-frontend
|
|
15
15
|
govspeak-preview
|
|
16
16
|
info-frontend
|
|
17
|
-
licence-finder
|
|
18
17
|
release
|
|
19
18
|
search-admin
|
|
20
19
|
signon
|
|
@@ -49,7 +48,9 @@ module GovukPublishingComponents
|
|
|
49
48
|
|
|
50
49
|
application_dirs.each do |application|
|
|
51
50
|
application_path = [path, application].join("/")
|
|
52
|
-
|
|
51
|
+
dir = application
|
|
52
|
+
dir = Rails.application.class.module_parent_name.underscore.dasherize unless ENV["MAIN_COMPONENT_GUIDE"]
|
|
53
|
+
app = AuditApplications.new(application_path, application, dir)
|
|
53
54
|
applications_found += 1 if app.data[:application_found]
|
|
54
55
|
results << app.data
|
|
55
56
|
end
|
|
@@ -2,7 +2,7 @@ module GovukPublishingComponents
|
|
|
2
2
|
class AuditApplications
|
|
3
3
|
attr_reader :data
|
|
4
4
|
|
|
5
|
-
def initialize(path, name)
|
|
5
|
+
def initialize(path, name, dir)
|
|
6
6
|
@path = path
|
|
7
7
|
application_found = application_exists(path)
|
|
8
8
|
components_found = []
|
|
@@ -59,6 +59,7 @@ module GovukPublishingComponents
|
|
|
59
59
|
# applications might not have all of these things for all components
|
|
60
60
|
options = {
|
|
61
61
|
application_name: name,
|
|
62
|
+
application_dir: dir,
|
|
62
63
|
templates_path: "app/views/components",
|
|
63
64
|
stylesheets_path: "app/assets/stylesheets/components",
|
|
64
65
|
javascripts_path: "app/assets/javascripts/components/",
|
|
@@ -72,6 +73,7 @@ module GovukPublishingComponents
|
|
|
72
73
|
|
|
73
74
|
@data = {
|
|
74
75
|
name: name,
|
|
76
|
+
dir: dir,
|
|
75
77
|
application_found: application_found,
|
|
76
78
|
components_found: components_found,
|
|
77
79
|
gem_style_references: @gem_style_references.flatten.uniq.sort,
|
|
@@ -12,7 +12,6 @@ module GovukPublishingComponents
|
|
|
12
12
|
frontend
|
|
13
13
|
government-frontend
|
|
14
14
|
info-frontend
|
|
15
|
-
licence-finder
|
|
16
15
|
service-manual-frontend
|
|
17
16
|
smart-answers
|
|
18
17
|
whitehall
|
|
@@ -93,6 +92,7 @@ module GovukPublishingComponents
|
|
|
93
92
|
|
|
94
93
|
data << {
|
|
95
94
|
name: result[:name],
|
|
95
|
+
dir: result[:dir],
|
|
96
96
|
application_found: result[:application_found],
|
|
97
97
|
uses_static: application_uses_static,
|
|
98
98
|
summary: summary,
|
|
@@ -13,6 +13,7 @@ module GovukPublishingComponents
|
|
|
13
13
|
@helpers_path = options[:helpers_path] || "lib/govuk_publishing_components/presenters"
|
|
14
14
|
|
|
15
15
|
@application_name = options[:application_name] || "govuk_publishing_components"
|
|
16
|
+
@application_dir = options[:application_dir] || "govuk_publishing_components"
|
|
16
17
|
@all_templates = Dir["#{path}/#{@templates_path}/*.erb"].sort
|
|
17
18
|
@templates_full_path = "#{path}/#{@templates_path}/"
|
|
18
19
|
|
|
@@ -57,7 +58,7 @@ module GovukPublishingComponents
|
|
|
57
58
|
component_templates.each do |component|
|
|
58
59
|
component_detail = {}
|
|
59
60
|
component_detail[:name] = component
|
|
60
|
-
component_detail[:application] = @
|
|
61
|
+
component_detail[:application] = @application_dir
|
|
61
62
|
component_detail[:link] = get_component_link(component) unless @auditing_an_application
|
|
62
63
|
file_details = [
|
|
63
64
|
{
|
|
@@ -214,7 +215,7 @@ module GovukPublishingComponents
|
|
|
214
215
|
|
|
215
216
|
def get_asset_link(a_thing, component)
|
|
216
217
|
url = "https://github.com/alphagov"
|
|
217
|
-
repo = @
|
|
218
|
+
repo = @application_dir
|
|
218
219
|
blob = "blob/main"
|
|
219
220
|
link = nil
|
|
220
221
|
link = "#{url}/#{repo}/#{blob}/#{@templates_path}/_#{component.gsub(' ', '_')}.html.erb" if a_thing == "template"
|
|
@@ -9,6 +9,7 @@ This component uses the component wrapper helper. It accepts the following optio
|
|
|
9
9
|
- `aria` - accepts a hash of aria attributes
|
|
10
10
|
- `classes` - accepts a space separated string of classes, these should not be used for styling and must be prefixed with `js-`
|
|
11
11
|
- `role` - accepts a space separated string of roles
|
|
12
|
+
- `lang` - accepts a language attribute value
|
|
12
13
|
"
|
|
13
14
|
end
|
|
14
15
|
end
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
|
|
35
35
|
<% accordion_content = capture do %>
|
|
36
36
|
<% if application[:application_found] %>
|
|
37
|
-
<% github_link = 'https://github.com/alphagov/' + application[:
|
|
37
|
+
<% github_link = 'https://github.com/alphagov/' + application[:dir] + '/blob/main/' %>
|
|
38
38
|
|
|
39
39
|
<% if @other_applications %>
|
|
40
40
|
<% if application[:uses_individual_asset_model] %>
|
|
@@ -43,13 +43,15 @@
|
|
|
43
43
|
"HTML",
|
|
44
44
|
class: "gem-c-attachment__attribute",
|
|
45
45
|
)
|
|
46
|
+
data_attributes[:module] ? data_attributes[:module] << " ga4-link-tracker" : data_attributes[:module] = "ga4-link-tracker"
|
|
47
|
+
data_attributes[:ga4_link] = { "event_name": "navigation", "type": "attachment" }.to_json
|
|
46
48
|
when "external"
|
|
47
49
|
attributes << tag.span(
|
|
48
50
|
attachment.url,
|
|
49
51
|
class: "gem-c-attachment__attribute",
|
|
50
52
|
)
|
|
51
53
|
end
|
|
52
|
-
|
|
54
|
+
|
|
53
55
|
%>
|
|
54
56
|
<%= tag.section class: class_names(container_class_names) do %>
|
|
55
57
|
<%= tag.div class: "gem-c-attachment__thumbnail" do %>
|