我怎样才能在按下一个键后开始我的打字测试,而不是必须按开始按钮->单击文本框->键入?

问题描述 投票:0回答:1

我的打字测试基于我在 GitHub 上找到的一个随机引用 API,我想做一个测试,计时器/测试在第一次击键时开始。

存储库链接:https://github.com/Tbscuddles/Tbswpmtest

javascript testing typing
1个回答
0
投票

当测试开始时,在keydown

上收听
<textarea>
事件
并启动计时器:

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

使用

once: true
只发射一次。

一定要在

resetTest()
中删除这个监听器,以防它从未被解雇:

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

把它们放在一起:

//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>

© www.soinside.com 2019 - 2024. All rights reserved.