I'm kinda new to programming, but recently I was trying to do little first project of mine called timer count, it's just simple local website which I open when I'm deciding to start programming during the day and it counts the time. I created 2 buttons with 2 different functions (start,stop), but the problem I'm stuck on is I don't know how to implement stop function. The idea is that timer should stop after button click, and when I click start button it should start from saved time.
Here's HTML/CSS code:
<div class="timer-display-id">
<h1>Timer </h1>
<p id="timer">00:00:00 </p>
<button id="start-timer" onclick="start()">Start </button>
<button id="stop-timer" onclick="stop()">Stop </button>
</div>
<script src="timer.js"></script>
and here's JS code:
function stop() {
// not exactly sure if this function should be here, anyway no idea what to add to get this to work
clearInterval(interval);
start.disabled = false;
}
function convertSec(cnt) {
let sec = cnt % 60;
let min = Math.floor(cnt / 60);
if (sec < 10) {
if (min < 10) {return "0" + min + ":0" + sec;}
else {return min + ":0" + sec;}
}
else if ((min < 10) && (sec >= 10)) {return "0" + min + ":" + sec;}
else {return min + ":" + sec;}
}
function start() {
let ret = document.getElementById("timer");
let counter = 0;
let start = document.querySelector("#start-timer");
let stop = document.querySelector("#stop-timer");
start.disabled = true;
let interval = setInterval(function() {
ret.innerHTML = convertSec(counter++); // timer start counting here...
},1000);
}
I understand it might be very messy, kinda lack of logic, but it's best I can do for now. If you'd like to give some tips about code organizing, I'd appreciate it.
You nee to have interval accessible by both functions whileit holds the setInterval function, just move it outside the start function :
const ret = document.getElementById("timer");
const startBtn = document.querySelector("#start-timer");
let counter = 0;
let interval;
function stop() {
clearInterval(interval);
startBtn.disabled = false;
}
function convertSec(cnt) {
let sec = cnt % 60;
let min = Math.floor(cnt / 60);
if (sec < 10) {
if (min < 10) {
return "0" + min + ":0" + sec;
} else {
return min + ":0" + sec;
}
} else if ((min < 10) && (sec >= 10)) {
return "0" + min + ":" + sec;
} else {
return min + ":" + sec;
}
}
function start() {
startBtn.disabled = true;
interval = setInterval(function() {
ret.innerHTML = convertSec(counter++); // timer start counting here...
}, 1000);
}
<div class="timer-display-id">
<h1>Timer </h1>
<p id="timer">00:00:00 </p>
<button id="start-timer" onclick="start()">Start </button>
<button id="stop-timer" onclick="stop()">Stop </button>
</div>
If you want the count to be saved after you hit "stop", and to re-start from the same point, you will need to define your count variable somewhere outside the start() function, so that it can tell what count to restart from. At the moment, count is local to the start() function, which will reset it to zero every time.
By using the 1s interval timer to update the count, your counter will round each period to whole seconds. It would be slightly more complicated, but if you want to be able to add up the partial seconds from multiple counts, it would be more accurate to use something like Date.getTime() to record the time the start button is pressed, then check the elapsed time when stop() is triggered, and add that to your count. You might still want to use an interval timer to regularly update the current value though. Again, you would need to check that the variables you want to use have the correct scope, so that they are visible to the functions that use them, and not lost between function calls.
Related
I have taken this simple timer method from here.
What I want is pretty simple, yet I can’t figure it out.
When the timer reaches zero (0:00), I want a popup alert. At the same time, the timer should continue in negative time.
So everything is working, except the popup. Any idea why?
window.onload = function() {
var minute = 0;
var sec = 3;
setInterval(function() {
document.getElementById("timer").innerHTML = minute + " : " + sec;
sec--;
if (sec == 00) {
minute --;
sec = 59;
if (minute == 0 && sec == 00) {
alert("You failed!");
}
}
}, 1000);
}
<div class="countdown" class="failed" id="coutdown">
Time remaining to find solution: <span id="timer">10 : 00</span>
</div>
window.onload = function() {
var minute = 0;
var sec = 3;
var timer = document.getElementById("timer");
setInterval(function() {
if (sec === 0) {
timer.innerHTML = minute + " : " + sec;
if (minute === 0 && sec === 0) {
alert("You failed!");
}
minute--;
sec = 60;
} else {
timer.innerHTML = minute + " : " + sec;
}
sec--;
}, 1000);
}
<div class="countdown" class="failed" id="coutdown">
Time remaining to find solution: <span id="timer">10 : 00</span>
</div>
You are checking minute and second conditions after minute-- in your code, which means -1 is not equal to zero. Write an if condition before making minus 1 in your code.
Please use console.log("You failed!") instead of alert("You failed!") to ensure an accurate result.
Your conditional is checking whether sec == 0 immediately after you set sec = 59, so the conditional will never occur. Do you mean to have the order of this setter and the conditional swapped?
This is what I mean by restructuring the code entirely into reusable functions. comment what you don't understand and I will explain. I try not to hard code anything timer fetches its starter value from HTML.
const display = document.getElementById("timer");
function toArray(domEl){
return domEl.innerHTML.split(':').map(el => +el);
}
function getSec(timeArr){
if(timeArr.length > 3 || timeArr.length === 0) return;
return timeArr.reverse().map((el, i) => el * 60 ** i).reduce((cur,accu)=> cur + accu);
}
let totalSec = getSec(toArray(display))
setInterval(()=>{
totalSec--;
display.textContent = formatTime(totalSec);
},1000)
function formatTime(sec){
const time = {hr:0, min:0, sec:0};
time.hr = ~~(sec/3600) || 0;
time.min = ~~(~~(sec%3600)/60);
time.sec = ~~(sec%3600)%60;
if(time.hr===0 && time.min===0 && time.sec ===0) alert("You Faild!")
return `${time.hr ? time.hr + ':':''}${padTime(time.min)}:${padTime(time.sec)}`
}
function padTime(time){
return time? String(time).padStart(2,0):0;
}
<div class="countdown" class="failed" id="coutdown">
Time remaining to find solution: <span id="timer">0:01:05</span>
</div>
I am making a timer and for some reason the timer is not properly decrementing using the countDown function in the code below. I am using setTimeout to call it countDown repeatedly but when I checked the debugger JavaScript does not even go to that line, after the second-to-last line timeEl.textContent = tempMinutes + ":" + tempSeconds; it just stops. I tried setInterval but its the same.
I want to know how to have the timer go down and setTimeout to do its thing, but how? Any advice or help is greatly appreciated!
const workBtnEl = document.querySelector("#work-btn");
const shortBreakBtnEl = document.querySelector("#short-break-btn");
const longBreakBtnEl = document.querySelector("#long-break-btn");
let timeEl = document.querySelector("#time");
const work = 25;
const shortBreak = 5;
const longBreak = 15;
let currentMinutes, currentSeconds = 0;
workBtnEl.addEventListener("click", function() {
timeEl.textContent = "25:00";
currentMinutes = work;
countDown(currentMinutes, 0);
});
function countDown(minutes, seconds) {
if (seconds == 0) {
if (minutes == 0) {
return;
}
minutes -= 1;
seconds = 59;
}
let tempSeconds = seconds;
let tempMinutes = minutes;
if (seconds < 10) {
tempSeconds = "0" + seconds;
}
if (minutes < 10) {
tempMinutes = "0" + minutes
}
timeEl.textContent = tempMinutes + ":" + tempSeconds;
let time = setTimeout(countDown, 1000, minutes, seconds);
}
<button id="work-btn">
Work
</button>
<button id="short-break-btn">
Short break
</button>
<button id="long-break-btn">
Long break
</button>
<span id="time">Time</span>
You never decrease seconds when it is non-zero.
So add that after the if block:
if (seconds == 0) {
// your code...
} else seconds--; // <---
You need to reduce the seconds variable in the countDown function otherwise the same text will be printed to your text area each time.
Right now you just have a condition if the seconds are 0 then set seconds to 59.
See what you have done in this line :
let currentMinutes, currentSeconds = 0;
currentMinutes will be undefined mostly, I used Node REPL to check
If you have something like :
let a, b = 0
The value of a was undefined & b got set to zero
An appropriate assignment would be
let currentMinutes = 0;
let currentSeconds = 0;
I have the following code and cannot get the chat timestamp to update without refresh. I am new to javascript.
function timeSince(date) {
var seconds = Math.floor((new Date() - date) / 1000);
var interval = seconds / 31536000;
if (interval > 1) {
return Math.floor(interval) + " years";
}
interval = seconds / 2592000;
if (interval > 1) {
return Math.floor(interval) + " months";
}
interval = seconds / 86400;
if (interval > 1) {
return Math.floor(interval) + " days";
}
interval = seconds / 3600;
if (interval > 1) {
return Math.floor(interval) + " hours";
}
interval = seconds / 60;
if (interval > 1) {
return Math.floor(interval) + " minutes";
}
return Math.floor(seconds) + " seconds";
}
setInterval(timeSince, 1000);
var aDay = 24*60*60*1000;
console.log(timeSince(new Date(Date.now()-aDay)));
console.log(timeSince(new Date(Date.now()-aDay*2)));
const dates = new Date(message.timestamp)
if (message.user === currentUser) position = 'right';
const messageItem = `
<div class="message ${position}">
<span class="small">${timeSince(dates)}</span><br>
I tried: setInterval(timeSince, 1000); and setInterval(timeSince(), 1000); and setInterval(timeSince(date, 1000); and tried each in different place within the function, can't get to work.
timeSince just returns your formatted string with the duration. Setting an interval on this function will do practically nothing. You have to use the return value.
setInterval(function(){
var time = timeSince(message.timestamp);
//You can use a better selector here,
//but without more information, this is the best I can do.
document.getElementsByClassName("small")[0].innerHTML = time;
}, 1000);
found a half solution. I had to insert the setInterval under the function that calls the function under which sits the timesince function. Now the whole thing updates after the interval i set and not just the time, but setting an update interval of 1 minute makes it fine with me.
Apparently since I have several functions under one, the setInterval doesn't work, or didn't work in my case.
draw message is the function under which the timeSince function resides
Maybe coz i didn't provide this info here before i didn't get the right help
Solution:
this:
function getConversation(recipient) {
setInterval(function(){
$.getJSON(`/api/v1/message/?target=${recipient}`, function (data) {
messageList.children('.message').remove();
for (let i = data['results'].length - 1; i >= 0; i--) {
drawMessage(data['results'][i]);
}
messageList.animate({scrollTop: messageList.prop('scrollHeight')});
});
}, 60000);}
or this:
function getConversation(recipient) {
$.getJSON(`/api/v1/message/?target=${recipient}`, function (data) {
messageList.children('.message').remove();
for (let i = data['results'].length - 1; i >= 0; i--) {
drawMessage(data['results'][i]);
}
**setInterval(getConversation(recipient), 1000);**
messageList.animate({scrollTop: messageList.prop('scrollHeight')});
});
}
Thank you David for your help
A single cookie timer (meaning value) is an idea without a hitch, I want it to pause after 1 hour and start doing what it means after clicking on a motion.
Google didn't help. https://jsfiddle.net/m6vqyeu8/
Please share your version or help wrote your own.
<!doctype html>
<html>
<head>
<title>timer</title>
<meta charset=utf-8>
</head>
<script>
let initialValue = 0.50000096;
let multiplier = 0.00000001;
let getCookie = (c_name) => {
let i, x, y, ARRcookies = document.cookie.split(";");
for (i = 0; i < ARRcookies.length; i++) {
x = ARRcookies[i].substr(0, ARRcookies[i].indexOf("="));
y = ARRcookies[i].substr(ARRcookies[i].indexOf("=") + 1);
x = x.replace(/^\s+|\s+$/g, "");
if (x == c_name) {
return unescape(y);
}
}
}
let setCookie = (c_name, value, exdays) => {
let exdate = new Date();
exdate.setDate(exdate.getDate() + exdays);
let c_value = escape(value) + ((exdays == null) ? "" : "; expires=" + exdate.toUTCString());
document.cookie = c_name + "=" + c_value;
}
let lastUpdated = getCookie('lastUpdated') * 1;
if (!lastUpdated) {
lastUpdated = Date.now();
setCookie('lastUpdated', lastUpdated, 9999);
}
let diff = (Date.now() - lastUpdated) / 1000;
let cu = (diff * multiplier) + initialValue;
let doCu = () => {
document.getElementById('cu').innerHTML = cu.toFixed(8);
cu = cu + multiplier;
}
document.write("<div id='cu' style='text-align: center; font-size: 40pt'></div>\n");
setInterval(doCu, 1000);
doCu();
</script>
<body>
</body>
</html>
In order to pause and resume the counter you should save the return value of the setInterval funciton and clear it or create a new one for pause and resume. Here is the example:
let interval = setInterval(doCu, 1000)
doCu()
function stop() {
clearInterval(interval)
}
function resume() {
interval = setInterval(doCu, 1000)
}
Add that to the end of your script and add 2 buttons like the following in order to be able to test it.
<button onclick="stop()">
Pause
</button>
<button onclick="resume()">
Resume
</button>
To stop the timer after one hour you can add the following code
// Stop the timer after one hour has passed.
// setTimeout calls function stop (that is used to pause the timer aswell) after 1 hour
// 1000 milis is a second. Times 60 is a minute. Times 60 is an hour
setTimeout(stop, 1000 * 60 * 60)
For the timer to automatically stop after an hour from the moment you click resume change the resume function like this:
function resume() {
interval = setInterval(doCu, 1000)
// When you resume the timer, add a timeout so it will stop in an hour.
setTimeout(stop, 1000 * 60 * 60)
}
I have updated the fiddle so you can see how it is completed.
Updated JSFiddle Link
EDIT:
Made timer stop after an hour
Renamed pause function to stop so it is more clear what it does.
Added ability to stop timer after an hour after resume
I'm having a problem get this countdown timer to stop at zero so the time won't show as a negative value. The console.log is getting called and works fine but for some reason the clearInterval() is not. This is driving me crazy and I'm close to quitting.
const timerContainer = document.getElementById('timerContainer');
const THREEMINUTES = 60 * 0.1;//5 seconds for testing
startTimer(THREEMINUTES, timerContainer);
function startTimer(duration, display) {
let start = Date.now();
let diff, min, sec;
let timer = () => {
diff = duration - (((Date.now() - start) / 1000) | 0);
//use bitwise to truncate the float
min = (diff / 60) | 0;
sec = (diff % 60) | 0;
min = min < 10 ? '0' + min : min;
sec = sec < 10 ? '0' + sec : sec;
display.textContent = min + ':' + sec;
if (diff <= 0) {
stopTimer();
submit.disabled = 'true';
};
};
//call timer immediately otherwise we wait a full second
timer();
setInterval(timer, 1000);
function stopTimer() {
clearInterval(timer);
console.log("time's up", diff);
};
}
<div id="timerContainer"></div>
You are not saving the result of setInterval(timer, 1000);
you should use this:
let timerId;
timer();
timerId = setInterval(timer, 1000);
function stopTimer() {
clearInterval(timerId);
console.log("time's up", diff)
};
As you might see, the result of setInterval is a number (object in node), and all you then need to do is pass that value to clearInterval thus we save the value in the variable timerId for reference.
Don't pass the function that you want stopped to clearInterval().
Pass a reference to the timer that you started, so you need to make sure that when you start a timer, you capture a reference to the ID that will be returned from it.
// Function that the timer will invoke
function callback(){
. . .
}
// Set up and initiate a timer and capture a reference to its unique ID
var timerID = setInterval(callback, 1000);
// When needed, cancel the timer by passing the reference to it
clearInterval(timerID);
The code is fixed make sure you fix your submit button code.
You should first assign the value of setInterval to a variable. That variable is used while calling clearInterval which infact clears the interval.
const timerContainer = document.getElementById('timerContainer');
const THREEMINUTES = 60 * 0.1;//5 seconds for testing
startTimer(THREEMINUTES, timerContainer);
var timer = null;
function startTimer(duration, display) {
let start = Date.now();
let diff, min, sec;
let timer = () => {
diff = duration - (((Date.now() - start) / 1000) | 0);
//use bitwise to truncate the float
min = (diff / 60) | 0;
sec = (diff % 60) | 0;
min = min < 10 ? '0' + min : min;
sec = sec < 10 ? '0' + sec : sec;
display.textContent = min + ':' + sec;
if (diff <= 0) {
stopTimer();
submit.disabled = 'true';
};
};
//call timer immediately otherwise we wait a full second
timer();
timer = setInterval(timer, 1000);
function stopTimer() {
clearInterval(timer);
console.log("time's up", diff);
};
}