From 4f91d117a10c31ad66e024e52331be51b8136591 Mon Sep 17 00:00:00 2001 From: Andy Mantell <134642+andymantell@users.noreply.github.com> Date: Fri, 23 Jul 2021 13:34:06 +0100 Subject: [PATCH 01/17] Add "None of these" JavaScript behaviour to checkboxes See original at https://github.com/alphagov/govuk-frontend/pull/2151 --- .../checkboxes/none-of-the-above.njk | 98 +++++++++++ app/pages/examples.njk | 1 + packages/common.js | 9 +- packages/components/checkboxes/README.md | 161 ++++++++++++++++++ packages/components/checkboxes/checkboxes.js | 57 +++++++ packages/components/checkboxes/template.njk | 1 + 6 files changed, 325 insertions(+), 2 deletions(-) create mode 100644 app/components/checkboxes/none-of-the-above.njk diff --git a/app/components/checkboxes/none-of-the-above.njk b/app/components/checkboxes/none-of-the-above.njk new file mode 100644 index 000000000..c9ca22bc6 --- /dev/null +++ b/app/components/checkboxes/none-of-the-above.njk @@ -0,0 +1,98 @@ +{% set html_style = 'background-color: #f0f4f5;' %} +{% set title = 'Checkboxes with conditional content' %} +{% from 'components/checkboxes/macro.njk' import checkboxes %} +{% from 'components/input/macro.njk' import input %} +{% extends 'layout.njk' %} + +{% set emailHtml %} + {{ input({ + id: "email", + name: "email", + classes: "nhsuk-u-width-two-thirds", + label: { + text: "Email address" + } + }) }} +{% endset -%} + +{% set phoneHtml %} + {{ input({ + id: "phone", + name: "phone", + classes: "nhsuk-u-width-two-thirds", + label: { + text: "Phone number" + } + }) }} +{% endset -%} + +{% set mobileHtml %} + {{ input({ + id: "mobile", + name: "mobile", + classes: "nhsuk-u-width-two-thirds", + label: { + text: "Mobile phone number" + } + }) }} +{% endset -%} + +{% block body %} + +
+
+ +
+
+ {{ checkboxes({ + "idPrefix": "contact", + "name": "contact", + "fieldset": { + "legend": { + "text": "How would you prefer to be contacted?", + "classes": "nhsuk-fieldset__legend--l", + "isPageHeading": "true" + } + }, + "hint": { + "text": "Select all options that are relevant to you." + }, + "items": [ + { + "value": "email", + "text": "Email", + "conditional": { + "html": emailHtml + } + }, + { + "value": "phone", + "text": "Phone", + "conditional": { + "html": phoneHtml + } + }, + { + "value": "text", + "text": "Text message", + "conditional": { + "html": mobileHtml + } + }, + { + divider: "or" + }, + { + value: "none", + text: "None of the above", + behaviour: "exclusive" + } + ] + }) }} +
+
+ +
+
+ +{% endblock %} diff --git a/app/pages/examples.njk b/app/pages/examples.njk index 3b1e4d30c..9f5757238 100644 --- a/app/pages/examples.njk +++ b/app/pages/examples.njk @@ -42,6 +42,7 @@
  • Checkboxes with legend as page heading
  • Checkboxes with error message
  • Checkboxes with conditional content
  • +
  • Checkboxes with "none of the above" option
  • Contents list
  • Date input
  • Date input with autocomplete attribute
  • diff --git a/packages/common.js b/packages/common.js index 0da099e3d..0fe6a6691 100644 --- a/packages/common.js +++ b/packages/common.js @@ -25,8 +25,13 @@ export const toggleConditionalInput = (input, className) => { // Get the conditional element from the input data-aria-controls attribute const conditionalElement = document.getElementById(conditionalId); if (conditionalElement) { - conditionalElement.classList.toggle(className); - toggleAttribute(input, 'aria-expanded'); + if (input.checked) { + conditionalElement.classList.remove(className); + input.setAttribute('aria-expanded', false); + } else { + conditionalElement.classList.add(className); + input.setAttribute('aria-expanded', true); + } } } }; diff --git a/packages/components/checkboxes/README.md b/packages/components/checkboxes/README.md index 606344447..27e6fb1a1 100644 --- a/packages/components/checkboxes/README.md +++ b/packages/components/checkboxes/README.md @@ -508,6 +508,166 @@ Find out more about the checkboxes component and when to use it in the [NHS digi --- +### Checkboxes with "none of the above" option + +[Preview the checkboxes with "none of the above" option](https://nhsuk.github.io/nhsuk-frontend/components/checkboxes/conditional.html) + +#### HTML markup + +```html +
    +
    + +

    + How would you prefer to be contacted? +

    +
    +
    + Select all options that are relevant to you. +
    +
    +
    + + +
    +
    +
    + + +
    +
    +
    + + +
    +
    +
    + + +
    +
    +
    + + +
    +
    +
    + + +
    +
    +
    or
    +
    + + +
    +
    +
    +
    +``` + +#### Nunjucks macro + +``` +{% from 'components/checkboxes/macro.njk' import checkboxes %} +{% from 'components/input/macro.njk' import input %} + +{% set emailHtml %} + {{ input({ + id: "email", + name: "email", + classes: "nhsuk-u-width-two-thirds", + label: { + text: "Email address" + } + }) }} +{% endset -%} + +{% set phoneHtml %} + {{ input({ + id: "phone", + name: "phone", + classes: "nhsuk-u-width-two-thirds", + label: { + text: "Phone number" + } + }) }} +{% endset -%} + +{% set mobileHtml %} + {{ input({ + id: "mobile", + name: "mobile", + classes: "nhsuk-u-width-two-thirds", + label: { + text: "Mobile phone number" + } + }) }} +{% endset -%} + +{{ checkboxes({ + "idPrefix": "contact", + "name": "contact", + "fieldset": { + "legend": { + "text": "How would you prefer to be contacted?", + "classes": "nhsuk-fieldset__legend--l", + "isPageHeading": "true" + } + }, + "hint": { + "text": "Select all options that are relevant to you." + }, + "items": [ + { + "value": "email", + "text": "Email", + "conditional": { + "html": emailHtml + } + }, + { + "value": "phone", + "text": "Phone", + "conditional": { + "html": phoneHtml + } + }, + { + "value": "text", + "text": "Text message", + "conditional": { + "html": mobileHtml + } + }, + { + divider: "or" + }, + { + value: "none", + text: "None of the above", + behaviour: "exclusive" + } + ] +}) }} +``` + +--- + ### Nunjucks arguments The checkboxes Nunjucks macro takes the following arguments: @@ -534,6 +694,7 @@ The checkboxes Nunjucks macro takes the following arguments: | **items[].conditional.html** | string | No | HTML to be displayed when the checkbox is checked | | **classes** | string | No | Optional additional classes to add to the checkboxes container. Separate each class with a space. | | **attributes** | object | No | Any extra HTML attributes (for example data attributes) to add to the checkboxes container. | +| **behaviour** | string | No | If set to `exclusive`, implements a "None of these" type behaviour via javascript when checkboxes are clicked | If you are using Nunjucks macros in production be aware that using `html` arguments, or ones ending with `html` can be a [security risk](https://developer.mozilla.org/en-US/docs/Glossary/Cross-site_scripting). Read more about this in the [Nunjucks documentation](https://mozilla.github.io/nunjucks/api.html#user-defined-templates-warning). diff --git a/packages/components/checkboxes/checkboxes.js b/packages/components/checkboxes/checkboxes.js index ece7acc18..6df3ebce3 100644 --- a/packages/components/checkboxes/checkboxes.js +++ b/packages/components/checkboxes/checkboxes.js @@ -5,6 +5,52 @@ import { toggleConditionalInput } from '../../common'; * Test at http://0.0.0.0:3000/components/checkboxes/conditional.html */ +/** + * Uncheck other checkboxes + * + * Find any other checkbox inputs with the same name value, and uncheck them. + * This is useful for when a “None of these" checkbox is checked. + */ + const unCheckAllInputsExcept = function (input) { + const allInputsWithSameName = document.querySelectorAll('input[type="checkbox"][name="' + input.name + '"]') + + allInputsWithSameName.forEach((inputWithSameName) => { + const hasSameFormOwner = input.form === inputWithSameName.form + if (hasSameFormOwner && inputWithSameName !== input) { + inputWithSameName.checked = false + } + }) + + syncAllConditionalReveals(input) +} + +/** + * Uncheck exclusive inputs + * + * Find any checkbox inputs with the same name value and the 'exclusive' behaviour, + * and uncheck them. This helps prevent someone checking both a regular checkbox and a + * "None of these" checkbox in the same fieldset. + */ +const unCheckExclusiveInputs = function (input) { + const allInputsWithSameNameAndExclusiveBehaviour = document.querySelectorAll( + 'input[data-behaviour="exclusive"][type="checkbox"][name="' + input.name + '"]' + ) + + allInputsWithSameNameAndExclusiveBehaviour.forEach((exclusiveInput) => { + const hasSameFormOwner = input.form === exclusiveInput.form + if (hasSameFormOwner) { + exclusiveInput.checked = false + } + }) + + syncAllConditionalReveals(input) +} + +const syncAllConditionalReveals = function(input) { + const allInputsWithSameName = document.querySelectorAll('input[type="checkbox"][name="' + input.name + '"]'); + Array.from(allInputsWithSameName).map((input) => toggleConditionalInput(input, 'nhsuk-checkboxes__conditional--hidden')); +} + export default () => { // Checkbox input DOMElements inside a conditional form group const checkboxInputs = document.querySelectorAll('.nhsuk-checkboxes--conditional .nhsuk-checkboxes__input'); @@ -16,6 +62,17 @@ export default () => { const handleClick = (event) => { // Toggle conditional content based on checked state toggleConditionalInput(event.target, 'nhsuk-checkboxes__conditional--hidden'); + + if (!event.target.checked) { + return + } + + // Handle 'exclusive' checkbox behaviour (ie "None of these") + if (event.target.getAttribute('data-behaviour') === 'exclusive') { + unCheckAllInputsExcept(event.target) + } else { + unCheckExclusiveInputs(event.target) + } }; // Attach handleClick as click to checkboxInputs diff --git a/packages/components/checkboxes/template.njk b/packages/components/checkboxes/template.njk index 65e0ec13e..d0968332d 100644 --- a/packages/components/checkboxes/template.njk +++ b/packages/components/checkboxes/template.njk @@ -56,6 +56,7 @@ From 4ca14f1267e754ce1224a438743cd3f763032182 Mon Sep 17 00:00:00 2001 From: Andy Mantell <134642+andymantell@users.noreply.github.com> Date: Fri, 23 Jul 2021 13:39:25 +0100 Subject: [PATCH 02/17] JS Linting fixes --- packages/components/checkboxes/checkboxes.js | 46 ++++++++++---------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/packages/components/checkboxes/checkboxes.js b/packages/components/checkboxes/checkboxes.js index 6df3ebce3..7f085c723 100644 --- a/packages/components/checkboxes/checkboxes.js +++ b/packages/components/checkboxes/checkboxes.js @@ -5,24 +5,29 @@ import { toggleConditionalInput } from '../../common'; * Test at http://0.0.0.0:3000/components/checkboxes/conditional.html */ +const syncAllConditionalReveals = function syncAllConditionalReveals(input) { + const allInputsWithSameName = document.querySelectorAll(`input[type="checkbox"][name="${input.name}"]`); + Array.from(allInputsWithSameName).map((item) => toggleConditionalInput(item, 'nhsuk-checkboxes__conditional--hidden')); +}; + /** * Uncheck other checkboxes * * Find any other checkbox inputs with the same name value, and uncheck them. * This is useful for when a “None of these" checkbox is checked. */ - const unCheckAllInputsExcept = function (input) { - const allInputsWithSameName = document.querySelectorAll('input[type="checkbox"][name="' + input.name + '"]') +const unCheckAllInputsExcept = function unCheckAllInputsExcept(input) { + const allInputsWithSameName = document.querySelectorAll(`input[type="checkbox"][name="${input.name}"]`); allInputsWithSameName.forEach((inputWithSameName) => { - const hasSameFormOwner = input.form === inputWithSameName.form + const hasSameFormOwner = input.form === inputWithSameName.form; if (hasSameFormOwner && inputWithSameName !== input) { - inputWithSameName.checked = false + inputWithSameName.checked = false; // eslint-disable-line no-param-reassign } - }) + }); - syncAllConditionalReveals(input) -} + syncAllConditionalReveals(input); +}; /** * Uncheck exclusive inputs @@ -31,25 +36,20 @@ import { toggleConditionalInput } from '../../common'; * and uncheck them. This helps prevent someone checking both a regular checkbox and a * "None of these" checkbox in the same fieldset. */ -const unCheckExclusiveInputs = function (input) { +const unCheckExclusiveInputs = function unCheckExclusiveInputs(input) { const allInputsWithSameNameAndExclusiveBehaviour = document.querySelectorAll( - 'input[data-behaviour="exclusive"][type="checkbox"][name="' + input.name + '"]' - ) + `input[data-behaviour="exclusive"][type="checkbox"][name="${input.name}"]` + ); allInputsWithSameNameAndExclusiveBehaviour.forEach((exclusiveInput) => { - const hasSameFormOwner = input.form === exclusiveInput.form + const hasSameFormOwner = input.form === exclusiveInput.form; if (hasSameFormOwner) { - exclusiveInput.checked = false + exclusiveInput.checked = false; // eslint-disable-line no-param-reassign } - }) - - syncAllConditionalReveals(input) -} + }); -const syncAllConditionalReveals = function(input) { - const allInputsWithSameName = document.querySelectorAll('input[type="checkbox"][name="' + input.name + '"]'); - Array.from(allInputsWithSameName).map((input) => toggleConditionalInput(input, 'nhsuk-checkboxes__conditional--hidden')); -} + syncAllConditionalReveals(input); +}; export default () => { // Checkbox input DOMElements inside a conditional form group @@ -64,14 +64,14 @@ export default () => { toggleConditionalInput(event.target, 'nhsuk-checkboxes__conditional--hidden'); if (!event.target.checked) { - return + return; } // Handle 'exclusive' checkbox behaviour (ie "None of these") if (event.target.getAttribute('data-behaviour') === 'exclusive') { - unCheckAllInputsExcept(event.target) + unCheckAllInputsExcept(event.target); } else { - unCheckExclusiveInputs(event.target) + unCheckExclusiveInputs(event.target); } }; From 8ad390b36d4202d91dcb5a6eb151dafc0a46d0e7 Mon Sep 17 00:00:00 2001 From: Andy Mantell <134642+andymantell@users.noreply.github.com> Date: Fri, 23 Jul 2021 13:56:28 +0100 Subject: [PATCH 03/17] Add backstop reference images for checkboxe none of these --- tests/backstop/backstop.js | 4 ++++ ...he_above_option_0_document_0_iPhone_5_SE.png | Bin 0 -> 18076 bytes ...the_above_option_0_document_1_iPhone_6-8.png | Bin 0 -> 18460 bytes ...ne_of_the_above_option_0_document_2_iPad.png | Bin 0 -> 24113 bytes ...ove_option_0_document_3_Surface_iPad_Pro.png | Bin 0 -> 25126 bytes 5 files changed, 4 insertions(+) create mode 100644 tests/backstop/bitmaps_reference/nhsuk-frontend_Checkboxes_with_none_of_the_above_option_0_document_0_iPhone_5_SE.png create mode 100644 tests/backstop/bitmaps_reference/nhsuk-frontend_Checkboxes_with_none_of_the_above_option_0_document_1_iPhone_6-8.png create mode 100644 tests/backstop/bitmaps_reference/nhsuk-frontend_Checkboxes_with_none_of_the_above_option_0_document_2_iPad.png create mode 100644 tests/backstop/bitmaps_reference/nhsuk-frontend_Checkboxes_with_none_of_the_above_option_0_document_3_Surface_iPad_Pro.png diff --git a/tests/backstop/backstop.js b/tests/backstop/backstop.js index 38207fde1..07046bfeb 100644 --- a/tests/backstop/backstop.js +++ b/tests/backstop/backstop.js @@ -134,6 +134,10 @@ module.exports = { url: `${TEST_URL}/checkboxes/conditional.html`, clickSelector: '#contact-1', }, + { + label: 'Checkboxes with "none of the above" option', + url: `${TEST_URL}/checkboxes/none-of-the-above.html`, + }, { label: 'Contents list', url: `${TEST_URL}/contents-list/index.html`, diff --git a/tests/backstop/bitmaps_reference/nhsuk-frontend_Checkboxes_with_none_of_the_above_option_0_document_0_iPhone_5_SE.png b/tests/backstop/bitmaps_reference/nhsuk-frontend_Checkboxes_with_none_of_the_above_option_0_document_0_iPhone_5_SE.png new file mode 100644 index 0000000000000000000000000000000000000000..da5e8dbff3222093098b299103ab0a9384d63a6b GIT binary patch literal 18076 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 DdAe~n literal 0 HcmV?d00001 diff --git a/tests/backstop/bitmaps_reference/nhsuk-frontend_Checkboxes_with_none_of_the_above_option_0_document_1_iPhone_6-8.png b/tests/backstop/bitmaps_reference/nhsuk-frontend_Checkboxes_with_none_of_the_above_option_0_document_1_iPhone_6-8.png new file mode 100644 index 0000000000000000000000000000000000000000..4bf2ef6a21699db338faf8bca7c64fc480e5a782 GIT binary patch literal 18460 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 dAb?!J4zFDfOtPYxzDyIZWR#?fUl@PFKDm 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 literal 0 HcmV?d00001 From 455c04322e6f68716ea187f064437a36c90f5c1f Mon Sep 17 00:00:00 2001 From: Andy Mantell <134642+andymantell@users.noreply.github.com> Date: Fri, 23 Jul 2021 16:09:33 +0100 Subject: [PATCH 04/17] Constrain checkbox selectors to same form as target checkbox --- .../checkboxes/none-of-the-above.njk | 84 ++++++++++--------- packages/components/checkboxes/checkboxes.js | 6 +- 2 files changed, 46 insertions(+), 44 deletions(-) diff --git a/app/components/checkboxes/none-of-the-above.njk b/app/components/checkboxes/none-of-the-above.njk index c9ca22bc6..5cbab3ba1 100644 --- a/app/components/checkboxes/none-of-the-above.njk +++ b/app/components/checkboxes/none-of-the-above.njk @@ -44,51 +44,53 @@
    - {{ checkboxes({ - "idPrefix": "contact", - "name": "contact", - "fieldset": { - "legend": { - "text": "How would you prefer to be contacted?", - "classes": "nhsuk-fieldset__legend--l", - "isPageHeading": "true" - } - }, - "hint": { - "text": "Select all options that are relevant to you." - }, - "items": [ - { - "value": "email", - "text": "Email", - "conditional": { - "html": emailHtml +
    + {{ checkboxes({ + "idPrefix": "contact", + "name": "contact", + "fieldset": { + "legend": { + "text": "How would you prefer to be contacted?", + "classes": "nhsuk-fieldset__legend--l", + "isPageHeading": "true" } }, - { - "value": "phone", - "text": "Phone", - "conditional": { - "html": phoneHtml - } + "hint": { + "text": "Select all options that are relevant to you." }, - { - "value": "text", - "text": "Text message", - "conditional": { - "html": mobileHtml + "items": [ + { + "value": "email", + "text": "Email", + "conditional": { + "html": emailHtml + } + }, + { + "value": "phone", + "text": "Phone", + "conditional": { + "html": phoneHtml + } + }, + { + "value": "text", + "text": "Text message", + "conditional": { + "html": mobileHtml + } + }, + { + divider: "or" + }, + { + value: "none", + text: "None of the above", + behaviour: "exclusive" } - }, - { - divider: "or" - }, - { - value: "none", - text: "None of the above", - behaviour: "exclusive" - } - ] - }) }} + ] + }) }} +
    diff --git a/packages/components/checkboxes/checkboxes.js b/packages/components/checkboxes/checkboxes.js index 7f085c723..292481410 100644 --- a/packages/components/checkboxes/checkboxes.js +++ b/packages/components/checkboxes/checkboxes.js @@ -6,7 +6,7 @@ import { toggleConditionalInput } from '../../common'; */ const syncAllConditionalReveals = function syncAllConditionalReveals(input) { - const allInputsWithSameName = document.querySelectorAll(`input[type="checkbox"][name="${input.name}"]`); + const allInputsWithSameName = input.form.querySelectorAll(`input[type="checkbox"][name="${input.name}"]`); Array.from(allInputsWithSameName).map((item) => toggleConditionalInput(item, 'nhsuk-checkboxes__conditional--hidden')); }; @@ -17,7 +17,7 @@ const syncAllConditionalReveals = function syncAllConditionalReveals(input) { * This is useful for when a “None of these" checkbox is checked. */ const unCheckAllInputsExcept = function unCheckAllInputsExcept(input) { - const allInputsWithSameName = document.querySelectorAll(`input[type="checkbox"][name="${input.name}"]`); + const allInputsWithSameName = input.form.querySelectorAll(`input[type="checkbox"][name="${input.name}"]`); allInputsWithSameName.forEach((inputWithSameName) => { const hasSameFormOwner = input.form === inputWithSameName.form; @@ -37,7 +37,7 @@ const unCheckAllInputsExcept = function unCheckAllInputsExcept(input) { * "None of these" checkbox in the same fieldset. */ const unCheckExclusiveInputs = function unCheckExclusiveInputs(input) { - const allInputsWithSameNameAndExclusiveBehaviour = document.querySelectorAll( + const allInputsWithSameNameAndExclusiveBehaviour = input.form.querySelectorAll( `input[data-behaviour="exclusive"][type="checkbox"][name="${input.name}"]` ); From a119446c3114d0acb76878a76ab9b33f4a360d04 Mon Sep 17 00:00:00 2001 From: Andy Mantell <134642+andymantell@users.noreply.github.com> Date: Mon, 26 Jul 2021 11:23:25 +0100 Subject: [PATCH 05/17] Rework radio conditionals to ensure nested conditionsl work if necessary Fixes #609 --- app/components/radios/nested-conditionals.njk | 128 ++++++++++++++++++ app/pages/examples.njk | 1 + packages/components/radios/radios.js | 32 +++-- 3 files changed, 149 insertions(+), 12 deletions(-) create mode 100644 app/components/radios/nested-conditionals.njk diff --git a/app/components/radios/nested-conditionals.njk b/app/components/radios/nested-conditionals.njk new file mode 100644 index 000000000..3821a7dbe --- /dev/null +++ b/app/components/radios/nested-conditionals.njk @@ -0,0 +1,128 @@ +{% set html_style = 'background-color: #f0f4f5;' %} +{% set title = 'Radios with nested conditonal content' %} +{% from 'components/radios/macro.njk' import radios %} +{% from 'components/input/macro.njk' import input %} +{% from 'components/warning-callout/macro.njk' import warningCallout %} +{% extends 'layout.njk' %} + +{% set emailHtml %} + {{ input({ + id: "email", + name: "email", + classes: "nhsuk-u-width-two-thirds", + label: { + text: "Email address" + } + }) }} +{% endset -%} + +{% set phoneHtml %} + {{ input({ + id: "phone", + name: "phone", + classes: "nhsuk-u-width-two-thirds", + label: { + text: "Phone number" + } + }) }} +{% endset -%} + +{% set mobileHtml %} + {{ input({ + id: "mobile", + name: "mobile", + classes: "nhsuk-u-width-two-thirds", + label: { + text: "Mobile phone number" + } + }) }} +{% endset -%} + +{%- set nestedConditional %} + {{ radios({ + "idPrefix": "inner", + "name": "inner", + "fieldset": { + "legend": { + "text": "How would you prefer to be contacted?", + "classes": "nhsuk-fieldset__legend--l", + "isPageHeading": "true" + } + }, + "hint": { + "text": "Select one option." + }, + "items": [ + { + "value": "email", + "text": "Email", + "conditional": { + "html": emailHtml + } + }, + { + "value": "phone", + "text": "Phone", + "conditional": { + "html": phoneHtml + } + }, + { + "value": "text", + "text": "Text message", + "conditional": { + "html": mobileHtml + } + } + ] + }) }} +{% endset -%} + +{% block body %} + +
    +
    + +
    +
    + + {{ warningCallout({ + "heading": "Important", + "HTML": "

    Please do everything in your power to avoid nested conditionals like this. The example is here to demonstrate that it works - not as a recommendation!

    " + }) }} +
    + {{ radios({ + "idPrefix": "outer", + "name": "outer", + "fieldset": { + "legend": { + "text": "How would you prefer to be contacted?", + "classes": "nhsuk-fieldset__legend--l", + "isPageHeading": "true" + } + }, + "hint": { + "text": "Select one option." + }, + "items": [ + { + "value": "no-conditional", + "text": "No conditional" + }, + { + "value": "nested", + "text": "Nested conditional", + "conditional": { + "html": nestedConditional + } + } + ] + }) }} +
    +
    +
    + +
    +
    + +{% endblock %} diff --git a/app/pages/examples.njk b/app/pages/examples.njk index 9f5757238..5fb991a6f 100644 --- a/app/pages/examples.njk +++ b/app/pages/examples.njk @@ -97,6 +97,7 @@
  • Radios without fieldset
  • Radios with hint text and error message
  • Radios with conditional content
  • +
  • Radios with nested conditional radios
  • Select
  • Select with hint text and error message
  • Skip link
  • diff --git a/packages/components/radios/radios.js b/packages/components/radios/radios.js index 1ac446ad2..f7035eb49 100644 --- a/packages/components/radios/radios.js +++ b/packages/components/radios/radios.js @@ -8,23 +8,31 @@ import { toggleConditionalInput } from '../../common'; export default () => { // Radio input HTMLElements inside a conditional form group const radioInputs = document.querySelectorAll('.nhsuk-radios--conditional .nhsuk-radios__input'); - // Conditional content inside a conditional form group - const conditionalInputs = document.querySelectorAll('.nhsuk-radios--conditional .nhsuk-radios__conditional'); /** - * Toggle classes and attributes - * @param {Object} event click event object + * Update all conditional reveals to match checked state */ - const handleClick = (event) => { - // Hide all conditional content on all input clicks - radioInputs.forEach((input) => input.setAttribute('aria-expanded', 'false')); - conditionalInputs.forEach((input) => input.classList.add('nhsuk-radios__conditional--hidden')); - // Toggle conditional content based on checked state - toggleConditionalInput(event.target, 'nhsuk-radios__conditional--hidden'); + const syncAllConditionalReveals = () => { + radioInputs.forEach((input) => toggleConditionalInput(input, 'nhsuk-radios__conditional--hidden')); }; - // Attach handleClick as click to radioInputs + // When the page is restored after navigating 'back' in some browsers the + // state of form controls is not restored until *after* the DOMContentLoaded + // event is fired, so we need to sync after the pageshow event in browsers + // that support it. + if ('onpageshow' in window) { + window.addEventListener('pageshow', syncAllConditionalReveals) + } else { + window.addEventListener('DOMContentLoaded', syncAllConditionalReveals) + } + + // Although we've set up handlers to sync state on the pageshow or + // DOMContentLoaded event, init could be called after those events have fired, + // for example if they are added to the page dynamically, so sync now too. + syncAllConditionalReveals(); + + // Attach event handler to radioInputs radioInputs.forEach((radioButton) => { - radioButton.addEventListener('change', handleClick); + radioButton.addEventListener('change', syncAllConditionalReveals); }); }; From 5026f05916ba8cc4c756688c60dbd953926d3075 Mon Sep 17 00:00:00 2001 From: Andy Mantell <134642+andymantell@users.noreply.github.com> Date: Mon, 26 Jul 2021 11:25:50 +0100 Subject: [PATCH 06/17] ensure checkbox conditional content re-shows after forward/back navigation --- app/components/checkboxes/conditional.njk | 68 ++++++++++---------- packages/components/checkboxes/checkboxes.js | 18 +++++- 2 files changed, 51 insertions(+), 35 deletions(-) diff --git a/app/components/checkboxes/conditional.njk b/app/components/checkboxes/conditional.njk index c19f22a24..df5499f3b 100644 --- a/app/components/checkboxes/conditional.njk +++ b/app/components/checkboxes/conditional.njk @@ -44,43 +44,45 @@
    - {{ checkboxes({ - "idPrefix": "contact", - "name": "contact", - "fieldset": { - "legend": { - "text": "How would you prefer to be contacted?", - "classes": "nhsuk-fieldset__legend--l", - "isPageHeading": "true" - } - }, - "hint": { - "text": "Select all options that are relevant to you." - }, - "items": [ - { - "value": "email", - "text": "Email", - "conditional": { - "html": emailHtml +
    + {{ checkboxes({ + "idPrefix": "contact", + "name": "contact", + "fieldset": { + "legend": { + "text": "How would you prefer to be contacted?", + "classes": "nhsuk-fieldset__legend--l", + "isPageHeading": "true" } }, - { - "value": "phone", - "text": "Phone", - "conditional": { - "html": phoneHtml - } + "hint": { + "text": "Select all options that are relevant to you." }, - { - "value": "text", - "text": "Text message", - "conditional": { - "html": mobileHtml + "items": [ + { + "value": "email", + "text": "Email", + "conditional": { + "html": emailHtml + } + }, + { + "value": "phone", + "text": "Phone", + "conditional": { + "html": phoneHtml + } + }, + { + "value": "text", + "text": "Text message", + "conditional": { + "html": mobileHtml + } } - } - ] - }) }} + ] + }) }} +
    diff --git a/packages/components/checkboxes/checkboxes.js b/packages/components/checkboxes/checkboxes.js index 292481410..32e829a7a 100644 --- a/packages/components/checkboxes/checkboxes.js +++ b/packages/components/checkboxes/checkboxes.js @@ -4,10 +4,9 @@ import { toggleConditionalInput } from '../../common'; * Conditionally show content when a checkbox button is checked * Test at http://0.0.0.0:3000/components/checkboxes/conditional.html */ - const syncAllConditionalReveals = function syncAllConditionalReveals(input) { const allInputsWithSameName = input.form.querySelectorAll(`input[type="checkbox"][name="${input.name}"]`); - Array.from(allInputsWithSameName).map((item) => toggleConditionalInput(item, 'nhsuk-checkboxes__conditional--hidden')); + allInputsWithSameName.forEach((item) => toggleConditionalInput(item, 'nhsuk-checkboxes__conditional--hidden')); }; /** @@ -75,6 +74,21 @@ export default () => { } }; + // When the page is restored after navigating 'back' in some browsers the + // state of form controls is not restored until *after* the DOMContentLoaded + // event is fired, so we need to sync after the pageshow event in browsers + // that support it. + if ('onpageshow' in window) { + window.addEventListener('pageshow', () => checkboxInputs.forEach((input) => syncAllConditionalReveals(input))); + } else { + window.addEventListener('DOMContentLoaded', () => checkboxInputs.forEach((input) => syncAllConditionalReveals(input))); + } + + // Although we've set up handlers to sync state on the pageshow or + // DOMContentLoaded event, init could be called after those events have fired, + // for example if they are added to the page dynamically, so sync now too. + checkboxInputs.forEach((input) => syncAllConditionalReveals(input)); + // Attach handleClick as click to checkboxInputs checkboxInputs.forEach((checkboxButton) => { checkboxButton.addEventListener('change', handleClick); From 66993aa6ddba801332e83f79ae325a69872bf72e Mon Sep 17 00:00:00 2001 From: Andy Mantell <134642+andymantell@users.noreply.github.com> Date: Mon, 26 Jul 2021 11:26:54 +0100 Subject: [PATCH 07/17] Linting fixes --- packages/components/radios/radios.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/components/radios/radios.js b/packages/components/radios/radios.js index f7035eb49..a33008660 100644 --- a/packages/components/radios/radios.js +++ b/packages/components/radios/radios.js @@ -12,7 +12,7 @@ export default () => { /** * Update all conditional reveals to match checked state */ - const syncAllConditionalReveals = () => { + const syncAllConditionalReveals = () => { radioInputs.forEach((input) => toggleConditionalInput(input, 'nhsuk-radios__conditional--hidden')); }; @@ -21,9 +21,9 @@ export default () => { // event is fired, so we need to sync after the pageshow event in browsers // that support it. if ('onpageshow' in window) { - window.addEventListener('pageshow', syncAllConditionalReveals) + window.addEventListener('pageshow', syncAllConditionalReveals); } else { - window.addEventListener('DOMContentLoaded', syncAllConditionalReveals) + window.addEventListener('DOMContentLoaded', syncAllConditionalReveals); } // Although we've set up handlers to sync state on the pageshow or From 45c91309261a04bc21e424f888747f68e3b7b2d5 Mon Sep 17 00:00:00 2001 From: Andy Mantell <134642+andymantell@users.noreply.github.com> Date: Mon, 26 Jul 2021 13:08:55 +0100 Subject: [PATCH 08/17] Fix incorrect aria-expanded attribute on checkboxes --- packages/common.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/common.js b/packages/common.js index 0fe6a6691..d3c8bb85c 100644 --- a/packages/common.js +++ b/packages/common.js @@ -27,10 +27,10 @@ export const toggleConditionalInput = (input, className) => { if (conditionalElement) { if (input.checked) { conditionalElement.classList.remove(className); - input.setAttribute('aria-expanded', false); + input.setAttribute('aria-expanded', true); } else { conditionalElement.classList.add(className); - input.setAttribute('aria-expanded', true); + input.setAttribute('aria-expanded', false); } } } From efa6b2e09aea7538bfd67da992da1abcf077e591 Mon Sep 17 00:00:00 2001 From: Andy Mantell <134642+andymantell@users.noreply.github.com> Date: Mon, 26 Jul 2021 13:09:20 +0100 Subject: [PATCH 09/17] Fix checkbox / util tests for new checkbox changes --- tests/integration/checkboxes.test.js | 8 ++++---- tests/integration/common.test.js | 4 ++++ 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/tests/integration/checkboxes.test.js b/tests/integration/checkboxes.test.js index 2edced87a..8ee9a4f56 100644 --- a/tests/integration/checkboxes.test.js +++ b/tests/integration/checkboxes.test.js @@ -13,10 +13,10 @@ describe('Checkboxes module', () => { describe('displays conditional content', () => { it('when checking the input', () => { - document.body.innerHTML = `
    + document.body.innerHTML = `
    Test
    -
    `; +
    `; const input = document.querySelector('#input-1'); const conditional = document.querySelector('#conditional-1'); Checkboxes(); @@ -28,10 +28,10 @@ describe('Checkboxes module', () => { describe('hides conditional content', () => { it('when unchecking the input', () => { - document.body.innerHTML = `
    + document.body.innerHTML = `
    Test
    -
    `; +
    `; const input = document.querySelector('#input-1'); const conditional = document.querySelector('#conditional-1'); Checkboxes(); diff --git a/tests/integration/common.test.js b/tests/integration/common.test.js index 1b34a7bbb..66ed0d4aa 100644 --- a/tests/integration/common.test.js +++ b/tests/integration/common.test.js @@ -81,9 +81,11 @@ describe('toggleConditionalInput util', () => { const content = document.querySelector('div'); expect(input).not.toBeNull(); expect(content).not.toBeNull(); + input.checked = true; toggleConditionalInput(input, 'hidden'); expect(content.classList.contains('hidden')).toEqual(false); expect(input.getAttribute('aria-expanded')).toEqual('true'); + input.checked = false; toggleConditionalInput(input, 'hidden'); expect(content.classList.contains('hidden')).toEqual(true); expect(input.getAttribute('aria-expanded')).toEqual('false'); @@ -95,9 +97,11 @@ describe('toggleConditionalInput util', () => { const content = document.querySelector('div'); expect(input).not.toBeNull(); expect(content).not.toBeNull(); + input.checked = false; toggleConditionalInput(input, 'hidden'); expect(content.classList.contains('hidden')).toEqual(true); expect(input.getAttribute('aria-expanded')).toEqual('false'); + input.checked = true; toggleConditionalInput(input, 'hidden'); expect(content.classList.contains('hidden')).toEqual(false); expect(input.getAttribute('aria-expanded')).toEqual('true'); From f505691caa293a664de7f57ca71aec7583c772e4 Mon Sep 17 00:00:00 2001 From: Andy Mantell <134642+andymantell@users.noreply.github.com> Date: Tue, 27 Jul 2021 13:31:25 +0100 Subject: [PATCH 10/17] Reworking the checkbox exclusive / none of these behaviour to cope with different input names within a single group --- .../checkboxes/none-of-the-above.njk | 16 +++- packages/components/checkboxes/README.md | 75 ++++++++++--------- packages/components/checkboxes/checkboxes.js | 20 ++--- packages/components/checkboxes/template.njk | 3 +- 4 files changed, 65 insertions(+), 49 deletions(-) diff --git a/app/components/checkboxes/none-of-the-above.njk b/app/components/checkboxes/none-of-the-above.njk index 5cbab3ba1..e6bd13f96 100644 --- a/app/components/checkboxes/none-of-the-above.njk +++ b/app/components/checkboxes/none-of-the-above.njk @@ -62,6 +62,8 @@ { "value": "email", "text": "Email", + "name": "email", + "exclusiveGroup": "communication-preferences", "conditional": { "html": emailHtml } @@ -69,6 +71,8 @@ { "value": "phone", "text": "Phone", + "name": "phone", + "exclusiveGroup": "communication-preferences", "conditional": { "html": phoneHtml } @@ -76,17 +80,21 @@ { "value": "text", "text": "Text message", + "name": "text", + "exclusiveGroup": "communication-preferences", "conditional": { "html": mobileHtml } }, { - divider: "or" + "divider": "or" }, { - value: "none", - text: "None of the above", - behaviour: "exclusive" + "value": "none", + "text": "None of the above", + "name": "none", + "exclusive": true, + "exclusiveGroup": "communication-preferences" } ] }) }} diff --git a/packages/components/checkboxes/README.md b/packages/components/checkboxes/README.md index 27e6fb1a1..89c168ae8 100644 --- a/packages/components/checkboxes/README.md +++ b/packages/components/checkboxes/README.md @@ -522,59 +522,55 @@ Find out more about the checkboxes component and when to use it in the [NHS digi How would you prefer to be contacted? +
    Select all options that are relevant to you.
    +
    - - -
    + + +
    +
    - - + +
    +
    - - + +
    +
    - - + +
    +
    - - + +
    +
    - - + +
    +
    or
    +
    - - -
    + + + @@ -636,6 +632,8 @@ Find out more about the checkboxes component and when to use it in the [NHS digi { "value": "email", "text": "Email", + "name": "email", + "exclusiveGroup": "communication-preferences", "conditional": { "html": emailHtml } @@ -643,6 +641,8 @@ Find out more about the checkboxes component and when to use it in the [NHS digi { "value": "phone", "text": "Phone", + "name": "phone", + "exclusiveGroup": "communication-preferences", "conditional": { "html": phoneHtml } @@ -650,17 +650,21 @@ Find out more about the checkboxes component and when to use it in the [NHS digi { "value": "text", "text": "Text message", + "name": "text", + "exclusiveGroup": "communication-preferences", "conditional": { "html": mobileHtml } }, { - divider: "or" + "divider": "or" }, { - value: "none", - text: "None of the above", - behaviour: "exclusive" + "value": "none", + "text": "None of the above", + "name": "none", + "exclusive": true, + "exclusiveGroup": "communication-preferences" } ] }) }} @@ -694,7 +698,8 @@ The checkboxes Nunjucks macro takes the following arguments: | **items[].conditional.html** | string | No | HTML to be displayed when the checkbox is checked | | **classes** | string | No | Optional additional classes to add to the checkboxes container. Separate each class with a space. | | **attributes** | object | No | Any extra HTML attributes (for example data attributes) to add to the checkboxes container. | -| **behaviour** | string | No | If set to `exclusive`, implements a "None of these" type behaviour via javascript when checkboxes are clicked | +| **exclusive** | boolean | No | If set to `true`, marks this checkbox as the "None" option in a "None of these" type behaviour. Unchecking all other checkboxes in the group when "None" is clicked | +| **exclusiveGroup** | string | No | Used in conjunction with `exclusive` - this should be set to a string which groups checkboxes together into a set for use in a "None of these" scenario. | If you are using Nunjucks macros in production be aware that using `html` arguments, or ones ending with `html` can be a [security risk](https://developer.mozilla.org/en-US/docs/Glossary/Cross-site_scripting). Read more about this in the [Nunjucks documentation](https://mozilla.github.io/nunjucks/api.html#user-defined-templates-warning). diff --git a/packages/components/checkboxes/checkboxes.js b/packages/components/checkboxes/checkboxes.js index 32e829a7a..4ebcffa74 100644 --- a/packages/components/checkboxes/checkboxes.js +++ b/packages/components/checkboxes/checkboxes.js @@ -5,8 +5,8 @@ import { toggleConditionalInput } from '../../common'; * Test at http://0.0.0.0:3000/components/checkboxes/conditional.html */ const syncAllConditionalReveals = function syncAllConditionalReveals(input) { - const allInputsWithSameName = input.form.querySelectorAll(`input[type="checkbox"][name="${input.name}"]`); - allInputsWithSameName.forEach((item) => toggleConditionalInput(item, 'nhsuk-checkboxes__conditional--hidden')); + const allInputsInForm = input.form.querySelectorAll(`input[type="checkbox"]`); + allInputsInForm.forEach((item) => toggleConditionalInput(item, 'nhsuk-checkboxes__conditional--hidden')); }; /** @@ -16,9 +16,11 @@ const syncAllConditionalReveals = function syncAllConditionalReveals(input) { * This is useful for when a “None of these" checkbox is checked. */ const unCheckAllInputsExcept = function unCheckAllInputsExcept(input) { - const allInputsWithSameName = input.form.querySelectorAll(`input[type="checkbox"][name="${input.name}"]`); + const allInputsInSameExclusiveGroup = input.form.querySelectorAll( + `input[type="checkbox"][data-checkbox-exclusive-group="${input.getAttribute('data-checkbox-exclusive-group')}"]` + ); - allInputsWithSameName.forEach((inputWithSameName) => { + allInputsInSameExclusiveGroup.forEach((inputWithSameName) => { const hasSameFormOwner = input.form === inputWithSameName.form; if (hasSameFormOwner && inputWithSameName !== input) { inputWithSameName.checked = false; // eslint-disable-line no-param-reassign @@ -36,11 +38,11 @@ const unCheckAllInputsExcept = function unCheckAllInputsExcept(input) { * "None of these" checkbox in the same fieldset. */ const unCheckExclusiveInputs = function unCheckExclusiveInputs(input) { - const allInputsWithSameNameAndExclusiveBehaviour = input.form.querySelectorAll( - `input[data-behaviour="exclusive"][type="checkbox"][name="${input.name}"]` + const allExclusiveInputsInSameExclusiveGroup = input.form.querySelectorAll( + `input[type="checkbox"][data-checkbox-exclusive][data-checkbox-exclusive-group="${input.getAttribute('data-checkbox-exclusive-group')}"]` ); - allInputsWithSameNameAndExclusiveBehaviour.forEach((exclusiveInput) => { + allExclusiveInputsInSameExclusiveGroup.forEach((exclusiveInput) => { const hasSameFormOwner = input.form === exclusiveInput.form; if (hasSameFormOwner) { exclusiveInput.checked = false; // eslint-disable-line no-param-reassign @@ -52,7 +54,7 @@ const unCheckExclusiveInputs = function unCheckExclusiveInputs(input) { export default () => { // Checkbox input DOMElements inside a conditional form group - const checkboxInputs = document.querySelectorAll('.nhsuk-checkboxes--conditional .nhsuk-checkboxes__input'); + const checkboxInputs = document.querySelectorAll('.nhsuk-checkboxes .nhsuk-checkboxes__input'); /** * Toggle classes and attributes @@ -67,7 +69,7 @@ export default () => { } // Handle 'exclusive' checkbox behaviour (ie "None of these") - if (event.target.getAttribute('data-behaviour') === 'exclusive') { + if (event.target.hasAttribute("data-checkbox-exclusive")) { unCheckAllInputsExcept(event.target); } else { unCheckExclusiveInputs(event.target); diff --git a/packages/components/checkboxes/template.njk b/packages/components/checkboxes/template.njk index d0968332d..2ec9cd7b8 100644 --- a/packages/components/checkboxes/template.njk +++ b/packages/components/checkboxes/template.njk @@ -56,7 +56,8 @@ From 45393a8e1971ecd396c7712623544789da201d1e Mon Sep 17 00:00:00 2001 From: Andy Mantell <134642+andymantell@users.noreply.github.com> Date: Tue, 27 Jul 2021 13:32:42 +0100 Subject: [PATCH 11/17] JS linting --- packages/components/checkboxes/checkboxes.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/components/checkboxes/checkboxes.js b/packages/components/checkboxes/checkboxes.js index 4ebcffa74..04224fc6c 100644 --- a/packages/components/checkboxes/checkboxes.js +++ b/packages/components/checkboxes/checkboxes.js @@ -5,7 +5,7 @@ import { toggleConditionalInput } from '../../common'; * Test at http://0.0.0.0:3000/components/checkboxes/conditional.html */ const syncAllConditionalReveals = function syncAllConditionalReveals(input) { - const allInputsInForm = input.form.querySelectorAll(`input[type="checkbox"]`); + const allInputsInForm = input.form.querySelectorAll('input[type="checkbox"]'); allInputsInForm.forEach((item) => toggleConditionalInput(item, 'nhsuk-checkboxes__conditional--hidden')); }; @@ -69,7 +69,7 @@ export default () => { } // Handle 'exclusive' checkbox behaviour (ie "None of these") - if (event.target.hasAttribute("data-checkbox-exclusive")) { + if (event.target.hasAttribute('data-checkbox-exclusive')) { unCheckAllInputsExcept(event.target); } else { unCheckExclusiveInputs(event.target); From 90f2c4a1e2817cfdbe7d418b085b52bb92562cc1 Mon Sep 17 00:00:00 2001 From: Andy Mantell <134642+andymantell@users.noreply.github.com> Date: Tue, 27 Jul 2021 13:35:14 +0100 Subject: [PATCH 12/17] Fix bad link in readme --- packages/components/checkboxes/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/components/checkboxes/README.md b/packages/components/checkboxes/README.md index 89c168ae8..938fad9b3 100644 --- a/packages/components/checkboxes/README.md +++ b/packages/components/checkboxes/README.md @@ -510,7 +510,7 @@ Find out more about the checkboxes component and when to use it in the [NHS digi ### Checkboxes with "none of the above" option -[Preview the checkboxes with "none of the above" option](https://nhsuk.github.io/nhsuk-frontend/components/checkboxes/conditional.html) +[Preview the checkboxes with "none of the above" option](https://nhsuk.github.io/nhsuk-frontend/components/checkboxes/none-of-the-above.html) #### HTML markup From a27fcff6cc49d9cc822a24be8f7747375ca2eac0 Mon Sep 17 00:00:00 2001 From: Andy Mantell <134642+andymantell@users.noreply.github.com> Date: Tue, 27 Jul 2021 13:38:15 +0100 Subject: [PATCH 13/17] Tweak code comments in checkboxes js --- packages/components/checkboxes/checkboxes.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/components/checkboxes/checkboxes.js b/packages/components/checkboxes/checkboxes.js index 04224fc6c..480393d83 100644 --- a/packages/components/checkboxes/checkboxes.js +++ b/packages/components/checkboxes/checkboxes.js @@ -12,7 +12,7 @@ const syncAllConditionalReveals = function syncAllConditionalReveals(input) { /** * Uncheck other checkboxes * - * Find any other checkbox inputs with the same name value, and uncheck them. + * Find any other checkbox inputs with the checkbox group value, and uncheck them. * This is useful for when a “None of these" checkbox is checked. */ const unCheckAllInputsExcept = function unCheckAllInputsExcept(input) { @@ -33,7 +33,7 @@ const unCheckAllInputsExcept = function unCheckAllInputsExcept(input) { /** * Uncheck exclusive inputs * - * Find any checkbox inputs with the same name value and the 'exclusive' behaviour, + * Find any checkbox inputs with the same checkbox group value and the 'exclusive' behaviour, * and uncheck them. This helps prevent someone checking both a regular checkbox and a * "None of these" checkbox in the same fieldset. */ From 27e43aec9d8adccc93dd7935c39102eee113b1f1 Mon Sep 17 00:00:00 2001 From: Andy Mantell <134642+andymantell@users.noreply.github.com> Date: Tue, 27 Jul 2021 13:40:37 +0100 Subject: [PATCH 14/17] Fix checkboxes tests to cope with recent markup tweak --- tests/integration/checkboxes.test.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/integration/checkboxes.test.js b/tests/integration/checkboxes.test.js index 8ee9a4f56..af10f80f4 100644 --- a/tests/integration/checkboxes.test.js +++ b/tests/integration/checkboxes.test.js @@ -6,14 +6,14 @@ describe('Checkboxes module', () => { Checkboxes(); }); it('if there are no conditional checkboxes inside the container', () => { - document.body.innerHTML = '
    '; + document.body.innerHTML = '
    '; Checkboxes(); }); }); describe('displays conditional content', () => { it('when checking the input', () => { - document.body.innerHTML = `
    + document.body.innerHTML = `
    Test
    `; @@ -28,7 +28,7 @@ describe('Checkboxes module', () => { describe('hides conditional content', () => { it('when unchecking the input', () => { - document.body.innerHTML = `
    + document.body.innerHTML = `
    Test
    `; From e4c3d56f9e3e5f6bef43256932c12c2da10f3930 Mon Sep 17 00:00:00 2001 From: Andy Mantell <134642+andymantell@users.noreply.github.com> Date: Tue, 27 Jul 2021 13:49:11 +0100 Subject: [PATCH 15/17] Add changelog entry for JS 'none of these' behaviour --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7c6a64ef1..6e631a645 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # NHS.UK frontend Changelog +## 5.2.0 - Unreleased + +:new: **New features** + +- Add "None of these" JavaScript behaviour to checkboxes - allowing all checkboxes in a group to be automatically unchecked when the "None of the above" option is checked ([PR 756](https://github.com/nhsuk/nhsuk-frontend/pull/756)) + ## 5.1.0 - 14 May 2021 :new: **New features** From 02f1114b9a36edefd3f861c5c31141f983b6ba6d Mon Sep 17 00:00:00 2001 From: Andy Mantell <134642+andymantell@users.noreply.github.com> Date: Thu, 29 Jul 2021 08:39:08 +0100 Subject: [PATCH 16/17] Fix incorrect title on checkbox demo page --- app/components/checkboxes/none-of-the-above.njk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/components/checkboxes/none-of-the-above.njk b/app/components/checkboxes/none-of-the-above.njk index e6bd13f96..f0ff196d3 100644 --- a/app/components/checkboxes/none-of-the-above.njk +++ b/app/components/checkboxes/none-of-the-above.njk @@ -1,5 +1,5 @@ {% set html_style = 'background-color: #f0f4f5;' %} -{% set title = 'Checkboxes with conditional content' %} +{% set title = 'Checkboxes with "none of the above" option' %} {% from 'components/checkboxes/macro.njk' import checkboxes %} {% from 'components/input/macro.njk' import input %} {% extends 'layout.njk' %} From 7420eec322c5a7e7ac98cfc6418f6637621a6913 Mon Sep 17 00:00:00 2001 From: Andy Mantell <134642+andymantell@users.noreply.github.com> Date: Thu, 29 Jul 2021 08:40:18 +0100 Subject: [PATCH 17/17] Remove duplicated h1 tag from nested conditionals page --- app/components/radios/nested-conditionals.njk | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/app/components/radios/nested-conditionals.njk b/app/components/radios/nested-conditionals.njk index 3821a7dbe..99ef5465c 100644 --- a/app/components/radios/nested-conditionals.njk +++ b/app/components/radios/nested-conditionals.njk @@ -45,8 +45,7 @@ "fieldset": { "legend": { "text": "How would you prefer to be contacted?", - "classes": "nhsuk-fieldset__legend--l", - "isPageHeading": "true" + "classes": "nhsuk-fieldset__legend--l" } }, "hint": {