{"version":3,"file":"character-count.mjs","sources":["../../../../src/govuk/components/character-count/character-count.mjs"],"sourcesContent":["import { closestAttributeValue } from '../../common/closest-attribute-value.mjs'\nimport {\n  validateConfig,\n  ConfigurableComponent,\n  configOverride\n} from '../../common/configuration.mjs'\nimport { formatErrorMessage } from '../../common/index.mjs'\nimport { ConfigError, ElementError } from '../../errors/index.mjs'\nimport { I18n } from '../../i18n.mjs'\n\n/**\n * Character count component\n *\n * Tracks the number of characters or words in the `.govuk-js-character-count`\n * `<textarea>` inside the element. Displays a message with the remaining number\n * of characters/words available, or the number of characters/words in excess.\n *\n * You can configure the message to only appear after a certain percentage\n * of the available characters/words has been entered.\n *\n * @preserve\n * @augments ConfigurableComponent<CharacterCountConfig>\n */\nexport class CharacterCount extends ConfigurableComponent {\n  /** @private */\n  $textarea\n\n  /** @private */\n  count = 0\n\n  /** @private */\n  $visibleCountMessage\n\n  /** @private */\n  $screenReaderCountMessage\n\n  /**\n   * @private\n   * @type {number | null}\n   */\n  lastInputTimestamp = null\n\n  /** @private */\n  lastInputValue = ''\n\n  /**\n   * @private\n   * @type {number | null}\n   */\n  valueChecker = null\n\n  /** @private */\n  i18n\n\n  /** @private */\n  maxLength;\n\n  /**\n   * Character count config override\n   *\n   * To ensure data-attributes take complete precedence, even if they change\n   * the type of count, we need to reset the `maxlength` and `maxwords` from\n   * the JavaScript config.\n   *\n   * @internal\n   * @param {CharacterCountConfig} datasetConfig - configuration specified by dataset\n   * @returns {CharacterCountConfig} - configuration to override by dataset\n   */\n  [configOverride](datasetConfig) {\n    let configOverrides = {}\n    if ('maxwords' in datasetConfig || 'maxlength' in datasetConfig) {\n      configOverrides = {\n        maxlength: undefined,\n        maxwords: undefined\n      }\n    }\n\n    return configOverrides\n  }\n\n  /**\n   * @param {Element | null} $root - HTML element to use for character count\n   * @param {CharacterCountConfig} [config] - Character count config\n   */\n  constructor($root, config = {}) {\n    super($root, config)\n\n    const $textarea = this.$root.querySelector('.govuk-js-character-count')\n    if (\n      !(\n        $textarea instanceof HTMLTextAreaElement ||\n        $textarea instanceof HTMLInputElement\n      )\n    ) {\n      throw new ElementError({\n        component: CharacterCount,\n        element: $textarea,\n        expectedType: 'HTMLTextareaElement or HTMLInputElement',\n        identifier: 'Form field (`.govuk-js-character-count`)'\n      })\n    }\n\n    // Check for valid config\n    const errors = validateConfig(CharacterCount.schema, this.config)\n    if (errors[0]) {\n      throw new ConfigError(formatErrorMessage(CharacterCount, errors[0]))\n    }\n\n    this.i18n = new I18n(this.config.i18n, {\n      // Read the fallback if necessary rather than have it set in the defaults\n      locale: closestAttributeValue(this.$root, 'lang')\n    })\n\n    // Determine the limit attribute (characters or words)\n    this.maxLength = this.config.maxwords ?? this.config.maxlength ?? Infinity\n\n    this.$textarea = $textarea\n\n    const textareaDescriptionId = `${this.$textarea.id}-info`\n    const $textareaDescription = document.getElementById(textareaDescriptionId)\n    if (!$textareaDescription) {\n      throw new ElementError({\n        component: CharacterCount,\n        element: $textareaDescription,\n        identifier: `Count message (\\`id=\"${textareaDescriptionId}\"\\`)`\n      })\n    }\n\n    // Pre-existing validation error rendered from server\n    this.$errorMessage = this.$root.querySelector('.govuk-error-message')\n\n    // Inject a description for the textarea if none is present already\n    // for when the component was rendered with no maxlength, maxwords\n    // nor custom textareaDescriptionText\n    // eslint-disable-next-line @typescript-eslint/prefer-regexp-exec\n    if ($textareaDescription.textContent.match(/^\\s*$/)) {\n      $textareaDescription.textContent = this.i18n.t('textareaDescription', {\n        count: this.maxLength\n      })\n    }\n\n    // Move the textarea description to be immediately after the textarea\n    // Kept for backwards compatibility\n    this.$textarea.insertAdjacentElement('afterend', $textareaDescription)\n\n    // Create the *screen reader* specific live-updating counter\n    // This doesn't need any styling classes, as it is never visible\n    const $screenReaderCountMessage = document.createElement('div')\n    $screenReaderCountMessage.className =\n      'govuk-character-count__sr-status govuk-visually-hidden'\n    $screenReaderCountMessage.setAttribute('aria-live', 'polite')\n    this.$screenReaderCountMessage = $screenReaderCountMessage\n    $textareaDescription.insertAdjacentElement(\n      'afterend',\n      $screenReaderCountMessage\n    )\n\n    // Create our live-updating counter element, copying the classes from the\n    // textarea description for backwards compatibility as these may have been\n    // configured\n    const $visibleCountMessage = document.createElement('div')\n    $visibleCountMessage.className = $textareaDescription.className\n    $visibleCountMessage.classList.add('govuk-character-count__status')\n    $visibleCountMessage.setAttribute('aria-hidden', 'true')\n    this.$visibleCountMessage = $visibleCountMessage\n    $textareaDescription.insertAdjacentElement('afterend', $visibleCountMessage)\n\n    // Hide the textarea description\n    $textareaDescription.classList.add('govuk-visually-hidden')\n\n    // Remove hard limit if set\n    this.$textarea.removeAttribute('maxlength')\n\n    this.bindChangeEvents()\n\n    // When the page is restored after navigating 'back' in some browsers the\n    // state of form controls is not restored until *after* the DOMContentLoaded\n    // event is fired, so we need to sync after the pageshow event.\n    window.addEventListener('pageshow', () => {\n      // If the current value of the textarea is the same as what's\n      // in the HTML, don't re-run when users have not edited the field yet\n      // (new page load or BF cache navigation without having edited).\n      if (this.$textarea.value !== this.$textarea.textContent) {\n        this.updateCount()\n        this.updateCountMessage()\n      }\n    })\n\n    // Although we've set up handlers to sync state on the pageshow event, init\n    // could be called after those events have fired, for example if they are\n    // added to the page dynamically, so update now too.\n    this.updateCount()\n    this.updateCountMessage()\n  }\n\n  /**\n   * Bind change events\n   *\n   * Set up event listeners on the $textarea so that the count messages update\n   * when the user types.\n   *\n   * @private\n   */\n  bindChangeEvents() {\n    this.$textarea.addEventListener('input', () => this.handleInput())\n\n    // Bind focus/blur events to start/stop polling\n    this.$textarea.addEventListener('focus', () => this.handleFocus())\n    this.$textarea.addEventListener('blur', () => this.handleBlur())\n  }\n\n  /**\n   * Handle input event\n   *\n   * Update the visible character counter and keep track of when the last update\n   * happened for each keypress\n   *\n   * @private\n   */\n  handleInput() {\n    this.updateCount()\n    this.updateVisibleCountMessage()\n    this.lastInputTimestamp = Date.now()\n  }\n\n  /**\n   * Handle focus event\n   *\n   * Speech recognition software such as Dragon NaturallySpeaking will modify\n   * the fields by directly changing its `value`. These changes don't trigger\n   * events in JavaScript, so we need to poll to handle when and if they occur.\n   *\n   * Once the keyup event hasn't been detected for at least 1000 ms (1s), check\n   * if the textarea value has changed and update the count message if it has.\n   *\n   * This is so that the update triggered by the manual comparison doesn't\n   * conflict with debounced KeyboardEvent updates.\n   *\n   * @private\n   */\n  handleFocus() {\n    this.valueChecker = window.setInterval(() => {\n      if (\n        !this.lastInputTimestamp ||\n        Date.now() - 500 >= this.lastInputTimestamp\n      ) {\n        this.updateIfValueChanged()\n      }\n    }, 1000)\n  }\n\n  /**\n   * Handle blur event\n   *\n   * Stop checking the textarea value once the textarea no longer has focus\n   *\n   * @private\n   */\n  handleBlur() {\n    // Cancel value checking on blur\n    if (this.valueChecker) {\n      window.clearInterval(this.valueChecker)\n    }\n  }\n\n  /**\n   * Update count message if textarea value has changed\n   *\n   * @private\n   */\n  updateIfValueChanged() {\n    if (this.$textarea.value !== this.lastInputValue) {\n      this.lastInputValue = this.$textarea.value\n      this.updateCountMessage()\n    }\n  }\n\n  /**\n   * Update count message\n   *\n   * Helper function to update both the visible and screen reader-specific\n   * counters simultaneously (e.g. on init)\n   *\n   * @private\n   */\n  updateCountMessage() {\n    this.updateVisibleCountMessage()\n    this.updateScreenReaderCountMessage()\n  }\n\n  /**\n   * Update visible count message\n   *\n   * @private\n   */\n  updateVisibleCountMessage() {\n    const remainingNumber = this.maxLength - this.count\n    const isError = remainingNumber < 0\n\n    // If input is over the threshold, remove the disabled class which renders\n    // the counter invisible.\n    this.$visibleCountMessage.classList.toggle(\n      'govuk-character-count__message--disabled',\n      !this.isOverThreshold()\n    )\n\n    // Update styles\n    if (!this.$errorMessage) {\n      // Only toggle the textarea error class if there isn't an error message\n      // already, as it may be unrelated to the limit (eg: allowed characters)\n      // and would set the border colour back to black.\n      this.$textarea.classList.toggle('govuk-textarea--error', isError)\n    }\n    this.$visibleCountMessage.classList.toggle('govuk-error-message', isError)\n    this.$visibleCountMessage.classList.toggle('govuk-hint', !isError)\n\n    // Update message\n    this.$visibleCountMessage.textContent = this.getCountMessage()\n  }\n\n  /**\n   * Update screen reader count message\n   *\n   * @private\n   */\n  updateScreenReaderCountMessage() {\n    // If over the threshold, remove the aria-hidden attribute, allowing screen\n    // readers to announce the content of the element.\n    if (this.isOverThreshold()) {\n      this.$screenReaderCountMessage.removeAttribute('aria-hidden')\n    } else {\n      this.$screenReaderCountMessage.setAttribute('aria-hidden', 'true')\n    }\n\n    // Update message\n    this.$screenReaderCountMessage.textContent = this.getCountMessage()\n  }\n\n  /**\n   * Count the number of characters (or words, if `config.maxwords` is set)\n   * in the given text, and update the component-wide count\n   *\n   * @private\n   */\n  updateCount() {\n    const text = this.$textarea.value\n\n    if (this.config.maxwords) {\n      const tokens = text.match(/\\S+/g) ?? [] // Matches consecutive non-whitespace chars\n      this.count = tokens.length\n      return\n    }\n\n    this.count = text.length\n  }\n\n  /**\n   * Get count message\n   *\n   * @private\n   * @returns {string} Status message\n   */\n  getCountMessage() {\n    const remainingNumber = this.maxLength - this.count\n    const countType = this.config.maxwords ? 'words' : 'characters'\n    return this.formatCountMessage(remainingNumber, countType)\n  }\n\n  /**\n   * Formats the message shown to users according to what's counted\n   * and how many remain\n   *\n   * @private\n   * @param {number} remainingNumber - The number of words/characaters remaining\n   * @param {string} countType - \"words\" or \"characters\"\n   * @returns {string} Status message\n   */\n  formatCountMessage(remainingNumber, countType) {\n    if (remainingNumber === 0) {\n      return this.i18n.t(`${countType}AtLimit`)\n    }\n\n    const translationKeySuffix =\n      remainingNumber < 0 ? 'OverLimit' : 'UnderLimit'\n\n    return this.i18n.t(`${countType}${translationKeySuffix}`, {\n      count: Math.abs(remainingNumber)\n    })\n  }\n\n  /**\n   * Check if count is over threshold\n   *\n   * Checks whether the value is over the configured threshold for the input.\n   * If there is no configured threshold, it is set to 0 and this function will\n   * always return true.\n   *\n   * @private\n   * @returns {boolean} true if the current count is over the config.threshold\n   *   (or no threshold is set)\n   */\n  isOverThreshold() {\n    // No threshold means we're always above threshold so save some computation\n    if (!this.config.threshold) {\n      return true\n    }\n\n    // Determine the remaining number of characters/words\n    const currentLength = this.count\n    const maxLength = this.maxLength\n\n    const thresholdValue = (maxLength * this.config.threshold) / 100\n\n    return thresholdValue <= currentLength\n  }\n\n  /**\n   * Name for the component used when initialising using data-module attributes.\n   */\n  static moduleName = 'govuk-character-count'\n\n  /**\n   * Character count default config\n   *\n   * @see {@link CharacterCountConfig}\n   * @constant\n   * @type {CharacterCountConfig}\n   */\n  static defaults = Object.freeze({\n    threshold: 0,\n    i18n: {\n      // Characters\n      charactersUnderLimit: {\n        one: 'You have %{count} character remaining',\n        other: 'You have %{count} characters remaining'\n      },\n      charactersAtLimit: 'You have 0 characters remaining',\n      charactersOverLimit: {\n        one: 'You have %{count} character too many',\n        other: 'You have %{count} characters too many'\n      },\n      // Words\n      wordsUnderLimit: {\n        one: 'You have %{count} word remaining',\n        other: 'You have %{count} words remaining'\n      },\n      wordsAtLimit: 'You have 0 words remaining',\n      wordsOverLimit: {\n        one: 'You have %{count} word too many',\n        other: 'You have %{count} words too many'\n      },\n      textareaDescription: {\n        other: ''\n      }\n    }\n  })\n\n  /**\n   * Character count config schema\n   *\n   * @constant\n   * @satisfies {Schema<CharacterCountConfig>}\n   */\n  static schema = Object.freeze({\n    properties: {\n      i18n: { type: 'object' },\n      maxwords: { type: 'number' },\n      maxlength: { type: 'number' },\n      threshold: { type: 'number' }\n    },\n    anyOf: [\n      {\n        required: ['maxwords'],\n        errorMessage: 'Either \"maxlength\" or \"maxwords\" must be provided'\n      },\n      {\n        required: ['maxlength'],\n        errorMessage: 'Either \"maxlength\" or \"maxwords\" must be provided'\n      }\n    ]\n  })\n}\n\n/**\n * Character count config\n *\n * @see {@link CharacterCount.defaults}\n * @typedef {object} CharacterCountConfig\n * @property {number} [maxlength] - The maximum number of characters.\n *   If maxwords is provided, the maxlength option will be ignored.\n * @property {number} [maxwords] - The maximum number of words. If maxwords is\n *   provided, the maxlength option will be ignored.\n * @property {number} [threshold=0] - The percentage value of the limit at\n *   which point the count message is displayed. If this attribute is set, the\n *   count message will be hidden by default.\n * @property {CharacterCountTranslations} [i18n=CharacterCount.defaults.i18n] - Character count translations\n */\n\n/**\n * Character count translations\n *\n * @see {@link CharacterCount.defaults.i18n}\n * @typedef {object} CharacterCountTranslations\n *\n * Messages shown to users as they type. It provides feedback on how many words\n * or characters they have remaining or if they are over the limit. This also\n * includes a message used as an accessible description for the textarea.\n * @property {TranslationPluralForms} [charactersUnderLimit] - Message displayed\n *   when the number of characters is under the configured maximum, `maxlength`.\n *   This message is displayed visually and through assistive technologies. The\n *   component will replace the `%{count}` placeholder with the number of\n *   remaining characters. This is a [pluralised list of\n *   messages](https://frontend.design-system.service.gov.uk/localise-govuk-frontend).\n * @property {string} [charactersAtLimit] - Message displayed when the number of\n *   characters reaches the configured maximum, `maxlength`. This message is\n *   displayed visually and through assistive technologies.\n * @property {TranslationPluralForms} [charactersOverLimit] - Message displayed\n *   when the number of characters is over the configured maximum, `maxlength`.\n *   This message is displayed visually and through assistive technologies. The\n *   component will replace the `%{count}` placeholder with the number of\n *   remaining characters. This is a [pluralised list of\n *   messages](https://frontend.design-system.service.gov.uk/localise-govuk-frontend).\n * @property {TranslationPluralForms} [wordsUnderLimit] - Message displayed when\n *   the number of words is under the configured maximum, `maxlength`. This\n *   message is displayed visually and through assistive technologies. The\n *   component will replace the `%{count}` placeholder with the number of\n *   remaining words. This is a [pluralised list of\n *   messages](https://frontend.design-system.service.gov.uk/localise-govuk-frontend).\n * @property {string} [wordsAtLimit] - Message displayed when the number of\n *   words reaches the configured maximum, `maxlength`. This message is\n *   displayed visually and through assistive technologies.\n * @property {TranslationPluralForms} [wordsOverLimit] - Message displayed when\n *   the number of words is over the configured maximum, `maxlength`. This\n *   message is displayed visually and through assistive technologies. The\n *   component will replace the `%{count}` placeholder with the number of\n *   remaining words. This is a [pluralised list of\n *   messages](https://frontend.design-system.service.gov.uk/localise-govuk-frontend).\n * @property {TranslationPluralForms} [textareaDescription] - Message made\n *   available to assistive technologies, if none is already present in the\n *   HTML, to describe that the component accepts only a limited amount of\n *   content. It is visible on the page when JavaScript is unavailable. The\n *   component will replace the `%{count}` placeholder with the value of the\n *   `maxlength` or `maxwords` parameter.\n */\n\n/**\n * @import { Schema } from '../../common/configuration.mjs'\n * @import { TranslationPluralForms } from '../../i18n.mjs'\n */\n"],"names":["CharacterCount","ConfigurableComponent","configOverride","datasetConfig","configOverrides","maxlength","undefined","maxwords","constructor","$root","config","_ref","_this$config$maxwords","$textarea","count","$visibleCountMessage","$screenReaderCountMessage","lastInputTimestamp","lastInputValue","valueChecker","i18n","maxLength","querySelector","HTMLTextAreaElement","HTMLInputElement","ElementError","component","element","expectedType","identifier","errors","validateConfig","schema","ConfigError","formatErrorMessage","I18n","locale","closestAttributeValue","Infinity","textareaDescriptionId","id","$textareaDescription","document","getElementById","$errorMessage","textContent","match","t","insertAdjacentElement","createElement","className","setAttribute","classList","add","removeAttribute","bindChangeEvents","window","addEventListener","value","updateCount","updateCountMessage","handleInput","handleFocus","handleBlur","updateVisibleCountMessage","Date","now","setInterval","updateIfValueChanged","clearInterval","updateScreenReaderCountMessage","remainingNumber","isError","toggle","isOverThreshold","getCountMessage","text","_text$match","tokens","length","countType","formatCountMessage","translationKeySuffix","Math","abs","threshold","currentLength","thresholdValue","moduleName","defaults","Object","freeze","charactersUnderLimit","one","other","charactersAtLimit","charactersOverLimit","wordsUnderLimit","wordsAtLimit","wordsOverLimit","textareaDescription","properties","type","anyOf","required","errorMessage"],"mappings":"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"}