Building a Word Counter in JavaScript
There are various reasons a web application may want to collect input from its users. However, there are times you want to limit how much input you get from your user. In this tutorial, we’ll learn how to create a word counter in JavaScript and stop the user from entering any further information when they get to the limit.
We’ll start off with our markup. Create a new folder (you can call it word count) and inside it, create a new file index.html. Add this snippet of code:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Word Counter</title>
</head>
<body>
<h2>Word Count: <span id="count">0</span></h2>
<textarea id="input" rows="10"></textarea>
<script src="main.js"></script>
</body>
</html>
Our markup is quite simple. We have a counter that will be updated with Javascript. Then a textarea
to enable users to enter some text. We’ve also included an id for both the counter and the textarea
so we can create a reference to them from our script. Lastly, we import a JavaScript file we haven’t created yet.
If you run the code in your browser using any web server, you’ll see something similar to this.
Go ahead and create a new file main.js
in the same folder. Let’s add some code.
var count = document.getElementById('count');
var input = document.getElementById('input');
The counter will update as the user enters texts so we grab a reference to the id of both the textarea
and the count to be updated. So far so good.
What we need to do now is listen to changes to our text input and count the words. The keyup
event is fired when the user’s hands have left a previously pressed key so we’ll use that like so:
input.addEventListener('keyup', function(e){
...
});
A Simple Word Counter
In the previous step, we set up the event listener. Let’s write a simple function that would do the actual word counting.
input.addEventListener('keyup', function(e){
wordCounter(e.target.value);
});
We modify the previous code to add a function call passing in the current value of the input. Let’s write the actual function.
function wordCounter(text) {
var text = input.value;
var wordCount = 0;
for (var i = 0; i <= text.length; i++) {
if (text.charAt(i) == ' ') {
wordCount++;
}
}
count.innerText = wordCount;
}
The function takes one argument text which is the user’s input. It creates a wordCount
which starts off at 0. Then we loop through the string using a for-loop. If space is encountered (‘ ‘), we add 1 to the wordCount
. After the loop, we update the counter on-screen by assigning wordCount
to the innerText of the onscreen counter.
So far so good, it works… kinda. A little snag you would hit with this solution is that it assumes that if an empty string is encountered, add one to the count. It doesn’t really take note of the actual words so if I just keep typing spaces, the count still increases.
This is not what we want so let’s make a better word counter
A “Better” Word Counter
Our previous solution took only empty strings into consideration so it had a few issues. Let’s tweak the solution a bit.
function wordCounter(text) {
var text = input.value.split(' ');
var wordCount = 0;
for (var i = 0; i < text.length; i++) {
if (text[i] !== ' ') {
wordCount++;
}
}
count.innerText = wordCount;
}
This time we split the user’s input text into an array of string using a specified delimiter, in this case, an empty string (‘ ‘). Then we loop through the array, each time round the loop checking if the current item is an empty space (‘ ‘). If it’s not, we increase the wordCount
. After the loop, we update the word count on the screen.
This solution is arguably better than the last as it relies on the number of words to increase the word count instead of just checking for empty strings like the previous solution. It still has some gotchas.
The problem with this solution is that it assumes that anything that is not space is a word. So if a user enters
Hello world .
It is counted as 3 words because (.) is counted as one word. The same thing goes for other special characters and punctuation marks. But we can’t totally exclude them because they are part of the sentence.
As you might have guessed, we need to tweak our solution again.
An Even Better Word Counter
To improve this solution, we need to define what a “word” is. For simplicity and the purpose of this tutorial, we’ll define a word as a string that contains a number or letter. That means
"Man" is a word "Woman" is a word "@#$" is NOT a word "..." is NOT a word "Bank." is a word "@/p" is a word
The last one is a word because “p” is a letter.
With that in mind, we can write a method to check if a string is a word based on the above definition.
function isWord(str) {
...
}
The function accepts a string. We haven’t defined what it does yet. Every key on the keyboard has a key code. With this in mind, we can loop through a string and check if it contains at least one number or letter.
Let’s modify isWord
:
function isWord(str) {
var alphaNumericFound = false;
for (var i = 0; i < str.length; i++) {
var code = str.charCodeAt(i);
if ((code > 47 && code < 58) || // numeric (0-9)
(code > 64 && code < 91) || // upper alpha (A-Z)
(code > 96 && code < 123)) { // lower alpha (a-z)
alphaNumericFound = true;
return alphaNumericFound;
}
}
return alphaNumericFound;
}
At the top, we create a variable alphaNumericFound and set its default value to false. Next, we loop through the characters in the string. For each character, we get the character’s key code. Then check if the character is an alphanumeric character (number or letter). If we find an alphanumeric, we set alphaNumericFound to true and return the result immediately to the calling function because we already know this is a word. Let’s use the method.
We already have this method:
function wordCounter(text) {
var text = input.value.split(' ');
var wordCount = 0;
for (var i = 0; i < text.length; i++) {
if (text[i] !== ' ') {
wordCount++;
}
}
count.innerText = wordCount;
}
All we need to do is modify the if-statement to:
if (text[i] !== ' ' && isWord(text[i])) {
wordCount++;
}
This condition simply reads that if the string is not an empty string (space) and the string is a word, increase the word count. With this, we have an even better word counter. Here is the function in full:
function wordCounter(text) {
var text = input.value.split(' ');
var wordCount = 0;
for (var i = 0; i < text.length; i++) {
if (text[i] !== ' ' && isWord(text[i])) {
wordCount++;
}
}
count.innerText = wordCount;
}
Setting a Word Limit
Now that we have defined what a word is and have a functional counter, the final step is to add a limit to the words. Back at the top of the file, we’ll define a variable globalWordCounter as well as a word limit. For this tutorial, we’ll be setting a word limit of 10.
var globalWordCounter = 0;
var WORD_LIMIT = 10;
At the end of the wordCounter
method, we’ll update the global word count:
function wordCounter(text) {
...
globalWordCounter = wordCount;
}
We want to check if the global count is already up to the word limit when the user tries to enter a word.
input.addEventListener('keydown', function(e) {
...
});
We listen for the keydown
event which is triggered when a key is pressed down. Then we check if the global count is up to the limit.
if (globalWordCounter > WORD_LIMIT) {
e.preventDefault();
return;
}
If the global counter has reached the word limit, we cancel the default behaviour. The result is that the user is not able to enter any new strings. But there is a little problem with this: the user can’t also delete a word. No key works in fact. We can set an exception for the backspace/delete key by detecting if the key pressed was backspace/delete.
input.addEventListener('keydown', function(e) {
if (globalWordCounter > WORD_LIMIT && e.code !== "Backspace") {
e.preventDefault();
return;
}
});
If users get to the limit, they can delete some words but not add new words until it’s below the word limit. We can also add a nice prompt to notify users that they have reached the word limit:
input.addEventListener('keydown', function(e) {
if (globalWordCounter > WORD_LIMIT && e.code !== "Backspace") {
e.preventDefault();
return;
}
});
Conclusion
In this tutorial, we have seen how to create a word counter using JavaScript. We also set a word limit on the number of words. You can check out the source code as a reference.