dxw_govuk_frontend_rails 3.5.0 → 3.10.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CONTRIBUTING.md +1 -0
- data/Gemfile.lock +3 -2
- data/README.md +45 -42
- data/lib/dxw_govuk_frontend_rails/version.rb +1 -1
- data/package-lock.json +3 -3
- data/package.json +1 -1
- data/vendor/assets/javascripts/govuk_frontend_rails.js +265 -121
- data/vendor/assets/stylesheets/_base.scss +3 -0
- data/vendor/assets/stylesheets/all.scss +1 -3
- data/vendor/assets/stylesheets/components/_all.scss +32 -29
- data/vendor/assets/stylesheets/components/accordion/_accordion.scss +2 -208
- data/vendor/assets/stylesheets/components/accordion/_index.scss +206 -0
- data/vendor/assets/stylesheets/components/back-link/_back-link.scss +2 -65
- data/vendor/assets/stylesheets/components/back-link/_index.scss +110 -0
- data/vendor/assets/stylesheets/components/breadcrumbs/_breadcrumbs.scss +2 -118
- data/vendor/assets/stylesheets/components/breadcrumbs/_index.scss +137 -0
- data/vendor/assets/stylesheets/components/button/_button.scss +2 -284
- data/vendor/assets/stylesheets/components/button/_index.scss +280 -0
- data/vendor/assets/stylesheets/components/character-count/_character-count.scss +2 -31
- data/vendor/assets/stylesheets/components/character-count/_index.scss +24 -0
- data/vendor/assets/stylesheets/components/checkboxes/_checkboxes.scss +2 -308
- data/vendor/assets/stylesheets/components/checkboxes/_index.scss +305 -0
- data/vendor/assets/stylesheets/components/date-input/_date-input.scss +2 -30
- data/vendor/assets/stylesheets/components/date-input/_index.scss +26 -0
- data/vendor/assets/stylesheets/components/details/_details.scss +2 -88
- data/vendor/assets/stylesheets/components/details/_index.scss +83 -0
- data/vendor/assets/stylesheets/components/error-message/_error-message.scss +2 -15
- data/vendor/assets/stylesheets/components/error-message/_index.scss +11 -0
- data/vendor/assets/stylesheets/components/error-summary/_error-summary.scss +2 -59
- data/vendor/assets/stylesheets/components/error-summary/_index.scss +43 -0
- data/vendor/assets/stylesheets/components/fieldset/_fieldset.scss +2 -68
- data/vendor/assets/stylesheets/components/fieldset/_index.scss +64 -0
- data/vendor/assets/stylesheets/components/file-upload/_file-upload.scss +2 -81
- data/vendor/assets/stylesheets/components/file-upload/_index.scss +50 -0
- data/vendor/assets/stylesheets/components/footer/_footer.scss +2 -244
- data/vendor/assets/stylesheets/components/footer/_index.scss +234 -0
- data/vendor/assets/stylesheets/components/header/_header.scss +2 -318
- data/vendor/assets/stylesheets/components/header/_index.scss +309 -0
- data/vendor/assets/stylesheets/components/hint/_hint.scss +2 -50
- data/vendor/assets/stylesheets/components/hint/_index.scss +44 -0
- data/vendor/assets/stylesheets/components/input/_index.scss +187 -0
- data/vendor/assets/stylesheets/components/input/_input.scss +2 -103
- data/vendor/assets/stylesheets/components/inset-text/_index.scss +24 -0
- data/vendor/assets/stylesheets/components/inset-text/_inset-text.scss +2 -28
- data/vendor/assets/stylesheets/components/label/_index.scss +41 -0
- data/vendor/assets/stylesheets/components/label/_label.scss +2 -45
- data/vendor/assets/stylesheets/components/notification-banner/_index.scss +89 -0
- data/vendor/assets/stylesheets/components/notification-banner/_notification-banner.scss +2 -0
- data/vendor/assets/stylesheets/components/panel/_index.scss +44 -0
- data/vendor/assets/stylesheets/components/panel/_panel.scss +2 -44
- data/vendor/assets/stylesheets/components/phase-banner/_index.scss +27 -0
- data/vendor/assets/stylesheets/components/phase-banner/_phase-banner.scss +2 -31
- data/vendor/assets/stylesheets/components/radios/_index.scss +342 -0
- data/vendor/assets/stylesheets/components/radios/_radios.scss +2 -346
- data/vendor/assets/stylesheets/components/select/_index.scss +49 -0
- data/vendor/assets/stylesheets/components/select/_select.scss +2 -57
- data/vendor/assets/stylesheets/components/skip-link/_index.scss +34 -0
- data/vendor/assets/stylesheets/components/skip-link/_skip-link.scss +2 -37
- data/vendor/assets/stylesheets/components/summary-list/_index.scss +145 -0
- data/vendor/assets/stylesheets/components/summary-list/_summary-list.scss +2 -157
- data/vendor/assets/stylesheets/components/table/_index.scss +50 -0
- data/vendor/assets/stylesheets/components/table/_table.scss +2 -54
- data/vendor/assets/stylesheets/components/tabs/_index.scss +135 -0
- data/vendor/assets/stylesheets/components/tabs/_tabs.scss +2 -142
- data/vendor/assets/stylesheets/components/tag/_index.scss +86 -0
- data/vendor/assets/stylesheets/components/tag/_tag.scss +2 -44
- data/vendor/assets/stylesheets/components/textarea/_index.scss +47 -0
- data/vendor/assets/stylesheets/components/textarea/_textarea.scss +2 -55
- data/vendor/assets/stylesheets/components/warning-text/_index.scss +57 -0
- data/vendor/assets/stylesheets/components/warning-text/_warning-text.scss +2 -60
- data/vendor/assets/stylesheets/core/_global-styles.scss +5 -3
- data/vendor/assets/stylesheets/core/_links.scss +5 -3
- data/vendor/assets/stylesheets/core/_lists.scss +17 -3
- data/vendor/assets/stylesheets/core/_section-break.scss +5 -3
- data/vendor/assets/stylesheets/core/_template.scss +5 -3
- data/vendor/assets/stylesheets/core/_typography.scss +5 -3
- data/vendor/assets/stylesheets/helpers/_clearfix.scss +1 -1
- data/vendor/assets/stylesheets/helpers/_colour.scss +1 -1
- data/vendor/assets/stylesheets/helpers/_device-pixels.scss +3 -3
- data/vendor/assets/stylesheets/helpers/_focused.scss +1 -1
- data/vendor/assets/stylesheets/helpers/_font-faces.scss +9 -11
- data/vendor/assets/stylesheets/helpers/_grid.scss +2 -1
- data/vendor/assets/stylesheets/helpers/_links.scss +96 -4
- data/vendor/assets/stylesheets/helpers/_media-queries.scss +2 -6
- data/vendor/assets/stylesheets/helpers/_shape-arrow.scss +1 -1
- data/vendor/assets/stylesheets/helpers/_spacing.scss +7 -6
- data/vendor/assets/stylesheets/helpers/_typography.scss +13 -12
- data/vendor/assets/stylesheets/helpers/_visually-hidden.scss +30 -30
- data/vendor/assets/stylesheets/objects/_form-group.scss +1 -4
- data/vendor/assets/stylesheets/objects/_grid.scss +3 -6
- data/vendor/assets/stylesheets/objects/_main-wrapper.scss +5 -4
- data/vendor/assets/stylesheets/objects/_width-container.scss +2 -4
- data/vendor/assets/stylesheets/overrides/_display.scss +12 -4
- data/vendor/assets/stylesheets/overrides/_spacing.scss +5 -3
- data/vendor/assets/stylesheets/overrides/_typography.scss +5 -3
- data/vendor/assets/stylesheets/overrides/_width.scss +6 -3
- data/vendor/assets/stylesheets/settings/_colours-applied.scss +11 -5
- data/vendor/assets/stylesheets/settings/_colours-organisations.scss +3 -0
- data/vendor/assets/stylesheets/settings/_colours-palette.scss +42 -35
- data/vendor/assets/stylesheets/settings/_compatibility.scss +0 -1
- data/vendor/assets/stylesheets/settings/_ie8.scss +1 -1
- data/vendor/assets/stylesheets/settings/_measurements.scss +4 -5
- data/vendor/assets/stylesheets/settings/_typography-font-families.scss +2 -2
- data/vendor/assets/stylesheets/settings/_typography-font.scss +14 -5
- data/vendor/assets/stylesheets/settings/_typography-responsive.scss +6 -2
- data/vendor/assets/stylesheets/tools/_compatibility.scss +1 -1
- data/vendor/assets/stylesheets/tools/_font-url.scss +1 -4
- data/vendor/assets/stylesheets/tools/_ie8.scss +1 -1
- data/vendor/assets/stylesheets/tools/_iff.scss +3 -1
- data/vendor/assets/stylesheets/tools/_image-url.scss +1 -4
- data/vendor/assets/stylesheets/tools/_px-to-em.scss +1 -1
- data/vendor/assets/stylesheets/tools/_px-to-rem.scss +1 -1
- data/vendor/assets/stylesheets/utilities/_visually-hidden.scss +0 -1
- data/vendor/assets/stylesheets/vendor/_sass-mq.scss +0 -4
- metadata +36 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b45f829ef6c112b8acdc675c702ea6c5b2ed784f67afd8c46fb5fd1ab9e6515f
|
4
|
+
data.tar.gz: cac2861100bd6e495f63cbf61792428d6dd86260ba6ac8a6499d7d4ddd7efcc8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2bbc39c25ed2bb297c569524f56b4dd998d4363b27f6a861ffd888c2dd5babcb07f9722d72cc7c54c9604522591a8ac2eefed5527137bd11833ea00bcf8777b7
|
7
|
+
data.tar.gz: 38df5dbcd807f25710609517b7aa8458824b09b0b7e33c04713adb18e9d3613fad3f63574ff2d450f32fbb8d51b8e950f767b3ce4ad3cd983e7026b4b5f2cf22
|
data/CONTRIBUTING.md
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
The [dxw standard contributing guide](https://github.com/dxw/.github/blob/main/CONTRIBUTING.md) applies for this repository.
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
dxw_govuk_frontend_rails (3.
|
4
|
+
dxw_govuk_frontend_rails (3.10.2)
|
5
5
|
|
6
6
|
GEM
|
7
7
|
remote: https://rubygems.org/
|
@@ -10,6 +10,7 @@ GEM
|
|
10
10
|
|
11
11
|
PLATFORMS
|
12
12
|
ruby
|
13
|
+
x86_64-darwin-19
|
13
14
|
|
14
15
|
DEPENDENCIES
|
15
16
|
bundler (~> 2.0)
|
@@ -17,4 +18,4 @@ DEPENDENCIES
|
|
17
18
|
rake (~> 13.0)
|
18
19
|
|
19
20
|
BUNDLED WITH
|
20
|
-
2.
|
21
|
+
2.2.1
|
data/README.md
CHANGED
@@ -1,88 +1,91 @@
|
|
1
1
|
# GOVUK Frontend for Rails
|
2
2
|
|
3
|
-
|
3
|
+
## Read this first
|
4
|
+
|
5
|
+
Although this gem makes it super easy to add the GOVUK Frontend to your
|
6
|
+
Rails applications, we would recommend using it as a guide to add the
|
7
|
+
GOVUK Frontend yourself.
|
8
|
+
|
9
|
+
## About Adds the GOVUK Frontend for Rails using the asset pipeline.
|
4
10
|
|
5
11
|
https://github.com/alphagov/govuk-frontend
|
6
12
|
|
7
13
|
## Breaking Changes in v3.0.0
|
8
14
|
|
9
|
-
This release of the GOVUK Frontend has breaking changes! Do not update to this
|
15
|
+
This release of the GOVUK Frontend has breaking changes! Do not update to this
|
16
|
+
version until you have read and understood:
|
10
17
|
|
11
|
-
You will not be required to updated any file paths with govuk as we take care of
|
18
|
+
You will not be required to updated any file paths with govuk as we take care of
|
19
|
+
that for you, all others changes will need to be managed:
|
12
20
|
|
13
21
|
https://github.com/alphagov/govuk-frontend/releases/tag/v3.0.0
|
14
22
|
|
15
23
|
## Limitations
|
16
24
|
|
17
|
-
This gem does not include the ie8 version of GOVUK Frontend, as the service
|
25
|
+
This gem does not include the ie8 version of GOVUK Frontend, as the service
|
26
|
+
standard no longer requires it:
|
18
27
|
|
19
28
|
https://www.gov.uk/service-manual/technology/designing-for-different-browsers-and-devices
|
20
29
|
|
21
|
-
This gem and its documentation cannot tell you how to use the GOVUK effectively,
|
30
|
+
This gem and its documentation cannot tell you how to use the GOVUK effectively,
|
31
|
+
see the GOVUK Design System documentation for that:
|
22
32
|
|
23
|
-
https://design-system.service.gov.uk/
|
24
|
-
## Installation
|
33
|
+
https://design-system.service.gov.uk/ ## Installation
|
25
34
|
|
26
35
|
Add this line to your application's Gemfile:
|
27
36
|
|
28
|
-
```ruby
|
29
|
-
gem 'dxw_govuk_frontend_rails'
|
30
|
-
```
|
37
|
+
```ruby gem 'dxw_govuk_frontend_rails' ```
|
31
38
|
|
32
39
|
And then execute:
|
33
40
|
|
34
41
|
$ bundle
|
35
42
|
|
36
|
-
## Usage
|
37
|
-
Your Rails app will need to have sass enabled.
|
43
|
+
## Usage Your Rails app will need to have sass enabled.
|
38
44
|
|
39
45
|
### Basic usage
|
40
46
|
|
41
|
-
If the service you are building does not need to modify or extend the GOVUK
|
47
|
+
If the service you are building does not need to modify or extend the GOVUK
|
48
|
+
Frontend all you need to do is import the main sass and javascript files into
|
49
|
+
your Rails app:
|
42
50
|
|
43
|
-
- create a sass file in your application:
|
44
|
-
```
|
45
|
-
|
46
|
-
```
|
47
|
-
-
|
48
|
-
|
49
|
-
@import "govuk-frontend-rails";
|
50
|
-
```
|
51
|
-
- require the `govuk-frontend-rails.scss` file in `application.css` or equivalent:
|
51
|
+
- create a sass file in your application: ```
|
52
|
+
app/assets/stylesheets/govuk_frontend_rails.scss ```
|
53
|
+
- import the styles into `govuk_frontend_rails.scss`: ```sass @import
|
54
|
+
"govuk-frontend-rails"; ```
|
55
|
+
- require the `govuk-frontend-rails.scss` file in `application.css` or
|
56
|
+
equivalent:
|
52
57
|
|
53
|
-
```
|
54
|
-
*= require govuk_frontend_rails
|
55
|
-
```
|
58
|
+
``` *= require govuk_frontend_rails ```
|
56
59
|
|
57
60
|
- require the javascript into `app/assets/javascripts/application.js`:
|
58
61
|
|
59
|
-
```
|
60
|
-
|
61
|
-
|
62
|
-
- initialise the GOVUK Frontend either in a .js file on in your application layout:
|
62
|
+
``` //= require govuk_frontend_rails ```
|
63
|
+
- initialise the GOVUK Frontend either in a .js file on in your application
|
64
|
+
layout:
|
63
65
|
|
64
|
-
```javascript
|
65
|
-
window.onload = function() {
|
66
|
-
window.GOVUKFrontend.initAll()
|
67
|
-
};
|
68
|
-
```
|
66
|
+
```javascript window.onload = function() { window.GOVUKFrontend.initAll() }; ```
|
69
67
|
- update your application markup to use the GOVUK Frontend class names
|
70
68
|
|
71
|
-
IMPORTANT: You cannot use the GOVUK Frontend without changes if the service you
|
69
|
+
IMPORTANT: You cannot use the GOVUK Frontend without changes if the service you
|
70
|
+
are building is not on GOV.UK, read and understand the guidance here:
|
72
71
|
|
73
72
|
https://www.gov.uk/service-manual/design/making-your-service-look-like-govuk#if-your-service-isnt-on-govuk
|
74
73
|
|
75
|
-
## Tracking version
|
76
|
-
We aim to tracking the version of GOVUK Frontend.
|
74
|
+
## Tracking version We aim to tracking the version of GOVUK Frontend.
|
77
75
|
|
78
76
|
## Updating to a new Version of GOVUK Frontend
|
79
77
|
|
80
78
|
When a new version of the GOVUK Frontend is released:
|
81
79
|
|
82
|
-
-
|
83
|
-
-
|
84
|
-
|
80
|
+
- make a new branch with the GOVUK Frontend version number
|
81
|
+
- set the new version number in `package.json` and
|
82
|
+
`lib/dxw_govuk_frontend_rails/version.rb`
|
83
|
+
- run `npm update` to get the new release of the GOVUK Frontend
|
84
|
+
- run `bundle exec rake` to compile the new assets
|
85
85
|
- commit the changes
|
86
86
|
- tag with the same release number as GOVUK Frontend
|
87
|
-
- push the
|
88
|
-
-
|
87
|
+
- push the change
|
88
|
+
- push the tag
|
89
|
+
- merge your branch
|
90
|
+
- make a new release of the tag on GitHub
|
91
|
+
- GitHub acitons will build the gem and push to Rubygems
|
data/package-lock.json
CHANGED
@@ -5,9 +5,9 @@
|
|
5
5
|
"requires": true,
|
6
6
|
"dependencies": {
|
7
7
|
"govuk-frontend": {
|
8
|
-
"version": "3.
|
9
|
-
"resolved": "https://registry.npmjs.org/govuk-frontend/-/govuk-frontend-3.
|
10
|
-
"integrity": "sha512-
|
8
|
+
"version": "3.10.2",
|
9
|
+
"resolved": "https://registry.npmjs.org/govuk-frontend/-/govuk-frontend-3.10.2.tgz",
|
10
|
+
"integrity": "sha512-MpMymgLsKoMw40MggZ0XLCAj1FY5N2s8Pf3aQR+k0cZOsegjLsnejxNfEB9qEl9jcma2fiiVcvsEZ+Ipo+Oo2g=="
|
11
11
|
}
|
12
12
|
}
|
13
13
|
}
|
data/package.json
CHANGED
@@ -891,7 +891,7 @@ Accordion.prototype.initHeaderAttributes = function ($headerWrapper, index) {
|
|
891
891
|
icon.className = this.iconClass;
|
892
892
|
icon.setAttribute('aria-hidden', 'true');
|
893
893
|
|
894
|
-
$
|
894
|
+
$button.appendChild(icon);
|
895
895
|
};
|
896
896
|
|
897
897
|
// When section toggled, set and store state
|
@@ -1542,13 +1542,22 @@ CharacterCount.prototype.init = function () {
|
|
1542
1542
|
// Remove hard limit if set
|
1543
1543
|
$module.removeAttribute('maxlength');
|
1544
1544
|
|
1545
|
-
//
|
1546
|
-
|
1547
|
-
|
1545
|
+
// When the page is restored after navigating 'back' in some browsers the
|
1546
|
+
// state of the character count is not restored until *after* the DOMContentLoaded
|
1547
|
+
// event is fired, so we need to sync after the pageshow event in browsers
|
1548
|
+
// that support it.
|
1549
|
+
if ('onpageshow' in window) {
|
1550
|
+
window.addEventListener('pageshow', this.sync.bind(this));
|
1551
|
+
} else {
|
1552
|
+
window.addEventListener('DOMContentLoaded', this.sync.bind(this));
|
1553
|
+
}
|
1554
|
+
|
1555
|
+
this.sync();
|
1556
|
+
};
|
1548
1557
|
|
1549
|
-
|
1550
|
-
|
1551
|
-
|
1558
|
+
CharacterCount.prototype.sync = function () {
|
1559
|
+
this.bindChangeEvents();
|
1560
|
+
this.updateCountMessage();
|
1552
1561
|
};
|
1553
1562
|
|
1554
1563
|
// Read data attributes
|
@@ -1596,8 +1605,7 @@ CharacterCount.prototype.checkIfValueChanged = function () {
|
|
1596
1605
|
if (!this.$textarea.oldValue) this.$textarea.oldValue = '';
|
1597
1606
|
if (this.$textarea.value !== this.$textarea.oldValue) {
|
1598
1607
|
this.$textarea.oldValue = this.$textarea.value;
|
1599
|
-
|
1600
|
-
boundUpdateCountMessage();
|
1608
|
+
this.updateCountMessage();
|
1601
1609
|
}
|
1602
1610
|
};
|
1603
1611
|
|
@@ -1666,44 +1674,91 @@ function Checkboxes ($module) {
|
|
1666
1674
|
this.$inputs = $module.querySelectorAll('input[type="checkbox"]');
|
1667
1675
|
}
|
1668
1676
|
|
1677
|
+
/**
|
1678
|
+
* Initialise Checkboxes
|
1679
|
+
*
|
1680
|
+
* Checkboxes can be associated with a 'conditionally revealed' content block –
|
1681
|
+
* for example, a checkbox for 'Phone' could reveal an additional form field for
|
1682
|
+
* the user to enter their phone number.
|
1683
|
+
*
|
1684
|
+
* These associations are made using a `data-aria-controls` attribute, which is
|
1685
|
+
* promoted to an aria-controls attribute during initialisation.
|
1686
|
+
*
|
1687
|
+
* We also need to restore the state of any conditional reveals on the page (for
|
1688
|
+
* example if the user has navigated back), and set up event handlers to keep
|
1689
|
+
* the reveal in sync with the checkbox state.
|
1690
|
+
*/
|
1669
1691
|
Checkboxes.prototype.init = function () {
|
1670
1692
|
var $module = this.$module;
|
1671
1693
|
var $inputs = this.$inputs;
|
1672
1694
|
|
1673
|
-
/**
|
1674
|
-
* Loop over all items with [data-controls]
|
1675
|
-
* Check if they have a matching conditional reveal
|
1676
|
-
* If they do, assign attributes.
|
1677
|
-
**/
|
1678
1695
|
nodeListForEach($inputs, function ($input) {
|
1679
|
-
var
|
1696
|
+
var target = $input.getAttribute('data-aria-controls');
|
1680
1697
|
|
1681
|
-
//
|
1682
|
-
//
|
1683
|
-
if (!
|
1698
|
+
// Skip checkboxes without data-aria-controls attributes, or where the
|
1699
|
+
// target element does not exist.
|
1700
|
+
if (!target || !$module.querySelector('#' + target)) {
|
1684
1701
|
return
|
1685
1702
|
}
|
1686
1703
|
|
1687
|
-
//
|
1688
|
-
|
1704
|
+
// Promote the data-aria-controls attribute to a aria-controls attribute
|
1705
|
+
// so that the relationship is exposed in the AOM
|
1706
|
+
$input.setAttribute('aria-controls', target);
|
1689
1707
|
$input.removeAttribute('data-aria-controls');
|
1690
|
-
|
1691
|
-
|
1708
|
+
});
|
1709
|
+
|
1710
|
+
// When the page is restored after navigating 'back' in some browsers the
|
1711
|
+
// state of form controls is not restored until *after* the DOMContentLoaded
|
1712
|
+
// event is fired, so we need to sync after the pageshow event in browsers
|
1713
|
+
// that support it.
|
1714
|
+
if ('onpageshow' in window) {
|
1715
|
+
window.addEventListener('pageshow', this.syncAllConditionalReveals.bind(this));
|
1716
|
+
} else {
|
1717
|
+
window.addEventListener('DOMContentLoaded', this.syncAllConditionalReveals.bind(this));
|
1718
|
+
}
|
1719
|
+
|
1720
|
+
// Although we've set up handlers to sync state on the pageshow or
|
1721
|
+
// DOMContentLoaded event, init could be called after those events have fired,
|
1722
|
+
// for example if they are added to the page dynamically, so sync now too.
|
1723
|
+
this.syncAllConditionalReveals();
|
1692
1724
|
|
1693
|
-
// Handle events
|
1694
1725
|
$module.addEventListener('click', this.handleClick.bind(this));
|
1695
1726
|
};
|
1696
1727
|
|
1697
|
-
|
1698
|
-
|
1699
|
-
|
1728
|
+
/**
|
1729
|
+
* Sync the conditional reveal states for all inputs in this $module.
|
1730
|
+
*/
|
1731
|
+
Checkboxes.prototype.syncAllConditionalReveals = function () {
|
1732
|
+
nodeListForEach(this.$inputs, this.syncConditionalRevealWithInputState.bind(this));
|
1733
|
+
};
|
1734
|
+
|
1735
|
+
/**
|
1736
|
+
* Sync conditional reveal with the input state
|
1737
|
+
*
|
1738
|
+
* Synchronise the visibility of the conditional reveal, and its accessible
|
1739
|
+
* state, with the input's checked state.
|
1740
|
+
*
|
1741
|
+
* @param {HTMLInputElement} $input Checkbox input
|
1742
|
+
*/
|
1743
|
+
Checkboxes.prototype.syncConditionalRevealWithInputState = function ($input) {
|
1744
|
+
var $target = this.$module.querySelector('#' + $input.getAttribute('aria-controls'));
|
1700
1745
|
|
1701
|
-
|
1702
|
-
|
1703
|
-
|
1746
|
+
if ($target && $target.classList.contains('govuk-checkboxes__conditional')) {
|
1747
|
+
var inputIsChecked = $input.checked;
|
1748
|
+
|
1749
|
+
$input.setAttribute('aria-expanded', inputIsChecked);
|
1750
|
+
$target.classList.toggle('govuk-checkboxes__conditional--hidden', !inputIsChecked);
|
1704
1751
|
}
|
1705
1752
|
};
|
1706
1753
|
|
1754
|
+
/**
|
1755
|
+
* Click event handler
|
1756
|
+
*
|
1757
|
+
* Handle a click within the $module – if the click occurred on a checkbox, sync
|
1758
|
+
* the state of any associated conditional reveal with the checkbox state.
|
1759
|
+
*
|
1760
|
+
* @param {MouseEvent} event Click event
|
1761
|
+
*/
|
1707
1762
|
Checkboxes.prototype.handleClick = function (event) {
|
1708
1763
|
var $target = event.target;
|
1709
1764
|
|
@@ -1711,7 +1766,7 @@ Checkboxes.prototype.handleClick = function (event) {
|
|
1711
1766
|
var isCheckbox = $target.getAttribute('type') === 'checkbox';
|
1712
1767
|
var hasAriaControls = $target.getAttribute('aria-controls');
|
1713
1768
|
if (isCheckbox && hasAriaControls) {
|
1714
|
-
this.
|
1769
|
+
this.syncConditionalRevealWithInputState($target);
|
1715
1770
|
}
|
1716
1771
|
};
|
1717
1772
|
|
@@ -1748,7 +1803,7 @@ Checkboxes.prototype.handleClick = function (event) {
|
|
1748
1803
|
|
1749
1804
|
if (detect) return
|
1750
1805
|
|
1751
|
-
|
1806
|
+
// Polyfill from https://raw.githubusercontent.com/Financial-Times/polyfill-service/1f3c09b402f65bf6e393f933a15ba63f1b86ef1f/packages/polyfill-library/polyfills/Element/prototype/closest/polyfill.js
|
1752
1807
|
Element.prototype.closest = function closest(selector) {
|
1753
1808
|
var node = this;
|
1754
1809
|
|
@@ -1904,173 +1959,257 @@ ErrorSummary.prototype.getAssociatedLegendOrLabel = function ($input) {
|
|
1904
1959
|
$input.closest('label')
|
1905
1960
|
};
|
1906
1961
|
|
1907
|
-
function
|
1962
|
+
function NotificationBanner ($module) {
|
1908
1963
|
this.$module = $module;
|
1909
1964
|
}
|
1910
1965
|
|
1911
|
-
|
1912
|
-
|
1966
|
+
/**
|
1967
|
+
* Initialise the component
|
1968
|
+
*/
|
1969
|
+
NotificationBanner.prototype.init = function () {
|
1913
1970
|
var $module = this.$module;
|
1971
|
+
// Check for module
|
1914
1972
|
if (!$module) {
|
1915
1973
|
return
|
1916
1974
|
}
|
1917
1975
|
|
1918
|
-
|
1919
|
-
|
1920
|
-
|
1976
|
+
this.setFocus();
|
1977
|
+
};
|
1978
|
+
|
1979
|
+
/**
|
1980
|
+
* Focus the element
|
1981
|
+
*
|
1982
|
+
* If `role="alert"` is set, focus the element to help some assistive technologies
|
1983
|
+
* prioritise announcing it.
|
1984
|
+
*
|
1985
|
+
* You can turn off the auto-focus functionality by setting `data-disable-auto-focus="true"` in the
|
1986
|
+
* component HTML. You might wish to do this based on user research findings, or to avoid a clash
|
1987
|
+
* with another element which should be focused when the page loads.
|
1988
|
+
*/
|
1989
|
+
NotificationBanner.prototype.setFocus = function () {
|
1990
|
+
var $module = this.$module;
|
1991
|
+
|
1992
|
+
if ($module.getAttribute('data-disable-auto-focus') === 'true') {
|
1993
|
+
return
|
1994
|
+
}
|
1995
|
+
|
1996
|
+
if ($module.getAttribute('role') !== 'alert') {
|
1921
1997
|
return
|
1922
1998
|
}
|
1923
1999
|
|
1924
|
-
//
|
1925
|
-
|
2000
|
+
// Set tabindex to -1 to make the element focusable with JavaScript.
|
2001
|
+
// Remove the tabindex on blur as the component doesn't need to be focusable after the page has
|
2002
|
+
// loaded.
|
2003
|
+
if (!$module.getAttribute('tabindex')) {
|
2004
|
+
$module.setAttribute('tabindex', '-1');
|
2005
|
+
|
2006
|
+
$module.addEventListener('blur', function () {
|
2007
|
+
$module.removeAttribute('tabindex');
|
2008
|
+
});
|
2009
|
+
}
|
2010
|
+
|
2011
|
+
$module.focus();
|
1926
2012
|
};
|
1927
2013
|
|
2014
|
+
function Header ($module) {
|
2015
|
+
this.$module = $module;
|
2016
|
+
this.$menuButton = $module && $module.querySelector('.govuk-js-header-toggle');
|
2017
|
+
this.$menu = this.$menuButton && $module.querySelector(
|
2018
|
+
'#' + this.$menuButton.getAttribute('aria-controls')
|
2019
|
+
);
|
2020
|
+
}
|
2021
|
+
|
1928
2022
|
/**
|
1929
|
-
*
|
1930
|
-
*
|
1931
|
-
*
|
1932
|
-
|
1933
|
-
|
1934
|
-
|
1935
|
-
|
1936
|
-
|
1937
|
-
node.className += ' ' + className;
|
2023
|
+
* Initialise header
|
2024
|
+
*
|
2025
|
+
* Check for the presence of the header, menu and menu button – if any are
|
2026
|
+
* missing then there's nothing to do so return early.
|
2027
|
+
*/
|
2028
|
+
Header.prototype.init = function () {
|
2029
|
+
if (!this.$module || !this.$menuButton || !this.$menu) {
|
2030
|
+
return
|
1938
2031
|
}
|
2032
|
+
|
2033
|
+
this.syncState(this.$menu.classList.contains('govuk-header__navigation--open'));
|
2034
|
+
this.$menuButton.addEventListener('click', this.handleMenuButtonClick.bind(this));
|
1939
2035
|
};
|
1940
2036
|
|
1941
2037
|
/**
|
1942
|
-
*
|
1943
|
-
*
|
1944
|
-
|
1945
|
-
|
1946
|
-
|
1947
|
-
|
1948
|
-
|
1949
|
-
|
1950
|
-
|
1951
|
-
|
1952
|
-
|
1953
|
-
this.toggleClass($toggleButton, 'govuk-header__menu-button--open');
|
2038
|
+
* Sync menu state
|
2039
|
+
*
|
2040
|
+
* Sync the menu button class and the accessible state of the menu and the menu
|
2041
|
+
* button with the visible state of the menu
|
2042
|
+
*
|
2043
|
+
* @param {boolean} isVisible Whether the menu is currently visible
|
2044
|
+
*/
|
2045
|
+
Header.prototype.syncState = function (isVisible) {
|
2046
|
+
this.$menuButton.classList.toggle('govuk-header__menu-button--open', isVisible);
|
2047
|
+
this.$menuButton.setAttribute('aria-expanded', isVisible);
|
2048
|
+
};
|
1954
2049
|
|
1955
|
-
|
1956
|
-
|
1957
|
-
|
2050
|
+
/**
|
2051
|
+
* Handle menu button click
|
2052
|
+
*
|
2053
|
+
* When the menu button is clicked, change the visibility of the menu and then
|
2054
|
+
* sync the accessibility state and menu button state
|
2055
|
+
*/
|
2056
|
+
Header.prototype.handleMenuButtonClick = function () {
|
2057
|
+
var isVisible = this.$menu.classList.toggle('govuk-header__navigation--open');
|
2058
|
+
this.syncState(isVisible);
|
1958
2059
|
};
|
1959
2060
|
|
1960
2061
|
function Radios ($module) {
|
1961
2062
|
this.$module = $module;
|
2063
|
+
this.$inputs = $module.querySelectorAll('input[type="radio"]');
|
1962
2064
|
}
|
1963
2065
|
|
2066
|
+
/**
|
2067
|
+
* Initialise Radios
|
2068
|
+
*
|
2069
|
+
* Radios can be associated with a 'conditionally revealed' content block – for
|
2070
|
+
* example, a radio for 'Phone' could reveal an additional form field for the
|
2071
|
+
* user to enter their phone number.
|
2072
|
+
*
|
2073
|
+
* These associations are made using a `data-aria-controls` attribute, which is
|
2074
|
+
* promoted to an aria-controls attribute during initialisation.
|
2075
|
+
*
|
2076
|
+
* We also need to restore the state of any conditional reveals on the page (for
|
2077
|
+
* example if the user has navigated back), and set up event handlers to keep
|
2078
|
+
* the reveal in sync with the radio state.
|
2079
|
+
*/
|
1964
2080
|
Radios.prototype.init = function () {
|
1965
2081
|
var $module = this.$module;
|
1966
|
-
var $inputs =
|
2082
|
+
var $inputs = this.$inputs;
|
1967
2083
|
|
1968
|
-
/**
|
1969
|
-
* Loop over all items with [data-controls]
|
1970
|
-
* Check if they have a matching conditional reveal
|
1971
|
-
* If they do, assign attributes.
|
1972
|
-
**/
|
1973
2084
|
nodeListForEach($inputs, function ($input) {
|
1974
|
-
var
|
2085
|
+
var target = $input.getAttribute('data-aria-controls');
|
1975
2086
|
|
1976
|
-
//
|
1977
|
-
//
|
1978
|
-
if (!
|
2087
|
+
// Skip radios without data-aria-controls attributes, or where the
|
2088
|
+
// target element does not exist.
|
2089
|
+
if (!target || !$module.querySelector('#' + target)) {
|
1979
2090
|
return
|
1980
2091
|
}
|
1981
2092
|
|
1982
|
-
//
|
1983
|
-
|
2093
|
+
// Promote the data-aria-controls attribute to a aria-controls attribute
|
2094
|
+
// so that the relationship is exposed in the AOM
|
2095
|
+
$input.setAttribute('aria-controls', target);
|
1984
2096
|
$input.removeAttribute('data-aria-controls');
|
1985
|
-
|
1986
|
-
|
2097
|
+
});
|
2098
|
+
|
2099
|
+
// When the page is restored after navigating 'back' in some browsers the
|
2100
|
+
// state of form controls is not restored until *after* the DOMContentLoaded
|
2101
|
+
// event is fired, so we need to sync after the pageshow event in browsers
|
2102
|
+
// that support it.
|
2103
|
+
if ('onpageshow' in window) {
|
2104
|
+
window.addEventListener('pageshow', this.syncAllConditionalReveals.bind(this));
|
2105
|
+
} else {
|
2106
|
+
window.addEventListener('DOMContentLoaded', this.syncAllConditionalReveals.bind(this));
|
2107
|
+
}
|
2108
|
+
|
2109
|
+
// Although we've set up handlers to sync state on the pageshow or
|
2110
|
+
// DOMContentLoaded event, init could be called after those events have fired,
|
2111
|
+
// for example if they are added to the page dynamically, so sync now too.
|
2112
|
+
this.syncAllConditionalReveals();
|
1987
2113
|
|
1988
2114
|
// Handle events
|
1989
2115
|
$module.addEventListener('click', this.handleClick.bind(this));
|
1990
2116
|
};
|
1991
2117
|
|
1992
|
-
|
1993
|
-
|
2118
|
+
/**
|
2119
|
+
* Sync the conditional reveal states for all inputs in this $module.
|
2120
|
+
*/
|
2121
|
+
Radios.prototype.syncAllConditionalReveals = function () {
|
2122
|
+
nodeListForEach(this.$inputs, this.syncConditionalRevealWithInputState.bind(this));
|
2123
|
+
};
|
1994
2124
|
|
1995
|
-
|
2125
|
+
/**
|
2126
|
+
* Sync conditional reveal with the input state
|
2127
|
+
*
|
2128
|
+
* Synchronise the visibility of the conditional reveal, and its accessible
|
2129
|
+
* state, with the input's checked state.
|
2130
|
+
*
|
2131
|
+
* @param {HTMLInputElement} $input Radio input
|
2132
|
+
*/
|
2133
|
+
Radios.prototype.syncConditionalRevealWithInputState = function ($input) {
|
2134
|
+
var $target = document.querySelector('#' + $input.getAttribute('aria-controls'));
|
2135
|
+
|
2136
|
+
if ($target && $target.classList.contains('govuk-radios__conditional')) {
|
1996
2137
|
var inputIsChecked = $input.checked;
|
1997
2138
|
|
1998
2139
|
$input.setAttribute('aria-expanded', inputIsChecked);
|
1999
|
-
|
2000
|
-
$content.classList.toggle('govuk-radios__conditional--hidden', !inputIsChecked);
|
2140
|
+
$target.classList.toggle('govuk-radios__conditional--hidden', !inputIsChecked);
|
2001
2141
|
}
|
2002
2142
|
};
|
2003
2143
|
|
2144
|
+
/**
|
2145
|
+
* Click event handler
|
2146
|
+
*
|
2147
|
+
* Handle a click within the $module – if the click occurred on a radio, sync
|
2148
|
+
* the state of the conditional reveal for all radio buttons in the same form
|
2149
|
+
* with the same name (because checking one radio could have un-checked a radio
|
2150
|
+
* in another $module)
|
2151
|
+
*
|
2152
|
+
* @param {MouseEvent} event Click event
|
2153
|
+
*/
|
2004
2154
|
Radios.prototype.handleClick = function (event) {
|
2005
2155
|
var $clickedInput = event.target;
|
2006
|
-
|
2156
|
+
|
2157
|
+
// Ignore clicks on things that aren't radio buttons
|
2007
2158
|
if ($clickedInput.type !== 'radio') {
|
2008
2159
|
return
|
2009
2160
|
}
|
2010
|
-
|
2011
|
-
//
|
2012
|
-
//
|
2013
|
-
// We also only want radios which have aria-controls, as they support conditional reveals.
|
2161
|
+
|
2162
|
+
// We only need to consider radios with conditional reveals, which will have
|
2163
|
+
// aria-controls attributes.
|
2014
2164
|
var $allInputs = document.querySelectorAll('input[type="radio"][aria-controls]');
|
2165
|
+
|
2015
2166
|
nodeListForEach($allInputs, function ($input) {
|
2016
|
-
// Only inputs with the same form owner should change.
|
2017
2167
|
var hasSameFormOwner = ($input.form === $clickedInput.form);
|
2018
|
-
|
2019
|
-
// In radios, only radios with the same name will affect each other.
|
2020
2168
|
var hasSameName = ($input.name === $clickedInput.name);
|
2169
|
+
|
2021
2170
|
if (hasSameName && hasSameFormOwner) {
|
2022
|
-
this.
|
2171
|
+
this.syncConditionalRevealWithInputState($input);
|
2023
2172
|
}
|
2024
2173
|
}.bind(this));
|
2025
2174
|
};
|
2026
2175
|
|
2027
2176
|
(function(undefined) {
|
2028
2177
|
|
2029
|
-
// Detection from https://
|
2178
|
+
// Detection from https://raw.githubusercontent.com/Financial-Times/polyfill-library/master/polyfills/Element/prototype/nextElementSibling/detect.js
|
2030
2179
|
var detect = (
|
2031
|
-
'
|
2180
|
+
'document' in this && "nextElementSibling" in document.documentElement
|
2032
2181
|
);
|
2033
2182
|
|
2034
2183
|
if (detect) return
|
2035
2184
|
|
2036
|
-
|
2037
|
-
(
|
2038
|
-
|
2039
|
-
|
2040
|
-
|
2041
|
-
|
2042
|
-
|
2043
|
-
|
2044
|
-
while (el && el.nodeType !== 1) { el = el.nextSibling; }
|
2045
|
-
return el;
|
2046
|
-
}
|
2047
|
-
});
|
2048
|
-
|
2049
|
-
}(this));
|
2185
|
+
// Polyfill from https://raw.githubusercontent.com/Financial-Times/polyfill-library/master/polyfills/Element/prototype/nextElementSibling/polyfill.js
|
2186
|
+
Object.defineProperty(Element.prototype, "nextElementSibling", {
|
2187
|
+
get: function(){
|
2188
|
+
var el = this.nextSibling;
|
2189
|
+
while (el && el.nodeType !== 1) { el = el.nextSibling; }
|
2190
|
+
return el;
|
2191
|
+
}
|
2192
|
+
});
|
2050
2193
|
|
2051
2194
|
}).call('object' === typeof window && window || 'object' === typeof self && self || 'object' === typeof global && global || {});
|
2052
2195
|
|
2053
2196
|
(function(undefined) {
|
2054
2197
|
|
2055
|
-
// Detection from https://
|
2198
|
+
// Detection from https://raw.githubusercontent.com/Financial-Times/polyfill-library/master/polyfills/Element/prototype/previousElementSibling/detect.js
|
2056
2199
|
var detect = (
|
2057
|
-
'
|
2200
|
+
'document' in this && "previousElementSibling" in document.documentElement
|
2058
2201
|
);
|
2059
2202
|
|
2060
2203
|
if (detect) return
|
2061
2204
|
|
2062
|
-
|
2063
|
-
|
2064
|
-
|
2065
|
-
|
2066
|
-
|
2067
|
-
|
2068
|
-
|
2069
|
-
|
2070
|
-
}
|
2071
|
-
});
|
2072
|
-
|
2073
|
-
}(this));
|
2205
|
+
// Polyfill from https://raw.githubusercontent.com/Financial-Times/polyfill-library/master/polyfills/Element/prototype/previousElementSibling/polyfill.js
|
2206
|
+
Object.defineProperty(Element.prototype, 'previousElementSibling', {
|
2207
|
+
get: function(){
|
2208
|
+
var el = this.previousSibling;
|
2209
|
+
while (el && el.nodeType !== 1) { el = el.previousSibling; }
|
2210
|
+
return el;
|
2211
|
+
}
|
2212
|
+
});
|
2074
2213
|
|
2075
2214
|
}).call('object' === typeof window && window || 'object' === typeof self && self || 'object' === typeof global && global || {});
|
2076
2215
|
|
@@ -2389,6 +2528,11 @@ function initAll (options) {
|
|
2389
2528
|
var $toggleButton = scope.querySelector('[data-module="govuk-header"]');
|
2390
2529
|
new Header($toggleButton).init();
|
2391
2530
|
|
2531
|
+
var $notificationBanners = scope.querySelectorAll('[data-module="govuk-notification-banner"]');
|
2532
|
+
nodeListForEach($notificationBanners, function ($notificationBanner) {
|
2533
|
+
new NotificationBanner($notificationBanner).init();
|
2534
|
+
});
|
2535
|
+
|
2392
2536
|
var $radios = scope.querySelectorAll('[data-module="govuk-radios"]');
|
2393
2537
|
nodeListForEach($radios, function ($radio) {
|
2394
2538
|
new Radios($radio).init();
|