The page has a textarea with a maxlength and an empty paragraph for its count:
<label for="bio">Bio</label>
<textarea id="bio" maxlength="20">Hi</textarea>
<p id="bio-count" aria-live="polite"></p>
Write attachCounter(textarea, output). It sets output's text to how many more characters fit: the textarea's maxlength minus the length of its value, written as 18 characters left, or 1 character left when exactly one is left.
Show the count as soon as it's called, then update it on every input event: it fires for typing, pasting, cutting, and dictation alike. When 5 or fewer characters are left, give output the class warning, and take it off when more are left again.
Also set the textarea's aria-describedby to the output's id, so screen readers read the count with the field. Return a function that stops the updates.
const stop = attachCounter(document.getElementById("bio"), document.getElementById("bio-count"));
// the count reads "18 characters left" (the textarea starts with "Hi")
// the user changes it to "Hello": "15 characters left"
stop(); // no more updates
const output = document.getElementById("bio-count");
attachCounter(document.getElementById("bio"), output);
expect(output.textContent).toBe("18 characters left");
const textarea = document.getElementById("bio");
const output = document.getElementById("bio-count");
attachCounter(textarea, output);
textarea.value = "Hello";
fire(textarea, "input");
expect(output.textContent).toBe("15 characters left");
textarea.value = "";
fire(textarea, "input");
expect(output.textContent).toBe("20 characters left");
const textarea = document.getElementById("bio");
const output = document.getElementById("bio-count");
attachCounter(textarea, output);
textarea.value = "a".repeat(19);
fire(textarea, "input");
expect(output.textContent).toBe("1 character left");
textarea.value = "a".repeat(20);
fire(textarea, "input");
expect(output.textContent).toBe("0 characters left");
const textarea = document.getElementById("bio");
const output = document.getElementById("bio-count");
attachCounter(textarea, output);
textarea.value = "a".repeat(14);
fire(textarea, "input");
expect(output.classList.contains("warning")).toBe(false);
textarea.value = "a".repeat(15);
fire(textarea, "input");
expect(output.classList.contains("warning")).toBe(true);
textarea.value = "a".repeat(10);
fire(textarea, "input");
expect(output.classList.contains("warning")).toBe(false);
const textarea = document.getElementById("bio");
const output = document.getElementById("bio-count");
textarea.setAttribute("maxlength", "5");
attachCounter(textarea, output);
expect(output.textContent).toBe("3 characters left");
const textarea = document.getElementById("bio");
attachCounter(textarea, document.getElementById("bio-count"));
expect(textarea.getAttribute("aria-describedby")).toBe("bio-count");
const textarea = document.getElementById("bio");
const output = document.getElementById("bio-count");
const stop = attachCounter(textarea, output);
stop();
textarea.value = "Hello";
fire(textarea, "input");
expect(output.textContent).toBe("18 characters left");
Run tests runs every test on your code, here in your browser. The problem is solved when they all pass.
Ctrl + Enter runs the tests (⌘ + Enter on a Mac).
I'm here to help with Character counter for a textarea. I give hints, never the solution, so you get to solve it yourself. Ask for a hint, select code to ask about it, or press Ask Tuto why on a failing test.
Your first 3 answers need no account. for free to keep asking.