I'm trying to figure out javascript ... Currently, I am using a countdown timer. I'd like to add/subtract 1 minute when the left or right key is pressed.
I tried the following:
$(document).keydown(function(e) {
switch(e.which) {
case 37: // left
current = parseInt($('#time2').textContent);
newtime = current + 60;
countdown_start(newtime)
break;
case 39: // right
alert('right');
break;
default: return;
}
e.preventDefault(); // prevent the default action (scroll / move caret)
});
But it has some really funky reaction ... and starts counting down twice...one with a NaNaNaNa...
Any help would be appreciated. Thanks!
.background-countdown
#start-game
= submit_tag 'Play', id: "start"
#time2
60:00
.test
asd
-##start-time
-# =text_field_tag 'start-time-input', "60:00", id: "start-time-input"
#hint-text.white-text
:javascript
function startTimer(duration, display) {
var timer = duration, minutes, seconds;
var countdown = setInterval(function () {
minutes = parseInt(timer / 60, 10)
seconds = parseInt(timer % 60, 10);
minutes = minutes < 10 ? "0" + minutes : minutes;
seconds = seconds < 10 ? "0" + seconds : seconds;
display.textContent = minutes + ":" + seconds;
if (--timer < 0) {
$('#start').show()
$('#start-time').show()
clearInterval(countdown)
}
}, 1000);
}
function countdown_start(sixtyMinutes = 3600) {
$(document).ready(function () {
display = document.querySelector('#time2');
startTimer(sixtyMinutes, display);
});
}
$('#start').click(function() {
countdown_start()
$('#start').hide()
event.preventDefault();
});
function get_text(){
var feedback = $.ajax({
type: "POST",
url: "/jquery/update_text",
async: false
}).complete(function(){
setTimeout(function(){get_text();}, 1000);
}).responseText;
}
$(function(){
get_text();
});
The problem here might be, that you are using clearInterval right, but you have not correctly saved the returned ID value of the setIntervall method.
Please have a look at the w3schools.com page:
http://www.w3schools.com/jsref/met_win_clearinterval.asp
They write in a note under the definition:
Note: To be able to use the clearInterval() method, you must use a global variable when creating the interval method
You save your ID locally so maybe you shouldn't do that.
Instead use a global variable, which just means that you declare it outside the functions section and use that reference over and over again, BUT what you also want to change is your order. First you are setting an interval and later in the startMethod-function you clear that same interval. I think if you change the order and make the variable global, it should work.
Related
Im working on code for a simple stopwatch. Last obstacle for me is reset the time to zero. The function resetTimer is where i am trying to implement the code. So the webpage will display a page with a timer and three buttons; stop, start and reset. When a user clicks the reset button, the timer is supposed to reset back to zero. I have been having trouble trying to make it work. Any help/ideas would be clutch.
I hope i made myself clear. Again i am trying to make the timer reset to 00:00:00
window.onload = function () {
//grab possible elements needed
const timerEl = document.getElementById("timer-text")
const startBtn = document.getElementById("start")
const restartBtn = document.getElementById("restart");
const stopBtn = document.getElementById('stop');
//hold variables of time and set to 0
let hours = parseInt('0');
let minutes = parseInt('0');
let seconds = parseInt('0');
let time;
function makeTwoNumbers(num) {
if (num < 10) {
return "0" + num
}
return num
}
//timer
let timer = () => {
seconds++
//console.log(seconds)
if (seconds == 60) {
minutes++
seconds = 0;
hours = 0
}
if (minutes == 60) {
hours++
minutes = 0;
hours = 0;
}
timerEl.textContent = makeTwoNumbers(hours)+ ": " + makeTwoNumbers(minutes) + ": " + makeTwoNumbers(seconds);
}
let runTheClock;
//timer is running
function runTimer() {
runTheClock = setInterval(timer, 20);;
}
function stopTimer() {
clearInterval(runTheClock)
}
//function will reset timer
function resetTimer() {
time--;
timerEl.textContent;
if (time === 0) {
stopTimer();
time = 0
}
}
restartBtn.addEventListener("click", function () {
resetTimer();
})
//button will pause the timer
stopBtn.addEventListener("click", function () {
stopTimer();
})
//button will start the timer
startBtn.addEventListener("click", function () {
runTimer();
})
}
Here's a fixed and slightly refactored version.
<html>
<body>
<div id="timer-text"></div>
<button id="start">start</button>
<button id="restart">restart</button>
<button id="stop">stop</button>
</body>
<script>
const timerEl = document.getElementById("timer-text")
const startBtn = document.getElementById("start")
const restartBtn = document.getElementById("restart");
const stopBtn = document.getElementById('stop');
let runTheClock;
let seconds = 0;
render(seconds);
function makeTwoNumbers(num) {
return ((num < 10) ? "0" : "") + num;
}
function tick() {
seconds++;
render(seconds);
}
function render(secs) {
const hours = Math.floor(secs / 3600);
const minutes = Math.floor(secs / 60) - (hours * 60);
const seconds = secs % 60;
const val = [hours, minutes, seconds].map(makeTwoNumbers).join(":");
console.log(val);
timerEl.textContent = val;
}
function runTimer() {
runTheClock = setInterval(tick, 1000);
}
function stopTimer() {
clearInterval(runTheClock)
}
function resetTimer() {
seconds = 0;
render(seconds);
}
restartBtn.addEventListener("click", resetTimer);
stopBtn.addEventListener("click", stopTimer);
startBtn.addEventListener("click", runTimer);
</script>
</html>
In the reset function it just sets seconds back to 0 and sets the textContent value so it appears on the page. I separated out the calculating and drawing of the time into a render fucntion, so it can be reused whenever it needs to be re-rendered.
To explain the render function.
We only need to store the number of seconds as a persistent variable between the periodic function calls. We can derive hours and minutes from it. This makes it much less error prone than trying to increment hours and minutes as well.
To calculate hours we just divide seconds by 3600 (or 60 x 60 the number of seconds in an hour) and round down.
To calculate minutes we can calculate the number of total minutes (seconds / 60 and round down) then subtract the number of minutes in the hours value we calculated (hours * 60).
For seconds we use modulus or % which is just a fancy word for remainder. So seconds % 60 gives us the remainder value of seconds / 60. For example 61 % 60 = 1. This isn't the only way these values could be calculated.
To build the display string. I just put all of the hours, minutes and seconds in an array. Then used the map method, which applies the function makeTwoNumbers to all of the values. I then used the join method to join all the strings using the delimiter :. It just saves some typing and means you only reference makeTwoNumbers once, making it less work to use a different function later if you want to.
Hope that helps.
I realized that you could simply reset seconds, hours, and minutes to 0 and use a variable true. This would reset it entirely to 0. I couldnt believe how simple it was
I have the following code that will refresh the "updt" page at the minute "50" of every hour.
It only works if I refresh the page manually. How can I modify the code to sense that the minute 50 has come.
function show_hide_me () {
var myDate = new Date();
var mins = myDate.getMinutes();
if (mins == 50){
doSomething();
}
}
function doSomething() {
alert("Page will refresh now");
document.getElementById("updt").click();
}
what you are missing is that you need to check if its 50th minute, every minute.
setInterval(function(){
show_hide_me();
}, 60*1000);
This will run your function every 60000 miliseconds i.e. one minute.
https://www.w3schools.com/jsref/met_win_setinterval.asp
As other users said, what you need is a loop and a method like window.reload(true) or window.location.href = location.href to be executed when mins == 50.
For example, use setInterval:
let intervalId = window.setInterval(function() {
let myDate = new Date();
let mins = myDate.getMinutes();
if (mins == 50){
window.location.href = location.href;
}
}, 60 * 1000); // every 60 seconds
All you have to do is wrap your function in a
setInterval
So that it can be executed maybe ever minute and would continuously check if it's 50minutes into an hour already.
A sample code would be:
setInterval(show_hide_me, 60000)
The reason for this is if the user happens to refresh the page, our checker would always execute our checker.
I think you should change your doSomething function to something like:
function doSomething() {
window.location = window.location.href;
}
Try this logic. This will refresh the page at the 50th minute for every hour.
(function() {
var time = 49 - (new Date()).getMinutes();
time = time >= 0 ? time : (50 + (10 + time));
console.log("Loaded : ", time);
setTimeout(function() {
window.location.reload();
}, time*60000);
})()
I have PHP page, where I added a countdown for 30 min. and as it ticks when I refresh the page or perform a query of 'insert' and redirect back to that page, the timer gets reset.
I want the timer to be constant and continue count without any interruptions when the page gets refreshed.
My code goes as:
function startTimer(duration, display) {
var timer = duration,
minutes, seconds;
setInterval(function() {
minutes = parseInt(timer / 60, 10)
seconds = parseInt(timer % 60, 10);
minutes = minutes < 10 ? "0" + minutes : minutes;
seconds = seconds < 10 ? "0" + seconds : seconds;
display.textContent = minutes + ":" + seconds;
if (--timer < 0) {
timer = duration;
}
}, 1000);
}
window.onload = function() {
var fiveMinutes = 60 * 30,
display = document.querySelector('#time');
startTimer(fiveMinutes, display);
};
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="timer">
<div>Section</div>
<div class="time">
<strong>Time left: <span id="time">30:00</span></strong>
</div>
</div>
Any Help Is Appreciated..
Use html5 local storage to update the timer value and when page load occurs read the timer value from local storage. I guess no other way.
Whenever your PHP page loads, the javascript is loaded with it. So
window.onload = function () {
var fiveMinutes = 60 * 30,
display = document.querySelector('#time');
startTimer(fiveMinutes, display);
};
is called and the timer starts at 5 minutes.
One solution would be to do an Ajax request in window.onload and get the remaining time.
Another solution would be to set the fiveMinutes variable (obviously it should be renamed more appropriately) via PHP, if the javascript code is inside your PHP file, like
<script>
...
var timeLeft = <?php echo $timeLeft ?>;
...
</script>
The first solution is the standard way to go and the second one is the easy way to go.
As others have pointed out, you could use local storage (if the your target clients support this feature see here)
<script>
function startTimer(duration, display) {
var timer = duration, minutes, seconds;
setInterval(function () {
minutes = parseInt(timer / 60, 10)
seconds = parseInt(timer % 60, 10);
minutes = minutes < 10 ? "0" + minutes : minutes;
seconds = seconds < 10 ? "0" + seconds : seconds;
display.textContent = minutes + ":" + seconds;
timer = --timer;
if (timer >= 0) {
localStorage.setItem('time', timer);
//timer = duration;
}
}, 1000);
}
window.onload = function () {
var countDown = 60 * 30;
var oldVal = localStorage.getItem('time');
if (oldVal && oldVal > 0) {
countDown = oldVal;
}
var display = document.querySelector('#time');
startTimer(countDown, display);
};
</script>
edit: of course one must not forget to check whether the stored value is below zero.
As already pointed out, you could store the current time with localStorage.
To do so you would save both minutes and seconds in each interval tick:
function startTimer(duration, display) {
var timer = duration, minutes, seconds;
setInterval(function () {
minutes = parseInt(timer / 60, 10)
seconds = parseInt(timer % 60, 10);
localStorage.setItem("minutes", minutes); // <--
localStorage.setItem("seconds", seconds); // <--
And in the load function you'd read from them and set the starting value appropriately. It's important to note that values are always stored as strings, and as such, it would be necessary to parse them back to numbers before passing them through:
window.onload = function () {
var timeLeft = 60 * 30,
display = document.querySelector('#time');
var minutes = localStorage.getItem("minutes"); //read minutes
var seconds = localStorage.getItem("seconds"); //read seconds
if (minutes && seconds){
timeLeft = Number(minutes) * 60 + Number(seconds); //set time with val from storage
}
startTimer(timeLeft, display);
};
I changed the name of your fiveMinutes to timeLeft to better reflect what it holds, and parsed both values to numbers with Number().
It's also important to mention that while this does keep the value after refreshes, it doesn't "count" the time while the page was closed. So keep that in mind.
Instead of refreshing the whole page try to use Ajax for communication and modify your html page using javascript.
Related to this previous Question: How to stop a Javascript Timer after the second countdown?
I figured out a way for my Pomodoro clock to function properly, but my code is pretty repetitive. I couldn't figure out a way to not recreate the same (or very similar function) without the second break timer continuously running. Any ideas?
function startTimer(duration, display) {
var timer = duration, minutes, seconds;
var countdown = setInterval(function () {
minutes = parseInt(timer / 60, 10)
seconds = parseInt(timer % 60, 10);
//minutes = minutes < 10 ? "0" + minutes : minutes;
seconds = seconds < 10 ? "0" + seconds : seconds;
display.textContent = minutes + ":" + seconds;
$(".startClock").click(function () {
clearInterval(countdown);
});
if (--timer < 0) {
clearInterval(countdown);
breakClock();
}
}, 500);
}
function breakTimer(duration, display) {
var timer = duration, minutes, seconds;
var countdown = setInterval(function () {
minutes = parseInt(timer / 60, 10)
seconds = parseInt(timer % 60, 10);
//minutes = minutes < 10 ? "0" + minutes : minutes;
seconds = seconds < 10 ? "0" + seconds : seconds;
display.textContent = minutes + ":" + seconds;
$(".startClock").click(function () {
clearInterval(countdown);
});
if (--timer < 0) {
clearInterval(countdown);
}
}, 500);
$("body").css("background-color", "#E13F86");
$("#title").text(function(i, text){
return text === 'Breaktime' ? 'Productive Countdown' : 'Breaktime'
});
}
var display = document.querySelector('#time');
function startClock() {
var twentyfiveMinutes = 60 * .25;
startTimer(twentyfiveMinutes, display);
}
function breakClock() {
var fiveMinutes = 60 * .05;
breakTimer(fiveMinutes, display);
}
$(".startClock").on("click", function() {
startClock();
});
Here's my codepen as well: http://codepen.io/cenjennifer/pen/pjzBVy?editors=101
Your code is fine. jfriend00 is right, this code does belong on the code review page.
But since I'm here, I will give some feedback. Make an object (using function(){}), and put all of your functions inside of the object.
Instead of recreating all your variables in each function, make them properties inside of the object, so that they are accessible to all of the functions, and so that you don't need to keep recreating them. (Variables like timer, hour, minutes, should be moved as object properties).
Also, don't use global variables, they can interfere with libraries you may find to be useful later on. You should namespace, so that the code is more organized, and does not get overwritten by other globals.
The easy way to reuse the function, is to share the timer returned by setInterval and provide a callback in the startTimer function (used for both start and break). The callback, if provided, takes care of the code to run after the timer finishes. Therefore the specific code can be omitted from startTimer. Also since the timer is shared, no matter when started, the original loop can be stopped when called again (the button is clicked again), so that too can be omitted from the startTimer function, thus making it ready for reusability. The whole would look something like:
var currentcountdown;
var display = document.querySelector('#time');
function startTimer(duration, callback) {
var timer = parseInt(duration), minutes, seconds;
clearInterval(currentcountdown);
currentcountdown = setInterval(function () {
minutes = Math.floor(timer / 60);
seconds = Math.floor(timer % 60);
//minutes = minutes < 10 ? "0" + minutes : minutes;
seconds = seconds < 10 ? "0" + seconds : seconds;
display.textContent = minutes + ":" + seconds;
if (--timer < 0) {
clearInterval(currentcountdown);
if(callback)
callback();
}
}, 500);
}
function startClock() {
$("body").css("background-color", "black");
$("#title").text('Productive Countdown');
var twentyfiveMinutes = 60 * .25;
startTimer(twentyfiveMinutes, breakClock);
}
function breakClock() {
$("body").css("background-color", "#E13F86");
$("#title").text('Breaktime');
var fiveMinutes = 60 * .05;
startTimer(fiveMinutes);
}
$(".startClock").on("click", function() {
startClock();
});
As mentioned in the other post, synthetic sugar would be to put all values into objects (such as duration/background/title) and optionally put the timer and its variables (display/timer) into an object, but for straight forward re-usability of the function the above should provide a good start.
I have a fairly complex page with lots of ajax calls and subsequent dom manipulation. On one particular call it sets an interval with a time limit(essentially a timer). I have set up clearInterval() everywhere and even in the function but in very particular use cases(it is complex and I can't determine the exact cause and steps to reproduce the defect) .
$(function() {
window.timer_interval;
// ...
})
function timer()
{
var current = 0;
time_limit = 60;
window.timer_interval = setInterval(function() {
minute = ( "0" + Math.round(Math.floor((time_limit - current)/60))).slice(-2);
seconds = ("0" + ((time_limit - current)%60)).slice(-2);
$('#timer').html(minute + ":" + seconds);
if (current >= time_limit) {
clearInterval(window.timer_interval);
window.timer_interval = false;
}
current = current + 1;
}, 1000);
}
I have used firbug to detect the value for window.timer_interval , it is false and even the condition is satisfied.One thing might be that that a couple of image transfers fail
(this is possible application behaviour with code written to gracefully degrade). I am developing in Mozilla.
My guess is that you're setting the interval, and then setting the interval again without clearing it first, so that whatever was set previous will run forever.
If I am right adding a check to clear the interval before setInterval will correct the problem. I've created a function to the code below that will take place when you call setInterval.
// starts an interval function, making sure to cancel one that is previously running
function startSharedInterval(func) {
if (window.timer_interval) {
clearInterval(window.intervalID);
window.timer_interval = 0;
}
window.timer_interval = setInterval(func, 1000);
};
// ... in timer()
startSharedInterval(function () {
minute = ( "0" + Math.round(Math.floor((time_limit - current)/60))).slice(-2) ;
// ... rest of code
});
If you only have one timer, then you can avoid using global scope and take advantage of using closures so that the timer is always cleared.
In the code below, interval_id is created in the parent timer() function. This will be available to the inner anonymous function to clear when its execution after 60 is completed. You may have multiple instances running simultaneously this way.
function timer() {
var current = 0;
var time_limit = 60;
var interval_id = setInterval(function () {
minute = ("0" + Math.round(Math.floor((time_limit - current) / 60))).slice(-2);
seconds = ("0" + ((time_limit - current) % 60)).slice(-2);
$('#timer').html(minute + ":" + seconds);
if (current >= time_limit) {
clearInterval(interval_id);
}
current = current + 1;
}, 1000);
}