govuk_publishing_components 35.15.5 → 35.16.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/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 +19 -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/govuk_publishing_components/_all_components.scss +1 -0
- data/app/assets/stylesheets/govuk_publishing_components/components/_image-card.scss +26 -0
- data/app/assets/stylesheets/govuk_publishing_components/components/_option-select.scss +172 -0
- 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/docs/image_card.yml +13 -0
- data/app/views/govuk_publishing_components/components/docs/option_select.yml +343 -0
- data/config/locales/ar.yml +4 -0
- data/config/locales/az.yml +4 -0
- data/config/locales/be.yml +4 -0
- data/config/locales/bg.yml +4 -0
- data/config/locales/bn.yml +4 -0
- data/config/locales/cs.yml +4 -0
- data/config/locales/cy.yml +4 -0
- data/config/locales/da.yml +4 -0
- data/config/locales/de.yml +4 -0
- data/config/locales/dr.yml +4 -0
- data/config/locales/el.yml +4 -0
- data/config/locales/en.yml +4 -0
- data/config/locales/es-419.yml +4 -0
- data/config/locales/es.yml +4 -0
- data/config/locales/et.yml +4 -0
- data/config/locales/fa.yml +4 -0
- data/config/locales/fi.yml +4 -0
- data/config/locales/fr.yml +4 -0
- data/config/locales/gd.yml +4 -0
- data/config/locales/gu.yml +4 -0
- data/config/locales/he.yml +4 -0
- data/config/locales/hi.yml +4 -0
- data/config/locales/hr.yml +4 -0
- data/config/locales/hu.yml +4 -0
- data/config/locales/hy.yml +4 -0
- data/config/locales/id.yml +4 -0
- data/config/locales/is.yml +4 -0
- data/config/locales/it.yml +4 -0
- data/config/locales/ja.yml +4 -0
- data/config/locales/ka.yml +4 -0
- data/config/locales/kk.yml +4 -0
- data/config/locales/ko.yml +4 -0
- data/config/locales/lt.yml +4 -0
- data/config/locales/lv.yml +4 -0
- data/config/locales/ms.yml +4 -0
- data/config/locales/mt.yml +4 -0
- data/config/locales/nl.yml +4 -0
- data/config/locales/no.yml +4 -0
- data/config/locales/pa-pk.yml +4 -0
- data/config/locales/pa.yml +4 -0
- data/config/locales/pl.yml +4 -0
- data/config/locales/ps.yml +4 -0
- data/config/locales/pt.yml +4 -0
- data/config/locales/ro.yml +4 -0
- data/config/locales/ru.yml +4 -0
- data/config/locales/si.yml +4 -0
- data/config/locales/sk.yml +4 -0
- data/config/locales/sl.yml +4 -0
- data/config/locales/so.yml +4 -0
- data/config/locales/sq.yml +4 -0
- data/config/locales/sr.yml +4 -0
- data/config/locales/sv.yml +4 -0
- data/config/locales/sw.yml +4 -0
- data/config/locales/ta.yml +4 -0
- data/config/locales/th.yml +4 -0
- data/config/locales/tk.yml +4 -0
- data/config/locales/tr.yml +4 -0
- data/config/locales/uk.yml +4 -0
- data/config/locales/ur.yml +4 -0
- data/config/locales/uz.yml +4 -0
- data/config/locales/vi.yml +4 -0
- data/config/locales/zh-hk.yml +4 -0
- data/config/locales/zh-tw.yml +4 -0
- data/config/locales/zh.yml +4 -0
- data/lib/govuk_publishing_components/presenters/image_card_helper.rb +6 -2
- 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: d631949b7bdb6aa90aff397986118f929cbae4071ef96b3a623c123c6496224d
|
|
4
|
+
data.tar.gz: ef75a103619c27bc964664673a17475579132d0b909e254fce0afcc6316256d9
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: '01786b90a26218b6b5dff054852d4e67a77f36d307029ff6fd03f8b15cd005e9264f8719a03f78f05dc776f284c24c972eb6101940e8afd41a44a696c3b404f5'
|
|
7
|
+
data.tar.gz: 775eb1304962e2349b3e19c8ce7acfb92dc927443a7a01253692909c174f6b5e196129d40104f773794b2ac8e1674e0c65361e605808910f01163b9d69ad5f6a
|
|
@@ -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>
|
|
@@ -59,7 +59,8 @@ window.GOVUK.analyticsGa4.analyticsModules = window.GOVUK.analyticsGa4.analytics
|
|
|
59
59
|
devolved_nations_banner: this.getElementAttribute('data-ga4-devolved-nations-banner') || undefined,
|
|
60
60
|
cookie_banner: document.querySelector('[data-ga4-cookie-banner]') ? 'true' : undefined,
|
|
61
61
|
intervention: this.getInterventionPresence(),
|
|
62
|
-
query_string: this.getQueryString()
|
|
62
|
+
query_string: this.getQueryString(),
|
|
63
|
+
search_term: this.getSearchTerm()
|
|
63
64
|
}
|
|
64
65
|
}
|
|
65
66
|
window.GOVUK.analyticsGa4.core.sendData(data)
|
|
@@ -74,6 +75,23 @@ window.GOVUK.analyticsGa4.analyticsModules = window.GOVUK.analyticsGa4.analytics
|
|
|
74
75
|
return window.location.search
|
|
75
76
|
},
|
|
76
77
|
|
|
78
|
+
getSearchTerm: function () {
|
|
79
|
+
var queryString = this.getSearch()
|
|
80
|
+
|
|
81
|
+
if (!queryString) {
|
|
82
|
+
return undefined
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
var searchTerm = queryString.match(/keywords=([^&]*)/)
|
|
86
|
+
if (!searchTerm) {
|
|
87
|
+
return undefined
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
searchTerm = searchTerm[0].replace('keywords=', '')
|
|
91
|
+
searchTerm = this.PIIRemover.stripPIIWithOverride(searchTerm, true, true)
|
|
92
|
+
return searchTerm
|
|
93
|
+
},
|
|
94
|
+
|
|
77
95
|
getQueryString: function () {
|
|
78
96
|
var queryString = this.getSearch()
|
|
79
97
|
if (queryString) {
|
|
@@ -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.isFacetsContainerHidden = function isFacetsContainerHidden () {
|
|
272
|
+
var facetsContent = this.$optionSelect.parentElement
|
|
273
|
+
var isFacetsContentHidden = 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 (facetsContent) {
|
|
278
|
+
isFacetsContentHidden = !(facetsContent.offsetWidth || facetsContent.offsetHeight || facetsContent.getClientRects().length)
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
return isFacetsContentHidden
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
OptionSelect.prototype.setupHeight = function setupHeight () {
|
|
285
|
+
var initialOptionContainerHeight = this.$optionsContainer.clientHeight
|
|
286
|
+
var height = this.$optionList.offsetHeight
|
|
287
|
+
|
|
288
|
+
var isFacetsContainerHidden = this.isFacetsContainerHidden()
|
|
289
|
+
|
|
290
|
+
if (isFacetsContainerHidden) {
|
|
291
|
+
initialOptionContainerHeight = 200
|
|
292
|
+
height = 200
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
// Resize if the list is only slightly bigger than its container
|
|
296
|
+
// If isFacetsContainerHidden 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)
|
|
@@ -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";
|
|
@@ -41,6 +41,13 @@
|
|
|
41
41
|
}
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
+
@include govuk-media-query($from: tablet) {
|
|
45
|
+
.gem-c-image-card.gem-c-image-card--two-thirds {
|
|
46
|
+
margin: 0 (- govuk-spacing(3)) govuk-spacing(6) (- govuk-spacing(3));
|
|
47
|
+
display: block;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
44
51
|
@include govuk-media-query($from: mobile, $until: tablet) {
|
|
45
52
|
.gem-c-image-card {
|
|
46
53
|
margin: 0 (- govuk-spacing(3)) govuk-spacing(6) (- govuk-spacing(3));
|
|
@@ -53,6 +60,25 @@
|
|
|
53
60
|
.gem-c-image-card__text-wrapper {
|
|
54
61
|
@include govuk-grid-column($width: one-half, $at: mobile);
|
|
55
62
|
}
|
|
63
|
+
|
|
64
|
+
.gem-c-image-card__image-wrapper.gem-c-image-card__image-wrapper--one-third {
|
|
65
|
+
@include govuk-grid-column($width: one-third, $float: right, $at: mobile);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
.gem-c-image-card__text-wrapper.gem-c-image-card__text-wrapper--two-thirds {
|
|
69
|
+
@include govuk-grid-column($width: two-thirds, $float: right, $at: mobile);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
@include govuk-media-query($from: tablet) {
|
|
74
|
+
.gem-c-image-card__image-wrapper.gem-c-image-card__image-wrapper--one-third {
|
|
75
|
+
@include govuk-grid-column($width: one-third, $float: right, $at: tablet);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
.gem-c-image-card__text-wrapper.gem-c-image-card__text-wrapper--two-thirds {
|
|
79
|
+
@include govuk-grid-column($width: two-thirds, $float: right, $at: tablet);
|
|
80
|
+
padding-left: 0;
|
|
81
|
+
}
|
|
56
82
|
}
|
|
57
83
|
|
|
58
84
|
.gem-c-image-card__image {
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
@import "govuk_publishing_components/individual_component_support";
|
|
2
|
+
|
|
3
|
+
.gem-c-option-select {
|
|
4
|
+
position: relative;
|
|
5
|
+
padding: 0 0 govuk-spacing(2);
|
|
6
|
+
margin-bottom: govuk-spacing(2);
|
|
7
|
+
border-bottom: 1px solid $govuk-border-colour;
|
|
8
|
+
|
|
9
|
+
@include govuk-media-query($from: desktop) {
|
|
10
|
+
// Redefine scrollbars on desktop where these lists are scrollable
|
|
11
|
+
// so they are always visible in option lists
|
|
12
|
+
::-webkit-scrollbar {
|
|
13
|
+
-webkit-appearance: none;
|
|
14
|
+
width: 7px;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
::-webkit-scrollbar-thumb {
|
|
18
|
+
border-radius: 4px;
|
|
19
|
+
|
|
20
|
+
background-color: rgba(0, 0, 0, .5);
|
|
21
|
+
-webkit-box-shadow: 0 0 1px rgba(255, 255, 255, .87);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
.gem-c-checkboxes {
|
|
26
|
+
margin: 0;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
.gem-c-option-select__title {
|
|
31
|
+
@include govuk-font(19);
|
|
32
|
+
margin: 0;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
.gem-c-option-select__button {
|
|
36
|
+
z-index: 1;
|
|
37
|
+
background: none;
|
|
38
|
+
border: 0;
|
|
39
|
+
text-align: left;
|
|
40
|
+
padding: 0;
|
|
41
|
+
cursor: pointer;
|
|
42
|
+
color: $govuk-link-colour;
|
|
43
|
+
|
|
44
|
+
&:hover {
|
|
45
|
+
text-decoration: underline;
|
|
46
|
+
text-underline-offset: .1em;
|
|
47
|
+
@include govuk-link-hover-decoration;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
&::-moz-focus-inner {
|
|
51
|
+
border: 0;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
&:focus {
|
|
55
|
+
outline: none;
|
|
56
|
+
text-decoration: none;
|
|
57
|
+
@include govuk-focused-text;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
&[disabled] {
|
|
61
|
+
background-image: none;
|
|
62
|
+
color: inherit;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// Extend the touch area of the button to span the heading
|
|
66
|
+
&:after {
|
|
67
|
+
content: "";
|
|
68
|
+
position: absolute;
|
|
69
|
+
top: 0;
|
|
70
|
+
right: 0;
|
|
71
|
+
bottom: 0;
|
|
72
|
+
left: 0;
|
|
73
|
+
z-index: 2;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
.gem-c-option-select__icon {
|
|
78
|
+
display: none;
|
|
79
|
+
position: absolute;
|
|
80
|
+
top: 0;
|
|
81
|
+
left: 9px;
|
|
82
|
+
width: 30px;
|
|
83
|
+
height: 40px;
|
|
84
|
+
fill: govuk-colour("black");
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
.gem-c-option-select__container {
|
|
88
|
+
position: relative;
|
|
89
|
+
max-height: 200px;
|
|
90
|
+
overflow-y: auto;
|
|
91
|
+
overflow-x: hidden;
|
|
92
|
+
background-color: govuk-colour("white");
|
|
93
|
+
|
|
94
|
+
&:focus {
|
|
95
|
+
outline: 0;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
.gem-c-option-select__container--large {
|
|
100
|
+
max-height: 600px;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
.gem-c-option-select__container-inner {
|
|
104
|
+
padding: govuk-spacing(1) 13px;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
.gem-c-option-select__filter {
|
|
108
|
+
position: relative;
|
|
109
|
+
background: govuk-colour("white");
|
|
110
|
+
padding: 13px 13px govuk-spacing(2) 13px;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
.gem-c-option-select__filter-input {
|
|
114
|
+
@include govuk-font(19);
|
|
115
|
+
background: image-url("option-select/input-icon.svg") govuk-colour("white") no-repeat -5px -3px;
|
|
116
|
+
|
|
117
|
+
@include govuk-media-query($from: tablet) {
|
|
118
|
+
@include govuk-font(16);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
.gem-c-option-select__filter-input.govuk-input {
|
|
123
|
+
padding-left: 33px;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
.js-enabled {
|
|
127
|
+
.gem-c-option-select__heading {
|
|
128
|
+
position: relative;
|
|
129
|
+
padding: 10px 8px 5px 43px;
|
|
130
|
+
margin: 0;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
[aria-expanded="true"] ~ .gem-c-option-select__icon--up {
|
|
134
|
+
display: block;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
[aria-expanded="false"] ~ .gem-c-option-select__icon--down {
|
|
138
|
+
display: block;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
.gem-c-option-select__container {
|
|
142
|
+
height: 200px;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
.gem-c-option-select__container--large {
|
|
146
|
+
height: 600px;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
[data-closed-on-load="true"] .gem-c-option-select__container {
|
|
150
|
+
display: none;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
.gem-c-option-select__selected-counter {
|
|
155
|
+
@include govuk-font($size: 14);
|
|
156
|
+
color: $govuk-text-colour;
|
|
157
|
+
margin-top: 3px;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
.gem-c-option-select.js-closed {
|
|
161
|
+
.gem-c-option-select__filter,
|
|
162
|
+
.gem-c-option-select__container {
|
|
163
|
+
display: none;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
.gem-c-option-select.js-opened {
|
|
168
|
+
.gem-c-option-select__filter,
|
|
169
|
+
.gem-c-option-select__container {
|
|
170
|
+
display: block;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
@@ -7,11 +7,17 @@
|
|
|
7
7
|
brand_helper = GovukPublishingComponents::AppHelpers::BrandHelper.new(brand)
|
|
8
8
|
card_helper = GovukPublishingComponents::Presenters::ImageCardHelper.new(local_assigns, brand_helper)
|
|
9
9
|
shared_helper = GovukPublishingComponents::Presenters::SharedHelper.new(local_assigns)
|
|
10
|
+
|
|
10
11
|
classes = %w[gem-c-image-card]
|
|
12
|
+
classes << "govuk-grid-row" if card_helper.two_thirds
|
|
11
13
|
classes << "gem-c-image-card--large" if card_helper.large
|
|
14
|
+
classes << "gem-c-image-card--two-thirds" if card_helper.two_thirds
|
|
12
15
|
classes << "gem-c-image-card--no-image" unless (card_helper.image_src || card_helper.youtube_video_id)
|
|
13
16
|
classes << brand_helper.brand_class if brand_helper.brand_class
|
|
14
17
|
|
|
18
|
+
text_wrapper_classes = %w[gem-c-image-card__text-wrapper]
|
|
19
|
+
text_wrapper_classes << "gem-c-image-card__text-wrapper--two-thirds" if card_helper.two_thirds
|
|
20
|
+
|
|
15
21
|
font_size ||= card_helper.large ? 'm' : 's'
|
|
16
22
|
heading_class = %w[gem-c-image-card__title]
|
|
17
23
|
heading_class << shared_helper.get_heading_size(font_size, 's')
|
|
@@ -33,7 +39,7 @@
|
|
|
33
39
|
%>
|
|
34
40
|
<% if card_helper.href || card_helper.extra_details.any? %>
|
|
35
41
|
<%= content_tag(:div, class: classes, "data-module": data_modules, lang: card_helper.lang) do %>
|
|
36
|
-
|
|
42
|
+
<%= content_tag(:div, class: text_wrapper_classes) do %>
|
|
37
43
|
<div class="gem-c-image-card__header-and-context-wrapper">
|
|
38
44
|
<% if card_helper.heading_text %>
|
|
39
45
|
<%= content_tag(shared_helper.get_heading_level, class: heading_class) do %>
|
|
@@ -69,7 +75,7 @@
|
|
|
69
75
|
<% if card_helper.metadata %>
|
|
70
76
|
<p class="gem-c-image-card__metadata"><%= card_helper.metadata %></p>
|
|
71
77
|
<% end %>
|
|
72
|
-
|
|
78
|
+
<% end %>
|
|
73
79
|
<%= card_helper.media %>
|
|
74
80
|
<% end %>
|
|
75
81
|
<% end %>
|