There is a word-translation card page which includes:
- A 3-second countdown that runs immediately after the page loads and when you move to a new word after press the 'Correct' button.
- Word and his translate which appears after 'Excellent' button pressed. This button stops and hide the counter.
- Button 'Show answer' which appears if 'Excellent' didn't pressed in 3 sec.
- Buttons 'Wrong' and 'Correct' which appears if 'Excellent' or 'Show answer' buttons are pressed.
The problem is how the countdown works (unstable). Sometimes it doesn't restart after clicking "Correct". I tried manage countdown in separate function, but this approach provides much more issues. So now there is a timer that is called globally and a timer that is called when you click on the "Correct" button.I think the problem is near timerId. I will be glad to any comments and ideas on the code.
<div >
<div >
<h2 id="primary-word"></h2>
<h2 id="secondary-word"></h2>
</div>
<div >
<p id="timer-count">3</p>
<button id="btn-excellent" onClick="excellent()">Excellent!</button>
<button id="btn-show-answer" onClick="showAnswerF()">Show Answer</button>
<button id="btn-wrong">Wrong</button>
<button id="btn-correct" onClick="correctF()">Correct</button>
</div>
</div>
let currentWord = 0
let timerCount = 3
let fetched_data = {}
async function getDeck () {
let response = await fetch('/api/deck_words/2/', {
method: 'get',
headers: {
'X-Requested-With': 'XMLHttpRequest',
'Content-Type': 'application/json'
}
}
)
let data = await response.json()
let primaryElement = document.getElementById('primary-word')
primaryElement.innerText = await data[currentWord]['primary_word']
let secondaryElement = document.getElementById('secondary-word')
secondaryElement.innerText = await data[currentWord]['secondary_word']
return data
}
fetched_data = getDeck()
const getData = async () => {
return await getDeck()
}
data = getData();
function countDecrease() {
timerCount --
if (timerCount > 0) {
document.getElementById("timer-count").innerHTML = timerCount
} else {
hideExcellent()
}
}
function hideExcellent() {
showElement(true,'btn-excellent')
showElement(true,'timer-count')
showElement(false,'btn-show-answer')
}
let timerId = setInterval(() => countDecrease(), 1000)
setTimeout(() => {
clearInterval(timerId)
}, 3000)
function showElement(showProperty, elementClass) {
showProperty = !showProperty
let element = document.getElementById(elementClass)
element.style.display = (showProperty === true) ? "inline-block" : "none";
}
function showAnswerF() {
showElement(true,'btn-show-answer')
showElement(false,'secondary-word')
showElement(false,'btn-wrong')
showElement(false,'btn-correct')
}
function excellent() {
showElement(true,'timer-count')
showElement(true,'btn-excellent')
showElement(false,'btn-wrong')
showElement(false,'btn-correct')
showElement(false,'secondary-word')
clearInterval(timerId)
timerCount = 3
}
function correctF() {
currentWord
const changeWords = () => {
fetched_data.then((data) => {
document.getElementById('primary-word').innerText = data[currentWord]['primary_word']
document.getElementById('secondary-word').innerText = data[currentWord]['secondary_word']
document.getElementById("timer-count").innerText = '3'
timerCount = 3
timerId = setInterval(() => countDecrease(), 1000)
setTimeout(() => {
clearInterval(timerId)
}, 3000)
})
}
changeWords()
let countElement = document.getElementById('timer-count')
countElement.style.display = "block"
showElement(false,'btn-excellent')
showElement(true,'btn-wrong')
showElement(true,'btn-correct')
showElement(true,'secondary-word')
}
CodePudding user response:
Here's a countdown. The first count is after 1 second.
let count = 3;
new Array(count).fill(true).forEach((_,i) => {
setTimeout(() => console.log('countdown',count - i),(i 1) * 1000)
})
CodePudding user response:
I think this would be better handled with an async function, maybe like so.
const timerCount = document.querySelector("#timer-count")
const reset = document.querySelector("button")
function delay(ms) {
return new Promise(res => setTimeout(res, ms))
}
async function countDown() {
for (let i = 3; i >= 0; --i) {
timerCount.textContent = i
await delay(1000)
}
timerCount.textContent = ""
}
(async function() {
await countDown()
reset.addEventListener("click", async function click() {
await countDown()
reset.addEventListener("click", click, { once: true })
}, { once: true })
})()
<p id="timer-count"></p>
<button>Reset</button>