Skip to main content
Frontend is a free bonus on CodeMentor AI β€” the main product is Python. Register to save your progress and unlock all 290 Frontend lessons + 1,000+ Python lessons.Sign up β€” free
← ⚑ JavaScript & the browserΒ·Module C1 Β· Lesson 10
TaskBuild a live word counter. <textarea id='text'></textarea> + <p id='stats'>words: 0, chars: 0</p>. JS: compute() returns { words, chars } from the trimmed value (split on whitespace + filter empty tokens; chars = full length including spaces). render() reads text.value, destructures the result, writes 'words: X, chars: Y' into #stats. Wire 'input' event and call render() once on load.

Build a Live Word Counter in Vanilla JavaScript

250 XP14 minFREE
Theory

Combining everything in C1

This capstone wires together every C1 idea:

  • Variables (let, const)
  • Template literals
  • Arrays + .filter (filtering out empty tokens)
  • Objects + destructuring (returning { words, chars })
  • Arrow functions
  • Conditionals + the falsy gotcha (empty input)
  • Loops via forEach is fine here β€” single render path per input event

You'll also touch the DOM through getElementById + addEventListener("input", ...) β€” the same shape as the counter capstone, but driven by typing instead of clicking.

The pattern

const text = document.getElementById("text");
const out  = document.getElementById("stats");

const compute = (s) => {
  const trimmed = s.trim();
  if (!trimmed) return { words: 0, chars: 0 };
  const words = trimmed.split(/\\s+/).filter(Boolean).length;
  return { words, chars: s.length };
};

const render = () => {
  const { words, chars } = compute(text.value);
  out.textContent = \`words: ${words}, chars: ${chars}\`;
};

text.addEventListener("input", render);
render();

Run render once on load so the initial state is correct. After that, every keystroke fires input and re-renders.

Why .filter(Boolean)?

"hello world".split(/\\s+/) gives ["hello", "world"] β€” but " hello".split(/\\s+/) gives ["", "hello"] because of the leading whitespace. .filter(Boolean) drops the empty-string ones (empty strings are falsy β€” C1-08).

One small line that handles a real-world edge case the way a senior would.

2 tabs
Live preview
console output appears here…
← PreviousNext lesson β†’

Get one Python or web tip a day β€” by email

Short, hand-written, no spam. Unsubscribe in one click.