I have a pomodoro timer that is supposed to count down the "workminutes" a user has input and then the break minutes and then loop. The timer starts to count down WorkMinutes like it should and then break minutes(like it should), it then restarts and counts down the workminutes again like it should BUT when its done with that and it comes to the breakminutes a second time instead of counting down from eg. 1 minute it counts from -1 minute and up, so -1 minute and one second and so on. I'm a complete beginner in JavaScript so it would be very nice if you kept that in mind, any help i greatly appreciated. Here is the JavaScript code:
// we need some variables to store the work and break minutes
var workSeconds = "120", breakSeconds = "60";
// and a referens to interval
var xInterval;
var audio = new Audio('Bell_finished.mp3');
// start function
function start() {
xInterval = setInterval(workCountDown, 1000);
}
// stop function
function stop() {
clearInterval(xInterval);
}
// reset function; calls stop, save which re-stores the values of user inputs and then starts again.
function reset() {
stop();
save();
start();
}
// save function that saves the values of user inputs
function save() {
workSeconds = parseInt(document.getElementById("TaskTime").value)*60;
breakMinutes = parseInt(document.getElementById("BreakTime").value)*60;
}
// working count down function
function workCountDown() {
// counting down work seconds
workSeconds--;
// showing work seconds in "0:0" format:
document.getElementById("timer").innerText = Math.floor((workSeconds / 60)).toString() + ":" + (workSeconds % 60).toString();
// if workSeconds reaches to zero, stops the workInterval and starts the breakInterval:
if (workSeconds == 0) {
audio.play();
console.log("relaxing...");
clearInterval(xInterval);
xInterval = setInterval(breakCountDown, 1000);
}
}
// breaking count down function
function breakCountDown() {
// counting down break seconds
breakSeconds--;
// showing break seconds in "0:0" format:
document.getElementById("timer").innerText = Math.floor((breakSeconds / 60)).toString() + ":" + (breakSeconds % 60).toString();
// if breakSeconds reaches to zero, stops the breakInterval, resets the variables to initial values by calling save function and starts the workInterval again:
if (breakSeconds == 0) {
audio.play();
console.log("ready to work...");
reset();
}
}
as I said in the comment it works fine, just change breakMinutes to breakSeconds inside save function. here is an implementation of your code. you can run the snippet here and see the result
// we need some variables to store the work and break minutes
let workSeconds = "120",
breakSeconds = "60";
// and a referens to interval
let xInterval;
let isStarted = false;
// start function
function start() {
xInterval = setInterval(workCountDown, 1000);
}
// stop function
function stop() {
clearInterval(xInterval);
}
// reset function; calls stop, save which re-stores the values of user inputs and then starts again.
function reset() {
stop();
save();
start();
}
// save function that saves the values of user inputs
function save() {
workSeconds =
parseInt(document.getElementById("TaskTime").value || 120, 10) * 60;
breakSeconds =
parseInt(document.getElementById("BreakTime").value || 60, 10) * 60;
}
// working count down function
function workCountDown() {
// counting down work seconds
workSeconds--;
// showing work seconds in "0:0" format:
document.getElementById("timer").innerText =
Math.floor(workSeconds / 60).toString() +
":" +
(workSeconds % 60).toString();
// if workSeconds reaches to zero, stops the workInterval and starts the breakInterval:
if (workSeconds === 0) {
console.log("relaxing...");
clearInterval(xInterval);
xInterval = setInterval(breakCountDown, 1000);
}
}
// breaking count down function
function breakCountDown() {
// counting down break seconds
breakSeconds--;
// showing break seconds in "0:0" format:
document.getElementById("timer").innerText =
Math.floor(breakSeconds / 60).toString() +
":" +
(breakSeconds % 60).toString();
// if breakSeconds reaches to zero, stops the breakInterval, resets the variables to initial values by calling save function and starts the workInterval again:
if (breakSeconds === 0) {
console.log("ready to work...");
reset();
}
}
const startButton = document.getElementById("start-btn");
startButton.addEventListener("click", (e) => {
isStarted = !isStarted;
if (isStarted) {
save();
start();
startButton.textContent = "Stop";
} else {
stop();
startButton.textContent = "Start";
document.getElementById("timer").innerText = 0;
}
});
<label>Work Time: <input type="number" id="TaskTime" value="1" /></label>
<label>Break Time: <input type="number" id="BreakTime" value="1" /></label>
<div id="timer">0</div>
<button id="start-btn">Start</button>
Related
const secondsInterval = () => {
const date = getNow();
if (dayjs(date).minute() % 5 !== 0 && dayjs(date).second() !== 0) {
console.log("return...");
return;
}
console.log("checking...");
...
};
// Check every second, if we're at the 5-minute interval check.
setInterval(secondsInterval, 1000);
This seems to get stuck. It's "checking" on every second of each 5 minute mark. What am I doing wrong? Thanks in advance.
Goal: To "check" every minute and 00 seconds: :00:00, :05:00, :10:00, , :15:00, etc Thanks again.
You should find out what's the time to your next rounded 5 min. like this:
const FIVE_MIN = 1000 * 60 * 5;
function waitAndDoSomething() {
const msToNextRounded5Min = FIVE_MIN - (Date.now() % FIVE_MIN);
console.log(`Waiting ${msToNextRounded5Min}ms. to next rounded 5Min.`);
setTimeout(() => {
console.log('It is now rounded 5 min');
waitAndDoSomething();
}, msToNextRounded5Min);
}
waitAndDoSomething();
If all you care about is executing some code every 5 mins, then don't have it execute every second needlessly, only to return out. Just have it run every 5 mins (300000 MS) and have it do what you need to do and remove all the checking for 5 minute mark code out its unnecessary.
const secondsInterval = () => {
// -------------------- Remove ----------------
//const date = getNow();
//if (dayjs(date).minute() % 5 !== 0 && dayjs(date).second() !== 0) {
// console.log("return...");
// return;
//}
// -------------------- Remove ----------------
console.log("checking...");
...
};
// Check every 5 mins
setInterval(secondsInterval, 300000);
Your logic for the if is screwy. Here I reversed it so the if takes care of "do the thing" and the else returns.
const secondsInterval = () => {
const date = dayjs(new Date());
if (dayjs(date).minute() % 5 == 0 && dayjs(date).second() == 0) {
console.log("checking...");
} else {
console.log("returning...");
return;
}
//...
};
// Check every second, if we're at the 5-minute interval check.
setInterval(secondsInterval, 1000);
<script src="https://unpkg.com/dayjs#1.8.21/dayjs.min.js"></script>
I have a function everyXsecsForYsecs that will accept three arguments: a function, an interval time in seconds, and a total time in seconds.
everyXsecsForYsecs should invoke the given function every X * 1000 milliseconds, yet then stop invoking the function after Y * 1000 milliseconds. Addition to this, here is a simple callback function for everyXsecsForYsecs:
function sayHowdy(){
console.log('Howdy');
}
Then I call everyXsecsForYsecs as such:
everyXsecsForYsecs(sayHowdy, 1, 5);
So what I expect is to see 5 'Howdy' in the console, then function to stop. But what happens is that, function prints 'Howdy' for ever. Here is how I implemented everyXsecsForYsecs,
function everyXsecsForYsecs(callback, X, Y) {
x_mili = X * 1000;
y_mili = Y * 1000;
let id = setTimeout(function run(){
callback();
id = setTimeout(run, x_mili);
}, x_mili);
setTimeout(clearTimeout, y_mili, id);
}
I am suspicious about how I use clearTimeout with nested setTimeout,
What I am missing exactly?
By the time
setTimeout(clearTimeout, y_mili, id);
runs, id contains the timer id of the first outer setTimeout call. Cancelling that won't really help. If you'd replace it with:
setTimeout(() => clearTimeout(id), y_mili);
it'll clear the timeout with the id at that time, as you evaluate id when the timeout is done, and not when it get's started.
I'd write it as:
function everyXsecsForYsecs(callback, X, Y) {
let count = Math.floor(Y / X);
function recurring() {
callback();
if((count -= 1) >= 0)
setTimeout(recurring, X * 1000);
}
setTimeout(recurring, X * 1000);
}
let firstId = setTimeout(sayHowdy, 1000)
will call sayHowdy after 1000ms and store the timeout id within firstId
clearTimeout(firstId)
if this is called, the timeout referenced by the id will be cleared (no matter if it already is over or not)
But the question actually is, why you would want to clear the timeout, it's no interval, so you probably are in the wrong box.
have a look at this snippet, it does not repeat for seconds, but x times with recursion:
function fireAllXSecsYTimes(callback, fireAfterSeconds, counter) {
if (counter === 0) {
return;
}
setTimeout(() => {
callback();
counter--;
fireAllXSecsYTimes(callback, fireAfterSeconds, counter);
}, fireAfterSeconds * 1000)
}
what you asked for:
function fireAllXSecsForYSecs(callback, fireAfterSeconds, remainingSeconds) {
if (remainingSeconds <= 0) {
return;
}
setTimeout(() => {
callback();
fireAllXSecsForYSecs(callback, fireAfterSeconds, remainingSeconds - fireAfterSeconds);
}, fireAfterSeconds * 1000)
}
called with fireAllXSecsForYSecs(() => console.log('howdy'), 2, 5)
it will log 'howdy' 3 times, because on third execution, remainingSeconds still has 1 left. If you want to prevent this, just return if remainingSeconds <= 0 || remainingSeconds < fireAfterSeconds
Pass the reference not the value.
function sayHowdy() {
console.log('Howdy');
}
function everyXsecsForYsecs(callback, X, Y) {
x_mili = X * 1000;
y_mili = Y * 1000;
let id = setTimeout(function run() {
callback();
id = setTimeout(run, x_mili);
}, x_mili);
setTimeout(() => clearTimeout(id), y_mili);
//here you need to pass the reference to the id not the value
//which is constantly changing
}
everyXsecsForYsecs(sayHowdy, 1, 5);
Question
Every 2 seconds interval, the two numbers (i.e. Number 1 and Number 2) will generate random numbers containing integer values from 5 to 6.
For every random numbers generated, the 2 seconds interval will be reduced by 0.1 seconds.
The random speed text will show the current seconds interval for every random numbers generated.
Once the interval reaches 0.8 seconds, a javascript alert box will show the message “The interval has reached 0.8 seconds”.
When the user dismisses the alert, the random speed text is reset to the initial values and restarts the speed of two numbers to be randomly generated for every interval.
Current Code
var no1, no2, correctScore, wrongScore, missedScore, generatedNum, delay
generateTotal = 30;
function updateScreen(disabled) {
$('#correctScore').text(correctScore);
$('#wrongScore').text(wrongScore);
$('#missedScore').text(missedScore);
$('#generatedNum > span').text(generatedNum);
$("#number1 > span").text(no1);
$("#number2 > span").text(no2);
$(":input").val(generatedNum >= generateTotal ? "START!" : "MATCH!");
$(":input").prop('disabled', disabled);
}
function generate() {
if (no1 == no2 && !$(":input").prop('disabled')) ++missedScore;
if (generatedNum >= generateTotal) {
updateScreen(false); // needed to show missedScore.
if (confirm('The interval has reached 0.8 seconds')) start();
return; // exit
}
no1 = 5 + Math.floor(Math.random()*2);
no2 = 5 + Math.floor(Math.random()*2);
++generatedNum;
updateScreen(false);
setTimeout(generate, delay *= 0.95);
}
function start() {
correctScore = wrongScore = missedScore = generatedNum = 0;
delay = 2000;
updateScreen(true);
generate();
}
function check() {
if (generatedNum >= generateTotal) return start(); // Start pressed
if (no1 == no2) {
++correctScore;
} else {
++wrongScore;
}
updateScreen(true); // disable button
}
$(function(){
$(":input").click(check);
start();
});
$(function(){
$(":input").click(check);
start();
});
How can I decrease the value of a variable by 0.2 every 5 minutes?
I have a variable var = 7.2. Now I added a button so when I click on it the variable will increment by 1.
Now I want to add an option where the variable decrement by 0.2 every 5 minutes and stop at the original number 7.2.
I have already tried window.setInterval() without successs.
Try this.
function myFunction(){
if (counter === 0){
document.getElementById("dicht").src = "images/open.jpg";
degree = degree + 0.9;
temp.innerHTML = degree; //+ " " + "graden celsius in de wijnkoeler";
counter = 1;
} else if (counter === 1){
document.getElementById("dicht").src = "images/dicht.jpg";
var id = window.setInterval(function(){
degree = parseFloat(Math.max(7.2, (degree - 0.2)).toPrecision(2));
if(degree == 7.2){
window.clearInterval(id);
counter = 0;
}
temp.innerHTML = degree;
}, 1000 * 60 * 5);
}
}
Here is how to use setInterval
var number;
var interval = setInterval(function(){
if (number < 7.2 ) clearInterval(interval);
number = number - 0.2;
}, 300000);
It's done by using setInterval
var time = 7.2;
var fivemin = 300000;
$('someid').text(time);
setInterval(function(){
time = time - 0.2;
$('someid').text(time);
}, fivemin);
WORKING DEMO
Don't use setInterval, use setTimeout instead:
window.myVar = 7.2;
var incrementVar = function() {
window.myVar += 1;
}
var decrementVar = function() {
window.myVar -= 0.2;
setTimeout(decrementVar, (5 * 60 * 1000));
}
setTimeout(decrementVar, (5 * 60 * 1000));
And for the button:
My Button
This should do it:
// global variable
var myGlobal = 8.2;
window.onload = function countback() {
window.setInterval(function cb() {
if (myGlobal >= 7.4) {
myGlobal = parseFloat(myGlobal - .2).toFixed(1);
}
}, 5 * 60 * 1000);
};
NOTE: If you are using a JS library like jQuery some of this can be done much more easily.
Please Help! I'm new to Javascript, so there's probably an easier solution to this. Basically, I need it to prompt for a number and then count down from that number to zero. Once it reaches zero, I need it to count-up and stop at the same prompted number.
I got it to count down at first, then I completely butchered it, I have no clue what to do.
<script type="text/javascript">
// get number from user
var startNum = parseInt(prompt("Input a number to start counting down from.",""));
var counter = setInterval(timer, 1000);
console.log(startNum);
function timer() {
startNum--; // reduce number by 1
console.log(startNum);
if (startNum <= 0) {
clearInterval(counter);
}
}
var counter = setInterval(timer2, 1000);
var endNum = 0
function timer2() {
console.log(endNum)
endNum++; // add number by 1
console.log(endNum);
if (endNum >= startNum) {
clearInterval(counter);
}
}
</script>
You've got a couple issues here. the first one was pointed out by Rob in the comments. You're running both functions at the same time.
The other issue you have is that you're never storing the number. You're just subtracting and adding to nothing essentially.
So -
<script type="text/javascript">
// get number from user
var startNum = parseInt(prompt("Input a number to start counting down from.",""));
var currentNum = startNum;
var counter = setInterval(timer, 1000);
function timer() {
console.log(currentNum);
currentNum -= 1; // reduce number by 1
console.log(currentNum);
if (currentNum == 0) {
clearInterval(counter);
counter = setInterval(timer2, 1000);
}
}
function timer2() {
console.log(currentNum)
currentNum += 1; // add number by 1
console.log(currentNum);
if (currentNum == startNum) {
clearInterval(counter);
}
}
</script>
Something like this should do the trick. Basically creating another variable to hold your start number and consider that the current number and the value that is going to change.
here's a fiddle - http://jsfiddle.net/w5FM6/
cheers