govuk_publishing_components 21.57.1 → 21.60.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (99) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +31 -6
  3. data/app/assets/javascripts/component_guide/accessibility-test.js +21 -21
  4. data/app/assets/javascripts/component_guide/filter-components.js +19 -19
  5. data/app/assets/javascripts/component_guide/visual-regression.js +38 -37
  6. data/app/assets/javascripts/govuk_publishing_components/components/checkboxes.js +2 -2
  7. data/app/assets/javascripts/govuk_publishing_components/components/details.js +6 -4
  8. data/app/assets/javascripts/govuk_publishing_components/components/step-by-step-nav.js +4 -4
  9. data/app/assets/javascripts/govuk_publishing_components/lib/auto-track-event.js +31 -0
  10. data/app/assets/javascripts/govuk_publishing_components/lib/cookie-functions.js +24 -24
  11. data/app/assets/javascripts/govuk_publishing_components/lib/govspeak/youtube-link-enhancement.js +17 -17
  12. data/app/assets/stylesheets/component_guide/application.scss +15 -15
  13. data/app/assets/stylesheets/govuk_publishing_components/components/_action-link.scss +0 -8
  14. data/app/assets/stylesheets/govuk_publishing_components/components/_breadcrumbs.scss +1 -1
  15. data/app/assets/stylesheets/govuk_publishing_components/components/_checkboxes.scss +4 -0
  16. data/app/assets/stylesheets/govuk_publishing_components/components/_cookie-banner.scss +1 -8
  17. data/app/assets/stylesheets/govuk_publishing_components/components/_feedback.scss +0 -1
  18. data/app/assets/stylesheets/govuk_publishing_components/components/_govspeak-html-publication.scss +4 -5
  19. data/app/assets/stylesheets/govuk_publishing_components/components/_heading.scss +3 -8
  20. data/app/assets/stylesheets/govuk_publishing_components/components/_image-card.scss +1 -1
  21. data/app/assets/stylesheets/govuk_publishing_components/components/_input.scss +1 -1
  22. data/app/assets/stylesheets/govuk_publishing_components/components/_inverse-header.scss +5 -8
  23. data/app/assets/stylesheets/govuk_publishing_components/components/_list.scss +1 -0
  24. data/app/assets/stylesheets/govuk_publishing_components/components/_radio.scss +4 -0
  25. data/app/assets/stylesheets/govuk_publishing_components/components/_related-navigation.scss +2 -2
  26. data/app/assets/stylesheets/govuk_publishing_components/components/_search.scss +7 -3
  27. data/app/assets/stylesheets/govuk_publishing_components/components/_step-by-step-nav-header.scss +0 -5
  28. data/app/assets/stylesheets/govuk_publishing_components/components/_step-by-step-nav-related.scss +1 -4
  29. data/app/assets/stylesheets/govuk_publishing_components/components/_step-by-step-nav.scss +8 -12
  30. data/app/assets/stylesheets/govuk_publishing_components/components/_table.scss +21 -24
  31. data/app/assets/stylesheets/govuk_publishing_components/components/_tabs.scss +4 -8
  32. data/app/assets/stylesheets/govuk_publishing_components/components/govspeak/_attachment.scss +2 -0
  33. data/app/assets/stylesheets/govuk_publishing_components/components/govspeak/_button.scss +1 -4
  34. data/app/assets/stylesheets/govuk_publishing_components/components/govspeak/_charts.scss +6 -6
  35. data/app/assets/stylesheets/govuk_publishing_components/components/govspeak/_contact.scss +2 -0
  36. data/app/assets/stylesheets/govuk_publishing_components/components/govspeak/_footnotes.scss +2 -0
  37. data/app/assets/stylesheets/govuk_publishing_components/components/govspeak/_highlight-answer.scss +2 -0
  38. data/app/assets/stylesheets/govuk_publishing_components/components/govspeak/_place.scss +1 -1
  39. data/app/assets/stylesheets/govuk_publishing_components/components/govspeak/_typography.scss +2 -0
  40. data/app/assets/stylesheets/govuk_publishing_components/components/helpers/_markdown-typography.scss +1 -1
  41. data/app/assets/stylesheets/govuk_publishing_components/components/print/_govspeak.scss +2 -0
  42. data/app/assets/stylesheets/govuk_publishing_components/components/print/_step-by-step-nav-header.scss +0 -4
  43. data/app/assets/stylesheets/govuk_publishing_components/components/print/_step-by-step-nav.scss +2 -10
  44. data/app/controllers/govuk_publishing_components/audit_controller.rb +52 -0
  45. data/app/controllers/govuk_publishing_components/component_guide_controller.rb +2 -1
  46. data/app/models/govuk_publishing_components/audit_applications.rb +117 -0
  47. data/app/models/govuk_publishing_components/audit_comparer.rb +198 -0
  48. data/app/models/govuk_publishing_components/audit_components.rb +158 -0
  49. data/app/views/govuk_publishing_components/audit/show.html.erb +258 -0
  50. data/app/views/govuk_publishing_components/component_guide/index.html.erb +9 -4
  51. data/app/views/govuk_publishing_components/components/_breadcrumbs.html.erb +1 -1
  52. data/app/views/govuk_publishing_components/components/_image_card.html.erb +1 -1
  53. data/app/views/govuk_publishing_components/components/_list.html.erb +26 -0
  54. data/app/views/govuk_publishing_components/components/_machine_readable_metadata.html.erb +1 -1
  55. data/app/views/govuk_publishing_components/components/_radio.html.erb +13 -5
  56. data/app/views/govuk_publishing_components/components/_step_by_step_nav_header.html.erb +2 -2
  57. data/app/views/govuk_publishing_components/components/docs/checkboxes.yml +4 -0
  58. data/app/views/govuk_publishing_components/components/docs/govspeak.yml +45 -0
  59. data/app/views/govuk_publishing_components/components/docs/heading.yml +6 -3
  60. data/app/views/govuk_publishing_components/components/docs/image_card.yml +13 -1
  61. data/app/views/govuk_publishing_components/components/docs/list.yml +64 -0
  62. data/app/views/govuk_publishing_components/components/docs/radio.yml +4 -0
  63. data/config/routes.rb +1 -0
  64. data/lib/govuk_publishing_components/presenters/checkboxes_helper.rb +15 -7
  65. data/lib/govuk_publishing_components/presenters/heading_helper.rb +21 -1
  66. data/lib/govuk_publishing_components/presenters/image_card_helper.rb +2 -1
  67. data/lib/govuk_publishing_components/version.rb +1 -1
  68. data/node_modules/axe-core/package.json +145 -220
  69. data/node_modules/govuk-frontend/govuk/all.js +160 -57
  70. data/node_modules/govuk-frontend/govuk/components/character-count/character-count.js +16 -8
  71. data/node_modules/govuk-frontend/govuk/components/character-count/macro-options.json +6 -0
  72. data/node_modules/govuk-frontend/govuk/components/character-count/template.njk +1 -0
  73. data/node_modules/govuk-frontend/govuk/components/checkboxes/_index.scss +6 -5
  74. data/node_modules/govuk-frontend/govuk/components/checkboxes/checkboxes.js +68 -21
  75. data/node_modules/govuk-frontend/govuk/components/date-input/macro-options.json +1 -1
  76. data/node_modules/govuk-frontend/govuk/components/file-upload/_index.scss +0 -27
  77. data/node_modules/govuk-frontend/govuk/components/footer/_index.scss +0 -3
  78. data/node_modules/govuk-frontend/govuk/components/footer/template.njk +1 -1
  79. data/node_modules/govuk-frontend/govuk/components/header/template.njk +1 -1
  80. data/node_modules/govuk-frontend/govuk/components/hint/_index.scss +2 -2
  81. data/node_modules/govuk-frontend/govuk/components/hint/template.njk +2 -2
  82. data/node_modules/govuk-frontend/govuk/components/input/_index.scss +0 -3
  83. data/node_modules/govuk-frontend/govuk/components/input/macro-options.json +6 -0
  84. data/node_modules/govuk-frontend/govuk/components/input/template.njk +1 -0
  85. data/node_modules/govuk-frontend/govuk/components/radios/radios.js +76 -28
  86. data/node_modules/govuk-frontend/govuk/components/select/_index.scss +0 -3
  87. data/node_modules/govuk-frontend/govuk/components/skip-link/_index.scss +1 -0
  88. data/node_modules/govuk-frontend/govuk/components/textarea/_index.scss +0 -3
  89. data/node_modules/govuk-frontend/govuk/components/textarea/macro-options.json +6 -0
  90. data/node_modules/govuk-frontend/govuk/components/textarea/template.njk +1 -0
  91. data/node_modules/govuk-frontend/govuk/components/warning-text/_index.scss +4 -2
  92. data/node_modules/govuk-frontend/govuk/helpers/_colour.scss +1 -1
  93. data/node_modules/govuk-frontend/govuk/settings/_colours-applied.scss +2 -2
  94. data/node_modules/govuk-frontend/govuk/settings/_colours-palette.scss +1 -1
  95. data/node_modules/govuk-frontend/govuk/settings/_measurements.scss +4 -1
  96. data/node_modules/govuk-frontend/package.json +14 -81
  97. data/node_modules/jquery/package.json +44 -116
  98. metadata +46 -66
  99. data/Rakefile +0 -32
@@ -1,222 +1,147 @@
1
1
  {
2
- "_args": [
3
- [
4
- {
5
- "raw": "axe-core@^3.5.4",
6
- "scope": null,
7
- "escapedName": "axe-core",
8
- "name": "axe-core",
9
- "rawSpec": "^3.5.4",
10
- "spec": ">=3.5.4 <4.0.0",
11
- "type": "range"
12
- },
13
- "/var/lib/jenkins/workspace/ublishing_components_master-N4FWJIUY4CIFHKGZOAAEVVXODRY3YBORQOPIBBXWX72VUPSGJRRQ"
14
- ]
15
- ],
16
- "_from": "axe-core@>=3.5.4 <4.0.0",
17
- "_hasShrinkwrap": false,
18
- "_id": "axe-core@3.5.5",
19
- "_inCache": true,
20
- "_location": "/axe-core",
21
- "_nodeVersion": "10.21.0",
22
- "_npmOperationalInternal": {
23
- "host": "s3://npm-registry-packages",
24
- "tmp": "tmp/axe-core_3.5.5_1592406217427_0.7348143825163969"
25
- },
26
- "_npmUser": {
27
- "name": "npmdeque",
28
- "email": "axe@deque.com"
29
- },
30
- "_npmVersion": "6.14.4",
31
- "_phantomChildren": {},
32
- "_requested": {
33
- "raw": "axe-core@^3.5.4",
34
- "scope": null,
35
- "escapedName": "axe-core",
36
- "name": "axe-core",
37
- "rawSpec": "^3.5.4",
38
- "spec": ">=3.5.4 <4.0.0",
39
- "type": "range"
40
- },
41
- "_requiredBy": [
42
- "/"
43
- ],
44
- "_resolved": "https://registry.npmjs.org/axe-core/-/axe-core-3.5.5.tgz",
45
- "_shasum": "84315073b53fa3c0c51676c588d59da09a192227",
46
- "_shrinkwrap": null,
47
- "_spec": "axe-core@^3.5.4",
48
- "_where": "/var/lib/jenkins/workspace/ublishing_components_master-N4FWJIUY4CIFHKGZOAAEVVXODRY3YBORQOPIBBXWX72VUPSGJRRQ",
49
- "bugs": {
50
- "url": "https://github.com/dequelabs/axe-core/issues"
51
- },
52
- "contributors": [
53
- {
54
- "name": "David Sturley",
55
- "url": "http://deque.com/"
56
- },
57
- {
58
- "name": "Dylan Barrell",
59
- "email": "dylan@barrell.com",
60
- "url": "http://deque.com/"
61
- },
62
- {
63
- "name": "Wilco Fiers",
64
- "url": "http://deque.com/"
65
- },
66
- {
67
- "name": "Dian Fay",
68
- "url": "http://deque.com/"
69
- },
70
- {
71
- "name": "Marcy Sutton",
72
- "url": "http://deque.com/"
73
- }
74
- ],
75
- "dependencies": {},
76
- "description": "Accessibility engine for automated Web UI testing",
77
- "devDependencies": {
78
- "@babel/core": "^7.5.4",
79
- "@babel/plugin-proposal-object-rest-spread": "^7.5.4",
80
- "@babel/polyfill": "^7.4.4",
81
- "@babel/preset-env": "^7.5.4",
82
- "@deque/dot": "^1.1.5",
83
- "aria-query": "^3.0.0",
84
- "axios": "^0.19.0",
85
- "babelify": "^10.0.0",
86
- "blanket": "~1.2.3",
87
- "browserify": "^16.2.3",
88
- "chai": "~4.2.0",
89
- "clone": "~2.1.1",
90
- "core-js": "^3.2.1",
91
- "css-selector-parser": "^1.3.0",
92
- "derequire": "^2.0.6",
93
- "emoji-regex": "8.0.0",
94
- "es6-promise": "^4.2.6",
95
- "eslint": "^6.1.0",
96
- "eslint-config-prettier": "^6.2.0",
97
- "execa": "^2.0.2",
98
- "fs-extra": "^8.0.1",
99
- "globby": "^10.0.0",
100
- "grunt": "^1.0.3",
101
- "grunt-babel": "^8.0.0",
102
- "grunt-contrib-clean": "^2.0.0",
103
- "grunt-contrib-concat": "^1.0.1",
104
- "grunt-contrib-connect": "^2.0.0",
105
- "grunt-contrib-copy": "^1.0.0",
106
- "grunt-contrib-uglify": "^4.0.0",
107
- "grunt-contrib-watch": "^1.1.0",
108
- "grunt-parallel": "^0.5.1",
109
- "grunt-run": "^0.8.1",
110
- "html-entities": "^1.2.0",
111
- "husky": "^3.0.0",
112
- "jquery": "^3.0.0",
113
- "jsdoc": "^3.5.5",
114
- "lint-staged": "^9.2.1",
115
- "make-dir": "^3.0.0",
116
- "markdown-table": "^1.1.2",
117
- "memoizee": "^0.4.14",
118
- "minami": "^1.2.3",
119
- "mkdirp": "^0.5.1",
120
- "mocha": "^6.1.2",
121
- "mocha-headless-chrome": "^2.0.3",
122
- "prettier": "^1.17.1",
123
- "puppeteer": "^2.0.0",
124
- "revalidator": "~0.3.1",
125
- "selenium-webdriver": "~3.6.0",
126
- "sinon": "^7.5.0",
127
- "sri-toolbox": "^0.2.0",
128
- "standard-version": "^7.0.0",
129
- "typescript": "^3.5.3",
130
- "uglify-js": "^3.4.4",
131
- "weakmap-polyfill": "^2.0.0"
132
- },
133
- "directories": {},
134
- "dist": {
135
- "integrity": "sha512-5P0QZ6J5xGikH780pghEdbEKijCTrruK9KxtPZCFWUpef0f6GipO+xEZ5GKCb020mmqgbiNO6TcA55CriL784Q==",
136
- "shasum": "84315073b53fa3c0c51676c588d59da09a192227",
137
- "tarball": "https://registry.npmjs.org/axe-core/-/axe-core-3.5.5.tgz",
138
- "fileCount": 596,
139
- "unpackedSize": 2642777,
140
- "npm-signature": "-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJe6jDJCRA9TVsSAnZWagAAGCMQAJ1oBZRRo34GrgSa/2t6\nYeU2J8z5qkLNFILI65HVEzcu2e/TL8rHFgi9Q1Ga4szh41PTXJd0YfnPvYWt\nx+EiZ+TSoeSSksj5VoS3wjQFn2cQ55LyUOW0lQ3s1sPwEgALZPG3pLCn7GW+\nZiOW+Ai1FHESY/dbxZ1Rl1IrOt+jbOZqsczb0yk8PkZ9QwPJjZL70iLI8DRL\n5JMGoAmO4dJ3Vk+t2Dhy7vnwz+bFbs9lRKZaBJp4dYqY0F8HHC91hROv9pTP\n4hCNXevA6SKSf/Ddl7ub51EN1qQalYHQTQ0al4i0isv6NPlUnPVYaGzTHpZE\n2OTvoZ+dVqSDnCJqYH/WrIRfO0xA3bKTlRn6HyMkHFJOcXmi6NR/47uQfY/6\nr5a/N7nBsWh92aaoEw9ZVoNyMAgeEJlOt5uzXQgOWgJM8WIpqbTUJOeqXfEe\nI9FC2NhNU8Gqw9Ee24KCrCg8PWeODV/r47IHkQRdHqoqh1+/hzkUUhVP1smC\n6eI8qFTnhwws+EwNbxvBg73BCwsEiRwXaE7U0PToPLQvxyr0CRjqzJsl6Hhi\nOowldaReyMQALfJTipnc/Eb1VqCVQ1ABaYltnyVRnCL22mZUJGgq65OINJjT\nYGr9pWAh8r+C4MkIJf8C05eYJB6QL8+kry8YDDDtd2NdUHW8IKOax1p3MuqD\nG8u9\r\n=lmaS\r\n-----END PGP SIGNATURE-----\r\n"
141
- },
142
- "engines": {
143
- "node": ">=4"
144
- },
145
- "gitHead": "c19c8b616f9ed836fb72f14aaaff53072ea13fdc",
146
- "homepage": "https://www.deque.com/axe/",
147
- "keywords": [
148
- "Accessibility",
149
- "a11y",
150
- "testing",
151
- "unit",
152
- "tdd",
153
- "bdd",
154
- "axe"
155
- ],
156
- "license": "MPL-2.0",
157
- "lint-staged": {
158
- "*.{md,json,ts,html}": [
159
- "prettier --write",
160
- "git add"
161
- ],
162
- "*.js": [
163
- "eslint --fix",
164
- "prettier --write",
165
- "git add"
166
- ]
167
- },
168
- "main": "axe.js",
169
- "maintainers": [
170
- {
171
- "name": "dequelabs",
172
- "email": "labs@deque.com"
173
- },
174
- {
175
- "name": "dylanb",
176
- "email": "dylan@barrell.com"
177
- },
178
- {
179
- "name": "marcysutton",
180
- "email": "marcy.sutton@deque.com"
181
- },
182
- {
183
- "name": "wilcofiers",
184
- "email": "wilcofiers@gmail.com"
185
- }
186
- ],
187
- "name": "axe-core",
188
- "optionalDependencies": {},
189
- "readme": "ERROR: No README data found!",
190
- "repository": {
191
- "type": "git",
192
- "url": "git+https://github.com/dequelabs/axe-core.git"
193
- },
194
- "scripts": {
195
- "api-docs": "jsdoc --configure .jsdoc.json",
196
- "build": "grunt",
197
- "develop": "grunt dev --force",
198
- "eslint": "eslint --color --format stylish '{lib,test,build,doc}/**/*.js' 'Gruntfile.js'",
199
- "fmt": "prettier --write *.{json,md,js} **/*.ts './{.github,build,doc,lib,test}/**/*.{json,md,js,ts,html}'",
200
- "imports-gen": "node ./build/imports-generator",
201
- "next-release": "standard-version --scripts.prebump=./build/next-version.js --skip.commit=true --skip.tag=true",
202
- "prepublishOnly": "grunt build && grunt file-exists",
203
- "release": "standard-version -a",
204
- "rule-gen": "node build/rule-generator",
205
- "sri-update": "grunt build && node build/sri-update && git add sri-history.json",
206
- "sri-validate": "node build/sri-update --validate",
207
- "start": "npm run develop",
208
- "test": "tsc && grunt test",
209
- "test:examples": "node ./doc/examples/test-examples",
210
- "test:headless": "node ./build/test/headless",
211
- "test:locales": "mocha test/test-locales.js",
212
- "test:rule-help-version": "mocha test/test-rule-help-version.js",
213
- "version": "echo \"use 'npm run release' to bump axe-core version\" && exit 1"
214
- },
215
- "standard-version": {
216
- "scripts": {
217
- "postbump": "npm ci && npm run sri-update"
218
- }
219
- },
220
- "typings": "axe.d.ts",
221
- "version": "3.5.5"
2
+ "name": "axe-core",
3
+ "description": "Accessibility engine for automated Web UI testing",
4
+ "version": "3.5.5",
5
+ "license": "MPL-2.0",
6
+ "engines": {
7
+ "node": ">=4"
8
+ },
9
+ "contributors": [
10
+ {
11
+ "name": "David Sturley",
12
+ "organization": "Deque Systems, Inc.",
13
+ "url": "http://deque.com/"
14
+ },
15
+ {
16
+ "name": "Dylan Barrell",
17
+ "email": "dylan@barrell.com",
18
+ "organization": "Deque Systems, Inc.",
19
+ "url": "http://deque.com/"
20
+ },
21
+ {
22
+ "name": "Wilco Fiers",
23
+ "organization": "Deque Systems, Inc.",
24
+ "url": "http://deque.com/"
25
+ },
26
+ {
27
+ "name": "Dian Fay",
28
+ "organization": "Deque Systems, Inc.",
29
+ "url": "http://deque.com/"
30
+ },
31
+ {
32
+ "name": "Marcy Sutton",
33
+ "organization": "Deque Systems, Inc.",
34
+ "url": "http://deque.com/"
35
+ }
36
+ ],
37
+ "homepage": "https://www.deque.com/axe/",
38
+ "repository": {
39
+ "type": "git",
40
+ "url": "https://github.com/dequelabs/axe-core.git"
41
+ },
42
+ "keywords": [
43
+ "Accessibility",
44
+ "a11y",
45
+ "testing",
46
+ "unit",
47
+ "tdd",
48
+ "bdd",
49
+ "axe"
50
+ ],
51
+ "main": "axe.js",
52
+ "typings": "axe.d.ts",
53
+ "standard-version": {
54
+ "scripts": {
55
+ "postbump": "npm ci && npm run sri-update"
56
+ }
57
+ },
58
+ "scripts": {
59
+ "start": "npm run develop",
60
+ "develop": "grunt dev --force",
61
+ "api-docs": "jsdoc --configure .jsdoc.json",
62
+ "imports-gen": "node ./build/imports-generator",
63
+ "build": "grunt",
64
+ "eslint": "eslint --color --format stylish '{lib,test,build,doc}/**/*.js' 'Gruntfile.js'",
65
+ "test:headless": "node ./build/test/headless",
66
+ "test": "tsc && grunt test",
67
+ "test:examples": "node ./doc/examples/test-examples",
68
+ "test:locales": "mocha test/test-locales.js",
69
+ "test:rule-help-version": "mocha test/test-rule-help-version.js",
70
+ "version": "echo \"use 'npm run release' to bump axe-core version\" && exit 1",
71
+ "prepublishOnly": "grunt build && grunt file-exists",
72
+ "release": "standard-version -a",
73
+ "rule-gen": "node build/rule-generator",
74
+ "next-release": "standard-version --scripts.prebump=./build/next-version.js --skip.commit=true --skip.tag=true",
75
+ "sri-update": "grunt build && node build/sri-update && git add sri-history.json",
76
+ "sri-validate": "node build/sri-update --validate",
77
+ "fmt": "prettier --write *.{json,md,js} **/*.ts './{.github,build,doc,lib,test}/**/*.{json,md,js,ts,html}'"
78
+ },
79
+ "devDependencies": {
80
+ "@babel/core": "^7.5.4",
81
+ "@babel/plugin-proposal-object-rest-spread": "^7.5.4",
82
+ "@babel/polyfill": "^7.4.4",
83
+ "@babel/preset-env": "^7.5.4",
84
+ "@deque/dot": "^1.1.5",
85
+ "aria-query": "^3.0.0",
86
+ "axios": "^0.19.0",
87
+ "babelify": "^10.0.0",
88
+ "blanket": "~1.2.3",
89
+ "browserify": "^16.2.3",
90
+ "chai": "~4.2.0",
91
+ "clone": "~2.1.1",
92
+ "core-js": "^3.2.1",
93
+ "css-selector-parser": "^1.3.0",
94
+ "derequire": "^2.0.6",
95
+ "emoji-regex": "8.0.0",
96
+ "es6-promise": "^4.2.6",
97
+ "eslint": "^6.1.0",
98
+ "eslint-config-prettier": "^6.2.0",
99
+ "execa": "^2.0.2",
100
+ "fs-extra": "^8.0.1",
101
+ "globby": "^10.0.0",
102
+ "grunt": "^1.0.3",
103
+ "grunt-babel": "^8.0.0",
104
+ "grunt-contrib-clean": "^2.0.0",
105
+ "grunt-contrib-concat": "^1.0.1",
106
+ "grunt-contrib-connect": "^2.0.0",
107
+ "grunt-contrib-copy": "^1.0.0",
108
+ "grunt-contrib-uglify": "^4.0.0",
109
+ "grunt-contrib-watch": "^1.1.0",
110
+ "grunt-parallel": "^0.5.1",
111
+ "grunt-run": "^0.8.1",
112
+ "html-entities": "^1.2.0",
113
+ "husky": "^3.0.0",
114
+ "jquery": "^3.0.0",
115
+ "jsdoc": "^3.5.5",
116
+ "lint-staged": "^9.2.1",
117
+ "make-dir": "^3.0.0",
118
+ "markdown-table": "^1.1.2",
119
+ "memoizee": "^0.4.14",
120
+ "minami": "^1.2.3",
121
+ "mkdirp": "^0.5.1",
122
+ "mocha": "^6.1.2",
123
+ "mocha-headless-chrome": "^2.0.3",
124
+ "prettier": "^1.17.1",
125
+ "puppeteer": "^2.0.0",
126
+ "revalidator": "~0.3.1",
127
+ "selenium-webdriver": "~3.6.0",
128
+ "sinon": "^7.5.0",
129
+ "sri-toolbox": "^0.2.0",
130
+ "standard-version": "^7.0.0",
131
+ "typescript": "^3.5.3",
132
+ "uglify-js": "^3.4.4",
133
+ "weakmap-polyfill": "^2.0.0"
134
+ },
135
+ "dependencies": {},
136
+ "lint-staged": {
137
+ "*.{md,json,ts,html}": [
138
+ "prettier --write",
139
+ "git add"
140
+ ],
141
+ "*.js": [
142
+ "eslint --fix",
143
+ "prettier --write",
144
+ "git add"
145
+ ]
146
+ }
222
147
  }
@@ -1542,13 +1542,22 @@ CharacterCount.prototype.init = function () {
1542
1542
  // Remove hard limit if set
1543
1543
  $module.removeAttribute('maxlength');
1544
1544
 
1545
- // Bind event changes to the textarea
1546
- var boundChangeEvents = this.bindChangeEvents.bind(this);
1547
- boundChangeEvents();
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
- // Update count message
1550
- var boundUpdateCountMessage = this.updateCountMessage.bind(this);
1551
- boundUpdateCountMessage();
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
- var boundUpdateCountMessage = this.updateCountMessage.bind(this);
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 controls = $input.getAttribute('data-aria-controls');
1696
+ var target = $input.getAttribute('data-aria-controls');
1680
1697
 
1681
- // Check if input controls anything
1682
- // Check if content exists, before setting attributes.
1683
- if (!controls || !$module.querySelector('#' + controls)) {
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
- // If we have content that is controlled, set attributes.
1688
- $input.setAttribute('aria-controls', controls);
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
- this.setAttributes($input);
1691
- }.bind(this));
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
- Checkboxes.prototype.setAttributes = function ($input) {
1698
- var inputIsChecked = $input.checked;
1699
- $input.setAttribute('aria-expanded', inputIsChecked);
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
- var $content = this.$module.querySelector('#' + $input.getAttribute('aria-controls'));
1702
- if ($content) {
1703
- $content.classList.toggle('govuk-checkboxes__conditional--hidden', !inputIsChecked);
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.setAttributes($target);
1769
+ this.syncConditionalRevealWithInputState($target);
1715
1770
  }
1716
1771
  };
1717
1772
 
@@ -1959,67 +2014,115 @@ Header.prototype.handleClick = function (event) {
1959
2014
 
1960
2015
  function Radios ($module) {
1961
2016
  this.$module = $module;
2017
+ this.$inputs = $module.querySelectorAll('input[type="radio"]');
1962
2018
  }
1963
2019
 
2020
+ /**
2021
+ * Initialise Radios
2022
+ *
2023
+ * Radios can be associated with a 'conditionally revealed' content block – for
2024
+ * example, a radio for 'Phone' could reveal an additional form field for the
2025
+ * user to enter their phone number.
2026
+ *
2027
+ * These associations are made using a `data-aria-controls` attribute, which is
2028
+ * promoted to an aria-controls attribute during initialisation.
2029
+ *
2030
+ * We also need to restore the state of any conditional reveals on the page (for
2031
+ * example if the user has navigated back), and set up event handlers to keep
2032
+ * the reveal in sync with the radio state.
2033
+ */
1964
2034
  Radios.prototype.init = function () {
1965
2035
  var $module = this.$module;
1966
- var $inputs = $module.querySelectorAll('input[type="radio"]');
2036
+ var $inputs = this.$inputs;
1967
2037
 
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
2038
  nodeListForEach($inputs, function ($input) {
1974
- var controls = $input.getAttribute('data-aria-controls');
2039
+ var target = $input.getAttribute('data-aria-controls');
1975
2040
 
1976
- // Check if input controls anything
1977
- // Check if content exists, before setting attributes.
1978
- if (!controls || !$module.querySelector('#' + controls)) {
2041
+ // Skip radios without data-aria-controls attributes, or where the
2042
+ // target element does not exist.
2043
+ if (!target || !$module.querySelector('#' + target)) {
1979
2044
  return
1980
2045
  }
1981
2046
 
1982
- // If we have content that is controlled, set attributes.
1983
- $input.setAttribute('aria-controls', controls);
2047
+ // Promote the data-aria-controls attribute to a aria-controls attribute
2048
+ // so that the relationship is exposed in the AOM
2049
+ $input.setAttribute('aria-controls', target);
1984
2050
  $input.removeAttribute('data-aria-controls');
1985
- this.setAttributes($input);
1986
- }.bind(this));
2051
+ });
2052
+
2053
+ // When the page is restored after navigating 'back' in some browsers the
2054
+ // state of form controls is not restored until *after* the DOMContentLoaded
2055
+ // event is fired, so we need to sync after the pageshow event in browsers
2056
+ // that support it.
2057
+ if ('onpageshow' in window) {
2058
+ window.addEventListener('pageshow', this.syncAllConditionalReveals.bind(this));
2059
+ } else {
2060
+ window.addEventListener('DOMContentLoaded', this.syncAllConditionalReveals.bind(this));
2061
+ }
2062
+
2063
+ // Although we've set up handlers to sync state on the pageshow or
2064
+ // DOMContentLoaded event, init could be called after those events have fired,
2065
+ // for example if they are added to the page dynamically, so sync now too.
2066
+ this.syncAllConditionalReveals();
1987
2067
 
1988
2068
  // Handle events
1989
2069
  $module.addEventListener('click', this.handleClick.bind(this));
1990
2070
  };
1991
2071
 
1992
- Radios.prototype.setAttributes = function ($input) {
1993
- var $content = document.querySelector('#' + $input.getAttribute('aria-controls'));
2072
+ /**
2073
+ * Sync the conditional reveal states for all inputs in this $module.
2074
+ */
2075
+ Radios.prototype.syncAllConditionalReveals = function () {
2076
+ nodeListForEach(this.$inputs, this.syncConditionalRevealWithInputState.bind(this));
2077
+ };
1994
2078
 
1995
- if ($content && $content.classList.contains('govuk-radios__conditional')) {
2079
+ /**
2080
+ * Sync conditional reveal with the input state
2081
+ *
2082
+ * Synchronise the visibility of the conditional reveal, and its accessible
2083
+ * state, with the input's checked state.
2084
+ *
2085
+ * @param {HTMLInputElement} $input Radio input
2086
+ */
2087
+ Radios.prototype.syncConditionalRevealWithInputState = function ($input) {
2088
+ var $target = document.querySelector('#' + $input.getAttribute('aria-controls'));
2089
+
2090
+ if ($target && $target.classList.contains('govuk-radios__conditional')) {
1996
2091
  var inputIsChecked = $input.checked;
1997
2092
 
1998
2093
  $input.setAttribute('aria-expanded', inputIsChecked);
1999
-
2000
- $content.classList.toggle('govuk-radios__conditional--hidden', !inputIsChecked);
2094
+ $target.classList.toggle('govuk-radios__conditional--hidden', !inputIsChecked);
2001
2095
  }
2002
2096
  };
2003
2097
 
2098
+ /**
2099
+ * Click event handler
2100
+ *
2101
+ * Handle a click within the $module – if the click occurred on a radio, sync
2102
+ * the state of the conditional reveal for all radio buttons in the same form
2103
+ * with the same name (because checking one radio could have un-checked a radio
2104
+ * in another $module)
2105
+ *
2106
+ * @param {MouseEvent} event Click event
2107
+ */
2004
2108
  Radios.prototype.handleClick = function (event) {
2005
2109
  var $clickedInput = event.target;
2006
- // We only want to handle clicks for radio inputs
2110
+
2111
+ // Ignore clicks on things that aren't radio buttons
2007
2112
  if ($clickedInput.type !== 'radio') {
2008
2113
  return
2009
2114
  }
2010
- // Because checking one radio can uncheck a radio in another $module,
2011
- // we need to call set attributes on all radios in the same form, or document if they're not in a form.
2012
- //
2013
- // We also only want radios which have aria-controls, as they support conditional reveals.
2115
+
2116
+ // We only need to consider radios with conditional reveals, which will have
2117
+ // aria-controls attributes.
2014
2118
  var $allInputs = document.querySelectorAll('input[type="radio"][aria-controls]');
2119
+
2015
2120
  nodeListForEach($allInputs, function ($input) {
2016
- // Only inputs with the same form owner should change.
2017
2121
  var hasSameFormOwner = ($input.form === $clickedInput.form);
2018
-
2019
- // In radios, only radios with the same name will affect each other.
2020
2122
  var hasSameName = ($input.name === $clickedInput.name);
2123
+
2021
2124
  if (hasSameName && hasSameFormOwner) {
2022
- this.setAttributes($input);
2125
+ this.syncConditionalRevealWithInputState($input);
2023
2126
  }
2024
2127
  }.bind(this));
2025
2128
  };