govuk_publishing_components 29.9.0 → 29.12.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (179) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +16 -5
  3. data/app/assets/javascripts/govuk_publishing_components/analytics/page-content.js +4 -4
  4. data/app/assets/javascripts/govuk_publishing_components/analytics-ga4/gtm-click-tracking.js +46 -24
  5. data/app/assets/javascripts/govuk_publishing_components/analytics-ga4/gtm-page-views.js +98 -0
  6. data/app/assets/javascripts/govuk_publishing_components/analytics-ga4.js +3 -0
  7. data/app/assets/javascripts/govuk_publishing_components/components/accordion.js +28 -1
  8. data/app/assets/javascripts/govuk_publishing_components/vendor/lux/lux-measurer.js +2 -2
  9. data/app/assets/stylesheets/govuk_publishing_components/_all_components_print.scss +1 -0
  10. data/app/assets/stylesheets/govuk_publishing_components/components/_contextual-sidebar.scss +20 -0
  11. data/app/assets/stylesheets/govuk_publishing_components/components/_layout-super-navigation-header.scss +3 -8
  12. data/app/assets/stylesheets/govuk_publishing_components/components/govspeak/_attachment.scss +7 -1
  13. data/app/assets/stylesheets/govuk_publishing_components/components/print/_organisation-logo.scss +4 -0
  14. data/app/controllers/govuk_publishing_components/audit_controller.rb +3 -3
  15. data/app/controllers/govuk_publishing_components/component_guide_controller.rb +0 -9
  16. data/app/models/govuk_publishing_components/audit_comparer.rb +91 -34
  17. data/app/views/govuk_publishing_components/audit/_applications.html.erb +20 -9
  18. data/app/views/govuk_publishing_components/component_guide/index.html.erb +1 -19
  19. data/app/views/govuk_publishing_components/components/_accordion.html.erb +7 -5
  20. data/app/views/govuk_publishing_components/components/_attachment.html.erb +1 -3
  21. data/app/views/govuk_publishing_components/components/_character_count.html.erb +1 -1
  22. data/app/views/govuk_publishing_components/components/_date_input.html.erb +0 -1
  23. data/app/views/govuk_publishing_components/components/_error_alert.html.erb +6 -3
  24. data/app/views/govuk_publishing_components/components/_input.html.erb +0 -2
  25. data/app/views/govuk_publishing_components/components/_layout_footer.html.erb +23 -5
  26. data/app/views/govuk_publishing_components/components/_layout_super_navigation_header.html.erb +3 -8
  27. data/app/views/govuk_publishing_components/components/contextual_sidebar/_ukraine_cta.html.erb +18 -19
  28. data/app/views/govuk_publishing_components/components/docs/accordion.yml +22 -13
  29. data/app/views/govuk_publishing_components/components/docs/attachment.yml +0 -11
  30. data/app/views/govuk_publishing_components/components/docs/error_alert.yml +4 -0
  31. data/config/locales/ar.yml +1 -2
  32. data/config/locales/az.yml +1 -2
  33. data/config/locales/be.yml +1 -2
  34. data/config/locales/bg.yml +1 -2
  35. data/config/locales/bn.yml +1 -2
  36. data/config/locales/cs.yml +1 -2
  37. data/config/locales/cy.yml +1 -2
  38. data/config/locales/da.yml +1 -2
  39. data/config/locales/de.yml +1 -2
  40. data/config/locales/dr.yml +1 -2
  41. data/config/locales/el.yml +1 -2
  42. data/config/locales/en.yml +9 -2
  43. data/config/locales/es-419.yml +1 -2
  44. data/config/locales/es.yml +1 -2
  45. data/config/locales/et.yml +1 -2
  46. data/config/locales/fa.yml +1 -2
  47. data/config/locales/fi.yml +1 -2
  48. data/config/locales/fr.yml +1 -2
  49. data/config/locales/gd.yml +1 -2
  50. data/config/locales/gu.yml +1 -2
  51. data/config/locales/he.yml +1 -2
  52. data/config/locales/hi.yml +1 -2
  53. data/config/locales/hr.yml +1 -2
  54. data/config/locales/hu.yml +1 -2
  55. data/config/locales/hy.yml +1 -2
  56. data/config/locales/id.yml +1 -2
  57. data/config/locales/is.yml +1 -2
  58. data/config/locales/it.yml +1 -2
  59. data/config/locales/ja.yml +1 -2
  60. data/config/locales/ka.yml +1 -2
  61. data/config/locales/kk.yml +1 -2
  62. data/config/locales/ko.yml +1 -2
  63. data/config/locales/lt.yml +1 -2
  64. data/config/locales/lv.yml +1 -2
  65. data/config/locales/ms.yml +1 -2
  66. data/config/locales/mt.yml +1 -2
  67. data/config/locales/nl.yml +1 -2
  68. data/config/locales/no.yml +1 -2
  69. data/config/locales/pa-pk.yml +1 -2
  70. data/config/locales/pa.yml +1 -2
  71. data/config/locales/pl.yml +1 -2
  72. data/config/locales/ps.yml +1 -2
  73. data/config/locales/pt.yml +1 -2
  74. data/config/locales/ro.yml +1 -2
  75. data/config/locales/ru.yml +1 -2
  76. data/config/locales/si.yml +1 -2
  77. data/config/locales/sk.yml +1 -2
  78. data/config/locales/sl.yml +1 -2
  79. data/config/locales/so.yml +1 -2
  80. data/config/locales/sq.yml +1 -2
  81. data/config/locales/sr.yml +1 -2
  82. data/config/locales/sv.yml +1 -2
  83. data/config/locales/sw.yml +1 -2
  84. data/config/locales/ta.yml +1 -2
  85. data/config/locales/th.yml +1 -2
  86. data/config/locales/tk.yml +1 -2
  87. data/config/locales/tr.yml +1 -2
  88. data/config/locales/uk.yml +1 -2
  89. data/config/locales/ur.yml +1 -2
  90. data/config/locales/uz.yml +1 -2
  91. data/config/locales/vi.yml +1 -2
  92. data/config/locales/zh-hk.yml +1 -2
  93. data/config/locales/zh-tw.yml +1 -2
  94. data/config/locales/zh.yml +1 -2
  95. data/lib/govuk_publishing_components/presenters/attachment_helper.rb +0 -21
  96. data/lib/govuk_publishing_components/presenters/meta_tags.rb +6 -0
  97. data/lib/govuk_publishing_components/presenters/public_layout_helper.rb +35 -16
  98. data/lib/govuk_publishing_components/version.rb +1 -1
  99. data/node_modules/govuk-frontend/govuk/all.js +120 -49
  100. data/node_modules/govuk-frontend/govuk/components/back-link/macro-options.json +2 -2
  101. data/node_modules/govuk-frontend/govuk/components/breadcrumbs/_index.scss +0 -2
  102. data/node_modules/govuk-frontend/govuk/components/breadcrumbs/macro-options.json +2 -2
  103. data/node_modules/govuk-frontend/govuk/components/button/_index.scss +6 -16
  104. data/node_modules/govuk-frontend/govuk/components/button/macro-options.json +2 -2
  105. data/node_modules/govuk-frontend/govuk/components/character-count/character-count.js +120 -49
  106. data/node_modules/govuk-frontend/govuk/components/character-count/fixtures.json +33 -17
  107. data/node_modules/govuk-frontend/govuk/components/character-count/macro-options.json +2 -2
  108. data/node_modules/govuk-frontend/govuk/components/character-count/template.njk +1 -4
  109. data/node_modules/govuk-frontend/govuk/components/checkboxes/_index.scss +3 -2
  110. data/node_modules/govuk-frontend/govuk/components/checkboxes/fixtures.json +22 -10
  111. data/node_modules/govuk-frontend/govuk/components/checkboxes/macro-options.json +2 -2
  112. data/node_modules/govuk-frontend/govuk/components/date-input/fixtures.json +23 -23
  113. data/node_modules/govuk-frontend/govuk/components/date-input/template.njk +1 -1
  114. data/node_modules/govuk-frontend/govuk/components/details/macro-options.json +4 -4
  115. data/node_modules/govuk-frontend/govuk/components/error-message/macro-options.json +2 -2
  116. data/node_modules/govuk-frontend/govuk/components/error-summary/macro-options.json +3 -3
  117. data/node_modules/govuk-frontend/govuk/components/fieldset/macro-options.json +2 -2
  118. data/node_modules/govuk-frontend/govuk/components/footer/_index.scss +12 -22
  119. data/node_modules/govuk-frontend/govuk/components/header/_index.scss +13 -3
  120. data/node_modules/govuk-frontend/govuk/components/header/macro-options.json +2 -2
  121. data/node_modules/govuk-frontend/govuk/components/hint/macro-options.json +2 -2
  122. data/node_modules/govuk-frontend/govuk/components/input/_index.scss +4 -13
  123. data/node_modules/govuk-frontend/govuk/components/input/macro-options.json +5 -5
  124. data/node_modules/govuk-frontend/govuk/components/inset-text/macro-options.json +2 -2
  125. data/node_modules/govuk-frontend/govuk/components/label/macro-options.json +2 -2
  126. data/node_modules/govuk-frontend/govuk/components/panel/_index.scss +1 -1
  127. data/node_modules/govuk-frontend/govuk/components/panel/macro-options.json +4 -4
  128. data/node_modules/govuk-frontend/govuk/components/phase-banner/macro-options.json +2 -2
  129. data/node_modules/govuk-frontend/govuk/components/radios/_index.scss +5 -4
  130. data/node_modules/govuk-frontend/govuk/components/radios/fixtures.json +17 -12
  131. data/node_modules/govuk-frontend/govuk/components/radios/macro-options.json +2 -2
  132. data/node_modules/govuk-frontend/govuk/components/skip-link/_index.scss +1 -3
  133. data/node_modules/govuk-frontend/govuk/components/skip-link/macro-options.json +2 -2
  134. data/node_modules/govuk-frontend/govuk/components/summary-list/macro-options.json +5 -5
  135. data/node_modules/govuk-frontend/govuk/components/table/macro-options.json +4 -4
  136. data/node_modules/govuk-frontend/govuk/components/tabs/macro-options.json +2 -2
  137. data/node_modules/govuk-frontend/govuk/components/tag/macro-options.json +2 -2
  138. data/node_modules/govuk-frontend/govuk/components/warning-text/macro-options.json +2 -2
  139. data/node_modules/govuk-frontend/govuk/helpers/_colour.scss +3 -3
  140. data/node_modules/govuk-frontend/govuk/helpers/_links.scss +7 -5
  141. data/node_modules/govuk-frontend/govuk/helpers/_media-queries.scss +2 -2
  142. data/node_modules/govuk-frontend/govuk/helpers/_shape-arrow.scss +1 -1
  143. data/node_modules/govuk-frontend/govuk/helpers/_spacing.scss +3 -3
  144. data/node_modules/govuk-frontend/govuk/helpers/_typography.scss +2 -2
  145. data/node_modules/govuk-frontend/govuk/objects/_button-group.scss +10 -26
  146. data/node_modules/govuk-frontend/govuk/objects/_template.scss +1 -1
  147. data/node_modules/govuk-frontend/govuk/objects/_width-container.scss +0 -4
  148. data/node_modules/govuk-frontend/govuk/tools/_exports.scss +1 -1
  149. data/node_modules/govuk-frontend/govuk/tools/_font-url.scss +1 -1
  150. data/node_modules/govuk-frontend/govuk/tools/_image-url.scss +1 -1
  151. data/node_modules/govuk-frontend/govuk/tools/_px-to-em.scss +2 -2
  152. data/node_modules/govuk-frontend/govuk/tools/_px-to-rem.scss +1 -1
  153. data/node_modules/govuk-frontend/govuk-esm/all.mjs +88 -0
  154. data/node_modules/govuk-frontend/govuk-esm/common.mjs +28 -0
  155. data/node_modules/govuk-frontend/govuk-esm/components/accordion/accordion.mjs +374 -0
  156. data/node_modules/govuk-frontend/govuk-esm/components/button/button.mjs +64 -0
  157. data/node_modules/govuk-frontend/govuk-esm/components/character-count/character-count.mjs +251 -0
  158. data/node_modules/govuk-frontend/govuk-esm/components/checkboxes/checkboxes.mjs +164 -0
  159. data/node_modules/govuk-frontend/govuk-esm/components/details/details.mjs +147 -0
  160. data/node_modules/govuk-frontend/govuk-esm/components/error-summary/error-summary.mjs +168 -0
  161. data/node_modules/govuk-frontend/govuk-esm/components/header/header.mjs +52 -0
  162. data/node_modules/govuk-frontend/govuk-esm/components/notification-banner/notification-banner.mjs +55 -0
  163. data/node_modules/govuk-frontend/govuk-esm/components/radios/radios.mjs +122 -0
  164. data/node_modules/govuk-frontend/govuk-esm/components/skip-link/skip-link.mjs +94 -0
  165. data/node_modules/govuk-frontend/govuk-esm/components/tabs/tabs.mjs +282 -0
  166. data/node_modules/govuk-frontend/govuk-esm/vendor/polyfills/DOMTokenList.js +264 -0
  167. data/node_modules/govuk-frontend/govuk-esm/vendor/polyfills/Document.js +26 -0
  168. data/node_modules/govuk-frontend/govuk-esm/vendor/polyfills/Element/prototype/classList.js +93 -0
  169. data/node_modules/govuk-frontend/govuk-esm/vendor/polyfills/Element/prototype/closest.js +24 -0
  170. data/node_modules/govuk-frontend/govuk-esm/vendor/polyfills/Element/prototype/matches.js +23 -0
  171. data/node_modules/govuk-frontend/govuk-esm/vendor/polyfills/Element/prototype/nextElementSibling.js +22 -0
  172. data/node_modules/govuk-frontend/govuk-esm/vendor/polyfills/Element/prototype/previousElementSibling.js +22 -0
  173. data/node_modules/govuk-frontend/govuk-esm/vendor/polyfills/Element.js +114 -0
  174. data/node_modules/govuk-frontend/govuk-esm/vendor/polyfills/Event.js +252 -0
  175. data/node_modules/govuk-frontend/govuk-esm/vendor/polyfills/Function/prototype/bind.js +159 -0
  176. data/node_modules/govuk-frontend/govuk-esm/vendor/polyfills/Object/defineProperty.js +86 -0
  177. data/node_modules/govuk-frontend/govuk-esm/vendor/polyfills/Window.js +20 -0
  178. data/node_modules/govuk-frontend/package.json +8 -1
  179. metadata +29 -3
@@ -1017,9 +1017,9 @@ if (detect) return
1017
1017
  function CharacterCount ($module) {
1018
1018
  this.$module = $module;
1019
1019
  this.$textarea = $module.querySelector('.govuk-js-character-count');
1020
- if (this.$textarea) {
1021
- this.$countMessage = document.getElementById(this.$textarea.id + '-info');
1022
- }
1020
+ this.$visibleCountMessage = null;
1021
+ this.$screenReaderCountMessage = null;
1022
+ this.lastInputTimestamp = null;
1023
1023
  }
1024
1024
 
1025
1025
  CharacterCount.prototype.defaults = {
@@ -1029,18 +1029,39 @@ CharacterCount.prototype.defaults = {
1029
1029
 
1030
1030
  // Initialize component
1031
1031
  CharacterCount.prototype.init = function () {
1032
+ // Check that required elements are present
1033
+ if (!this.$textarea) {
1034
+ return
1035
+ }
1036
+
1032
1037
  // Check for module
1033
1038
  var $module = this.$module;
1034
1039
  var $textarea = this.$textarea;
1035
- var $countMessage = this.$countMessage;
1036
-
1037
- if (!$textarea || !$countMessage) {
1038
- return
1039
- }
1040
+ var $fallbackLimitMessage = document.getElementById($textarea.id + '-info');
1040
1041
 
1041
- // We move count message right after the field
1042
+ // Move the fallback count message to be immediately after the textarea
1042
1043
  // Kept for backwards compatibility
1043
- $textarea.insertAdjacentElement('afterend', $countMessage);
1044
+ $textarea.insertAdjacentElement('afterend', $fallbackLimitMessage);
1045
+
1046
+ // Create the *screen reader* specific live-updating counter
1047
+ // This doesn't need any styling classes, as it is never visible
1048
+ var $screenReaderCountMessage = document.createElement('div');
1049
+ $screenReaderCountMessage.className = 'govuk-character-count__sr-status govuk-visually-hidden';
1050
+ $screenReaderCountMessage.setAttribute('aria-live', 'polite');
1051
+ this.$screenReaderCountMessage = $screenReaderCountMessage;
1052
+ $fallbackLimitMessage.insertAdjacentElement('afterend', $screenReaderCountMessage);
1053
+
1054
+ // Create our live-updating counter element, copying the classes from the
1055
+ // fallback element for backwards compatibility as these may have been configured
1056
+ var $visibleCountMessage = document.createElement('div');
1057
+ $visibleCountMessage.className = $fallbackLimitMessage.className;
1058
+ $visibleCountMessage.classList.add('govuk-character-count__status');
1059
+ $visibleCountMessage.setAttribute('aria-hidden', 'true');
1060
+ this.$visibleCountMessage = $visibleCountMessage;
1061
+ $fallbackLimitMessage.insertAdjacentElement('afterend', $visibleCountMessage);
1062
+
1063
+ // Hide the fallback limit message
1064
+ $fallbackLimitMessage.classList.add('govuk-visually-hidden');
1044
1065
 
1045
1066
  // Read options set using dataset ('data-' values)
1046
1067
  this.options = this.getDataset($module);
@@ -1060,23 +1081,19 @@ CharacterCount.prototype.init = function () {
1060
1081
  }
1061
1082
 
1062
1083
  // Remove hard limit if set
1063
- $module.removeAttribute('maxlength');
1084
+ $textarea.removeAttribute('maxlength');
1085
+
1086
+ this.bindChangeEvents();
1064
1087
 
1065
1088
  // When the page is restored after navigating 'back' in some browsers the
1066
1089
  // state of the character count is not restored until *after* the DOMContentLoaded
1067
- // event is fired, so we need to sync after the pageshow event in browsers
1068
- // that support it.
1090
+ // event is fired, so we need to manually update it after the pageshow event
1091
+ // in browsers that support it.
1069
1092
  if ('onpageshow' in window) {
1070
- window.addEventListener('pageshow', this.sync.bind(this));
1093
+ window.addEventListener('pageshow', this.updateCountMessage.bind(this));
1071
1094
  } else {
1072
- window.addEventListener('DOMContentLoaded', this.sync.bind(this));
1095
+ window.addEventListener('DOMContentLoaded', this.updateCountMessage.bind(this));
1073
1096
  }
1074
-
1075
- this.sync();
1076
- };
1077
-
1078
- CharacterCount.prototype.sync = function () {
1079
- this.bindChangeEvents();
1080
1097
  this.updateCountMessage();
1081
1098
  };
1082
1099
 
@@ -1111,7 +1128,7 @@ CharacterCount.prototype.count = function (text) {
1111
1128
  // Bind input propertychange to the elements and update based on the change
1112
1129
  CharacterCount.prototype.bindChangeEvents = function () {
1113
1130
  var $textarea = this.$textarea;
1114
- $textarea.addEventListener('keyup', this.checkIfValueChanged.bind(this));
1131
+ $textarea.addEventListener('keyup', this.handleKeyUp.bind(this));
1115
1132
 
1116
1133
  // Bind focus/blur events to start/stop polling
1117
1134
  $textarea.addEventListener('focus', this.handleFocus.bind(this));
@@ -1129,42 +1146,64 @@ CharacterCount.prototype.checkIfValueChanged = function () {
1129
1146
  }
1130
1147
  };
1131
1148
 
1132
- // Update message box
1149
+ // Helper function to update both the visible and screen reader-specific
1150
+ // counters simultaneously (e.g. on init)
1133
1151
  CharacterCount.prototype.updateCountMessage = function () {
1134
- var countElement = this.$textarea;
1135
- var options = this.options;
1136
- var countMessage = this.$countMessage;
1152
+ this.updateVisibleCountMessage();
1153
+ this.updateScreenReaderCountMessage();
1154
+ };
1137
1155
 
1138
- // Determine the remaining number of characters/words
1139
- var currentLength = this.count(countElement.value);
1140
- var maxLength = this.maxLength;
1141
- var remainingNumber = maxLength - currentLength;
1156
+ // Update visible counter
1157
+ CharacterCount.prototype.updateVisibleCountMessage = function () {
1158
+ var $textarea = this.$textarea;
1159
+ var $visibleCountMessage = this.$visibleCountMessage;
1160
+ var remainingNumber = this.maxLength - this.count($textarea.value);
1142
1161
 
1143
- // Set threshold if presented in options
1144
- var thresholdPercent = options.threshold ? options.threshold : 0;
1145
- var thresholdValue = maxLength * thresholdPercent / 100;
1146
- if (thresholdValue > currentLength) {
1147
- countMessage.classList.add('govuk-character-count__message--disabled');
1148
- // Ensure threshold is hidden for users of assistive technologies
1149
- countMessage.setAttribute('aria-hidden', true);
1162
+ // If input is over the threshold, remove the disabled class which renders the
1163
+ // counter invisible.
1164
+ if (this.isOverThreshold()) {
1165
+ $visibleCountMessage.classList.remove('govuk-character-count__message--disabled');
1150
1166
  } else {
1151
- countMessage.classList.remove('govuk-character-count__message--disabled');
1152
- // Ensure threshold is visible for users of assistive technologies
1153
- countMessage.removeAttribute('aria-hidden');
1167
+ $visibleCountMessage.classList.add('govuk-character-count__message--disabled');
1154
1168
  }
1155
1169
 
1156
1170
  // Update styles
1157
1171
  if (remainingNumber < 0) {
1158
- countElement.classList.add('govuk-textarea--error');
1159
- countMessage.classList.remove('govuk-hint');
1160
- countMessage.classList.add('govuk-error-message');
1172
+ $textarea.classList.add('govuk-textarea--error');
1173
+ $visibleCountMessage.classList.remove('govuk-hint');
1174
+ $visibleCountMessage.classList.add('govuk-error-message');
1175
+ } else {
1176
+ $textarea.classList.remove('govuk-textarea--error');
1177
+ $visibleCountMessage.classList.remove('govuk-error-message');
1178
+ $visibleCountMessage.classList.add('govuk-hint');
1179
+ }
1180
+
1181
+ // Update message
1182
+ $visibleCountMessage.innerHTML = this.formattedUpdateMessage();
1183
+ };
1184
+
1185
+ // Update screen reader-specific counter
1186
+ CharacterCount.prototype.updateScreenReaderCountMessage = function () {
1187
+ var $screenReaderCountMessage = this.$screenReaderCountMessage;
1188
+
1189
+ // If over the threshold, remove the aria-hidden attribute, allowing screen
1190
+ // readers to announce the content of the element.
1191
+ if (this.isOverThreshold()) {
1192
+ $screenReaderCountMessage.removeAttribute('aria-hidden');
1161
1193
  } else {
1162
- countElement.classList.remove('govuk-textarea--error');
1163
- countMessage.classList.remove('govuk-error-message');
1164
- countMessage.classList.add('govuk-hint');
1194
+ $screenReaderCountMessage.setAttribute('aria-hidden', true);
1165
1195
  }
1166
1196
 
1167
1197
  // Update message
1198
+ $screenReaderCountMessage.innerHTML = this.formattedUpdateMessage();
1199
+ };
1200
+
1201
+ // Format update message
1202
+ CharacterCount.prototype.formattedUpdateMessage = function () {
1203
+ var $textarea = this.$textarea;
1204
+ var options = this.options;
1205
+ var remainingNumber = this.maxLength - this.count($textarea.value);
1206
+
1168
1207
  var charVerb = 'remaining';
1169
1208
  var charNoun = 'character';
1170
1209
  var displayNumber = remainingNumber;
@@ -1176,12 +1215,44 @@ CharacterCount.prototype.updateCountMessage = function () {
1176
1215
  charVerb = (remainingNumber < 0) ? 'too many' : 'remaining';
1177
1216
  displayNumber = Math.abs(remainingNumber);
1178
1217
 
1179
- countMessage.innerHTML = 'You have ' + displayNumber + ' ' + charNoun + ' ' + charVerb;
1218
+ return 'You have ' + displayNumber + ' ' + charNoun + ' ' + charVerb
1219
+ };
1220
+
1221
+ // Checks whether the value is over the configured threshold for the input.
1222
+ // If there is no configured threshold, it is set to 0 and this function will
1223
+ // always return true.
1224
+ CharacterCount.prototype.isOverThreshold = function () {
1225
+ var $textarea = this.$textarea;
1226
+ var options = this.options;
1227
+
1228
+ // Determine the remaining number of characters/words
1229
+ var currentLength = this.count($textarea.value);
1230
+ var maxLength = this.maxLength;
1231
+
1232
+ // Set threshold if presented in options
1233
+ var thresholdPercent = options.threshold ? options.threshold : 0;
1234
+ var thresholdValue = maxLength * thresholdPercent / 100;
1235
+
1236
+ return (thresholdValue <= currentLength)
1237
+ };
1238
+
1239
+ // Update the visible character counter and keep track of when the last update
1240
+ // happened for each keypress
1241
+ CharacterCount.prototype.handleKeyUp = function () {
1242
+ this.updateVisibleCountMessage();
1243
+ this.lastInputTimestamp = Date.now();
1180
1244
  };
1181
1245
 
1182
1246
  CharacterCount.prototype.handleFocus = function () {
1183
- // Check if value changed on focus
1184
- this.valueChecker = setInterval(this.checkIfValueChanged.bind(this), 1000);
1247
+ // If the field is focused, and a keyup event hasn't been detected for at
1248
+ // least 1000 ms (1 second), then run the manual change check.
1249
+ // This is so that the update triggered by the manual comparison doesn't
1250
+ // conflict with debounced KeyboardEvent updates.
1251
+ this.valueChecker = setInterval(function () {
1252
+ if (!this.lastInputTimestamp || (Date.now() - 500) >= this.lastInputTimestamp) {
1253
+ this.checkIfValueChanged();
1254
+ }
1255
+ }.bind(this), 1000);
1185
1256
  };
1186
1257
 
1187
1258
  CharacterCount.prototype.handleBlur = function () {
@@ -11,7 +11,7 @@
11
11
  "text": "Can you provide more detail?"
12
12
  }
13
13
  },
14
- "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=\"more-detail\">\n Can you provide more detail?\n </label>\n\n\n <textarea class=\"govuk-textarea govuk-js-character-count\" id=\"more-detail\" name=\"more-detail\" rows=\"5\" aria-describedby=\"more-detail-info\"></textarea>\n</div>\n\n <div id=\"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>",
14
+ "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=\"more-detail\">\n Can you provide more detail?\n </label>\n\n\n <textarea class=\"govuk-textarea govuk-js-character-count\" id=\"more-detail\" name=\"more-detail\" rows=\"5\" aria-describedby=\"more-detail-info\"></textarea>\n</div>\n\n <div id=\"more-detail-info\" class=\"govuk-hint govuk-character-count__message\">\n You can enter up to 10 characters\n</div>\n\n</div>",
15
15
  "hidden": false
16
16
  },
17
17
  {
@@ -27,7 +27,7 @@
27
27
  "text": "Don't include personal or financial information, eg your National Insurance number or credit card details."
28
28
  }
29
29
  },
30
- "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=\"with-hint\">\n Can you provide more detail?\n </label>\n\n \n \n <div id=\"with-hint-hint\" class=\"govuk-hint\">\n Don&#39;t include personal or financial information, eg your National Insurance number or credit card details.\n </div>\n\n\n <textarea class=\"govuk-textarea govuk-js-character-count\" id=\"with-hint\" name=\"with-hint\" rows=\"5\" aria-describedby=\"with-hint-info with-hint-hint\"></textarea>\n</div>\n\n <div id=\"with-hint-info\" class=\"govuk-hint govuk-character-count__message\" aria-live=\"polite\">\n You can enter up to 10 characters\n</div>\n\n</div>",
30
+ "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=\"with-hint\">\n Can you provide more detail?\n </label>\n\n \n \n <div id=\"with-hint-hint\" class=\"govuk-hint\">\n Don&#39;t include personal or financial information, eg your National Insurance number or credit card details.\n </div>\n\n\n <textarea class=\"govuk-textarea govuk-js-character-count\" id=\"with-hint\" name=\"with-hint\" rows=\"5\" aria-describedby=\"with-hint-info with-hint-hint\"></textarea>\n</div>\n\n <div id=\"with-hint-info\" class=\"govuk-hint govuk-character-count__message\">\n You can enter up to 10 characters\n</div>\n\n</div>",
31
31
  "hidden": false
32
32
  },
33
33
  {
@@ -41,7 +41,7 @@
41
41
  },
42
42
  "value": "221B Baker Street\nLondon\nNW1 6XE\n"
43
43
  },
44
- "html": "<div class=\"govuk-character-count\" data-module=\"govuk-character-count\" data-maxlength=\"100\">\n \n\n<div class=\"govuk-form-group\">\n <label class=\"govuk-label\" for=\"with-default-value\">\n Full address\n </label>\n\n\n <textarea class=\"govuk-textarea govuk-js-character-count\" id=\"with-default-value\" name=\"default-value\" rows=\"5\" aria-describedby=\"with-default-value-info\">221B Baker Street\nLondon\nNW1 6XE\n</textarea>\n</div>\n\n <div id=\"with-default-value-info\" class=\"govuk-hint govuk-character-count__message\" aria-live=\"polite\">\n You can enter up to 100 characters\n</div>\n\n</div>",
44
+ "html": "<div class=\"govuk-character-count\" data-module=\"govuk-character-count\" data-maxlength=\"100\">\n \n\n<div class=\"govuk-form-group\">\n <label class=\"govuk-label\" for=\"with-default-value\">\n Full address\n </label>\n\n\n <textarea class=\"govuk-textarea govuk-js-character-count\" id=\"with-default-value\" name=\"default-value\" rows=\"5\" aria-describedby=\"with-default-value-info\">221B Baker Street\nLondon\nNW1 6XE\n</textarea>\n</div>\n\n <div id=\"with-default-value-info\" class=\"govuk-hint govuk-character-count__message\">\n You can enter up to 100 characters\n</div>\n\n</div>",
45
45
  "hidden": false
46
46
  },
47
47
  {
@@ -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 <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>",
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\">\n You can enter up to 10 characters\n</div>\n\n</div>",
62
62
  "hidden": false
63
63
  },
64
64
  {
@@ -72,7 +72,7 @@
72
72
  },
73
73
  "rows": 8
74
74
  },
75
- "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=\"custom-rows\">\n Full address\n </label>\n\n\n <textarea class=\"govuk-textarea govuk-js-character-count\" id=\"custom-rows\" name=\"custom\" rows=\"8\" aria-describedby=\"custom-rows-info\"></textarea>\n</div>\n\n <div id=\"custom-rows-info\" class=\"govuk-hint govuk-character-count__message\" aria-live=\"polite\">\n You can enter up to 10 characters\n</div>\n\n</div>",
75
+ "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=\"custom-rows\">\n Full address\n </label>\n\n\n <textarea class=\"govuk-textarea govuk-js-character-count\" id=\"custom-rows\" name=\"custom\" rows=\"8\" aria-describedby=\"custom-rows-info\"></textarea>\n</div>\n\n <div id=\"custom-rows-info\" class=\"govuk-hint govuk-character-count__message\">\n You can enter up to 10 characters\n</div>\n\n</div>",
76
76
  "hidden": false
77
77
  },
78
78
  {
@@ -86,7 +86,7 @@
86
86
  "isPageHeading": true
87
87
  }
88
88
  },
89
- "html": "<div class=\"govuk-character-count\" data-module=\"govuk-character-count\" data-maxlength=\"10\">\n \n\n<div class=\"govuk-form-group\">\n <h1 class=\"govuk-label-wrapper\">\n <label class=\"govuk-label\" for=\"textarea-with-page-heading\">\n Full address\n </label>\n </h1>\n\n\n <textarea class=\"govuk-textarea govuk-js-character-count\" id=\"textarea-with-page-heading\" name=\"address\" rows=\"5\" aria-describedby=\"textarea-with-page-heading-info\"></textarea>\n</div>\n\n <div id=\"textarea-with-page-heading-info\" class=\"govuk-hint govuk-character-count__message\" aria-live=\"polite\">\n You can enter up to 10 characters\n</div>\n\n</div>",
89
+ "html": "<div class=\"govuk-character-count\" data-module=\"govuk-character-count\" data-maxlength=\"10\">\n \n\n<div class=\"govuk-form-group\">\n <h1 class=\"govuk-label-wrapper\">\n <label class=\"govuk-label\" for=\"textarea-with-page-heading\">\n Full address\n </label>\n </h1>\n\n\n <textarea class=\"govuk-textarea govuk-js-character-count\" id=\"textarea-with-page-heading\" name=\"address\" rows=\"5\" aria-describedby=\"textarea-with-page-heading-info\"></textarea>\n</div>\n\n <div id=\"textarea-with-page-heading-info\" class=\"govuk-hint govuk-character-count__message\">\n You can enter up to 10 characters\n</div>\n\n</div>",
90
90
  "hidden": false
91
91
  },
92
92
  {
@@ -99,7 +99,7 @@
99
99
  "text": "Full address"
100
100
  }
101
101
  },
102
- "html": "<div class=\"govuk-character-count\" data-module=\"govuk-character-count\" data-maxwords=\"10\">\n \n\n<div class=\"govuk-form-group\">\n <label class=\"govuk-label\" for=\"word-count\">\n Full address\n </label>\n\n\n <textarea class=\"govuk-textarea govuk-js-character-count\" id=\"word-count\" name=\"word-count\" rows=\"5\" aria-describedby=\"word-count-info\"></textarea>\n</div>\n\n <div id=\"word-count-info\" class=\"govuk-hint govuk-character-count__message\" aria-live=\"polite\">\n You can enter up to 10 words\n</div>\n\n</div>",
102
+ "html": "<div class=\"govuk-character-count\" data-module=\"govuk-character-count\" data-maxwords=\"10\">\n \n\n<div class=\"govuk-form-group\">\n <label class=\"govuk-label\" for=\"word-count\">\n Full address\n </label>\n\n\n <textarea class=\"govuk-textarea govuk-js-character-count\" id=\"word-count\" name=\"word-count\" rows=\"5\" aria-describedby=\"word-count-info\"></textarea>\n</div>\n\n <div id=\"word-count-info\" class=\"govuk-hint govuk-character-count__message\">\n You can enter up to 10 words\n</div>\n\n</div>",
103
103
  "hidden": false
104
104
  },
105
105
  {
@@ -113,7 +113,7 @@
113
113
  "text": "Full address"
114
114
  }
115
115
  },
116
- "html": "<div class=\"govuk-character-count\" data-module=\"govuk-character-count\" data-maxlength=\"10\" data-threshold=\"75\">\n \n\n<div class=\"govuk-form-group\">\n <label class=\"govuk-label\" for=\"with-threshold\">\n Full address\n </label>\n\n\n <textarea class=\"govuk-textarea govuk-js-character-count\" id=\"with-threshold\" name=\"with-threshold\" rows=\"5\" aria-describedby=\"with-threshold-info\"></textarea>\n</div>\n\n <div id=\"with-threshold-info\" class=\"govuk-hint govuk-character-count__message\" aria-live=\"polite\">\n You can enter up to 10 characters\n</div>\n\n</div>",
116
+ "html": "<div class=\"govuk-character-count\" data-module=\"govuk-character-count\" data-maxlength=\"10\" data-threshold=\"75\">\n \n\n<div class=\"govuk-form-group\">\n <label class=\"govuk-label\" for=\"with-threshold\">\n Full address\n </label>\n\n\n <textarea class=\"govuk-textarea govuk-js-character-count\" id=\"with-threshold\" name=\"with-threshold\" rows=\"5\" aria-describedby=\"with-threshold-info\"></textarea>\n</div>\n\n <div id=\"with-threshold-info\" class=\"govuk-hint govuk-character-count__message\">\n You can enter up to 10 characters\n</div>\n\n</div>",
117
117
  "hidden": false
118
118
  },
119
119
  {
@@ -127,7 +127,7 @@
127
127
  },
128
128
  "classes": "app-character-count--custom-modifier"
129
129
  },
130
- "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=\"with-classes\">\n With classes\n </label>\n\n\n <textarea class=\"govuk-textarea govuk-js-character-count app-character-count--custom-modifier\" id=\"with-classes\" name=\"with-classes\" rows=\"5\" aria-describedby=\"with-classes-info\"></textarea>\n</div>\n\n <div id=\"with-classes-info\" class=\"govuk-hint govuk-character-count__message\" aria-live=\"polite\">\n You can enter up to 10 characters\n</div>\n\n</div>",
130
+ "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=\"with-classes\">\n With classes\n </label>\n\n\n <textarea class=\"govuk-textarea govuk-js-character-count app-character-count--custom-modifier\" id=\"with-classes\" name=\"with-classes\" rows=\"5\" aria-describedby=\"with-classes-info\"></textarea>\n</div>\n\n <div id=\"with-classes-info\" class=\"govuk-hint govuk-character-count__message\">\n You can enter up to 10 characters\n</div>\n\n</div>",
131
131
  "hidden": true
132
132
  },
133
133
  {
@@ -143,7 +143,7 @@
143
143
  "data-attribute": "my data value"
144
144
  }
145
145
  },
146
- "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=\"with-attributes\">\n With attributes\n </label>\n\n\n <textarea class=\"govuk-textarea govuk-js-character-count\" id=\"with-attributes\" name=\"with-attributes\" rows=\"5\" aria-describedby=\"with-attributes-info\" data-attribute=\"my data value\"></textarea>\n</div>\n\n <div id=\"with-attributes-info\" class=\"govuk-hint govuk-character-count__message\" aria-live=\"polite\">\n You can enter up to 10 characters\n</div>\n\n</div>",
146
+ "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=\"with-attributes\">\n With attributes\n </label>\n\n\n <textarea class=\"govuk-textarea govuk-js-character-count\" id=\"with-attributes\" name=\"with-attributes\" rows=\"5\" aria-describedby=\"with-attributes-info\" data-attribute=\"my data value\"></textarea>\n</div>\n\n <div id=\"with-attributes-info\" class=\"govuk-hint govuk-character-count__message\">\n You can enter up to 10 characters\n</div>\n\n</div>",
147
147
  "hidden": true
148
148
  },
149
149
  {
@@ -159,7 +159,7 @@
159
159
  "classes": "app-character-count--custom-modifier"
160
160
  }
161
161
  },
162
- "html": "<div class=\"govuk-character-count\" data-module=\"govuk-character-count\" data-maxlength=\"10\">\n \n\n<div class=\"govuk-form-group app-character-count--custom-modifier\">\n <label class=\"govuk-label\" for=\"with-formgroup\">\n With formgroup\n </label>\n\n\n <textarea class=\"govuk-textarea govuk-js-character-count\" id=\"with-formgroup\" name=\"with-formgroup\" rows=\"5\" aria-describedby=\"with-formgroup-info\"></textarea>\n</div>\n\n <div id=\"with-formgroup-info\" class=\"govuk-hint govuk-character-count__message\" aria-live=\"polite\">\n You can enter up to 10 characters\n</div>\n\n</div>",
162
+ "html": "<div class=\"govuk-character-count\" data-module=\"govuk-character-count\" data-maxlength=\"10\">\n \n\n<div class=\"govuk-form-group app-character-count--custom-modifier\">\n <label class=\"govuk-label\" for=\"with-formgroup\">\n With formgroup\n </label>\n\n\n <textarea class=\"govuk-textarea govuk-js-character-count\" id=\"with-formgroup\" name=\"with-formgroup\" rows=\"5\" aria-describedby=\"with-formgroup-info\"></textarea>\n</div>\n\n <div id=\"with-formgroup-info\" class=\"govuk-hint govuk-character-count__message\">\n You can enter up to 10 characters\n</div>\n\n</div>",
163
163
  "hidden": true
164
164
  },
165
165
  {
@@ -175,7 +175,7 @@
175
175
  "classes": "app-custom-count-message"
176
176
  }
177
177
  },
178
- "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=\"with-custom-countmessage-class\">\n With custom countMessage class\n </label>\n\n\n <textarea class=\"govuk-textarea govuk-js-character-count\" id=\"with-custom-countmessage-class\" name=\"with-custom-countmessage-class\" rows=\"5\" aria-describedby=\"with-custom-countmessage-class-info\"></textarea>\n</div>\n\n <div id=\"with-custom-countmessage-class-info\" class=\"govuk-hint govuk-character-count__message app-custom-count-message\" aria-live=\"polite\">\n You can enter up to 10 characters\n</div>\n\n</div>",
178
+ "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=\"with-custom-countmessage-class\">\n With custom countMessage class\n </label>\n\n\n <textarea class=\"govuk-textarea govuk-js-character-count\" id=\"with-custom-countmessage-class\" name=\"with-custom-countmessage-class\" rows=\"5\" aria-describedby=\"with-custom-countmessage-class-info\"></textarea>\n</div>\n\n <div id=\"with-custom-countmessage-class-info\" class=\"govuk-hint govuk-character-count__message app-custom-count-message\">\n You can enter up to 10 characters\n</div>\n\n</div>",
179
179
  "hidden": true
180
180
  },
181
181
  {
@@ -189,7 +189,7 @@
189
189
  },
190
190
  "spellcheck": true
191
191
  },
192
- "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=\"with-spellcheck\">\n With spellcheck\n </label>\n\n\n <textarea class=\"govuk-textarea govuk-js-character-count\" id=\"with-spellcheck\" name=\"with-spellcheck\" rows=\"5\" spellcheck=\"true\" aria-describedby=\"with-spellcheck-info\"></textarea>\n</div>\n\n <div id=\"with-spellcheck-info\" class=\"govuk-hint govuk-character-count__message\" aria-live=\"polite\">\n You can enter up to 10 characters\n</div>\n\n</div>",
192
+ "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=\"with-spellcheck\">\n With spellcheck\n </label>\n\n\n <textarea class=\"govuk-textarea govuk-js-character-count\" id=\"with-spellcheck\" name=\"with-spellcheck\" rows=\"5\" spellcheck=\"true\" aria-describedby=\"with-spellcheck-info\"></textarea>\n</div>\n\n <div id=\"with-spellcheck-info\" class=\"govuk-hint govuk-character-count__message\">\n You can enter up to 10 characters\n</div>\n\n</div>",
193
193
  "hidden": true
194
194
  },
195
195
  {
@@ -203,7 +203,7 @@
203
203
  },
204
204
  "spellcheck": false
205
205
  },
206
- "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=\"without-spellcheck\">\n Without spellcheck\n </label>\n\n\n <textarea class=\"govuk-textarea govuk-js-character-count\" id=\"without-spellcheck\" name=\"without-spellcheck\" rows=\"5\" spellcheck=\"false\" aria-describedby=\"without-spellcheck-info\"></textarea>\n</div>\n\n <div id=\"without-spellcheck-info\" class=\"govuk-hint govuk-character-count__message\" aria-live=\"polite\">\n You can enter up to 10 characters\n</div>\n\n</div>",
206
+ "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=\"without-spellcheck\">\n Without spellcheck\n </label>\n\n\n <textarea class=\"govuk-textarea govuk-js-character-count\" id=\"without-spellcheck\" name=\"without-spellcheck\" rows=\"5\" spellcheck=\"false\" aria-describedby=\"without-spellcheck-info\"></textarea>\n</div>\n\n <div id=\"without-spellcheck-info\" class=\"govuk-hint govuk-character-count__message\">\n You can enter up to 10 characters\n</div>\n\n</div>",
207
207
  "hidden": true
208
208
  },
209
209
  {
@@ -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 <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>",
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\">\n You can enter up to 10 characters\n</div>\n\n</div>",
224
224
  "hidden": true
225
225
  },
226
226
  {
@@ -233,7 +233,7 @@
233
233
  "text": "Can you provide more detail?"
234
234
  }
235
235
  },
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>",
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\">\n You can enter up to 10 characters\n</div>\n\n</div>",
237
237
  "hidden": true
238
238
  },
239
239
  {
@@ -246,8 +246,24 @@
246
246
  "text": "Full address"
247
247
  }
248
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>",
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\">\n You can enter up to 10 characters\n</div>\n\n</div>",
250
250
  "hidden": false
251
+ },
252
+ {
253
+ "name": "with textarea maxlength attribute",
254
+ "options": {
255
+ "id": "maxlength-should-be-removed",
256
+ "name": "address",
257
+ "maxlength": 10,
258
+ "attributes": {
259
+ "maxlength": 10
260
+ },
261
+ "label": {
262
+ "text": "Full address"
263
+ }
264
+ },
265
+ "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=\"maxlength-should-be-removed\">\n Full address\n </label>\n\n\n <textarea class=\"govuk-textarea govuk-js-character-count\" id=\"maxlength-should-be-removed\" name=\"address\" rows=\"5\" aria-describedby=\"maxlength-should-be-removed-info\" maxlength=\"10\"></textarea>\n</div>\n\n <div id=\"maxlength-should-be-removed-info\" class=\"govuk-hint govuk-character-count__message\">\n You can enter up to 10 characters\n</div>\n\n</div>",
266
+ "hidden": true
251
267
  }
252
268
  ]
253
269
  }
@@ -27,13 +27,13 @@
27
27
  "name": "maxlength",
28
28
  "type": "string",
29
29
  "required": true,
30
- "description": "If `maxwords` is set, this is not required. The maximum number of characters. If `maxwords` is provided, the `maxlength` argument will be ignored."
30
+ "description": "If `maxwords` is set, this is not required. The maximum number of characters. If `maxwords` is provided, the `maxlength` option will be ignored."
31
31
  },
32
32
  {
33
33
  "name": "maxwords",
34
34
  "type": "string",
35
35
  "required": true,
36
- "description": "If `maxlength` is set, this is not required. The maximum number of words. If `maxwords` is provided, the `maxlength` argument will be ignored."
36
+ "description": "If `maxlength` is set, this is not required. The maximum number of words. If `maxwords` is provided, the `maxlength` option will be ignored."
37
37
  },
38
38
  {
39
39
  "name": "threshold",
@@ -29,9 +29,6 @@
29
29
  {{ govukHint({
30
30
  text: 'You can enter up to ' + (params.maxlength or params.maxwords) + (' words' if params.maxwords else ' characters'),
31
31
  id: params.id + '-info',
32
- classes: 'govuk-character-count__message' + (' ' + params.countMessage.classes if params.countMessage.classes),
33
- attributes: {
34
- 'aria-live': 'polite'
35
- }
32
+ classes: 'govuk-character-count__message' + (' ' + params.countMessage.classes if params.countMessage.classes)
36
33
  }) }}
37
34
  </div>
@@ -83,7 +83,7 @@
83
83
  left: 0;
84
84
  width: $govuk-checkboxes-size;
85
85
  height: $govuk-checkboxes-size;
86
- border: $govuk-border-width-form-element solid currentColor;
86
+ border: $govuk-border-width-form-element solid currentcolor;
87
87
  background: transparent;
88
88
  }
89
89
 
@@ -155,7 +155,8 @@
155
155
  cursor: default;
156
156
  }
157
157
 
158
- .govuk-checkboxes__input:disabled + .govuk-checkboxes__label {
158
+ .govuk-checkboxes__input:disabled + .govuk-checkboxes__label,
159
+ .govuk-checkboxes__input:disabled ~ .govuk-hint {
159
160
  opacity: .5;
160
161
  }
161
162
 
@@ -176,24 +176,36 @@
176
176
  {
177
177
  "name": "with disabled item",
178
178
  "options": {
179
- "name": "colours",
179
+ "name": "sign-in",
180
+ "fieldset": {
181
+ "legend": {
182
+ "text": "How do you want to sign in?",
183
+ "isPageHeading": true
184
+ }
185
+ },
180
186
  "items": [
181
187
  {
182
- "value": "red",
183
- "text": "Red"
184
- },
185
- {
186
- "value": "green",
187
- "text": "Green"
188
+ "name": "gateway",
189
+ "id": "government-gateway",
190
+ "value": "gov-gateway",
191
+ "text": "Sign in with Government Gateway",
192
+ "hint": {
193
+ "text": "You'll have a user ID if you've registered for Self Assessment or filed a tax return online before."
194
+ }
188
195
  },
189
196
  {
190
- "value": "blue",
191
- "text": "Blue",
197
+ "name": "verify",
198
+ "id": "govuk-verify",
199
+ "value": "gov-verify",
200
+ "text": "Sign in with GOV.UK Verify",
201
+ "hint": {
202
+ "text": "You'll have an account if you've already proved your identity with either Barclays, CitizenSafe, Digidentity, Experian, Post Office, Royal Mail or SecureIdentity."
203
+ },
192
204
  "disabled": true
193
205
  }
194
206
  ]
195
207
  },
196
- "html": "<div class=\"govuk-form-group\">\n\n <div class=\"govuk-checkboxes\"\n data-module=\"govuk-checkboxes\">\n \n \n \n \n \n \n \n \n <div class=\"govuk-checkboxes__item\">\n <input class=\"govuk-checkboxes__input\" id=\"colours\" name=\"colours\" type=\"checkbox\" value=\"red\">\n <label class=\"govuk-label govuk-checkboxes__label\" for=\"colours\">\n Red\n </label>\n \n </div>\n \n \n \n \n \n \n \n \n \n \n <div class=\"govuk-checkboxes__item\">\n <input class=\"govuk-checkboxes__input\" id=\"colours-2\" name=\"colours\" type=\"checkbox\" value=\"green\">\n <label class=\"govuk-label govuk-checkboxes__label\" for=\"colours-2\">\n Green\n </label>\n \n </div>\n \n \n \n \n \n \n \n \n \n \n <div class=\"govuk-checkboxes__item\">\n <input class=\"govuk-checkboxes__input\" id=\"colours-3\" name=\"colours\" type=\"checkbox\" value=\"blue\" disabled>\n <label class=\"govuk-label govuk-checkboxes__label\" for=\"colours-3\">\n Blue\n </label>\n \n </div>\n \n \n \n \n </div>\n\n</div>",
208
+ "html": "<div class=\"govuk-form-group\">\n\n <fieldset class=\"govuk-fieldset\">\n \n <legend class=\"govuk-fieldset__legend\">\n \n <h1 class=\"govuk-fieldset__heading\">\n How do you want to sign in?\n </h1>\n \n </legend>\n \n\n <div class=\"govuk-checkboxes\"\n data-module=\"govuk-checkboxes\">\n \n \n \n \n \n \n \n <div class=\"govuk-checkboxes__item\">\n <input class=\"govuk-checkboxes__input\" id=\"government-gateway\" name=\"gateway\" type=\"checkbox\" value=\"gov-gateway\" aria-describedby=\"government-gateway-item-hint\">\n <label class=\"govuk-label govuk-checkboxes__label\" for=\"government-gateway\">\n Sign in with Government Gateway\n </label>\n \n <div id=\"government-gateway-item-hint\" class=\"govuk-hint govuk-checkboxes__hint\">\n You&#39;ll have a user ID if you&#39;ve registered for Self Assessment or filed a tax return online before.\n </div>\n \n </div>\n \n \n \n \n \n \n \n \n \n \n <div class=\"govuk-checkboxes__item\">\n <input class=\"govuk-checkboxes__input\" id=\"govuk-verify\" name=\"verify\" type=\"checkbox\" value=\"gov-verify\" disabled aria-describedby=\"govuk-verify-item-hint\">\n <label class=\"govuk-label govuk-checkboxes__label\" for=\"govuk-verify\">\n Sign in with GOV.UK Verify\n </label>\n \n <div id=\"govuk-verify-item-hint\" class=\"govuk-hint govuk-checkboxes__hint\">\n You&#39;ll have an account if you&#39;ve already proved your identity with either Barclays, CitizenSafe, Digidentity, Experian, Post Office, Royal Mail or SecureIdentity.\n </div>\n \n </div>\n \n \n \n \n </div>\n \n\n</fieldset>\n\n\n</div>",
197
209
  "hidden": false
198
210
  },
199
211
  {
@@ -62,13 +62,13 @@
62
62
  "name": "text",
63
63
  "type": "string",
64
64
  "required": true,
65
- "description": "If `html` is set, this is not required. Text to use within each checkbox item label. If `html` is provided, the `text` argument will be ignored."
65
+ "description": "If `html` is set, this is not required. Text to use within each checkbox item label. If `html` is provided, the `text` option will be ignored."
66
66
  },
67
67
  {
68
68
  "name": "html",
69
69
  "type": "string",
70
70
  "required": true,
71
- "description": "If `text` is set, this is not required. HTML to use within each checkbox item label. If `html` is provided, the `text` argument will be ignored."
71
+ "description": "If `text` is set, this is not required. HTML to use within each checkbox item label. If `html` is provided, the `text` option will be ignored."
72
72
  },
73
73
  {
74
74
  "name": "id",