govuk_publishing_components 35.15.5 → 35.16.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/assets/config/govuk_publishing_components_manifest.js +1 -0
- data/app/assets/images/option-select/input-icon.svg +3 -0
- data/app/assets/javascripts/govuk_publishing_components/analytics-ga4/ga4-page-views.js +37 -15
- data/app/assets/javascripts/govuk_publishing_components/analytics-ga4/ga4-video-tracker.js +7 -1
- data/app/assets/javascripts/govuk_publishing_components/analytics-ga4/pii-remover.js +1 -1
- data/app/assets/javascripts/govuk_publishing_components/components/option-select.js +312 -0
- data/app/assets/stylesheets/component_guide/application.scss +6 -6
- data/app/assets/stylesheets/govuk_publishing_components/_all_components.scss +1 -0
- data/app/assets/stylesheets/govuk_publishing_components/components/_action-link.scss +15 -15
- data/app/assets/stylesheets/govuk_publishing_components/components/_big-number.scss +3 -2
- data/app/assets/stylesheets/govuk_publishing_components/components/_breadcrumbs.scss +3 -3
- data/app/assets/stylesheets/govuk_publishing_components/components/_button.scss +2 -2
- data/app/assets/stylesheets/govuk_publishing_components/components/_cards.scss +5 -5
- data/app/assets/stylesheets/govuk_publishing_components/components/_contents-list.scss +1 -1
- data/app/assets/stylesheets/govuk_publishing_components/components/_contextual-sidebar.scss +1 -1
- data/app/assets/stylesheets/govuk_publishing_components/components/_document-list.scss +2 -2
- data/app/assets/stylesheets/govuk_publishing_components/components/_image-card.scss +31 -5
- data/app/assets/stylesheets/govuk_publishing_components/components/_layout-super-navigation-header.scss +40 -35
- data/app/assets/stylesheets/govuk_publishing_components/components/_option-select.scss +172 -0
- data/app/assets/stylesheets/govuk_publishing_components/components/_step-by-step-nav.scss +23 -19
- data/app/assets/stylesheets/govuk_publishing_components/components/_table.scss +6 -6
- data/app/assets/stylesheets/govuk_publishing_components/components/_tabs.scss +2 -1
- data/app/assets/stylesheets/govuk_publishing_components/components/govspeak/_steps.scss +3 -1
- data/app/assets/stylesheets/govuk_publishing_components/components/govspeak/_typography.scss +4 -4
- data/app/assets/stylesheets/govuk_publishing_components/components/mixins/_media-down.scss +2 -2
- data/app/views/govuk_publishing_components/components/_attachment.html.erb +1 -1
- data/app/views/govuk_publishing_components/components/_contents_list.html.erb +20 -10
- data/app/views/govuk_publishing_components/components/_image_card.html.erb +8 -2
- data/app/views/govuk_publishing_components/components/_option_select.html.erb +71 -0
- data/app/views/govuk_publishing_components/components/_previous_and_next_navigation.html.erb +6 -6
- data/app/views/govuk_publishing_components/components/docs/contents_list.yml +1 -0
- data/app/views/govuk_publishing_components/components/docs/image_card.yml +13 -0
- data/app/views/govuk_publishing_components/components/docs/option_select.yml +343 -0
- data/config/locales/ar.yml +5 -0
- data/config/locales/az.yml +5 -0
- data/config/locales/be.yml +5 -0
- data/config/locales/bg.yml +5 -0
- data/config/locales/bn.yml +5 -0
- data/config/locales/cs.yml +5 -0
- data/config/locales/cy.yml +5 -0
- data/config/locales/da.yml +5 -0
- data/config/locales/de.yml +5 -0
- data/config/locales/dr.yml +5 -0
- data/config/locales/el.yml +5 -0
- data/config/locales/en.yml +6 -1
- data/config/locales/es-419.yml +5 -0
- data/config/locales/es.yml +5 -0
- data/config/locales/et.yml +5 -0
- data/config/locales/fa.yml +5 -0
- data/config/locales/fi.yml +5 -0
- data/config/locales/fr.yml +5 -0
- data/config/locales/gd.yml +5 -0
- data/config/locales/gu.yml +5 -0
- data/config/locales/he.yml +5 -0
- data/config/locales/hi.yml +5 -0
- data/config/locales/hr.yml +5 -0
- data/config/locales/hu.yml +5 -0
- data/config/locales/hy.yml +5 -0
- data/config/locales/id.yml +5 -0
- data/config/locales/is.yml +5 -0
- data/config/locales/it.yml +5 -0
- data/config/locales/ja.yml +5 -0
- data/config/locales/ka.yml +5 -0
- data/config/locales/kk.yml +5 -0
- data/config/locales/ko.yml +5 -0
- data/config/locales/lt.yml +5 -0
- data/config/locales/lv.yml +5 -0
- data/config/locales/ms.yml +5 -0
- data/config/locales/mt.yml +5 -0
- data/config/locales/nl.yml +5 -0
- data/config/locales/no.yml +5 -0
- data/config/locales/pa-pk.yml +5 -0
- data/config/locales/pa.yml +5 -0
- data/config/locales/pl.yml +5 -0
- data/config/locales/ps.yml +5 -0
- data/config/locales/pt.yml +5 -0
- data/config/locales/ro.yml +5 -0
- data/config/locales/ru.yml +5 -0
- data/config/locales/si.yml +5 -0
- data/config/locales/sk.yml +5 -0
- data/config/locales/sl.yml +5 -0
- data/config/locales/so.yml +5 -0
- data/config/locales/sq.yml +5 -0
- data/config/locales/sr.yml +5 -0
- data/config/locales/sv.yml +5 -0
- data/config/locales/sw.yml +5 -0
- data/config/locales/ta.yml +5 -0
- data/config/locales/th.yml +5 -0
- data/config/locales/tk.yml +5 -0
- data/config/locales/tr.yml +5 -0
- data/config/locales/uk.yml +5 -0
- data/config/locales/ur.yml +5 -0
- data/config/locales/uz.yml +5 -0
- data/config/locales/vi.yml +5 -0
- data/config/locales/zh-hk.yml +5 -0
- data/config/locales/zh-tw.yml +5 -0
- data/config/locales/zh.yml +5 -0
- data/lib/govuk_publishing_components/presenters/contents_list_helper.rb +8 -0
- data/lib/govuk_publishing_components/presenters/image_card_helper.rb +6 -2
- data/lib/govuk_publishing_components/presenters/meta_tags.rb +3 -0
- data/lib/govuk_publishing_components/version.rb +1 -1
- data/node_modules/axe-core/axe.js +6 -6
- data/node_modules/axe-core/axe.min.js +2 -2
- data/node_modules/axe-core/locales/_template.json +4 -4
- data/node_modules/axe-core/package.json +1 -1
- data/node_modules/axe-core/sri-history.json +4 -0
- metadata +7 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f215a358b5348fe905ec3b11ba2d3301dd263bbe5fe6961cdab3586de5f11ead
|
4
|
+
data.tar.gz: fee32e2c6b0b5a587b36577db5f51a731b8c3df67b5d7b30db4089650edf7efd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f687a3d509cc89bd128d4c696f8f504575188b3ade7b6e536587c09be27ce7d0a3733203c52acfb48252ba6655a99b020d64d8ae5d2afbb23994e0f16a6bc2ad
|
7
|
+
data.tar.gz: 82488d3f778c9c3dc22f27eab581965780b695a43ff0585fd191771dbbf6aa05c165616c61d89873342755e9c90b13e638766f116fef25a72baf8c08a265362f
|
@@ -60,6 +60,7 @@
|
|
60
60
|
//= link govuk_publishing_components/components/_metadata.css
|
61
61
|
//= link govuk_publishing_components/components/_modal-dialogue.css
|
62
62
|
//= link govuk_publishing_components/components/_notice.css
|
63
|
+
//= link govuk_publishing_components/components/_option-select.css
|
63
64
|
//= link govuk_publishing_components/components/_organisation-logo.css
|
64
65
|
//= link govuk_publishing_components/components/_panel.css
|
65
66
|
//= link govuk_publishing_components/components/_phase-banner.css
|
@@ -0,0 +1,3 @@
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36" width="40" height="40">
|
2
|
+
<path d="M25.7 24.8L21.9 21c.7-1 1.1-2.2 1.1-3.5 0-3.6-2.9-6.5-6.5-6.5S10 13.9 10 17.5s2.9 6.5 6.5 6.5c1.6 0 3-.6 4.1-1.5l3.7 3.7 1.4-1.4zM12 17.5c0-2.5 2-4.5 4.5-4.5s4.5 2 4.5 4.5-2 4.5-4.5 4.5-4.5-2-4.5-4.5z" fill="currentColor" />
|
3
|
+
</svg>
|
@@ -28,7 +28,7 @@ window.GOVUK.analyticsGa4.analyticsModules = window.GOVUK.analyticsGa4.analytics
|
|
28
28
|
schema_name: this.getMetaContent('schema-name'),
|
29
29
|
content_id: this.getMetaContent('content-id'),
|
30
30
|
|
31
|
-
browse_topic: this.getMetaContent('
|
31
|
+
browse_topic: this.getMetaContent('ga4-browse-topic'),
|
32
32
|
navigation_page_type: this.getMetaContent('navigation-page-type'),
|
33
33
|
navigation_list_type: this.getMetaContent('navigation-list-type'),
|
34
34
|
step_navs: this.getMetaContent('stepnavs'),
|
@@ -57,9 +57,11 @@ window.GOVUK.analyticsGa4.analyticsModules = window.GOVUK.analyticsGa4.analytics
|
|
57
57
|
emergency_banner: document.querySelector('[data-ga4-emergency-banner]') ? 'true' : undefined,
|
58
58
|
phase_banner: this.getElementAttribute('data-ga4-phase-banner') || undefined,
|
59
59
|
devolved_nations_banner: this.getElementAttribute('data-ga4-devolved-nations-banner') || undefined,
|
60
|
-
cookie_banner:
|
61
|
-
intervention: this.
|
62
|
-
query_string: this.getQueryString()
|
60
|
+
cookie_banner: this.getBannerPresence('[data-ga4-cookie-banner]'),
|
61
|
+
intervention: this.getBannerPresence('[data-ga4-intervention-banner]'),
|
62
|
+
query_string: this.getQueryString(),
|
63
|
+
search_term: this.getSearchTerm(),
|
64
|
+
spelling_suggestion: this.getMetaContent('spelling-suggestion')
|
63
65
|
}
|
64
66
|
}
|
65
67
|
window.GOVUK.analyticsGa4.core.sendData(data)
|
@@ -67,18 +69,35 @@ window.GOVUK.analyticsGa4.analyticsModules = window.GOVUK.analyticsGa4.analytics
|
|
67
69
|
},
|
68
70
|
|
69
71
|
getLocation: function () {
|
70
|
-
return this.PIIRemover.
|
72
|
+
return this.PIIRemover.stripPIIWithOverride(this.stripGaParam(document.location.href), true, true)
|
71
73
|
},
|
72
74
|
|
73
75
|
getSearch: function () {
|
74
76
|
return window.location.search
|
75
77
|
},
|
76
78
|
|
79
|
+
getSearchTerm: function () {
|
80
|
+
var queryString = this.getSearch()
|
81
|
+
|
82
|
+
if (!queryString) {
|
83
|
+
return undefined
|
84
|
+
}
|
85
|
+
|
86
|
+
var searchTerm = queryString.match(/keywords=([^&]*)/)
|
87
|
+
if (!searchTerm) {
|
88
|
+
return undefined
|
89
|
+
}
|
90
|
+
|
91
|
+
searchTerm = searchTerm[0].replace('keywords=', '')
|
92
|
+
searchTerm = this.PIIRemover.stripPIIWithOverride(searchTerm, true, true)
|
93
|
+
return searchTerm
|
94
|
+
},
|
95
|
+
|
77
96
|
getQueryString: function () {
|
78
97
|
var queryString = this.getSearch()
|
79
98
|
if (queryString) {
|
80
|
-
queryString = this.PIIRemover.stripPIIWithOverride(queryString, true, true)
|
81
99
|
queryString = this.stripGaParam(queryString)
|
100
|
+
queryString = this.PIIRemover.stripPIIWithOverride(queryString, true, true)
|
82
101
|
queryString = queryString.substring(1) // removes the '?' character from the start.
|
83
102
|
return queryString
|
84
103
|
}
|
@@ -97,7 +116,7 @@ window.GOVUK.analyticsGa4.analyticsModules = window.GOVUK.analyticsGa4.analytics
|
|
97
116
|
},
|
98
117
|
|
99
118
|
getTitle: function () {
|
100
|
-
return this.PIIRemover.
|
119
|
+
return this.PIIRemover.stripPIIWithOverride(document.title, true, true)
|
101
120
|
},
|
102
121
|
|
103
122
|
// window.httpStatusCode is set in the source of the error page in static
|
@@ -130,7 +149,10 @@ window.GOVUK.analyticsGa4.analyticsModules = window.GOVUK.analyticsGa4.analytics
|
|
130
149
|
var content = document.getElementById('content')
|
131
150
|
var html = document.querySelector('html')
|
132
151
|
if (content) {
|
133
|
-
|
152
|
+
var contentLanguage = content.getAttribute('lang')
|
153
|
+
if (contentLanguage) {
|
154
|
+
return contentLanguage
|
155
|
+
}
|
134
156
|
}
|
135
157
|
// html.getAttribute('lang') is untested - Jasmine would not allow lang to be set on <html>.
|
136
158
|
return html.getAttribute('lang') || this.nullValue
|
@@ -146,18 +168,18 @@ window.GOVUK.analyticsGa4.analyticsModules = window.GOVUK.analyticsGa4.analytics
|
|
146
168
|
return (withdrawn === 'withdrawn') ? 'true' : 'false'
|
147
169
|
},
|
148
170
|
|
149
|
-
|
171
|
+
getBannerPresence: function (bannerSelector) {
|
150
172
|
/* If the user hides the banner using JS, a cookie is set to hide it on future page loads.
|
151
|
-
* Therefore we need to start the
|
173
|
+
* Therefore we need to start the banner module early so that it hides if this cookie exists.
|
152
174
|
* Without this, our pageview object will track the banner as visible before it gets hidden. */
|
153
175
|
|
154
|
-
var
|
176
|
+
var banner = document.querySelector(bannerSelector)
|
155
177
|
|
156
|
-
if (
|
157
|
-
window.GOVUK.modules.start(
|
158
|
-
var
|
178
|
+
if (banner) {
|
179
|
+
window.GOVUK.modules.start(banner)
|
180
|
+
var bannerHidden = banner.getAttribute('hidden') === '' || banner.getAttribute('hidden')
|
159
181
|
|
160
|
-
if (
|
182
|
+
if (bannerHidden) {
|
161
183
|
return undefined
|
162
184
|
}
|
163
185
|
return 'true'
|
@@ -70,7 +70,7 @@ window.GOVUK.analyticsGa4.analyticsModules = window.GOVUK.analyticsGa4.analytics
|
|
70
70
|
var data = {}
|
71
71
|
data.event_name = 'video_' + event
|
72
72
|
data.type = 'video'
|
73
|
-
data.url = player.getVideoUrl()
|
73
|
+
data.url = this.cleanVideoUrl(player.getVideoUrl())
|
74
74
|
data.text = player.videoTitle
|
75
75
|
data.action = event
|
76
76
|
data.video_current_time = Math.round(player.getCurrentTime())
|
@@ -81,6 +81,12 @@ window.GOVUK.analyticsGa4.analyticsModules = window.GOVUK.analyticsGa4.analytics
|
|
81
81
|
var schema = schemas.mergeProperties(data, 'event_data')
|
82
82
|
|
83
83
|
window.GOVUK.analyticsGa4.core.sendData(schema)
|
84
|
+
},
|
85
|
+
|
86
|
+
cleanVideoUrl: function (url) {
|
87
|
+
url = url.replace(/[?]{1}t=[0-9]+[&]{1}/, '?') // replace ?t=123& with ?
|
88
|
+
url = url.replace(/[&]{1}t=[0-9]+/, '') // replace &t=123 with ''
|
89
|
+
return url
|
84
90
|
}
|
85
91
|
}
|
86
92
|
|
@@ -2,7 +2,7 @@
|
|
2
2
|
'use strict'
|
3
3
|
|
4
4
|
var GOVUK = global.GOVUK || {}
|
5
|
-
var EMAIL_PATTERN = /[^\s
|
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
7
|
var DATE_PATTERN_NUMERIC = /\d{4}(-?)\d{2}(-?)\d{2}/g
|
8
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
|
@@ -0,0 +1,312 @@
|
|
1
|
+
window.GOVUK = window.GOVUK || {}
|
2
|
+
window.GOVUK.Modules = window.GOVUK.Modules || {};
|
3
|
+
|
4
|
+
(function (Modules) {
|
5
|
+
/* This JavaScript provides two functional enhancements to option-select components:
|
6
|
+
1) A count that shows how many results have been checked in the option-container
|
7
|
+
2) Open/closing of the list of checkboxes
|
8
|
+
*/
|
9
|
+
function OptionSelect ($module) {
|
10
|
+
this.$optionSelect = $module
|
11
|
+
this.$options = this.$optionSelect.querySelectorAll("input[type='checkbox']")
|
12
|
+
this.$optionsContainer = this.$optionSelect.querySelector('.js-options-container')
|
13
|
+
this.$optionList = this.$optionsContainer.querySelector('.js-auto-height-inner')
|
14
|
+
this.$allCheckboxes = this.$optionsContainer.querySelectorAll('.govuk-checkboxes__item')
|
15
|
+
this.hasFilter = this.$optionSelect.getAttribute('data-filter-element') || ''
|
16
|
+
|
17
|
+
this.checkedCheckboxes = []
|
18
|
+
|
19
|
+
this.mq = window.matchMedia('(min-width: 641px)')
|
20
|
+
this.isClosedOnLoad = this.$optionSelect.getAttribute('data-closed-on-load')
|
21
|
+
this.isClosedOnLoadMobile = this.$optionSelect.getAttribute('data-closed-on-load-mobile')
|
22
|
+
}
|
23
|
+
|
24
|
+
OptionSelect.prototype.init = function () {
|
25
|
+
if (this.hasFilter.length) {
|
26
|
+
var filterEl = document.createElement('div')
|
27
|
+
filterEl.innerHTML = this.hasFilter
|
28
|
+
|
29
|
+
var optionSelectFilter = document.createElement('div')
|
30
|
+
optionSelectFilter.classList.add('gem-c-option-select__filter')
|
31
|
+
optionSelectFilter.innerHTML = filterEl.childNodes[0].nodeValue
|
32
|
+
|
33
|
+
this.$optionsContainer.parentNode.insertBefore(optionSelectFilter, this.$optionsContainer)
|
34
|
+
|
35
|
+
this.$filter = this.$optionSelect.querySelector('input[name="option-select-filter"]')
|
36
|
+
this.$filterCount = document.getElementById(this.$filter.getAttribute('aria-describedby'))
|
37
|
+
this.filterTextSingle = ' ' + this.$filterCount.getAttribute('data-single')
|
38
|
+
this.filterTextMultiple = ' ' + this.$filterCount.getAttribute('data-multiple')
|
39
|
+
this.filterTextSelected = ' ' + this.$filterCount.getAttribute('data-selected')
|
40
|
+
this.checkboxLabels = []
|
41
|
+
this.filterTimeout = 0
|
42
|
+
|
43
|
+
this.getAllCheckedCheckboxes()
|
44
|
+
for (var i = 0; i < this.$allCheckboxes.length; i++) {
|
45
|
+
this.checkboxLabels.push(this.cleanString(this.$allCheckboxes[i].textContent))
|
46
|
+
}
|
47
|
+
|
48
|
+
this.$filter.addEventListener('keyup', this.typeFilterText.bind(this))
|
49
|
+
}
|
50
|
+
|
51
|
+
// Attach listener to update checked count
|
52
|
+
this.$optionsContainer.querySelector('.gem-c-checkboxes__list').addEventListener('change', this.updateCheckedCount.bind(this))
|
53
|
+
|
54
|
+
// Replace div.container-head with a button
|
55
|
+
this.replaceHeadingSpanWithButton()
|
56
|
+
|
57
|
+
// Add js-collapsible class to parent for CSS
|
58
|
+
this.$optionSelect.classList.add('js-collapsible')
|
59
|
+
|
60
|
+
// Add open/close listeners
|
61
|
+
var button = this.$optionSelect.querySelector('.js-container-button')
|
62
|
+
button.addEventListener('click', this.toggleOptionSelect.bind(this))
|
63
|
+
|
64
|
+
// Toggle option visibility depending on screen size (min-width: 641px) and
|
65
|
+
// presence of any 'closed' properties (`data-closed-on-load`, `data-closed-on-load-mobile`).
|
66
|
+
// See https://github.com/alphagov/govuk-frontend/blob/main/packages/govuk-frontend/src/govuk/settings/_media-queries.scss#L10-L14
|
67
|
+
if (this.mq.matches) {
|
68
|
+
this.toggleVisibility(true)
|
69
|
+
} else {
|
70
|
+
this.toggleVisibility(false)
|
71
|
+
}
|
72
|
+
|
73
|
+
var checkedString = this.checkedString()
|
74
|
+
if (checkedString) {
|
75
|
+
this.attachCheckedCounter(checkedString)
|
76
|
+
}
|
77
|
+
}
|
78
|
+
|
79
|
+
OptionSelect.prototype.toggleVisibility = function (isTabletOrLarger) {
|
80
|
+
if (isTabletOrLarger) {
|
81
|
+
if (this.isClosedOnLoad === 'true') {
|
82
|
+
this.close()
|
83
|
+
} else {
|
84
|
+
this.setupHeight()
|
85
|
+
}
|
86
|
+
} else {
|
87
|
+
if (this.isClosedOnLoadMobile === 'true' || this.isClosedOnLoad === 'true') {
|
88
|
+
this.close()
|
89
|
+
} else {
|
90
|
+
this.setContainerHeight(201)
|
91
|
+
}
|
92
|
+
}
|
93
|
+
}
|
94
|
+
|
95
|
+
OptionSelect.prototype.typeFilterText = function (event) {
|
96
|
+
event.stopPropagation()
|
97
|
+
var ENTER_KEY = 13
|
98
|
+
|
99
|
+
if (event.keyCode !== ENTER_KEY) {
|
100
|
+
clearTimeout(this.filterTimeout)
|
101
|
+
this.filterTimeout = setTimeout(
|
102
|
+
function () { this.doFilter(this) }.bind(this),
|
103
|
+
300
|
104
|
+
)
|
105
|
+
} else {
|
106
|
+
event.preventDefault() // prevents finder forms from being submitted when user presses ENTER
|
107
|
+
}
|
108
|
+
}
|
109
|
+
|
110
|
+
OptionSelect.prototype.cleanString = function cleanString (text) {
|
111
|
+
text = text.replace(/&/g, 'and')
|
112
|
+
text = text.replace(/[’',:–-]/g, '') // remove punctuation characters
|
113
|
+
text = text.replace(/[.*+?^${}()|[\]\\]/g, '\\$&') // escape special characters
|
114
|
+
return text.trim().replace(/\s\s+/g, ' ').toLowerCase() // replace multiple spaces with one
|
115
|
+
}
|
116
|
+
|
117
|
+
OptionSelect.prototype.getAllCheckedCheckboxes = function getAllCheckedCheckboxes () {
|
118
|
+
this.checkedCheckboxes = []
|
119
|
+
|
120
|
+
for (var i = 0; i < this.$options.length; i++) {
|
121
|
+
if (this.$options[i].checked) {
|
122
|
+
this.checkedCheckboxes.push(i)
|
123
|
+
}
|
124
|
+
}
|
125
|
+
}
|
126
|
+
|
127
|
+
OptionSelect.prototype.doFilter = function doFilter (obj) {
|
128
|
+
var filterBy = obj.cleanString(obj.$filter.value)
|
129
|
+
var showCheckboxes = obj.checkedCheckboxes.slice()
|
130
|
+
var i = 0
|
131
|
+
|
132
|
+
for (i = 0; i < obj.$allCheckboxes.length; i++) {
|
133
|
+
if (showCheckboxes.indexOf(i) === -1 && obj.checkboxLabels[i].search(filterBy) !== -1) {
|
134
|
+
showCheckboxes.push(i)
|
135
|
+
}
|
136
|
+
}
|
137
|
+
|
138
|
+
for (i = 0; i < obj.$allCheckboxes.length; i++) {
|
139
|
+
obj.$allCheckboxes[i].style.display = 'none'
|
140
|
+
}
|
141
|
+
|
142
|
+
for (i = 0; i < showCheckboxes.length; i++) {
|
143
|
+
obj.$allCheckboxes[showCheckboxes[i]].style.display = 'block'
|
144
|
+
}
|
145
|
+
|
146
|
+
var lenChecked = obj.$optionsContainer.querySelectorAll('.govuk-checkboxes__input:checked').length
|
147
|
+
var len = showCheckboxes.length + lenChecked
|
148
|
+
var html = len + (len === 1 ? obj.filterTextSingle : obj.filterTextMultiple) + ', ' + lenChecked + obj.filterTextSelected
|
149
|
+
obj.$filterCount.innerHTML = html
|
150
|
+
}
|
151
|
+
|
152
|
+
OptionSelect.prototype.replaceHeadingSpanWithButton = function replaceHeadingSpanWithButton () {
|
153
|
+
/* Replace the span within the heading with a button element. This is based on feedback from Léonie Watson.
|
154
|
+
* The button has all of the accessibility hooks that are used by screen readers and etc.
|
155
|
+
* We do this in the JavaScript because if the JavaScript is not active then the button shouldn't
|
156
|
+
* be there as there is no JS to handle the click event.
|
157
|
+
*/
|
158
|
+
var containerHead = this.$optionSelect.querySelector('.js-container-button')
|
159
|
+
var jsContainerHeadHTML = containerHead.innerHTML
|
160
|
+
|
161
|
+
// Create button and replace the preexisting html with the button.
|
162
|
+
var button = document.createElement('button')
|
163
|
+
button.setAttribute('class', 'js-container-button gem-c-option-select__title gem-c-option-select__button')
|
164
|
+
// Add type button to override default type submit when this component is used within a form
|
165
|
+
button.setAttribute('type', 'button')
|
166
|
+
button.setAttribute('aria-expanded', true)
|
167
|
+
button.setAttribute('id', containerHead.getAttribute('id'))
|
168
|
+
button.setAttribute('aria-controls', this.$optionsContainer.getAttribute('id'))
|
169
|
+
button.innerHTML = jsContainerHeadHTML
|
170
|
+
containerHead.parentNode.replaceChild(button, containerHead)
|
171
|
+
|
172
|
+
// GA4 Accordion tracking. Relies on the ga4-finder-tracker setting the index first, so we wrap this in a custom event.
|
173
|
+
window.addEventListener('ga4-filter-indexes-added', function () {
|
174
|
+
if (window.GOVUK.analyticsGa4) {
|
175
|
+
if (window.GOVUK.analyticsGa4.Ga4FinderTracker) {
|
176
|
+
window.GOVUK.analyticsGa4.Ga4FinderTracker.addFilterButtonTracking(button, button.innerHTML)
|
177
|
+
}
|
178
|
+
}
|
179
|
+
})
|
180
|
+
}
|
181
|
+
|
182
|
+
OptionSelect.prototype.attachCheckedCounter = function attachCheckedCounter (checkedString) {
|
183
|
+
var element = document.createElement('div')
|
184
|
+
element.setAttribute('class', 'gem-c-option-select__selected-counter js-selected-counter')
|
185
|
+
element.innerHTML = checkedString
|
186
|
+
this.$optionSelect.querySelector('.js-container-button').insertAdjacentElement('afterend', element)
|
187
|
+
}
|
188
|
+
|
189
|
+
OptionSelect.prototype.updateCheckedCount = function updateCheckedCount () {
|
190
|
+
var checkedString = this.checkedString()
|
191
|
+
var checkedStringElement = this.$optionSelect.querySelector('.js-selected-counter')
|
192
|
+
|
193
|
+
if (checkedString) {
|
194
|
+
if (checkedStringElement === null) {
|
195
|
+
this.attachCheckedCounter(checkedString)
|
196
|
+
} else {
|
197
|
+
checkedStringElement.textContent = checkedString
|
198
|
+
}
|
199
|
+
} else if (checkedStringElement) {
|
200
|
+
checkedStringElement.parentNode.removeChild(checkedStringElement)
|
201
|
+
}
|
202
|
+
}
|
203
|
+
|
204
|
+
OptionSelect.prototype.checkedString = function checkedString () {
|
205
|
+
this.getAllCheckedCheckboxes()
|
206
|
+
var count = this.checkedCheckboxes.length
|
207
|
+
var checkedString = false
|
208
|
+
if (count > 0) {
|
209
|
+
checkedString = count + ' selected'
|
210
|
+
}
|
211
|
+
|
212
|
+
return checkedString
|
213
|
+
}
|
214
|
+
|
215
|
+
OptionSelect.prototype.toggleOptionSelect = function toggleOptionSelect (e) {
|
216
|
+
if (this.isClosed()) {
|
217
|
+
this.open()
|
218
|
+
} else {
|
219
|
+
this.close()
|
220
|
+
}
|
221
|
+
e.preventDefault()
|
222
|
+
}
|
223
|
+
|
224
|
+
OptionSelect.prototype.open = function open () {
|
225
|
+
if (this.isClosed()) {
|
226
|
+
this.$optionSelect.querySelector('.js-container-button').setAttribute('aria-expanded', true)
|
227
|
+
this.$optionSelect.classList.remove('js-closed')
|
228
|
+
this.$optionSelect.classList.add('js-opened')
|
229
|
+
if (!this.$optionsContainer.style.height) {
|
230
|
+
this.setupHeight()
|
231
|
+
}
|
232
|
+
}
|
233
|
+
}
|
234
|
+
|
235
|
+
OptionSelect.prototype.close = function close () {
|
236
|
+
this.$optionSelect.classList.remove('js-opened')
|
237
|
+
this.$optionSelect.classList.add('js-closed')
|
238
|
+
this.$optionSelect.querySelector('.js-container-button').setAttribute('aria-expanded', false)
|
239
|
+
}
|
240
|
+
|
241
|
+
OptionSelect.prototype.isClosed = function isClosed () {
|
242
|
+
return this.$optionSelect.classList.contains('js-closed')
|
243
|
+
}
|
244
|
+
|
245
|
+
OptionSelect.prototype.setContainerHeight = function setContainerHeight (height) {
|
246
|
+
this.$optionsContainer.style.height = height + 'px'
|
247
|
+
}
|
248
|
+
|
249
|
+
OptionSelect.prototype.isCheckboxVisible = function isCheckboxVisible (option) {
|
250
|
+
var initialOptionContainerHeight = this.$optionsContainer.clientHeight
|
251
|
+
var optionListOffsetTop = this.$optionList.getBoundingClientRect().top
|
252
|
+
var distanceFromTopOfContainer = option.getBoundingClientRect().top - optionListOffsetTop
|
253
|
+
return distanceFromTopOfContainer < initialOptionContainerHeight
|
254
|
+
}
|
255
|
+
|
256
|
+
OptionSelect.prototype.getVisibleCheckboxes = function getVisibleCheckboxes () {
|
257
|
+
var visibleCheckboxes = []
|
258
|
+
for (var i = 0; i < this.$options.length; i++) {
|
259
|
+
if (this.isCheckboxVisible(this.$options[i])) {
|
260
|
+
visibleCheckboxes.push(this.$options[i])
|
261
|
+
}
|
262
|
+
}
|
263
|
+
|
264
|
+
// add an extra checkbox, if the label of the first is too long it collapses onto itself
|
265
|
+
if (this.$options[visibleCheckboxes.length]) {
|
266
|
+
visibleCheckboxes.push(this.$options[visibleCheckboxes.length])
|
267
|
+
}
|
268
|
+
return visibleCheckboxes
|
269
|
+
}
|
270
|
+
|
271
|
+
OptionSelect.prototype.isComponentParentHidden = function isComponentParentHidden () {
|
272
|
+
var parentContent = this.$optionSelect.parentElement
|
273
|
+
var isparentContentHidden = false
|
274
|
+
// check whether this is hidden by progressive disclosure,
|
275
|
+
// because height calculations won't work
|
276
|
+
// would use offsetParent === null but for IE10+
|
277
|
+
if (parentContent) {
|
278
|
+
isparentContentHidden = !(parentContent.offsetWidth || parentContent.offsetHeight || parentContent.getClientRects().length)
|
279
|
+
}
|
280
|
+
|
281
|
+
return isparentContentHidden
|
282
|
+
}
|
283
|
+
|
284
|
+
OptionSelect.prototype.setupHeight = function setupHeight () {
|
285
|
+
var initialOptionContainerHeight = this.$optionsContainer.clientHeight
|
286
|
+
var height = this.$optionList.offsetHeight
|
287
|
+
|
288
|
+
var isComponentParentHidden = this.isComponentParentHidden()
|
289
|
+
|
290
|
+
if (isComponentParentHidden) {
|
291
|
+
initialOptionContainerHeight = 200
|
292
|
+
height = 200
|
293
|
+
}
|
294
|
+
|
295
|
+
// Resize if the list is only slightly bigger than its container
|
296
|
+
// If isComponentParentHidden is true, then 200 < 250
|
297
|
+
// And the container height is always set to 201px
|
298
|
+
if (height < initialOptionContainerHeight + 50) {
|
299
|
+
this.setContainerHeight(height + 1)
|
300
|
+
return
|
301
|
+
}
|
302
|
+
|
303
|
+
// Resize to cut last item cleanly in half
|
304
|
+
var visibleCheckboxes = this.getVisibleCheckboxes()
|
305
|
+
|
306
|
+
var lastVisibleCheckbox = visibleCheckboxes[visibleCheckboxes.length - 1]
|
307
|
+
var position = lastVisibleCheckbox.parentNode.offsetTop // parent element is relative
|
308
|
+
this.setContainerHeight(position + (lastVisibleCheckbox.clientHeight / 1.5))
|
309
|
+
}
|
310
|
+
|
311
|
+
Modules.OptionSelect = OptionSelect
|
312
|
+
})(window.GOVUK.Modules)
|
@@ -145,7 +145,7 @@ $gem-guide-border-width: 1px;
|
|
145
145
|
border: 0;
|
146
146
|
padding: govuk-spacing(2);
|
147
147
|
|
148
|
-
|
148
|
+
&::before {
|
149
149
|
display: none;
|
150
150
|
}
|
151
151
|
}
|
@@ -187,7 +187,7 @@ $gem-guide-border-width: 1px;
|
|
187
187
|
font-style: italic;
|
188
188
|
}
|
189
189
|
|
190
|
-
|
190
|
+
&::before {
|
191
191
|
@include govuk-font($size: 14);
|
192
192
|
content: attr(data-content);
|
193
193
|
position: absolute;
|
@@ -201,7 +201,7 @@ $gem-guide-border-width: 1px;
|
|
201
201
|
.component-guide-preview--warning {
|
202
202
|
border-color: govuk-colour("yellow");
|
203
203
|
|
204
|
-
|
204
|
+
&::before {
|
205
205
|
background-color: govuk-colour("yellow");
|
206
206
|
}
|
207
207
|
}
|
@@ -209,7 +209,7 @@ $gem-guide-border-width: 1px;
|
|
209
209
|
.component-guide-preview--violation {
|
210
210
|
border-color: govuk-colour("red");
|
211
211
|
|
212
|
-
|
212
|
+
&::before {
|
213
213
|
background-color: govuk-colour("red");
|
214
214
|
color: govuk-colour("white");
|
215
215
|
}
|
@@ -516,11 +516,11 @@ $code-delete-bg: #fadddd;
|
|
516
516
|
}
|
517
517
|
|
518
518
|
.component__count {
|
519
|
-
|
519
|
+
&::before {
|
520
520
|
content: "(";
|
521
521
|
}
|
522
522
|
|
523
|
-
|
523
|
+
&::after {
|
524
524
|
content: ")";
|
525
525
|
}
|
526
526
|
}
|
@@ -57,6 +57,7 @@ $govuk-new-link-styles: true;
|
|
57
57
|
@import "components/metadata";
|
58
58
|
@import "components/modal-dialogue";
|
59
59
|
@import "components/notice";
|
60
|
+
@import "components/option-select";
|
60
61
|
@import "components/organisation-logo";
|
61
62
|
@import "components/panel";
|
62
63
|
@import "components/phase-banner";
|
@@ -3,7 +3,7 @@
|
|
3
3
|
.gem-c-action-link {
|
4
4
|
display: table;
|
5
5
|
|
6
|
-
|
6
|
+
&::before {
|
7
7
|
content: "";
|
8
8
|
display: table-cell;
|
9
9
|
width: 60px;
|
@@ -66,7 +66,7 @@
|
|
66
66
|
.gem-c-action-link__subtext {
|
67
67
|
padding: 0;
|
68
68
|
|
69
|
-
|
69
|
+
&::before {
|
70
70
|
display: none;
|
71
71
|
}
|
72
72
|
}
|
@@ -82,7 +82,7 @@
|
|
82
82
|
position: relative;
|
83
83
|
padding-left: govuk-spacing(4);
|
84
84
|
|
85
|
-
|
85
|
+
&::before {
|
86
86
|
content: "";
|
87
87
|
position: absolute;
|
88
88
|
top: 10%;
|
@@ -95,14 +95,14 @@
|
|
95
95
|
}
|
96
96
|
|
97
97
|
.gem-c-action-link--white-arrow {
|
98
|
-
|
98
|
+
&::before {
|
99
99
|
background-image: image-url("govuk_publishing_components/action-link-arrow--white.png");
|
100
100
|
background-image: image-url("govuk_publishing_components/action-link-arrow--white.svg"), linear-gradient(transparent, transparent);
|
101
101
|
}
|
102
102
|
}
|
103
103
|
|
104
104
|
.gem-c-action-link--blue-arrow {
|
105
|
-
|
105
|
+
&::before {
|
106
106
|
width: 36px;
|
107
107
|
height: 28px;
|
108
108
|
background: image-url("govuk_publishing_components/action-link-arrow--blue.png");
|
@@ -120,7 +120,7 @@
|
|
120
120
|
}
|
121
121
|
|
122
122
|
.gem-c-action-link--simple {
|
123
|
-
|
123
|
+
&::before {
|
124
124
|
width: 30px;
|
125
125
|
height: 30px;
|
126
126
|
background: image-url("govuk_publishing_components/action-link-arrow--simple.png");
|
@@ -132,7 +132,7 @@
|
|
132
132
|
}
|
133
133
|
|
134
134
|
.gem-c-action-link--simple-light {
|
135
|
-
|
135
|
+
&::before {
|
136
136
|
width: 30px;
|
137
137
|
height: 30px;
|
138
138
|
background: image-url("govuk_publishing_components/action-link-arrow--simple-light.png");
|
@@ -144,14 +144,14 @@
|
|
144
144
|
}
|
145
145
|
|
146
146
|
.gem-c-action-link--dark-icon {
|
147
|
-
|
147
|
+
&::before {
|
148
148
|
background: image-url("govuk_publishing_components/action-link-arrow--dark.png");
|
149
149
|
background: image-url("govuk_publishing_components/action-link-arrow--dark.svg"), linear-gradient(transparent, transparent);
|
150
150
|
}
|
151
151
|
}
|
152
152
|
|
153
153
|
.gem-c-action-link--dark-large-icon {
|
154
|
-
|
154
|
+
&::before {
|
155
155
|
background: image-url("govuk_publishing_components/action-link-arrow--dark.png");
|
156
156
|
background: image-url("govuk_publishing_components/action-link-arrow--dark.svg"), linear-gradient(transparent, transparent);
|
157
157
|
height: 34px;
|
@@ -174,7 +174,7 @@
|
|
174
174
|
margin-bottom: govuk-spacing(2);
|
175
175
|
}
|
176
176
|
|
177
|
-
|
177
|
+
&::before {
|
178
178
|
height: 30px;
|
179
179
|
width: 35px;
|
180
180
|
background-repeat: no-repeat;
|
@@ -184,7 +184,7 @@
|
|
184
184
|
}
|
185
185
|
|
186
186
|
.gem-c-action-link--transparent-icon {
|
187
|
-
|
187
|
+
&::before {
|
188
188
|
background-image: image-url("govuk_publishing_components/action-link-arrow--transparent.svg");
|
189
189
|
}
|
190
190
|
}
|
@@ -192,7 +192,7 @@
|
|
192
192
|
.gem-c-action-link--brexit {
|
193
193
|
max-width: none;
|
194
194
|
|
195
|
-
|
195
|
+
&::before {
|
196
196
|
height: 30px;
|
197
197
|
width: 30px;
|
198
198
|
background-image: image-url("govuk_publishing_components/action-link-arrow--brexit.svg");
|
@@ -208,7 +208,7 @@
|
|
208
208
|
@include govuk-media-query($from: tablet) {
|
209
209
|
margin-bottom: govuk-spacing(2);
|
210
210
|
|
211
|
-
|
211
|
+
&::before {
|
212
212
|
width: 35px;
|
213
213
|
background-position: 0 4px;
|
214
214
|
background-size: 25px auto;
|
@@ -217,7 +217,7 @@
|
|
217
217
|
}
|
218
218
|
|
219
219
|
.gem-c-action-link--nhs {
|
220
|
-
|
220
|
+
&::before {
|
221
221
|
width: 80px;
|
222
222
|
height: 70px;
|
223
223
|
background: image-url("govuk_publishing_components/action-link--nhs.png");
|
@@ -232,7 +232,7 @@
|
|
232
232
|
color: govuk-colour("white");
|
233
233
|
|
234
234
|
.gem-c-action-link__subtext {
|
235
|
-
|
235
|
+
&::before {
|
236
236
|
border-color: govuk-colour("white");
|
237
237
|
}
|
238
238
|
}
|
@@ -16,8 +16,9 @@
|
|
16
16
|
@include govuk-font($size: 19, $weight: bold);
|
17
17
|
|
18
18
|
// This pseudo element is to bypass an issue with NVDA where block level elements are dictated separately.
|
19
|
-
// What's happening here is that the label and the number technically have an inline relationship
|
20
|
-
|
19
|
+
// What's happening here is that the label and the number technically have an inline relationship
|
20
|
+
// but appear to have a block relationship thanks to this element
|
21
|
+
&::before {
|
21
22
|
content: "";
|
22
23
|
display: block;
|
23
24
|
}
|