From c0df27367b3e35acac73f93780546feb4cd604d8 Mon Sep 17 00:00:00 2001 From: Kimberly Grey Date: Mon, 21 Mar 2022 15:54:21 +0000 Subject: [PATCH] Refactor character count to inject new element Changes the character count to inject a new element that is live updated, instead of overwriting the content of the initial HTML hint. This is intended to resolve an issue where screen readers are reading out all elements referenced in aria-describedby for each keystroke, and not just the updated counter element. https://github.com/alphagov/govuk-frontend/issues/2539 --- .../character-count/character-count.js | 21 ++++++++++++++----- .../components/character-count/template.njk | 5 +---- 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/govuk/components/character-count/character-count.js b/src/govuk/components/character-count/character-count.js index 9922c815ae..639fc622d7 100644 --- a/src/govuk/components/character-count/character-count.js +++ b/src/govuk/components/character-count/character-count.js @@ -6,7 +6,7 @@ function CharacterCount ($module) { this.$module = $module this.$textarea = $module.querySelector('.govuk-js-character-count') if (this.$textarea) { - this.$countMessage = document.getElementById(this.$textarea.id + '-info') + this.$fallbackLimitMessage = document.getElementById(this.$textarea.id + '-info') } } @@ -20,15 +20,26 @@ CharacterCount.prototype.init = function () { // Check for module var $module = this.$module var $textarea = this.$textarea - var $countMessage = this.$countMessage + var $fallbackLimitMessage = this.$fallbackLimitMessage - if (!$textarea || !$countMessage) { + if (!$textarea) { return } - // We move count message right after the field + // We move fallback count message right after the field // Kept for backwards compatibility - $textarea.insertAdjacentElement('afterend', $countMessage) + $textarea.insertAdjacentElement('afterend', $fallbackLimitMessage) + + // Create our live-updating counter element, copying the classes from the + // fallback element for backwards compatibility as these may have been configured + var $countMessage = document.createElement('div') + $countMessage.className = $fallbackLimitMessage.className + $countMessage.setAttribute('aria-live', 'polite') + this.$countMessage = $countMessage + $fallbackLimitMessage.insertAdjacentElement('afterend', $countMessage) + + // Hide the fallback limit message + $fallbackLimitMessage.classList.add('govuk-visually-hidden') // Read options set using dataset ('data-' values) this.options = this.getDataset($module) diff --git a/src/govuk/components/character-count/template.njk b/src/govuk/components/character-count/template.njk index d1eb46b1e7..297604176a 100644 --- a/src/govuk/components/character-count/template.njk +++ b/src/govuk/components/character-count/template.njk @@ -29,9 +29,6 @@ {{ govukHint({ text: 'You can enter up to ' + (params.maxlength or params.maxwords) + (' words' if params.maxwords else ' characters'), id: params.id + '-info', - classes: 'govuk-character-count__message' + (' ' + params.countMessage.classes if params.countMessage.classes), - attributes: { - 'aria-live': 'polite' - } + classes: 'govuk-character-count__message' + (' ' + params.countMessage.classes if params.countMessage.classes) }) }}