HomeJavascriptTyping Test With HTML, CSS & Javascript

Typing Test With HTML, CSS & Javascript

Hello and welcome to today’s tutorial. In today’s tutorial, we will be creating a typing test project. For this project, we will be needing HTML, CSS and Javascript.

This project would be very helpful for javascript intermediates. If you are looking for more projects to practice javascript, do check out this playlist. This playlist consists of around 50 projects along with source code. Anyone from beginners to experts can use them to practice their skills.

Now coming to our project, we will create a typing test application. This project generates a random test sentence on every window load event. The user has to click on the ‘Start Test’ button and start typing in the provided text area. The characters entered correctly are turned into green colour while wrong ones are turned into red.

The application shows two stats. The first is a countdown timer of 60seconds, and the second is the mistakes counter. For every mistake the user makes while typing, the mistake counter increase by one.

Other Tutorials You Might Like:

The typing test stops either when the user clicks on the ‘Stop test’ button or when the timer reaches 0. After the test ends, a result is displayed. The result consists of two stats first is the typing speed in wpm and the second is the accuracy in terms of percentage.

Video Tutorial:

I have a video version of this tutorial on my youtube channel. If you are interested in code along with me, you can check out the video down below. Also, do subscribe to my youtube channel, where I post new tutorials every alternate day.

 

Project Folder Structure:

Before we start to code, let us check out the project folder structure. We name the project folder as a Typing test. Inside this project, we have three files an HTML document, a stylesheet and a script file. We name these files index.html, style.css and script.js respectively.

HTML:

We begin with the HTML code. Copy the code provided below and paste it into our HTML document.

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Typing Test</title>
    <!-- Google Fonts -->
    <link
      href="https://fonts.googleapis.com/css2?family=Poppins:wght@400;600&display=swap"
      rel="stylesheet"
    />
    <!-- Stylesheet -->
    <link rel="stylesheet" href="style.css" />
  </head>
  <body>
    <div class="container">
      <div class="stats">
        <p>Time: <span id="timer">0s</span></p>
        <p>Mistakes: <span id="mistakes">0</span></p>
      </div>
      <div
        id="quote"
        onmousedown="return false"
        onselectstart="return false"
      ></div>
      <textarea
        rows="3"
        id="quote-input"
        placeholder="Type here when the test starts.."
      ></textarea>
      <button id="start-test" onclick="startTest()">Start Test</button>
      <button id="stop-test" onclick="displayResult()">Stop Test</button>
      <div class="result">
        <h3>Result</h3>
        <div class="wrapper">
          <p>Accuracy: <span id="accuracy"></span></p>
          <p>Speed: <span id="wpm"></span></p>
        </div>
      </div>
    </div>
    <!-- Script -->
    <script src="script.js"></script>
  </body>
</html>

CSS:

Next, we add some styles to our typing test app. For this we need CSS. Now copy the code below and paste it into your stylesheet.

* {
  padding: 0;
  margin: 0;
  box-sizing: border-box;
  font-family: "Poppins", sans-serif;
}
body {
  background-color: #3066f6;
}
.container {
  width: 80vmin;
  padding: 50px 30px;
  background-color: #ffffff;
  position: absolute;
  transform: translate(-50%, -50%);
  top: 50%;
  left: 50%;
  border-radius: 10px;
  box-shadow: 0 20px 40px rgba(0, 0, 0, 0.15);
}
.stats {
  text-align: right;
  font-size: 18px;
  margin-bottom: 30px;
}
.stats span {
  font-weight: 600;
}
#quote {
  text-align: justify;
  margin: 50px 0 30px 0;
}
textarea {
  resize: none;
  width: 100%;
  border-radius: 5px;
  padding: 10px 5px;
  font-size: 16px;
}
button {
  float: right;
  margin-top: 20px;
  background-color: #3066f6;
  color: #ffffff;
  border: none;
  padding: 10px 30px;
  border-radius: 5px;
  font-size: 18px;
}
.result {
  margin-top: 40px;
  display: none;
}
.result h3 {
  text-align: center;
  margin-bottom: 20px;
  font-size: 22px;
}
.wrapper {
  display: flex;
  justify-content: space-around;
}
.wrapper span {
  font-weight: 600;
}
.success {
  color: #44b267;
}
.fail {
  color: #e81c4e;
}

Javascript:

Lastly, we add functionality to this project by using javascript. Copy the code below and paste it into your javascript file.

//Random Quotes Api URL
const quoteApiUrl = "https://api.quotable.io/random?minLength=80&maxLength=100";
const quoteSection = document.getElementById("quote");
const userInput = document.getElementById("quote-input");
let quote = "";
let time = 60;
let timer = "";
let mistakes = 0;

//Display random quotes
const renderNewQuote = async () => {
  //Fetch contents from url
  const response = await fetch(quoteApiUrl);

  //Store response
  let data = await response.json();

  //Access quote
  quote = data.content;

  //Array of characters in the quote
  let arr = quote.split("").map((value) => {
    //wrap the characters in a span tag
    return "<span class='quote-chars'>" + value + "</span>";
  });
  //join array for displaying
  quoteSection.innerHTML += arr.join("");
};

//Logic for comparing input words with quote
userInput.addEventListener("input", () => {
  let quoteChars = document.querySelectorAll(".quote-chars");
  //Create an arrat from received span tags
  quoteChars = Array.from(quoteChars);

  //array of user input characters
  let userInputChars = userInput.value.split("");

  //loop through each character in quote
  quoteChars.forEach((char, index) => {
    //Check if char(quote character) = userInputChars[index](input character)
    if (char.innerText == userInputChars[index]) {
      char.classList.add("success");
    }
    //If user hasn't entered anything or backspaced
    else if (userInputChars[index] == null) {
      //Remove class if any
      if (char.classList.contains("success")) {
        char.classList.remove("success");
      } else {
        char.classList.remove("fail");
      }
    }
    //If user enter wrong character
    else {
      //Checks if we alreasy have added fail class
      if (!char.classList.contains("fail")) {
        //increment and display mistakes
        mistakes += 1;
        char.classList.add("fail");
      }
      document.getElementById("mistakes").innerText = mistakes;
    }
    //Returns true if all the characters are entered correctly
    let check = quoteChars.every((element) => {
      return element.classList.contains("success");
    });
    //End test if all characters are correct
    if (check) {
      displayResult();
    }
  });
});

//Update Timer on screen
function updateTimer() {
  if (time == 0) {
    //End test if timer reaches 0
    displayResult();
  } else {
    document.getElementById("timer").innerText = --time + "s";
  }
}

//Sets timer
const timeReduce = () => {
  time = 60;
  timer = setInterval(updateTimer, 1000);
};

//End Test
const displayResult = () => {
  //display result div
  document.querySelector(".result").style.display = "block";
  clearInterval(timer);
  document.getElementById("stop-test").style.display = "none";
  userInput.disabled = true;
  let timeTaken = 1;
  if (time != 0) {
    timeTaken = (60 - time) / 100;
  }
  document.getElementById("wpm").innerText =
    (userInput.value.length / 5 / timeTaken).toFixed(2) + " wpm";
  document.getElementById("accuracy").innerText =
    Math.round(
      ((userInput.value.length - mistakes) / userInput.value.length) * 100
    ) + " %";
};

//Start Test
const startTest = () => {
  mistakes = 0;
  timer = "";
  userInput.disabled = false;
  timeReduce();
  document.getElementById("start-test").style.display = "none";
  document.getElementById("stop-test").style.display = "block";
};

window.onload = () => {
  userInput.value = "";
  document.getElementById("start-test").style.display = "block";
  document.getElementById("stop-test").style.display = "none";
  userInput.disabled = true;
  renderNewQuote();
};

And that’s it. Your typing test app is now ready. If you have any issues while creating this project, you can download the source code by clicking the ‘Download code’ button below. Also, don’t forget to drop your suggestions and feedback in the comments below.

RELATED ARTICLES

1 COMMENT

LEAVE A REPLY

Please enter your comment!
Please enter your name here

one × five =

Most Popular