Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

How can i make my typing test start once a key is pressed, rather than having to press start button->click textbox->type?

My typing test is based on a random quote API I found on GitHub, and I want to make a test where the timer/test starts on the first key stroke.

Repository link: https://github.com/Tbscuddles/Tbswpmtest

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

>Solution :

When the test starts, listen for the keydown event on the <textarea> and start the timer:

userInput.addEventListener('keydown', timeReduce, { once: true });

Use once: true to only fire this once.

Be sure to remove this listener in resetTest() too, in case it was never fired:

userInput.removeEventListener('keydown', timeReduce, { once: true });

Putting it all together:

//Random quotes api
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 content from quote api url
  const response = await fetch(quoteApiUrl);
  let data = await response.json();
  quote = data.content;

  //Array of chars in quote
  let arr = quote.split("").map((value) => {
    return "<span class='quote-chars'>" + value + "</span>";
  });
  quoteSection.innerHTML += arr.join("");
};

//Logic to compare input words with quote
userInput.addEventListener("input", () => {
  let quoteChars = document.querySelectorAll(".quote-chars");
  quoteChars = Array.from(quoteChars);

  //Array of user input chars
  let userInputChars = userInput.value.split("");
  //Loop through each char in quote
  quoteChars.forEach((char, index) => {
    //Check chars with quote chars
    if (char.innerText == userInputChars[index]) {
      char.classList.add("success");
    }
    //If user hasn't entered anything or backspaced
    else if (userInputChars[index] == null) {
      if (char.classList.contains("success")) {
        char.classList.remove("success");
      } else {
        char.classList.remove("fail");
      }
    }
    //if user entered wrong char
    else {
      if (!char.classList.contains("fail")) {
        //increament and displaying mistakes
        mistakes++;
        char.classList.add("fail");
      }
      document.getElementById("mistakes").innerText = mistakes;
    }

    //Return true if all chars are correct
    let check = quoteChars.every((element) => {
      return element.classList.contains("success");
    });

    //End test if all chars are correct
    if (check) {
      displayResult();
    }
    // or end test if atleast 80% of char are correct
  });

});

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

//Set timer of the test
const timeReduce = () => {
  time = 60;
  timer = setInterval(updateTimer, 1000);
};

//End test
const displayResult = () => {
  //Display the result
  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) + "%";
  wpmScore = (userInput.value.length / 5 / timeTaken).toFixed(2);
  document.getElementById("wpm").innerText = wpmScore + "wpm";
  document.getElementById("accuracy").innerText = Math.round(((userInput.value.length - mistakes) / userInput.value.length) * 100) + "%";
  document.getElementById("wpm-score").innerText = wpmScore;

};

//Start test
const startTest = () => {
  mistakes = 0;
  timer = "60";
  userInput.disabled = false;
  document.getElementById("start-test").style.display = "none";
  document.getElementById("stop-test").style.display = "block";
  document.getElementById("reset-test").disabled = false;
  userInput.addEventListener('keydown', timeReduce, { once: true });
}

//Reset test
function resetTest() {
  userInput.removeEventListener('keydown', timeReduce, { once: true });
  clearInterval(timer);
  time = 60;
  mistakes = 0;
  userInput.value = "";
  quoteSection.innerHTML = "";
  document.getElementById("mistakes").innerText = mistakes;
  document.getElementById("timer").innerText = time + "s";
  document.getElementById("reset-test").disabled = true;
  document.getElementById("start-test").disabled = false;
  document.getElementById("start-test").innerHTML = "Start Test";
  document.getElementById("stop-test").disabled = false;
  document.getElementById("stop-test").style.display = "none";
  document.getElementById("start-test").style.display = "block";
  document.getElementById("wpm").innerText = "";
  document.getElementById("accuracy").innerText = "";
  renderNewQuote();

}

// generate a new quote and render it  
window.onload = () => {
  userInput.value = "";
  document.getElementById("start-test").style.display = "block";
  document.getElementById("stop-test").style.display = "none";
  userInput.disabled = true;
  renderNewQuote();
}
@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;500;600;700&display=swap');
body {
  background-color: #fff;
}

* {
  color: #000;
}

title {
  font-family: 'Lucida Sans';
}

h1,
h2,
h3 {
  margin: 0;
}

h1 {
  font-size: 24px;
  text-align: center;
}

h2 {
  font-size: 18px;
  text-align: center;
}

h3 {
  font-size: 16px;
  text-align: left;
}

* {
  font-family: 'Poppins', sans-serif;
  box-sizing: border-box;
}

.container {
  background-color: #f0f0f0;
}

.container {
  width: 80vmin;
  padding: 50px 30px;
}

.container {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}

.container {
  border-radius: 10px;
  box-shadow: 0 20px 40px rgba(0, 0, 0, 0.15);
}

.stats {
  font-size: 18px;
  text-align: center;
  font-family: 'Segoe UI';
}

.stats span {
  font-weight: 600;
}

#quote {
  text-align: justify;
  margin: 30px 0;
}

textarea {
  width: 100%;
  border-radius: 5px;
  padding: 10px 5px;
  font-size: 18px;
}

button {
  float: right;
  margin-top: 20px;
  background-color: #000;
  color: #fff;
  border: none;
  padding: 10px 30px;
  border-radius: 5px;
  font-size: 14px;
}

.result {
  margin-top: 40px;
  display: none;
}

.result h3 {
  font-size: 22px;
  text-align: center;
  margin-bottom: 20px;
}

.wrapper {
  display: flex;
  justify-content: space-around;
  align-items: center;
}

.wrapper span {
  font-weight: 600;
}

.success {
  color: #44b267;
}

.fail {
  color: #e81c4e;
}

img {
  width: 105%;
  margin: 1em auto;
  max-width: 100005px;
  height: 1000px;
  object-fit: cover;
  border-radius: 10px;
}
<h1>Engelsk WPM Test</h1>
<div class="container">
  <div class="stats">
    <p>Tid: <span id="timer">0s</span></p>
    <p>Feil: <span id="mistakes">0</span></p>
  </div>
  <div id="quote" onmousedown="return false" onselectstart="return false"></div>

  <textarea id="quote-input" rows="3" placeholder="Type here when test starts..."></textarea>

  <button id="start-test" onclick="startTest()">Start Test</button>
  <button id="stop-test" onclick="displayResult()">Stopp Test</button>
  <button id="reset-test" onclick="resetTest()" disabled>Prøv Igjen</button>

  <div class="result">
    <h3>Resultat</h3>
    <div class="wrapper">
      <p>Treffsikkerhet: <span id="accuracy"></span></p>
      <p>Hurtighet: <span id="wpm"></span></p>
    </div>
  </div>

</div>
<h2>Klarer du 200wpm?</h2>
<h3>Laget av Tbscuddles</h3>


<div class="galley">
  <img src="https://images4.alphacoders.com/109/1096950.jpg">
</div>
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading