govuk_publishing_components 35.11.0 → 35.13.0
Sign up to get free protection for your applications and to get access to all the features.
- 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 %>
|