Skip to content

Commit 649b198

Browse files
Add character count support for countFunction option
1 parent 58dd397 commit 649b198

2 files changed

Lines changed: 42 additions & 4 deletions

File tree

packages/nhsuk-frontend/src/nhsuk/components/character-count/character-count.jsdom.test.mjs

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -390,6 +390,40 @@ describe('Character count', () => {
390390

391391
expect(component.getCountMessage()).toBe('You have 97 words remaining')
392392
})
393+
394+
it('uses custom `countFunction` for `maxlength` limit when set', async () => {
395+
const component = new CharacterCount($root, {
396+
maxlength: 100,
397+
countFunction: jest.fn().mockReturnValue(10)
398+
})
399+
400+
$textarea.focus()
401+
await user.keyboard('Newly updated value')
402+
403+
expect(component.config.countFunction).toHaveBeenLastCalledWith(
404+
'Newly updated value'
405+
)
406+
407+
expect(component.getCountMessage()).toBe(
408+
'You have 90 characters remaining'
409+
)
410+
})
411+
412+
it('uses custom `countFunction` for `maxwords` limit when set', async () => {
413+
const component = new CharacterCount($root, {
414+
maxwords: 100,
415+
countFunction: jest.fn().mockReturnValue(10)
416+
})
417+
418+
$textarea.focus()
419+
await user.keyboard('Newly updated value')
420+
421+
expect(component.config.countFunction).toHaveBeenLastCalledWith(
422+
'Newly updated value'
423+
)
424+
425+
expect(component.getCountMessage()).toBe('You have 90 words remaining')
426+
})
393427
})
394428

395429
describe('with HTML lang attribute', () => {

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

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ export class CharacterCount extends ConfigurableComponent {
6161
const {
6262
i18n,
6363
maxlength,
64+
countFunction,
6465
countType,
6566
screenReaderCountMessageClass,
6667
textareaDescriptionClass,
@@ -72,9 +73,9 @@ export class CharacterCount extends ConfigurableComponent {
7273
locale: closestAttributeValue(this.$root, 'lang')
7374
})
7475

75-
if ('Segmenter' in Intl && countType === 'graphemes') {
76+
if ('Segmenter' in Intl && (countType === 'graphemes' || !!countFunction)) {
7677
this.segmenter = new Intl.Segmenter(this.i18n.locale, {
77-
granularity: 'grapheme'
78+
granularity: countType === 'words' ? 'word' : 'grapheme'
7879
})
7980
}
8081

@@ -212,10 +213,11 @@ export class CharacterCount extends ConfigurableComponent {
212213
*/
213214
updateCount(text) {
214215
const { $textarea, countFunctions } = this
215-
const { countType } = this.config
216+
let { countType, countFunction } = this.config
216217

217218
text ??= $textarea.value
218-
this.length = countFunctions[countType].call(this, text)
219+
countFunction ??= countFunctions[countType]
220+
this.length = countFunction.call(this, text)
219221
}
220222

221223
/**
@@ -519,6 +521,7 @@ export class CharacterCount extends ConfigurableComponent {
519521
maxlength: { type: 'number' },
520522
threshold: { type: 'number' },
521523
countType: { type: 'string' },
524+
countFunction: { type: 'function' },
522525
textareaDescriptionClass: { type: 'string' },
523526
visibleCountMessageClass: { type: 'string' },
524527
screenReaderCountMessageClass: { type: 'string' },
@@ -565,6 +568,7 @@ export function initCharacterCounts(options) {
565568
* @property {number} [threshold=0] - The percentage value of the limit at which point the count message is displayed.
566569
* If this attribute is set, the count message will be hidden by default.
567570
* @property {'characters' | 'graphemes' | 'words'} countType - The count type (`"characters"`, `"graphemes"` or `"words"`) used to count the text.
571+
* @property {(this: CharacterCount, text: string) => number} [countFunction] - Custom character or word counting function.
568572
* @property {string} textareaDescriptionClass - Textarea description class
569573
* @property {string} visibleCountMessageClass - Visible count message class
570574
* @property {string} screenReaderCountMessageClass - Screen reader count message class

0 commit comments

Comments
 (0)