I want to preface this by saying I have very little knowledge of JS as you'll probably be able to tell, I also wasn't sure what to title this.
Anyway, I'm trying to make a simple script where it counts up to 30 minutes and then at 30 minutes returns a message by using a while loop. However, I want the condition where heliTime =! endTime to only run every minute. I can get the script to run every minute however in runs the entire function each minute instead of just one check.
setInterval(function arran() {
var startTime = 0;
var minutes = 1000 * 60;
//var seconds = 1000;
var heliTime = startTime
var endTime = 30 * minutes;
var messageCount = 0;
while (heliTime !== endTime) {
var messageCount = messageCount + 1;
console.log("No heli yet! " + messageCount);
var heliTime = heliTime + minutes;
}
return console.log("Heli should be arriving soon!");
},60 * 1000);
The messageCount variable is just debug so that can be ignored, any help with my problem would be greatly appreciated. :)
I would say that measuring real time by the frequence of callbacks by setInterval as Tobbe Widner suggest seems to me as a strange idea. I think it is better to use some explicit time source such as
function runDelayedWithProgress(waitIntervalSeconds, delayedAction, progressIntervalSeconds, progressAction) {
var startTime = new Date().getTime();
var iid = setInterval(function() {
var curTime = new Date().getTime()
var elapsedSeconds = (curTime - startTime)/1000;
if(elapsedSeconds >= waitIntervalSeconds) {
clearInterval(iid);
delayedAction();
}
else {
progressAction(Math.round(elapsedSeconds));
}
}, progressIntervalSeconds*1000);
}
runDelayedWithProgress(30*60, function() {
console.log("Heli should be arriving soon!")
},
60, function(elapsed){
console.log("No heli yet! " + elapsed);
});
Related
I have a web page where I entered a countdown code and it works well. However, I can only call it 1 time with the id in html.
Second or third time, it no longer works. How can I always use it? I would need it 3 or 4 times on the page. Thank you.
This is the code:
var counter = null;
window.onload = function() {
initCounter();
};
function initCounter() {
// get count from localStorage, or set to initial value of 1000
count = getLocalStorage('count') || 1000;
counter = setInterval(timer, 1000); //1000 will run it every 1 second
}
function setLocalStorage(key, val) {
if (window.localStorage) {
window.localStorage.setItem(key, val);
}
return val;
}
function getLocalStorage(key) {
return window.localStorage ? window.localStorage.getItem(key) : '';
}
function timer() {
count = setLocalStorage('count', count - 1);
if (count == -1) {
clearInterval(counter);
return;
}
var seconds = count % 60;
var minutes = Math.floor(count / 60);
var hours = Math.floor(minutes / 60);
minutes %= 60;
hours %= 60;
document.getElementById("timer").innerHTML = hours + " ore " + minutes + " min " + seconds + " sec"; // watch for spelling
}
You need to encapsulate the functionality in a way that can be called many times. It usually helps to think about the question "As a programmer, how I'd like to use this?"
Usually, it's a single function that takes some parameters and does something and/or returns something.
As an example... wouldn't it be nice if we had a function startMyTimer(...) that takes a timerId, and an element and sets up a timer that will update that element? We already have the signature:
function startMyTimer(timerId, element) { ... }
And now you can build everything inside this function. JS allows declaring functions within functions, which helps with encapsulation, so copying from your code it would look like:
function startMyTimer(timerId, element) {
var count = getLocalStorage(timerId) || 1000;
var counter = setInterval(timer, 1000); //1000 will run it every 1 second
function timer() {
count = setLocalStorage(timerId, count - 1);
if (count == -1) {
clearInterval(counter);
return;
}
var seconds = count % 60;
var minutes = Math.floor(count / 60);
var hours = Math.floor(minutes / 60);
minutes %= 60;
hours %= 60;
element.innerHTML = hours + " ore " + minutes + " min " + seconds + " sec"; // watch for spelling
}
}
Note that now count and counter are both private to the scope of startMyTimer, so only within this function (and any function inside this one, such as function timer()) will see these variables.
So if you want to do exactly what you did, you'd use this function as
window.onload = function() {
startMyTimer('count', document.getElementById("timer"));
};
Again, this is just an example of a posible solution - Maybe you could pass in the element id instead of the element, or a timer duration, etc., and the best solution is the one that fits best your needs.
I am trying to build an accurate countdown timer that shows mins and seconds left. I have tried 2 approaches. Approach 1 uses the setTimer function and calculates the drift. For that approach, some values get skipped and some values get repeated. Approach 2 yields all of the necessary values, but the values are not getting printed to the screen at even intervals (tested in repl.it). How can I make a timer that is both accurate and prints all of the values ?
Approach1:
function countTime(duration) {
var expected = 1;
var secsLeft;
var startT = new Date().getTime();
var oneSecond = 1000;
var expected = startT + oneSecond;
window.setTimeout(step, oneSecond);
function step() {
var nowT = new Date().getTime();
var drift = nowT - expected;
if (drift > oneSecond) {
console.log("drift is over 1 second long!");
}
console.log('drift is ' + drift);
var msDelta = nowT - startT;
var secsLeft = duration - Math.floor(msDelta / 1000);
console.log("secsLeft" + secsLeft);
if (secsLeft === 0) {
++count;
console.log("cleared");
} else {
expected += oneSecond;
setTimeout(step, Math.max(0, oneSecond - drift));
}
}
}
countTime(60);
Approach2:
function countTime(duration) {
var expected = 1;
var secsLeft;
var inter;
var startT = new Date().getTime();
inter = setInterval(function() {
//change in seconds
var sChange = Math.floor((new Date().getTime() - startT) / 1000);
if (sChange === expected) {
expected++;
secsLeft = duration - sChange;
console.log("seconds Left" + secsLeft);
}
if (secsLeft === 0) {
window.clearInterval(inter);
console.log("cleared");
}
}, 100);
}
countTime(60);
Consider using requestAnimationFrame.
function countTime(duration) {
requestAnimationFrame(function(starttime) {
var last = null;
function frame(delta) {
var timeleft = Math.floor(duration - (delta - starttime)/1000),
minutes = Math.floor(timeleft/60),
seconds = timeleft%60;
if( timeleft > 0) {
if( last != timeleft) {
console.log("Time left: "+minutes+"m "+seconds+"s");
last = timeleft;
}
requestAnimationFrame(frame);
}
}
frame(starttime);
});
}
countTime(60);
This will be precise to within the framerate of the browser itself :)
function(){
date = get the date
curSeconds = compute the number of seconds to be displayed
if(oldSeconds!=curSeconds) then refresh display and do oldSeconds = curSeconds;
}
Call this function quite often, the more you call it, the more accurate your timer will be. I advise you to use requestAnimationFrame() instead of setTimout() it will be called 60 times per second (period 16ms) since it is the refresh rate of most displays, it is the maximum visible "accuracy". Also it won't be called when page is not visible.
Simple, clean, no drift over long periods of time.
It also handle not being called for a while.
I found a JSFiddle with a timer that counts up every second.
Except i want this to work with just the minutes and seconds. No hours.
Any ideas?
DATE_OBJ.getSeconds() to get seconds of Date object.
DATE_OBJ. getMinutes() to get minutes of Date object.
setInterval to invoke handler function after every second(1000ms).
var handler = function() {
var date = new Date();
var sec = date.getSeconds();
var min = date.getMinutes();
document.getElementById("time").textContent = (min < 10 ? "0" + min : min) + ":" + (sec < 10 ? "0" + sec : sec);
};
setInterval(handler, 1000);
handler();
<h1 id="time" style="text-align: center"></h1>
Here's a very hackish approach - http://jsfiddle.net/gPrwW/1/
HTML -
<div id="worked">31:14</div>
JS :
$(document).ready(function (e) {
var $worked = $("#worked");
function update() {
var myTime = $worked.html();
var ss = myTime.split(":");
var dt = new Date();
dt.setHours(0);
dt.setMinutes(ss[0]);
dt.setSeconds(ss[1]);
var dt2 = new Date(dt.valueOf() + 1000);
var temp = dt2.toTimeString().split(" ");
var ts = temp[0].split(":");
$worked.html(ts[1]+":"+ts[2]);
setTimeout(update, 1000);
}
setTimeout(update, 1000);
});
The precise way of handling this is the following:
store the time of the start of the script
in a function that gets called repeatedly get the time elapsed
convert the elapsed time in whatever format you want and show it
Sample code:
var initialTime = Date.now();
function checkTime(){
var timeDifference = Date.now() - initialTime;
var formatted = convertTime(timeDifference);
document.getElementById('time').innerHTML = '' + formatted;
}
function convertTime(miliseconds) {
var totalSeconds = Math.floor(miliseconds/1000);
var minutes = Math.floor(totalSeconds/60);
var seconds = totalSeconds - minutes * 60;
return minutes + ':' + seconds;
}
window.setInterval(checkTime, 100);
You can easily change the granularity of checking the time (currently set at 0.1 seconds). This timer has the advantage that it will never be out of sync when it updates.
You can make a function that increments a counter every time it's called, shows the value as:
counter/60 minutes, counter%60 seconds
Then you can use the setInterval function to make JavaScript call your code every second. It's not extremely precise, but it's good enough for simple timers.
var initialTime = Date.now();
function checkTime(){
var timeDifference = Date.now() - initialTime;
var formatted = convertTime(timeDifference);
document.getElementById('time').innerHTML = '' + formatted;
}
function convertTime(miliseconds) {
var totalSeconds = Math.floor(miliseconds/1000);
var minutes = Math.floor(totalSeconds/60);
var seconds = totalSeconds - minutes * 60;
return minutes + ':' + seconds;
}
window.setInterval(checkTime, 100);
This might be something?
plain count up timer in javascript
It is based on the setInterval method
setInterval(setTime, 1000);
So lets say we have 4 Divs (3 hidden, 1 visible), the user is able to toggle between them through javascript/jQuery.
I want to calculate time spent on each Div, and send an xhr containing that time to server to store it in the database. This xhr will be sent when the user toggle the div view.
How can I do that? Any hints will be greatly appreciated.
Thanks,
At any point, you can record a a start/lap time in a variable with:
var start = new Date();
When you want to calculate the elapsed time, simply subtract the stored date from a new Date instance:
var elapsed = new Date() - start;
This will give you the elapsed time in milliseconds. Do additional math (division) to calculate seconds, minutes, etc.
Here you go:
HTML:
<div id="divs">
<div>First</div>
<div class="selected">Second</div>
<div>Third</div>
<div>Fourth</div>
</div>
<p id="output"></p>
JavaScript:
var divs = $('#divs > div'),
output = $('#output'),
tarr = [0, 0, 0, 0],
delay = 100;
divs.click(function() {
$(this).addClass('selected').siblings().removeClass('selected');
});
setInterval(function() {
var idx = divs.filter('.selected').index();
tarr[idx] = tarr[idx] + delay;
output.text('Times (in ms): ' + tarr);
}, delay);
Live demo: http://jsfiddle.net/7svZr/2/
I keep the times in milliseconds because integers are cleaner and safer (0.1 + 0.2 != 0.3). Note that you can adjust the "precision" (the delay of the interval function) by setting the delay variable.
Here is a reusable class, example is included in code:
/*
Help track time lapse - tells you the time difference between each "check()" and since the "start()"
*/
var TimeCapture = function () {
var start = new Date().getTime();
var last = start;
var now = start;
this.start = function () {
start = new Date().getTime();
};
this.check = function (message) {
now = (new Date().getTime());
console.log(message, 'START:', now - start, 'LAST:', now - last);
last = now;
};
};
//Example:
var time = new TimeCapture();
//begin tracking time
time.start();
//...do stuff
time.check('say something here')//look at your console for output
//..do more stuff
time.check('say something else')//look at your console for output
//..do more stuff
time.check('say something else one more time')//look at your console for output
I use a really easy function to provide time elapsed in this format: hh/mm/ss
onclick/onfocus/etc..
var start_time = new Date();
on leaving:
var end_time = new Date();
var elapsed_ms = end_time - start_time;
var seconds = Math.round(elapsed_ms / 1000);
var minutes = Math.round(seconds / 60);
var hours = Math.round(minutes / 60);
var sec = TrimSecondsMinutes(seconds);
var min = TrimSecondsMinutes(minutes);
function TrimSecondsMinutes(elapsed) {
if (elapsed >= 60)
return TrimSecondsMinutes(elapsed - 60);
return elapsed;
}
Javascript console internally has a function called "console.time() and console.timeEnd() to do the same. Simple you can use them
console.time("List API");
setTimeout(()=> {
console.timeEnd("List API");
},5000);
More details can be found here
https://developer.mozilla.org/en-US/docs/Web/API/Console/time
I created an ES6 class based on #Shawn Dotey's answer.
The check() method does not log a message, but returns the elapsed time.
The method start() is not needed in his example (the constructor already "starts" it). So I replaced it by reset() which makes more sense.
export default class TimeCapture
{
constructor()
{
this.reset();
}
reset()
{
this.startTime = new Date().getTime();
this.lastTime = this.startTime;
this.nowTime = this.startTime;
}
check()
{
this.nowTime = new Date().getTime();
const elapsed = this.nowTime - this.lastTime;
this.lastTime = this.nowTime;
return elapsed;
}
}
Use it in your project like this:
import TimeCapture from './time-capture';
const timeCapture = new TimeCapture();
setTimeout(function() {
console.log( timeCapture.check() + " ms have elapsed" ); //~100 ms have elapsed
timeCapture.reset();
setTimeout(function() {
console.log( timeCapture.check() + " ms have elapsed" ); //~200 ms have elapsed
}, 200);
}, 100);
On a download page, I would like to have it so that when the page loads, a 10 second timer automatically starts. On the page, I would like some text to say something like "You can begin your download in 10 seconds..." Then, after the time is up a download button appears for people to click on and start their download.
How can I do this, and what code do I use to include it into a page?
See: http://jsfiddle.net/rATW7/
It's backwards-compatible and not so secure, but 10 seconds isn't much to worry about anyways.
You can use setInterval() to do this.
Note that make sure the countdownElement has an existing text node, which can be any whitespace. If you can't guarantee that, just use innerHTML or innerText/textContent.
window.onload = function() {
var countdownElement = document.getElementById('countdown'),
downloadButton = document.getElementById('download'),
seconds = 10,
second = 0,
interval;
downloadButton.style.display = 'none';
interval = setInterval(function() {
countdownElement.firstChild.data = 'You can start your download in ' + (seconds - second) + ' seconds';
if (second >= seconds) {
downloadButton.style.display = 'block';
clearInterval(interval);
}
second++;
}, 1000);
}
jsFiddle.
Noone could ensure that your intervals are exact, especially if tab (or browser) is inactive (see e.g. this post), so it's better to rely on time difference instead of counter:
var sTime = new Date().getTime();
var countDown = 30;
function UpdateTime() {
var cTime = new Date().getTime();
var diff = cTime - sTime;
var seconds = countDown - Math.floor(diff / 1000);
//show seconds
}
UpdateTime();
var counter = setInterval(UpdateTime, 500);
The working fiddle
A modification of the Fiddle provided by Yuriy which does NOT use JQuery, and works with hours as well if the # of seconds are large enough.
<div id="countdowntimertxt" class="countdowntimer">00:00:00</div>
<script type="text/javascript">
var sTime = new Date().getTime();
var countDown = 3700; // Number of seconds to count down from.
function UpdateCountDownTime() {
var cTime = new Date().getTime();
var diff = cTime - sTime;
var timeStr = '';
var seconds = countDown - Math.floor(diff / 1000);
if (seconds >= 0) {
var hours = Math.floor(seconds / 3600);
var minutes = Math.floor( (seconds-(hours*3600)) / 60);
seconds -= (hours*3600) + (minutes*60);
if( hours < 10 ){
timeStr = "0" + hours;
}else{
timeStr = hours;
}
if( minutes < 10 ){
timeStr = timeStr + ":0" + minutes;
}else{
timeStr = timeStr + ":" + minutes;
}
if( seconds < 10){
timeStr = timeStr + ":0" + seconds;
}else{
timeStr = timeStr + ":" + seconds;
}
document.getElementById("countdowntimertxt").innerHTML = timeStr;
}else{
document.getElementById("countdowntimertxt").style.display="none";
clearInterval(counter);
}
}
UpdateCountDownTime();
var counter = setInterval(UpdateCountDownTime, 500);
</script>
I was writing a reply with code, but alex's reply is better than my quick & dirty solution.
Take into account that if you want to do something like what Rapidshare and others do, you will have to generate the link at the server side and retrieve it with AJAX, otherwise the only thing whoever wants to get the download immediately needs to do is to see the source code of your page ;-)
This is very simple, yes you can make it very easily. Here's the live link, where you can find the codding for making countdown timer , before download link appears : http://www.makingdifferent.com/make-countdown-timer-download-button-link-appears/
Cheers !!
You can use setTimeout function of javascript :
// make the button not visible
setTimeout(()=>{
// here make button visible and clickable
},10000)
// here 10000 -> 10 seconds timeout