Skip to content

Commit d0b52ec

Browse files
committed
Refactor count method to reduce repetition
1 parent a3f5c2e commit d0b52ec

File tree

1 file changed

+26
-13
lines changed

1 file changed

+26
-13
lines changed

packages/govuk-frontend/src/govuk/components/character-count/character-count.mjs

Lines changed: 26 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@ export class CharacterCount extends ConfigurableComponent {
2525
/** @private */
2626
$textarea
2727

28+
/** @private */
29+
count = 0
30+
2831
/** @private */
2932
$visibleCountMessage
3033

@@ -173,11 +176,19 @@ export class CharacterCount extends ConfigurableComponent {
173176
// When the page is restored after navigating 'back' in some browsers the
174177
// state of form controls is not restored until *after* the DOMContentLoaded
175178
// event is fired, so we need to sync after the pageshow event.
176-
window.addEventListener('pageshow', () => this.updateCountMessage())
179+
window.addEventListener('pageshow', () => {
180+
// If the current value of the textarea is the same as what's
181+
// in the HTML, don't re-run.
182+
if(this.$textarea.value !== this.$textarea.innerHTML) {
183+
this.updateCount()
184+
this.updateCountMessage()
185+
}
186+
})
177187

178188
// Although we've set up handlers to sync state on the pageshow event, init
179189
// could be called after those events have fired, for example if they are
180190
// added to the page dynamically, so update now too.
191+
this.updateCount()
181192
this.updateCountMessage()
182193
}
183194

@@ -190,22 +201,23 @@ export class CharacterCount extends ConfigurableComponent {
190201
* @private
191202
*/
192203
bindChangeEvents() {
193-
this.$textarea.addEventListener('keyup', () => this.handleKeyUp())
204+
this.$textarea.addEventListener('input', () => this.handleInput())
194205

195206
// Bind focus/blur events to start/stop polling
196207
this.$textarea.addEventListener('focus', () => this.handleFocus())
197208
this.$textarea.addEventListener('blur', () => this.handleBlur())
198209
}
199210

200211
/**
201-
* Handle key up event
212+
* Handle input event
202213
*
203214
* Update the visible character counter and keep track of when the last update
204215
* happened for each keypress
205216
*
206217
* @private
207218
*/
208-
handleKeyUp() {
219+
handleInput() {
220+
this.updateCount()
209221
this.updateVisibleCountMessage()
210222
this.lastInputTimestamp = Date.now()
211223
}
@@ -281,7 +293,7 @@ export class CharacterCount extends ConfigurableComponent {
281293
* @private
282294
*/
283295
updateVisibleCountMessage() {
284-
const remainingNumber = this.maxLength - this.count(this.$textarea.value)
296+
const remainingNumber = this.maxLength - this.count
285297
const isError = remainingNumber < 0
286298

287299
// If input is over the threshold, remove the disabled class which renders
@@ -325,19 +337,20 @@ export class CharacterCount extends ConfigurableComponent {
325337

326338
/**
327339
* Count the number of characters (or words, if `config.maxwords` is set)
328-
* in the given text
340+
* in the given text, and update the component-wide count
329341
*
330342
* @private
331-
* @param {string} text - The text to count the characters of
332-
* @returns {number} the number of characters (or words) in the text
333343
*/
334-
count(text) {
344+
updateCount() {
345+
const text = this.$textarea.value
346+
335347
if (this.config.maxwords) {
336348
const tokens = text.match(/\S+/g) ?? [] // Matches consecutive non-whitespace chars
337-
return tokens.length
349+
this.count = tokens.length
350+
return
338351
}
339352

340-
return text.length
353+
this.count = text.length
341354
}
342355

343356
/**
@@ -347,7 +360,7 @@ export class CharacterCount extends ConfigurableComponent {
347360
* @returns {string} Status message
348361
*/
349362
getCountMessage() {
350-
const remainingNumber = this.maxLength - this.count(this.$textarea.value)
363+
const remainingNumber = this.maxLength - this.count
351364
const countType = this.config.maxwords ? 'words' : 'characters'
352365
return this.formatCountMessage(remainingNumber, countType)
353366
}
@@ -392,7 +405,7 @@ export class CharacterCount extends ConfigurableComponent {
392405
}
393406

394407
// Determine the remaining number of characters/words
395-
const currentLength = this.count(this.$textarea.value)
408+
const currentLength = this.count
396409
const maxLength = this.maxLength
397410

398411
const thresholdValue = (maxLength * this.config.threshold) / 100

0 commit comments

Comments
 (0)