HomePOSTTyping Test App with HTML and CSS (updated)

Typing Test App with HTML and CSS (updated)

Typing Test App with Html and CSS Source code free 2021 updated

index.html

<img width=
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Typing Test App</title>
    <!-- Google Fonts -->
    <link
      href="https://fonts.googleapis.com/css2?family=Poppins:wght@400;600&display=swap"
      rel="stylesheet"
    />
  </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 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>
    <a href="https://www.youtube.com/c/TechnicDude" target="_blank"
      >My Youtube Channel</a
    >
    <script>
      //Random quotes API url (minimum quote length 80 and maximum length 100)
      const quote_api_url =
        "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(quote_api_url);
        //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 the array for displaying
        quoteSection.innerHTML += arr.join("");
      };
      //Logic for comparing the input words with quote
      userInput.addEventListener("input", () => {
        //Select all the span tags/all characters
        let quoteChars = document.querySelectorAll(".quote-chars");
        //Create an array from the 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)
      index would be the quote character's index
    */
          if (char.innerText == userInputChars[index]) {
            //Green color if true
            char.classList.add("success");
          }
          // If user hasn't entered anything or backspaced
          else if (userInputChars[index] == null) {
            // Remove classes if any
            if (char.classList.contains("success")) {
              char.classList.remove("success");
            } else {
              char.classList.remove("fail");
            }
          }
          //if user enters wrong character
          else {
            //Checks if we have already added the fail class
            if (!char.classList.contains("fail")) {
              //increment and display mistakes variable
              mistakes += 1;
              //red color
              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.getElementsByClassName("result")[0].style.display = "block";
        clearInterval(timer);
        document.getElementById("stop-test").style.display = "none";
        userInput.disabled = true;
        let timeTaken = 1;

        console.log(time);
        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 = () => {
        //initially
        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();
      };
    </script>
  </body>
</html>

style.css

 * {
        padding: 0;
        margin: 0;
        -webkit-box-sizing: border-box;
                box-sizing: border-box;
        font-family: "Poppins", sans-serif;
      }
      body {
        background-color: #3066f6;
        min-height: 100vh;
        display: -ms-grid;
        display: grid;
        place-items: center;
      }

      .container {
        width: 95vw;
        background-color: #ffffff;
        padding: 50px 15px;
        border-radius: 10px;
        -webkit-box-shadow: 0 20px 40px rgba(0, 0, 0, 0.2);
                box-shadow: 0 20px 40px rgba(0, 0, 0, 0.2);
      }
      a {
        background-color: #ffffff;
        display: block;
        width: 95vw;
        text-align: center;
        padding: 15px 0;
        font-size: 18px;
        color: #3066f6;
        text-decoration: none;
        font-weight: 600;
        border-radius: 5px;
        -webkit-box-shadow: 0 20px 40px rgba(0, 0, 0, 0.2);
                box-shadow: 0 20px 40px rgba(0, 0, 0, 0.2);
      }
      .success {
        color: #44b267;
      }
      .fail {
        color: #e81c4e;
      }
      .result {
        display: none;
      }
      .stats {
        text-align: right;
        margin-bottom: 30px;
        font-size: 18px;
      }
      .stats span {
        font-weight: 600;
      }
      textarea {
        resize: none;
        width: 100%;
        border-radius: 5px;
        padding: 10px 5px;
        font-size: 16px;
      }
      #quote {
        text-align: justify;
        margin: 50px 0 30px 0;
      }
      button {
        float: right;
        margin-top: 20px;
        background-color: #3066f6;
        color: #ffffff;
        border: none;
        font-size: 18px;
        padding: 10px 30px;
        border-radius: 5px;
      }
      .result {
        margin-top: 40px;
      }
      .result h3 {
        text-align: center;
        margin-bottom: 20px;
        font-size: 22px;
      }
      .wrapper {
        display: -webkit-box;
        display: -ms-flexbox;
        display: flex;
        -ms-flex-pack: distribute;
            justify-content: space-around;
      }
      .wrapper span {
        font-weight: 600;
      }

OUTPUT

<img width=

Additional Reading

READ MORE

If you found this post useful, don’t forget to share this with your friends, and if you have any query feel free to comment it in the comment section.

Thank you 😊 Keep Learning !

RELATED ARTICLES

LEAVE A REPLY

Please enter your comment!
Please enter your name here

- Advertisment -

Most Popular

- Advertisment -