govuk_publishing_components 28.5.0 → 28.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (118) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/javascripts/govuk_publishing_components/analytics/track-select-change.js +4 -3
  3. data/app/assets/javascripts/govuk_publishing_components/components/accordion.js +21 -291
  4. data/app/assets/javascripts/govuk_publishing_components/components/button.js +1 -1
  5. data/app/assets/javascripts/govuk_publishing_components/components/character-count.js +1 -1
  6. data/app/assets/javascripts/govuk_publishing_components/components/checkboxes.js +1 -1
  7. data/app/assets/javascripts/govuk_publishing_components/components/details.js +1 -1
  8. data/app/assets/javascripts/govuk_publishing_components/components/error-summary.js +1 -1
  9. data/app/assets/javascripts/govuk_publishing_components/components/layout-header.js +1 -1
  10. data/app/assets/javascripts/govuk_publishing_components/components/radio.js +1 -1
  11. data/app/assets/javascripts/govuk_publishing_components/components/skip-link.js +5 -0
  12. data/app/assets/javascripts/govuk_publishing_components/components/step-by-step-nav.js +40 -37
  13. data/app/assets/javascripts/govuk_publishing_components/components/tabs.js +1 -1
  14. data/app/assets/javascripts/govuk_publishing_components/lib/govspeak/barchart-enhancement.js +2 -1
  15. data/app/assets/javascripts/govuk_publishing_components/lib/govspeak/magna-charta.js +8 -10
  16. data/app/assets/javascripts/govuk_publishing_components/lib/initial-focus.js +4 -3
  17. data/app/assets/javascripts/govuk_publishing_components/lib/toggle-input-class-on-focus.js +4 -3
  18. data/app/assets/javascripts/govuk_publishing_components/lib/toggle.js +4 -3
  19. data/app/assets/stylesheets/govuk_publishing_components/components/_accordion.scss +1 -329
  20. data/app/assets/stylesheets/govuk_publishing_components/components/_share-links.scss +1 -1
  21. data/app/assets/stylesheets/govuk_publishing_components/components/_step-by-step-nav.scss +95 -56
  22. data/app/assets/stylesheets/govuk_publishing_components/components/print/_accordion.scss +6 -17
  23. data/app/assets/stylesheets/govuk_publishing_components/govuk_frontend_support.scss +0 -9
  24. data/app/views/govuk_publishing_components/components/_accordion.html.erb +31 -16
  25. data/app/views/govuk_publishing_components/components/_button.html.erb +1 -1
  26. data/app/views/govuk_publishing_components/components/_character_count.html.erb +2 -2
  27. data/app/views/govuk_publishing_components/components/_checkboxes.html.erb +2 -2
  28. data/app/views/govuk_publishing_components/components/_error_message.html.erb +1 -1
  29. data/app/views/govuk_publishing_components/components/_error_summary.html.erb +0 -1
  30. data/app/views/govuk_publishing_components/components/_inset_text.html.erb +12 -1
  31. data/app/views/govuk_publishing_components/components/_layout_footer.html.erb +1 -1
  32. data/app/views/govuk_publishing_components/components/_modal_dialogue.html.erb +1 -1
  33. data/app/views/govuk_publishing_components/components/_radio.html.erb +1 -1
  34. data/app/views/govuk_publishing_components/components/_skip_link.html.erb +1 -1
  35. data/app/views/govuk_publishing_components/components/docs/accordion.yml +2 -97
  36. data/app/views/govuk_publishing_components/components/docs/govspeak.yml +1 -1
  37. data/app/views/govuk_publishing_components/components/docs/inset_text.yml +6 -0
  38. data/app/views/govuk_publishing_components/components/docs/share_links.yml +1 -1
  39. data/app/views/govuk_publishing_components/components/docs/step_by_step_nav.yml +13 -13
  40. data/app/views/govuk_publishing_components/components/docs/tabs.yml +1 -1
  41. data/app/views/govuk_publishing_components/components/docs/textarea.yml +1 -1
  42. data/app/views/govuk_publishing_components/components/layout_header/_navigation_items.html.erb +11 -11
  43. data/lib/govuk_publishing_components/version.rb +1 -1
  44. data/node_modules/govuk-frontend/govuk/all.js +294 -76
  45. data/node_modules/govuk-frontend/govuk/components/accordion/_index.scss +274 -99
  46. data/node_modules/govuk-frontend/govuk/components/accordion/accordion.js +169 -65
  47. data/node_modules/govuk-frontend/govuk/components/accordion/fixtures.json +37 -5
  48. data/node_modules/govuk-frontend/govuk/components/accordion/macro-options.json +4 -4
  49. data/node_modules/govuk-frontend/govuk/components/button/button.js +2 -2
  50. data/node_modules/govuk-frontend/govuk/components/character-count/character-count.js +3 -3
  51. data/node_modules/govuk-frontend/govuk/components/character-count/fixtures.json +15 -2
  52. data/node_modules/govuk-frontend/govuk/components/checkboxes/checkboxes.js +8 -10
  53. data/node_modules/govuk-frontend/govuk/components/checkboxes/fixtures.json +52 -15
  54. data/node_modules/govuk-frontend/govuk/components/cookie-banner/_index.scss +0 -2
  55. data/node_modules/govuk-frontend/govuk/components/cookie-banner/fixtures.json +31 -0
  56. data/node_modules/govuk-frontend/govuk/components/date-input/fixtures.json +25 -25
  57. data/node_modules/govuk-frontend/govuk/components/details/details.js +2 -2
  58. data/node_modules/govuk-frontend/govuk/components/error-message/_index.scss +1 -0
  59. data/node_modules/govuk-frontend/govuk/components/error-message/fixtures.json +8 -8
  60. data/node_modules/govuk-frontend/govuk/components/error-message/template.njk +2 -2
  61. data/node_modules/govuk-frontend/govuk/components/error-summary/error-summary.js +24 -3
  62. data/node_modules/govuk-frontend/govuk/components/error-summary/fixtures.json +25 -16
  63. data/node_modules/govuk-frontend/govuk/components/error-summary/macro-options.json +6 -0
  64. data/node_modules/govuk-frontend/govuk/components/error-summary/template.njk +2 -1
  65. data/node_modules/govuk-frontend/govuk/components/file-upload/fixtures.json +4 -4
  66. data/node_modules/govuk-frontend/govuk/components/footer/_index.scss +3 -37
  67. data/node_modules/govuk-frontend/govuk/components/footer/fixtures.json +119 -15
  68. data/node_modules/govuk-frontend/govuk/components/footer/macro-options.json +6 -0
  69. data/node_modules/govuk-frontend/govuk/components/footer/template.njk +1 -1
  70. data/node_modules/govuk-frontend/govuk/components/header/_index.scss +10 -4
  71. data/node_modules/govuk-frontend/govuk/components/header/fixtures.json +11 -11
  72. data/node_modules/govuk-frontend/govuk/components/header/header.js +4 -4
  73. data/node_modules/govuk-frontend/govuk/components/header/template.njk +4 -3
  74. data/node_modules/govuk-frontend/govuk/components/hint/_index.scss +1 -3
  75. data/node_modules/govuk-frontend/govuk/components/input/_index.scss +1 -1
  76. data/node_modules/govuk-frontend/govuk/components/input/fixtures.json +40 -40
  77. data/node_modules/govuk-frontend/govuk/components/input/template.njk +4 -3
  78. data/node_modules/govuk-frontend/govuk/components/notification-banner/notification-banner.js +499 -2
  79. data/node_modules/govuk-frontend/govuk/components/phase-banner/fixtures.json +2 -2
  80. data/node_modules/govuk-frontend/govuk/components/radios/_index.scss +0 -8
  81. data/node_modules/govuk-frontend/govuk/components/radios/fixtures.json +44 -45
  82. data/node_modules/govuk-frontend/govuk/components/radios/radios.js +4 -4
  83. data/node_modules/govuk-frontend/govuk/components/radios/template.njk +2 -9
  84. data/node_modules/govuk-frontend/govuk/components/select/_index.scss +6 -1
  85. data/node_modules/govuk-frontend/govuk/components/select/fixtures.json +3 -3
  86. data/node_modules/govuk-frontend/govuk/components/skip-link/_index.scss +13 -0
  87. data/node_modules/govuk-frontend/govuk/components/skip-link/fixtures.json +9 -9
  88. data/node_modules/govuk-frontend/govuk/components/skip-link/skip-link.js +1108 -0
  89. data/node_modules/govuk-frontend/govuk/components/skip-link/template.njk +1 -1
  90. data/node_modules/govuk-frontend/govuk/components/summary-list/_index.scss +20 -23
  91. data/node_modules/govuk-frontend/govuk/components/summary-list/fixtures.json +86 -1
  92. data/node_modules/govuk-frontend/govuk/components/summary-list/template.njk +1 -4
  93. data/node_modules/govuk-frontend/govuk/components/tabs/_index.scss +2 -2
  94. data/node_modules/govuk-frontend/govuk/components/tabs/tabs.js +2 -2
  95. data/node_modules/govuk-frontend/govuk/components/tag/_index.scss +0 -5
  96. data/node_modules/govuk-frontend/govuk/components/tag/fixtures.json +2 -2
  97. data/node_modules/govuk-frontend/govuk/components/textarea/_index.scss +1 -1
  98. data/node_modules/govuk-frontend/govuk/components/textarea/fixtures.json +4 -4
  99. data/node_modules/govuk-frontend/govuk/core/_all.scss +0 -1
  100. data/node_modules/govuk-frontend/govuk/core/_global-styles.scss +0 -6
  101. data/node_modules/govuk-frontend/govuk/core/_links.scss +0 -6
  102. data/node_modules/govuk-frontend/govuk/core/_lists.scss +0 -6
  103. data/node_modules/govuk-frontend/govuk/core/_section-break.scss +0 -6
  104. data/node_modules/govuk-frontend/govuk/core/_typography.scss +0 -6
  105. data/node_modules/govuk-frontend/govuk/objects/_all.scss +1 -0
  106. data/node_modules/govuk-frontend/govuk/objects/_main-wrapper.scss +15 -30
  107. data/node_modules/govuk-frontend/govuk/{core → objects}/_template.scss +1 -5
  108. data/node_modules/govuk-frontend/govuk/overrides/_display.scss +0 -6
  109. data/node_modules/govuk-frontend/govuk/overrides/_spacing.scss +0 -6
  110. data/node_modules/govuk-frontend/govuk/overrides/_text-align.scss +0 -6
  111. data/node_modules/govuk-frontend/govuk/overrides/_typography.scss +0 -6
  112. data/node_modules/govuk-frontend/govuk/overrides/_width.scss +0 -6
  113. data/node_modules/govuk-frontend/govuk/settings/_colours-organisations.scss +3 -0
  114. data/node_modules/govuk-frontend/govuk/settings/_measurements.scss +0 -10
  115. data/node_modules/govuk-frontend/govuk/tools/_all.scss +0 -1
  116. data/node_modules/govuk-frontend/package.json +1 -1
  117. metadata +8 -7
  118. data/node_modules/govuk-frontend/govuk/tools/_iff.scss +0 -17
@@ -1,7 +1,7 @@
1
1
  (function (global, factory) {
2
2
  typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
3
- typeof define === 'function' && define.amd ? define('GOVUKFrontend', factory) :
4
- (global.GOVUKFrontend = factory());
3
+ typeof define === 'function' && define.amd ? define('GOVUKFrontend.Accordion', factory) :
4
+ (global.GOVUKFrontend = global.GOVUKFrontend || {}, global.GOVUKFrontend.Accordion = factory());
5
5
  }(this, (function () { 'use strict';
6
6
 
7
7
  /**
@@ -762,19 +762,28 @@ function Accordion ($module) {
762
762
  this.$module = $module;
763
763
  this.moduleId = $module.getAttribute('id');
764
764
  this.$sections = $module.querySelectorAll('.govuk-accordion__section');
765
- this.$openAllButton = '';
765
+ this.$showAllButton = '';
766
766
  this.browserSupportsSessionStorage = helper.checkForSessionStorage();
767
767
 
768
768
  this.controlsClass = 'govuk-accordion__controls';
769
- this.openAllClass = 'govuk-accordion__open-all';
770
- this.iconClass = 'govuk-accordion__icon';
769
+ this.showAllClass = 'govuk-accordion__show-all';
770
+ this.showAllTextClass = 'govuk-accordion__show-all-text';
771
771
 
772
+ this.sectionExpandedClass = 'govuk-accordion__section--expanded';
773
+ this.sectionButtonClass = 'govuk-accordion__section-button';
772
774
  this.sectionHeaderClass = 'govuk-accordion__section-header';
773
- this.sectionHeaderFocusedClass = 'govuk-accordion__section-header--focused';
774
775
  this.sectionHeadingClass = 'govuk-accordion__section-heading';
776
+ this.sectionHeadingTextClass = 'govuk-accordion__section-heading-text';
777
+ this.sectionHeadingTextFocusClass = 'govuk-accordion__section-heading-text-focus';
778
+
779
+ this.sectionShowHideToggleClass = 'govuk-accordion__section-toggle';
780
+ this.sectionShowHideToggleFocusClass = 'govuk-accordion__section-toggle-focus';
781
+ this.sectionShowHideTextClass = 'govuk-accordion__section-toggle-text';
782
+ this.upChevronIconClass = 'govuk-accordion-nav__chevron';
783
+ this.downChevronIconClass = 'govuk-accordion-nav__chevron--down';
784
+
775
785
  this.sectionSummaryClass = 'govuk-accordion__section-summary';
776
- this.sectionButtonClass = 'govuk-accordion__section-button';
777
- this.sectionExpandedClass = 'govuk-accordion__section--expanded';
786
+ this.sectionSummaryFocusClass = 'govuk-accordion__section-summary-focus';
778
787
  }
779
788
 
780
789
  // Initialize component
@@ -785,32 +794,39 @@ Accordion.prototype.init = function () {
785
794
  }
786
795
 
787
796
  this.initControls();
788
-
789
797
  this.initSectionHeaders();
790
798
 
791
- // See if "Open all" button text should be updated
799
+ // See if "Show all sections" button text should be updated
792
800
  var areAllSectionsOpen = this.checkIfAllSectionsOpen();
793
- this.updateOpenAllButton(areAllSectionsOpen);
801
+ this.updateShowAllButton(areAllSectionsOpen);
794
802
  };
795
803
 
796
804
  // Initialise controls and set attributes
797
805
  Accordion.prototype.initControls = function () {
798
- // Create "Open all" button and set attributes
799
- this.$openAllButton = document.createElement('button');
800
- this.$openAllButton.setAttribute('type', 'button');
801
- this.$openAllButton.innerHTML = 'Open all <span class="govuk-visually-hidden">sections</span>';
802
- this.$openAllButton.setAttribute('class', this.openAllClass);
803
- this.$openAllButton.setAttribute('aria-expanded', 'false');
804
- this.$openAllButton.setAttribute('type', 'button');
806
+ // Create "Show all" button and set attributes
807
+ this.$showAllButton = document.createElement('button');
808
+ this.$showAllButton.setAttribute('type', 'button');
809
+ this.$showAllButton.setAttribute('class', this.showAllClass);
810
+ this.$showAllButton.setAttribute('aria-expanded', 'false');
805
811
 
806
- // Create control wrapper and add controls to it
807
- var accordionControls = document.createElement('div');
808
- accordionControls.setAttribute('class', this.controlsClass);
809
- accordionControls.appendChild(this.$openAllButton);
810
- this.$module.insertBefore(accordionControls, this.$module.firstChild);
812
+ // Create icon, add to element
813
+ var $icon = document.createElement('span');
814
+ $icon.classList.add(this.upChevronIconClass);
815
+ this.$showAllButton.appendChild($icon);
811
816
 
812
- // Handle events for the controls
813
- this.$openAllButton.addEventListener('click', this.onOpenOrCloseAllToggle.bind(this));
817
+ // Create control wrapper and add controls to it
818
+ var $accordionControls = document.createElement('div');
819
+ $accordionControls.setAttribute('class', this.controlsClass);
820
+ $accordionControls.appendChild(this.$showAllButton);
821
+ this.$module.insertBefore($accordionControls, this.$module.firstChild);
822
+
823
+ // Build additional wrapper for Show all toggle text and place after icon
824
+ var $wrappershowAllText = document.createElement('span');
825
+ $wrappershowAllText.classList.add(this.showAllTextClass);
826
+ this.$showAllButton.appendChild($wrappershowAllText);
827
+
828
+ // Handle click events on the show/hide all button
829
+ this.$showAllButton.addEventListener('click', this.onShowOrHideAllToggle.bind(this));
814
830
  };
815
831
 
816
832
  // Initialise section headers
@@ -818,13 +834,12 @@ Accordion.prototype.initSectionHeaders = function () {
818
834
  // Loop through section headers
819
835
  nodeListForEach(this.$sections, function ($section, i) {
820
836
  // Set header attributes
821
- var header = $section.querySelector('.' + this.sectionHeaderClass);
822
- this.initHeaderAttributes(header, i);
823
-
837
+ var $header = $section.querySelector('.' + this.sectionHeaderClass);
838
+ this.constructHeaderMarkup($header, i);
824
839
  this.setExpanded(this.isExpanded($section), $section);
825
840
 
826
841
  // Handle events
827
- header.addEventListener('click', this.onSectionToggle.bind(this, $section));
842
+ $header.addEventListener('click', this.onSectionToggle.bind(this, $section));
828
843
 
829
844
  // See if there is any state stored in sessionStorage and set the sections to
830
845
  // open or closed.
@@ -832,51 +847,100 @@ Accordion.prototype.initSectionHeaders = function () {
832
847
  }.bind(this));
833
848
  };
834
849
 
835
- // Set individual header attributes
836
- Accordion.prototype.initHeaderAttributes = function ($headerWrapper, index) {
837
- var $module = this;
850
+ Accordion.prototype.constructHeaderMarkup = function ($headerWrapper, index) {
838
851
  var $span = $headerWrapper.querySelector('.' + this.sectionButtonClass);
839
852
  var $heading = $headerWrapper.querySelector('.' + this.sectionHeadingClass);
840
853
  var $summary = $headerWrapper.querySelector('.' + this.sectionSummaryClass);
841
854
 
842
- // Copy existing span element to an actual button element, for improved accessibility.
855
+ // Create a button element that will replace the '.govuk-accordion__section-button' span
843
856
  var $button = document.createElement('button');
844
857
  $button.setAttribute('type', 'button');
845
- $button.setAttribute('id', this.moduleId + '-heading-' + (index + 1));
846
858
  $button.setAttribute('aria-controls', this.moduleId + '-content-' + (index + 1));
847
859
 
848
860
  // Copy all attributes (https://developer.mozilla.org/en-US/docs/Web/API/Element/attributes) from $span to $button
849
861
  for (var i = 0; i < $span.attributes.length; i++) {
850
862
  var attr = $span.attributes.item(i);
851
- $button.setAttribute(attr.nodeName, attr.nodeValue);
863
+ // Add all attributes but not ID as this is being added to
864
+ // the section heading ($headingText)
865
+ if (attr.nodeName !== 'id') {
866
+ $button.setAttribute(attr.nodeName, attr.nodeValue);
867
+ }
852
868
  }
853
869
 
854
- $button.addEventListener('focusin', function (e) {
855
- if (!$headerWrapper.classList.contains($module.sectionHeaderFocusedClass)) {
856
- $headerWrapper.className += ' ' + $module.sectionHeaderFocusedClass;
870
+ // Create container for heading text so it can be styled
871
+ var $headingText = document.createElement('span');
872
+ $headingText.classList.add(this.sectionHeadingTextClass);
873
+ // Copy the span ID to the heading text to allow it to be referenced by `aria-labelledby` on the
874
+ // hidden content area without "Show this section"
875
+ $headingText.id = $span.id;
876
+
877
+ // Create an inner heading text container to limit the width of the focus state
878
+ var $headingTextFocus = document.createElement('span');
879
+ $headingTextFocus.classList.add(this.sectionHeadingTextFocusClass);
880
+ $headingText.appendChild($headingTextFocus);
881
+ // span could contain HTML elements (see https://www.w3.org/TR/2011/WD-html5-20110525/content-models.html#phrasing-content)
882
+ $headingTextFocus.innerHTML = $span.innerHTML;
883
+
884
+ // Create container for show / hide icons and text.
885
+ var $showToggle = document.createElement('span');
886
+ $showToggle.classList.add(this.sectionShowHideToggleClass);
887
+ // Tell Google not to index the 'show' text as part of the heading
888
+ // For the snippet to work with JavaScript, it must be added before adding the page element to the
889
+ // page's DOM. See https://developers.google.com/search/docs/advanced/robots/robots_meta_tag#data-nosnippet-attr
890
+ $showToggle.setAttribute('data-nosnippet', '');
891
+ // Create an inner container to limit the width of the focus state
892
+ var $showToggleFocus = document.createElement('span');
893
+ $showToggleFocus.classList.add(this.sectionShowHideToggleFocusClass);
894
+ $showToggle.appendChild($showToggleFocus);
895
+ // Create wrapper for the show / hide text. Append text after the show/hide icon
896
+ var $showToggleText = document.createElement('span');
897
+ var $icon = document.createElement('span');
898
+ $icon.classList.add(this.upChevronIconClass);
899
+ $showToggleFocus.appendChild($icon);
900
+ $showToggleText.classList.add(this.sectionShowHideTextClass);
901
+ $showToggleFocus.appendChild($showToggleText);
902
+
903
+ // Append elements to the button:
904
+ // 1. Heading text
905
+ // 2. Punctuation
906
+ // 3. (Optional: Summary line followed by punctuation)
907
+ // 4. Show / hide toggle
908
+ $button.appendChild($headingText);
909
+ $button.appendChild(this.getButtonPunctuationEl());
910
+
911
+ // If summary content exists add to DOM in correct order
912
+ if (typeof ($summary) !== 'undefined' && $summary !== null) {
913
+ // Create a new `span` element and copy the summary line content from the original `div` to the
914
+ // new `span`
915
+ // This is because the summary line text is now inside a button element, which can only contain
916
+ // phrasing content
917
+ var $summarySpan = document.createElement('span');
918
+ // Create an inner summary container to limit the width of the summary focus state
919
+ var $summarySpanFocus = document.createElement('span');
920
+ $summarySpanFocus.classList.add(this.sectionSummaryFocusClass);
921
+ $summarySpan.appendChild($summarySpanFocus);
922
+
923
+ // Get original attributes, and pass them to the replacement
924
+ for (var j = 0, l = $summary.attributes.length; j < l; ++j) {
925
+ var nodeName = $summary.attributes.item(j).nodeName;
926
+ var nodeValue = $summary.attributes.item(j).nodeValue;
927
+ $summarySpan.setAttribute(nodeName, nodeValue);
857
928
  }
858
- });
859
929
 
860
- $button.addEventListener('blur', function (e) {
861
- $headerWrapper.classList.remove($module.sectionHeaderFocusedClass);
862
- });
930
+ // Copy original contents of summary to the new summary span
931
+ $summarySpanFocus.innerHTML = $summary.innerHTML;
863
932
 
864
- if (typeof ($summary) !== 'undefined' && $summary !== null) {
865
- $button.setAttribute('aria-describedby', this.moduleId + '-summary-' + (index + 1));
933
+ // Replace the original summary `div` with the new summary `span`
934
+ $summary.parentNode.replaceChild($summarySpan, $summary);
935
+
936
+ $button.appendChild($summarySpan);
937
+ $button.appendChild(this.getButtonPunctuationEl());
866
938
  }
867
939
 
868
- // $span could contain HTML elements (see https://www.w3.org/TR/2011/WD-html5-20110525/content-models.html#phrasing-content)
869
- $button.innerHTML = $span.innerHTML;
940
+ $button.appendChild($showToggle);
870
941
 
871
942
  $heading.removeChild($span);
872
943
  $heading.appendChild($button);
873
-
874
- // Add "+/-" icon
875
- var icon = document.createElement('span');
876
- icon.className = this.iconClass;
877
- icon.setAttribute('aria-hidden', 'true');
878
-
879
- $button.appendChild(icon);
880
944
  };
881
945
 
882
946
  // When section toggled, set and store state
@@ -889,10 +953,9 @@ Accordion.prototype.onSectionToggle = function ($section) {
889
953
  };
890
954
 
891
955
  // When Open/Close All toggled, set and store state
892
- Accordion.prototype.onOpenOrCloseAllToggle = function () {
956
+ Accordion.prototype.onShowOrHideAllToggle = function () {
893
957
  var $module = this;
894
958
  var $sections = this.$sections;
895
-
896
959
  var nowExpanded = !this.checkIfAllSectionsOpen();
897
960
 
898
961
  nodeListForEach($sections, function ($section) {
@@ -901,23 +964,37 @@ Accordion.prototype.onOpenOrCloseAllToggle = function () {
901
964
  $module.storeState($section);
902
965
  });
903
966
 
904
- $module.updateOpenAllButton(nowExpanded);
967
+ $module.updateShowAllButton(nowExpanded);
905
968
  };
906
969
 
907
970
  // Set section attributes when opened/closed
908
971
  Accordion.prototype.setExpanded = function (expanded, $section) {
972
+ var $icon = $section.querySelector('.' + this.upChevronIconClass);
973
+ var $showHideText = $section.querySelector('.' + this.sectionShowHideTextClass);
909
974
  var $button = $section.querySelector('.' + this.sectionButtonClass);
975
+ var $newButtonText = expanded ? 'Hide' : 'Show';
976
+
977
+ // Build additional copy of "this section" for assistive technology and place inside toggle link
978
+ var $visuallyHiddenText = document.createElement('span');
979
+ $visuallyHiddenText.classList.add('govuk-visually-hidden');
980
+ $visuallyHiddenText.innerHTML = ' this section';
981
+
982
+ $showHideText.innerHTML = $newButtonText;
983
+ $showHideText.appendChild($visuallyHiddenText);
910
984
  $button.setAttribute('aria-expanded', expanded);
911
985
 
986
+ // Swap icon, change class
912
987
  if (expanded) {
913
988
  $section.classList.add(this.sectionExpandedClass);
989
+ $icon.classList.remove(this.downChevronIconClass);
914
990
  } else {
915
991
  $section.classList.remove(this.sectionExpandedClass);
992
+ $icon.classList.add(this.downChevronIconClass);
916
993
  }
917
994
 
918
- // See if "Open all" button text should be updated
995
+ // See if "Show all sections" button text should be updated
919
996
  var areAllSectionsOpen = this.checkIfAllSectionsOpen();
920
- this.updateOpenAllButton(areAllSectionsOpen);
997
+ this.updateShowAllButton(areAllSectionsOpen);
921
998
  };
922
999
 
923
1000
  // Get state of section
@@ -936,12 +1013,20 @@ Accordion.prototype.checkIfAllSectionsOpen = function () {
936
1013
  return areAllSectionsOpen
937
1014
  };
938
1015
 
939
- // Update "Open all" button
940
- Accordion.prototype.updateOpenAllButton = function (expanded) {
941
- var newButtonText = expanded ? 'Close all' : 'Open all';
942
- newButtonText += '<span class="govuk-visually-hidden"> sections</span>';
943
- this.$openAllButton.setAttribute('aria-expanded', expanded);
944
- this.$openAllButton.innerHTML = newButtonText;
1016
+ // Update "Show all sections" button
1017
+ Accordion.prototype.updateShowAllButton = function (expanded) {
1018
+ var $showAllIcon = this.$showAllButton.querySelector('.' + this.upChevronIconClass);
1019
+ var $showAllText = this.$showAllButton.querySelector('.' + this.showAllTextClass);
1020
+ var newButtonText = expanded ? 'Hide all sections' : 'Show all sections';
1021
+ this.$showAllButton.setAttribute('aria-expanded', expanded);
1022
+ $showAllText.innerHTML = newButtonText;
1023
+
1024
+ // Swap icon, toggle class
1025
+ if (expanded) {
1026
+ $showAllIcon.classList.remove(this.downChevronIconClass);
1027
+ } else {
1028
+ $showAllIcon.classList.add(this.downChevronIconClass);
1029
+ }
945
1030
  };
946
1031
 
947
1032
  // Check for `window.sessionStorage`, and that it actually works.
@@ -965,7 +1050,7 @@ var helper = {
965
1050
  // Set the state of the accordions in sessionStorage
966
1051
  Accordion.prototype.storeState = function ($section) {
967
1052
  if (this.browserSupportsSessionStorage) {
968
- // We need a unique way of identifying each content in the accordion. Since
1053
+ // We need a unique way of identifying each content in the Accordion. Since
969
1054
  // an `#id` should be unique and an `id` is required for `aria-` attributes
970
1055
  // `id` can be safely used.
971
1056
  var $button = $section.querySelector('.' + this.sectionButtonClass);
@@ -1006,6 +1091,25 @@ Accordion.prototype.setInitialState = function ($section) {
1006
1091
  }
1007
1092
  };
1008
1093
 
1094
+ /**
1095
+ * Create an element to improve semantics of the section button with punctuation
1096
+ * @return {object} DOM element
1097
+ *
1098
+ * Used to add pause (with a comma) for assistive technology.
1099
+ * Example: [heading]Section A ,[pause] Show this section.
1100
+ * https://accessibility.blog.gov.uk/2017/12/18/what-working-on-gov-uk-navigation-taught-us-about-accessibility/
1101
+ *
1102
+ * Adding punctuation to the button can also improve its general semantics by dividing its contents
1103
+ * into thematic chunks.
1104
+ * See https://github.com/alphagov/govuk-frontend/issues/2327#issuecomment-922957442
1105
+ */
1106
+ Accordion.prototype.getButtonPunctuationEl = function () {
1107
+ var $punctuationEl = document.createElement('span');
1108
+ $punctuationEl.classList.add('govuk-visually-hidden', 'govuk-accordion__section-heading-divider');
1109
+ $punctuationEl.innerHTML = ', ';
1110
+ return $punctuationEl
1111
+ };
1112
+
1009
1113
  return Accordion;
1010
1114
 
1011
1115
  })));
@@ -11,7 +11,7 @@
11
11
  "text": "Section A"
12
12
  },
13
13
  "content": {
14
- "html": "<ul class=\"govuk-list govuk-list--bullet\">\n <li>Example item 1</li>\n</ul>\n"
14
+ "html": "<p class=\"govuk-body\">\n We need to know your nationality so we can work out which elections you’re entitled to vote in. If you cannot provide your nationality, you’ll have to send copies of identity documents through the post.\n</p>\n"
15
15
  }
16
16
  },
17
17
  {
@@ -24,7 +24,7 @@
24
24
  }
25
25
  ]
26
26
  },
27
- "html": "<div class=\"govuk-accordion\" data-module=\"govuk-accordion\" id=\"default-example\">\n \n \n <div class=\"govuk-accordion__section \">\n <div class=\"govuk-accordion__section-header\">\n <h2 class=\"govuk-accordion__section-heading\">\n <span class=\"govuk-accordion__section-button\" id=\"default-example-heading-1\">\n Section A\n </span>\n </h2>\n \n </div>\n <div id=\"default-example-content-1\" class=\"govuk-accordion__section-content\" aria-labelledby=\"default-example-heading-1\">\n <ul class=\"govuk-list govuk-list--bullet\">\n <li>Example item 1</li>\n</ul>\n\n </div>\n </div>\n \n \n \n <div class=\"govuk-accordion__section \">\n <div class=\"govuk-accordion__section-header\">\n <h2 class=\"govuk-accordion__section-heading\">\n <span class=\"govuk-accordion__section-button\" id=\"default-example-heading-2\">\n Section B\n </span>\n </h2>\n \n </div>\n <div id=\"default-example-content-2\" class=\"govuk-accordion__section-content\" aria-labelledby=\"default-example-heading-2\">\n <ul class=\"govuk-list govuk-list--bullet\">\n <li>Example item 2</li>\n</ul>\n\n </div>\n </div>\n \n \n</div>",
27
+ "html": "<div class=\"govuk-accordion\" data-module=\"govuk-accordion\" id=\"default-example\">\n \n \n <div class=\"govuk-accordion__section \">\n <div class=\"govuk-accordion__section-header\">\n <h2 class=\"govuk-accordion__section-heading\">\n <span class=\"govuk-accordion__section-button\" id=\"default-example-heading-1\">\n Section A\n </span>\n </h2>\n \n </div>\n <div id=\"default-example-content-1\" class=\"govuk-accordion__section-content\" aria-labelledby=\"default-example-heading-1\">\n <p class=\"govuk-body\">\n We need to know your nationality so we can work out which elections you’re entitled to vote in. If you cannot provide your nationality, you’ll have to send copies of identity documents through the post.\n</p>\n\n </div>\n </div>\n \n \n \n <div class=\"govuk-accordion__section \">\n <div class=\"govuk-accordion__section-header\">\n <h2 class=\"govuk-accordion__section-heading\">\n <span class=\"govuk-accordion__section-button\" id=\"default-example-heading-2\">\n Section B\n </span>\n </h2>\n \n </div>\n <div id=\"default-example-content-2\" class=\"govuk-accordion__section-content\" aria-labelledby=\"default-example-heading-2\">\n <ul class=\"govuk-list govuk-list--bullet\">\n <li>Example item 2</li>\n</ul>\n\n </div>\n </div>\n \n \n</div>",
28
28
  "hidden": false
29
29
  },
30
30
  {
@@ -40,7 +40,7 @@
40
40
  "text": "Additional description"
41
41
  },
42
42
  "content": {
43
- "html": "<ul class=\"govuk-list govuk-list--bullet\">\n <li>Example item 1</li>\n</ul>\n"
43
+ "html": "<p class=\"govuk-body\">\n We need to know your nationality so we can work out which elections you’re entitled to vote in. If you cannot provide your nationality, you’ll have to send copies of identity documents through the post.\n</p>\n<ul class=\"govuk-list govuk-list--bullet\">\n <li>Example item 1</li>\n</ul>\n"
44
44
  }
45
45
  },
46
46
  {
@@ -48,7 +48,39 @@
48
48
  "text": "Test 2"
49
49
  },
50
50
  "summary": {
51
- "html": "<span class=\"govuk-!-font-weight-regular\">Additional description</span>"
51
+ "html": "<span class=\"govuk-!-font-weight-regular\">Additional description (wrapped in span)</span>"
52
+ },
53
+ "content": {
54
+ "html": "<ul class=\"govuk-list govuk-list--bullet\">\n <li>Example item 2</li>\n</ul>\n"
55
+ }
56
+ }
57
+ ]
58
+ },
59
+ "html": "<div class=\"govuk-accordion\" data-module=\"govuk-accordion\" id=\"with-descriptions\">\n \n \n <div class=\"govuk-accordion__section \">\n <div class=\"govuk-accordion__section-header\">\n <h2 class=\"govuk-accordion__section-heading\">\n <span class=\"govuk-accordion__section-button\" id=\"with-descriptions-heading-1\">\n Test\n </span>\n </h2>\n \n <div class=\"govuk-accordion__section-summary govuk-body\" id=\"with-descriptions-summary-1\">\n Additional description\n </div>\n \n </div>\n <div id=\"with-descriptions-content-1\" class=\"govuk-accordion__section-content\" aria-labelledby=\"with-descriptions-heading-1\">\n <p class=\"govuk-body\">\n We need to know your nationality so we can work out which elections you’re entitled to vote in. If you cannot provide your nationality, you’ll have to send copies of identity documents through the post.\n</p>\n<ul class=\"govuk-list govuk-list--bullet\">\n <li>Example item 1</li>\n</ul>\n\n </div>\n </div>\n \n \n \n <div class=\"govuk-accordion__section \">\n <div class=\"govuk-accordion__section-header\">\n <h2 class=\"govuk-accordion__section-heading\">\n <span class=\"govuk-accordion__section-button\" id=\"with-descriptions-heading-2\">\n Test 2\n </span>\n </h2>\n \n <div class=\"govuk-accordion__section-summary govuk-body\" id=\"with-descriptions-summary-2\">\n <span class=\"govuk-!-font-weight-regular\">Additional description (wrapped in span)</span>\n </div>\n \n </div>\n <div id=\"with-descriptions-content-2\" class=\"govuk-accordion__section-content\" aria-labelledby=\"with-descriptions-heading-2\">\n <ul class=\"govuk-list govuk-list--bullet\">\n <li>Example item 2</li>\n</ul>\n\n </div>\n </div>\n \n \n</div>",
60
+ "hidden": false
61
+ },
62
+ {
63
+ "name": "with long content and description",
64
+ "options": {
65
+ "id": "with-long-content-and-description",
66
+ "items": [
67
+ {
68
+ "heading": {
69
+ "text": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc quis tortor porttitor."
70
+ },
71
+ "summary": {
72
+ "text": "Etiam diam dui, tempus ut pharetra in, aliquet non dui. Nunc pulvinar maximus tortor, ac finibus augue congue vitae. Donec sed cursus lorem."
73
+ },
74
+ "content": {
75
+ "html": "<ul class=\"govuk-list govuk-list--bullet\">\n <li>Example item 1</li>\n</ul>\n"
76
+ }
77
+ },
78
+ {
79
+ "heading": {
80
+ "text": "Praesent faucibus leo feugiat libero pharetra lacinia. Aliquam aliquet ante vitae mollis vestibulum."
81
+ },
82
+ "summary": {
83
+ "html": "<span class=\"govuk-!-font-weight-regular\">Maecenas nec <abbr>est</abbr> sapien. Etiam varius luctus mauris non porttitor. </span>"
52
84
  },
53
85
  "content": {
54
86
  "html": "<ul class=\"govuk-list govuk-list--bullet\">\n <li>Example item 2</li>\n</ul>\n"
@@ -56,7 +88,7 @@
56
88
  }
57
89
  ]
58
90
  },
59
- "html": "<div class=\"govuk-accordion\" data-module=\"govuk-accordion\" id=\"with-descriptions\">\n \n \n <div class=\"govuk-accordion__section \">\n <div class=\"govuk-accordion__section-header\">\n <h2 class=\"govuk-accordion__section-heading\">\n <span class=\"govuk-accordion__section-button\" id=\"with-descriptions-heading-1\">\n Test\n </span>\n </h2>\n \n <div class=\"govuk-accordion__section-summary govuk-body\" id=\"with-descriptions-summary-1\">\n Additional description\n </div>\n \n </div>\n <div id=\"with-descriptions-content-1\" class=\"govuk-accordion__section-content\" aria-labelledby=\"with-descriptions-heading-1\">\n <ul class=\"govuk-list govuk-list--bullet\">\n <li>Example item 1</li>\n</ul>\n\n </div>\n </div>\n \n \n \n <div class=\"govuk-accordion__section \">\n <div class=\"govuk-accordion__section-header\">\n <h2 class=\"govuk-accordion__section-heading\">\n <span class=\"govuk-accordion__section-button\" id=\"with-descriptions-heading-2\">\n Test 2\n </span>\n </h2>\n \n <div class=\"govuk-accordion__section-summary govuk-body\" id=\"with-descriptions-summary-2\">\n <span class=\"govuk-!-font-weight-regular\">Additional description</span>\n </div>\n \n </div>\n <div id=\"with-descriptions-content-2\" class=\"govuk-accordion__section-content\" aria-labelledby=\"with-descriptions-heading-2\">\n <ul class=\"govuk-list govuk-list--bullet\">\n <li>Example item 2</li>\n</ul>\n\n </div>\n </div>\n \n \n</div>",
91
+ "html": "<div class=\"govuk-accordion\" data-module=\"govuk-accordion\" id=\"with-long-content-and-description\">\n \n \n <div class=\"govuk-accordion__section \">\n <div class=\"govuk-accordion__section-header\">\n <h2 class=\"govuk-accordion__section-heading\">\n <span class=\"govuk-accordion__section-button\" id=\"with-long-content-and-description-heading-1\">\n Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc quis tortor porttitor.\n </span>\n </h2>\n \n <div class=\"govuk-accordion__section-summary govuk-body\" id=\"with-long-content-and-description-summary-1\">\n Etiam diam dui, tempus ut pharetra in, aliquet non dui. Nunc pulvinar maximus tortor, ac finibus augue congue vitae. Donec sed cursus lorem.\n </div>\n \n </div>\n <div id=\"with-long-content-and-description-content-1\" class=\"govuk-accordion__section-content\" aria-labelledby=\"with-long-content-and-description-heading-1\">\n <ul class=\"govuk-list govuk-list--bullet\">\n <li>Example item 1</li>\n</ul>\n\n </div>\n </div>\n \n \n \n <div class=\"govuk-accordion__section \">\n <div class=\"govuk-accordion__section-header\">\n <h2 class=\"govuk-accordion__section-heading\">\n <span class=\"govuk-accordion__section-button\" id=\"with-long-content-and-description-heading-2\">\n Praesent faucibus leo feugiat libero pharetra lacinia. Aliquam aliquet ante vitae mollis vestibulum.\n </span>\n </h2>\n \n <div class=\"govuk-accordion__section-summary govuk-body\" id=\"with-long-content-and-description-summary-2\">\n <span class=\"govuk-!-font-weight-regular\">Maecenas nec <abbr>est</abbr> sapien. Etiam varius luctus mauris non porttitor. </span>\n </div>\n \n </div>\n <div id=\"with-long-content-and-description-content-2\" class=\"govuk-accordion__section-content\" aria-labelledby=\"with-long-content-and-description-heading-2\">\n <ul class=\"govuk-list govuk-list--bullet\">\n <li>Example item 2</li>\n</ul>\n\n </div>\n </div>\n \n \n</div>",
60
92
  "hidden": false
61
93
  },
62
94
  {
@@ -33,13 +33,13 @@
33
33
  "name": "heading.text",
34
34
  "type": "string",
35
35
  "required": true,
36
- "description": "The title of each section. If `heading.html` is supplied, this is ignored. This is used both as the title for each section, and as the button to open or close each section."
36
+ "description": "The title of each section. If `heading.html` is supplied, this is ignored."
37
37
  },
38
38
  {
39
39
  "name": "heading.html",
40
40
  "type": "string",
41
41
  "required": true,
42
- "description": "The HTML content of the header for each section which is used both as the title for each section, and as the button to open or close each section."
42
+ "description": "The HTML content of the header for each section. Used as the title for each section. The header is inside the HTML `<button>` element, so you can only add [phrasing content](https://html.spec.whatwg.org/#phrasing-content) to it."
43
43
  },
44
44
  {
45
45
  "name": "summary.text",
@@ -51,7 +51,7 @@
51
51
  "name": "summary.html",
52
52
  "type": "string",
53
53
  "required": false,
54
- "description": "HTML content for summary line."
54
+ "description": "The HTML content for the summary line. The summary line is inside the HTML `<button>` element, so you can only add [phrasing content](https://html.spec.whatwg.org/#phrasing-content) to it."
55
55
  },
56
56
  {
57
57
  "name": "content.text",
@@ -69,7 +69,7 @@
69
69
  "name": "expanded",
70
70
  "type": "boolean",
71
71
  "required": false,
72
- "description": "Whether the section should be expanded upon initial load or not. Defaults to `false`."
72
+ "description": "Sets whether the section should be expanded when the page loads for the first time. Defaults to `false`."
73
73
  }
74
74
  ]
75
75
  }
@@ -1,7 +1,7 @@
1
1
  (function (global, factory) {
2
2
  typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
3
- typeof define === 'function' && define.amd ? define('GOVUKFrontend', factory) :
4
- (global.GOVUKFrontend = factory());
3
+ typeof define === 'function' && define.amd ? define('GOVUKFrontend.Button', factory) :
4
+ (global.GOVUKFrontend = global.GOVUKFrontend || {}, global.GOVUKFrontend.Button = factory());
5
5
  }(this, (function () { 'use strict';
6
6
 
7
7
  (function(undefined) {
@@ -1,7 +1,7 @@
1
1
  (function (global, factory) {
2
2
  typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
3
- typeof define === 'function' && define.amd ? define('GOVUKFrontend', factory) :
4
- (global.GOVUKFrontend = factory());
3
+ typeof define === 'function' && define.amd ? define('GOVUKFrontend.CharacterCount', factory) :
4
+ (global.GOVUKFrontend = global.GOVUKFrontend || {}, global.GOVUKFrontend.CharacterCount = factory());
5
5
  }(this, (function () { 'use strict';
6
6
 
7
7
  (function(undefined) {
@@ -1018,7 +1018,7 @@ function CharacterCount ($module) {
1018
1018
  this.$module = $module;
1019
1019
  this.$textarea = $module.querySelector('.govuk-js-character-count');
1020
1020
  if (this.$textarea) {
1021
- this.$countMessage = $module.querySelector('[id="' + this.$textarea.id + '-info"]');
1021
+ this.$countMessage = document.getElementById(this.$textarea.id + '-info');
1022
1022
  }
1023
1023
  }
1024
1024
 
@@ -58,7 +58,7 @@
58
58
  "text": "Please do not exceed the maximum allowed limit"
59
59
  }
60
60
  },
61
- "html": "<div class=\"govuk-character-count\" data-module=\"govuk-character-count\" data-maxlength=\"10\">\n \n\n<div class=\"govuk-form-group govuk-form-group--error\">\n <label class=\"govuk-label\" for=\"exceeding-characters\">\n Full address\n </label>\n\n\n \n \n <span id=\"exceeding-characters-error\" class=\"govuk-error-message\">\n <span class=\"govuk-visually-hidden\">Error:</span> Please do not exceed the maximum allowed limit\n </span>\n\n <textarea class=\"govuk-textarea govuk-textarea--error govuk-js-character-count govuk-textarea--error\" id=\"exceeding-characters\" name=\"exceeding\" rows=\"5\" aria-describedby=\"exceeding-characters-info exceeding-characters-error\">221B Baker Street\nLondon\nNW1 6XE\n</textarea>\n</div>\n\n <div id=\"exceeding-characters-info\" class=\"govuk-hint govuk-character-count__message\" aria-live=\"polite\">\n You can enter up to 10 characters\n</div>\n\n</div>",
61
+ "html": "<div class=\"govuk-character-count\" data-module=\"govuk-character-count\" data-maxlength=\"10\">\n \n\n<div class=\"govuk-form-group govuk-form-group--error\">\n <label class=\"govuk-label\" for=\"exceeding-characters\">\n Full address\n </label>\n\n\n \n \n <p id=\"exceeding-characters-error\" class=\"govuk-error-message\">\n <span class=\"govuk-visually-hidden\">Error:</span> Please do not exceed the maximum allowed limit\n </p>\n\n <textarea class=\"govuk-textarea govuk-textarea--error govuk-js-character-count govuk-textarea--error\" id=\"exceeding-characters\" name=\"exceeding\" rows=\"5\" aria-describedby=\"exceeding-characters-info exceeding-characters-error\">221B Baker Street\nLondon\nNW1 6XE\n</textarea>\n</div>\n\n <div id=\"exceeding-characters-info\" class=\"govuk-hint govuk-character-count__message\" aria-live=\"polite\">\n You can enter up to 10 characters\n</div>\n\n</div>",
62
62
  "hidden": false
63
63
  },
64
64
  {
@@ -220,7 +220,7 @@
220
220
  "text": "Error message"
221
221
  }
222
222
  },
223
- "html": "<div class=\"govuk-character-count\" data-module=\"govuk-character-count\" data-maxlength=\"10\">\n \n\n<div class=\"govuk-form-group govuk-form-group--error\">\n <label class=\"govuk-label\" for=\"with-custom-error-class\">\n With custom error class\n </label>\n\n\n \n \n <span id=\"with-custom-error-class-error\" class=\"govuk-error-message\">\n <span class=\"govuk-visually-hidden\">Error:</span> Error message\n </span>\n\n <textarea class=\"govuk-textarea govuk-textarea--error govuk-js-character-count govuk-textarea--error app-character-count--custom-modifier\" id=\"with-custom-error-class\" name=\"with-custom-error-class\" rows=\"5\" aria-describedby=\"with-custom-error-class-info with-custom-error-class-error\"></textarea>\n</div>\n\n <div id=\"with-custom-error-class-info\" class=\"govuk-hint govuk-character-count__message\" aria-live=\"polite\">\n You can enter up to 10 characters\n</div>\n\n</div>",
223
+ "html": "<div class=\"govuk-character-count\" data-module=\"govuk-character-count\" data-maxlength=\"10\">\n \n\n<div class=\"govuk-form-group govuk-form-group--error\">\n <label class=\"govuk-label\" for=\"with-custom-error-class\">\n With custom error class\n </label>\n\n\n \n \n <p id=\"with-custom-error-class-error\" class=\"govuk-error-message\">\n <span class=\"govuk-visually-hidden\">Error:</span> Error message\n </p>\n\n <textarea class=\"govuk-textarea govuk-textarea--error govuk-js-character-count govuk-textarea--error app-character-count--custom-modifier\" id=\"with-custom-error-class\" name=\"with-custom-error-class\" rows=\"5\" aria-describedby=\"with-custom-error-class-info with-custom-error-class-error\"></textarea>\n</div>\n\n <div id=\"with-custom-error-class-info\" class=\"govuk-hint govuk-character-count__message\" aria-live=\"polite\">\n You can enter up to 10 characters\n</div>\n\n</div>",
224
224
  "hidden": true
225
225
  },
226
226
  {
@@ -235,6 +235,19 @@
235
235
  },
236
236
  "html": "<div class=\"govuk-character-count\" data-module=\"govuk-character-count\" data-maxlength=\"10\">\n \n\n<div class=\"govuk-form-group\">\n <label class=\"govuk-label\" for=\"1_more-detail\">\n Can you provide more detail?\n </label>\n\n\n <textarea class=\"govuk-textarea govuk-js-character-count\" id=\"1_more-detail\" name=\"more-detail\" rows=\"5\" aria-describedby=\"1_more-detail-info\"></textarea>\n</div>\n\n <div id=\"1_more-detail-info\" class=\"govuk-hint govuk-character-count__message\" aria-live=\"polite\">\n You can enter up to 10 characters\n</div>\n\n</div>",
237
237
  "hidden": true
238
+ },
239
+ {
240
+ "name": "with id with special characters",
241
+ "options": {
242
+ "id": "user1.profile[address]",
243
+ "name": "address",
244
+ "maxlength": 10,
245
+ "label": {
246
+ "text": "Full address"
247
+ }
248
+ },
249
+ "html": "<div class=\"govuk-character-count\" data-module=\"govuk-character-count\" data-maxlength=\"10\">\n \n\n<div class=\"govuk-form-group\">\n <label class=\"govuk-label\" for=\"user1.profile[address]\">\n Full address\n </label>\n\n\n <textarea class=\"govuk-textarea govuk-js-character-count\" id=\"user1.profile[address]\" name=\"address\" rows=\"5\" aria-describedby=\"user1.profile[address]-info\"></textarea>\n</div>\n\n <div id=\"user1.profile[address]-info\" class=\"govuk-hint govuk-character-count__message\" aria-live=\"polite\">\n You can enter up to 10 characters\n</div>\n\n</div>",
250
+ "hidden": false
238
251
  }
239
252
  ]
240
253
  }
@@ -1,7 +1,7 @@
1
1
  (function (global, factory) {
2
2
  typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
3
- typeof define === 'function' && define.amd ? define('GOVUKFrontend', factory) :
4
- (global.GOVUKFrontend = factory());
3
+ typeof define === 'function' && define.amd ? define('GOVUKFrontend.Checkboxes', factory) :
4
+ (global.GOVUKFrontend = global.GOVUKFrontend || {}, global.GOVUKFrontend.Checkboxes = factory());
5
5
  }(this, (function () { 'use strict';
6
6
 
7
7
  (function(undefined) {
@@ -1056,7 +1056,7 @@ Checkboxes.prototype.init = function () {
1056
1056
 
1057
1057
  // Skip checkboxes without data-aria-controls attributes, or where the
1058
1058
  // target element does not exist.
1059
- if (!target || !$module.querySelector('#' + target)) {
1059
+ if (!target || !document.getElementById(target)) {
1060
1060
  return
1061
1061
  }
1062
1062
 
@@ -1100,7 +1100,7 @@ Checkboxes.prototype.syncAllConditionalReveals = function () {
1100
1100
  * @param {HTMLInputElement} $input Checkbox input
1101
1101
  */
1102
1102
  Checkboxes.prototype.syncConditionalRevealWithInputState = function ($input) {
1103
- var $target = this.$module.querySelector('#' + $input.getAttribute('aria-controls'));
1103
+ var $target = document.getElementById($input.getAttribute('aria-controls'));
1104
1104
 
1105
1105
  if ($target && $target.classList.contains('govuk-checkboxes__conditional')) {
1106
1106
  var inputIsChecked = $input.checked;
@@ -1123,10 +1123,9 @@ Checkboxes.prototype.unCheckAllInputsExcept = function ($input) {
1123
1123
  var hasSameFormOwner = ($input.form === $inputWithSameName.form);
1124
1124
  if (hasSameFormOwner && $inputWithSameName !== $input) {
1125
1125
  $inputWithSameName.checked = false;
1126
+ this.syncConditionalRevealWithInputState($inputWithSameName);
1126
1127
  }
1127
- });
1128
-
1129
- this.syncAllConditionalReveals();
1128
+ }.bind(this));
1130
1129
  };
1131
1130
 
1132
1131
  /**
@@ -1145,10 +1144,9 @@ Checkboxes.prototype.unCheckExclusiveInputs = function ($input) {
1145
1144
  var hasSameFormOwner = ($input.form === $exclusiveInput.form);
1146
1145
  if (hasSameFormOwner) {
1147
1146
  $exclusiveInput.checked = false;
1147
+ this.syncConditionalRevealWithInputState($exclusiveInput);
1148
1148
  }
1149
- });
1150
-
1151
- this.syncAllConditionalReveals();
1149
+ }.bind(this));
1152
1150
  };
1153
1151
 
1154
1152
  /**