I am making a Rubik’s cube scrambler and timer website, and it works fine so far. I have a scrambler, a timer, and a list of times (everything still in development). The timer works fine but the only problem is that when it updates to the next minute and resets the second count, for example it is at 0:59
then it should go to 1:00
but instead it goes to 1:60
before going to 1:01
. Any help would be appreciated!
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Speedcubing Timer</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
<style>
* {
padding:20px;
}
#times-list-template {
height:20vh;
max-height: 20vh;
overflow-y: auto;
}
.hidden {
display:none;
}
#timer-info-box {
position:fixed;
bottom:90vh;
height:10vh;
background-color:gray;
padding:5px;
}
</style>
</head>
<body>
<h1>CubeTimer v1.0</h1>
<div class="row">
<div class="col-xs-5">
<h1>Scramble</h1>
<h3 id="scramble"></h1>
</div>
<div class="col-xs-5">
<h1>Timer<i class="fa-solid fa-circle-info" id="timer-info"></i></h1>
<h3 id="timer"><span id="minutes"></span>:<span id="seconds"></span></h3>
<button onclick="list_time()" class="btn btn-primary">Save to list</button>
</div>
<div class="col-xs-5">
<div id="timer-info-box" class="hidden"><p>Press the spacebar to start the timer!</p></div>
<h1>Times</h1>
<div id="times-list"><ol id="times-list-template"></ol></div>
</div>
</div>
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
<script src="https://kit.fontawesome.com/c63b6d877c.js" crossorigin="anonymous"></script>
<script>
let scramble = Math.floor(Math.random() * 12);
function scramble_translator() {
let scramble = Math.floor(Math.random() * 12);
if (scramble <= 1) {
scramble = 'R '
} else if (scramble > 1 && scramble <= 2) {
scramble = 'R' '
} else if (scramble > 2 && scramble <= 3) {
scramble = 'U '
} else if (scramble > 3 && scramble <= 4) {
scramble = 'U' '
} else if (scramble > 4 && scramble <= 5) {
scramble = 'L '
} else if (scramble > 5 && scramble <= 6) {
scramble = 'L' '
} else if (scramble > 6 && scramble <= 7) {
scramble = 'F '
} else if (scramble > 7 && scramble <= 8) {
scramble = 'F' '
} else if (scramble > 8 && scramble <= 9) {
scramble = 'D '
} else if (scramble > 9 && scramble <= 10) {
scramble = 'D' '
} else if (scramble > 10 && scramble <= 11) {
scramble = 'B '
} else if (scramble > 11 && scramble <= 12) {
scramble = 'B' '
}
document.getElementById('scramble').innerHTML += scramble;
}
for (let i = 0; i < 20; i++) {
scramble_translator();
}
document.getElementById('seconds').innerHTML = 0;
document.getElementById('minutes').innerHTML = 0;
let intervalId;
let minutes = 0;
let seconds = 0;
function timer() {
document.addEventListener('keydown', function(event) {
if (event.key === ' ') {
if (seconds === 0) {
intervalId = setInterval(function() {
seconds++;
document.getElementById('seconds').innerHTML = seconds;
if (seconds > 59 || seconds > 60 && seconds > 119 || seconds > 120 && seconds > 179 || seconds > 180 && seconds > 239) {
minutes++;
document.getElementById('minutes').innerHTML = minutes;
seconds = 0;
}
}, 1000);
} else {
clearInterval(intervalId);
}
}
});
}
timer();
function list_time() {
let new_time = $('#timer').html();
$('<div>').html(new_time).appendTo('#times-list-template');
document.getElementById('scramble').innerHTML = '';
for (let i = 0; i < 20; i++) {
scramble_translator();
}
}
document.getElementById('timer-info').addEventListener('mouseover', (event) => {
document.getElementById('timer-info-box').classList.remove('hidden');
});
document.getElementById('timer-info').addEventListener('mouseout', (event) => {
document.getElementById('timer-info-box').classList.add('hidden');
});
document.addEventListener('keydown', (event) => {
if (event.key === 'Enter') {
list_time();
}
});
</script>
</body>
</html>
3
Answers
There are some problems in your attempt, including:
The condition
if (seconds > 59 || seconds > 60 ...
makes little sense. Whenseconds > 59
is true, the rest of the condition will not even be evaluated, since that is enough to have the whole expression evaluate to true. Instead, you would benefit from using arithmetic: there is a remainder operator in JavaScript, so you can easily extract the number of seconds (within a single minute) from a total number of seconds, and from that derive the number of minutes. So I would suggest to just keep increasingseconds
and then derive the two components from that with simple arithmetic.if (seconds === 0)
is not a good condition to see if the timer has already started. Remember that the number of seconds is regularly set back to 0 (every time a minute passes). Instead, test whether theintervalId
has been set, and clear it whenever you clear the timer.The number of seconds are traditionally displayed with 2 digits, so you should prefix with an extra "0" when the number of seconds is less than 10.
Here is how it could work. I removed all Cube related stuff, and CSS, as it is not related to your question:
Note that using
setInterval
is not a guarantee for having a precise time measurement. See How to create an accurate timer in javascript? for what you need to do to get a more accurate timing.checkout this simple script that I just uploaded to github.
let me know if it’s helped you or not.
countDown timer link
Setting up a flow control statement like this:
doesn’t work the way you’d expect it. Once
seconds
is 60 or more, the first condition will always returnstrue
for every second that passes after the 59th second. There are many other syntactical errors and code smells that keep it from functioning, so instead of going through each one, we’ll focus on a working solution instead. The following example has details commented within.