I am using this to have a timer in my app: https://gist.github.com/electricg/4372563.
Anyhow, I want to start my timer not from the beginning but from a variable value - "data". Data contains the number of milliseconds.
How do I go about it?
I have tried modifing x.startAt - which didn't give any error, but strange output.
You should change the lapTime property instead of startAt;
var lapTime = 10000; //milliseconds
Change this function
// Duration
this.time = function() {
return lapTime + (startAt ? now() - startAt : 100);
};
You have to change the initial value in this function.
Related
I am trying to create a Countup counter Starting from 1 to 10000 and i do not want it to reset when user refreshes the page or cancels the page. The Counter should start from 1 for every user that visits the page and keep running in background till it gets to 10000 even if the page is closed.
I have written the page below which;
Starts from the specified number for every new visitor
Saves the progress and does not reset when page is refreshed, however
It does not keep counting when page is closed and starts from the last progress when user closes the tab and comes back later. My code is
function countUp() {
var countEl = document.querySelector('.counter');
var countBar = document.querySelector('.progress-bar');
var x = parseInt(localStorage.getItem('lastCount')) - 1 || 1;
var y = countEl.dataset.to;
var z = countBar.dataset.to;
function addNum() {
countEl.innerHTML = x;
x += 1;
if (x > y && x > z) {
clearInterval(timer);
}
localStorage.setItem('lastCount', x);
}
var timer = window.setInterval(addNum, 1000);
localStorage.setItem("addNum", counter);
toggleBtn.addEventListener('click', function(){
countUp();
toggleBtn.classList.add('hidden');
});
}
countUp();</script>
<body onload=countUp();>
<div class="counter" data-from="0" data-to="10000000"></div>
<div class="progress-bar" data-from="0" data-to="10000000"></div>
</body>
It's difficult to show an example on StackOverflow because it doesn't let you fiddle with localStorage but, it sounds like you want something like:
When a user visits the page check localStorage for a timestamp.
If timestamp exists, go to step 4
Timestamp doesn't exist so get the current timestamp and stash it in localStorage.
Get the current timestamp. Subtract the timestamp from before. If over 10,000, stop, you're done.
Display difference calculated in step 4.
Start a 1 second timer, when time is up, go to step 4.
Something along those lines should work even if they refresh the page and since you are calculating from the original timestamp it will "count" in the background even if the page is closed.
window.addEventListener("DOMContentLoaded", () => {
const start = localStorage.getItem("timestamp") || Date.now();
localStorage.setItem("timestamp", start);
function tick() {
const now = Date.now();
const seconds = Math.floor((now - start) / 1000);
const display = document.getElementById("display");
if (seconds > 10000) return display.innerHTML = "We're done";
display.innerHTML = seconds;
setTimeout(tick, 1000);
}
tick();
});
<div id="display"></div>
So, client-side code can't normally execute when a client-side javascript page is closed.
What you could do, however, is calculate where the timer should be then next time it is loaded.
For example, in your addNum() function, you could in addition to the last count, also store the current date (and time).
function addNum() {
countEl.innerHTML = x;
x += 1;
if (x > y && x > z) {
clearInterval(timer);
}
localStorage.setItem('lastCount', x);
localStorage.setItem('lastDate', new Date());
}
Then, when your code starts, you can retrieve lastDate, and then subtract the current Date() from it.
Then use that to add the difference to your counter.
function countUp() {
let storedCount = parseInt(localStorage.getItem('lastCount'));
let storedDate = Date.parse(localStorage.getItem('lastDate'));
let now = new Date()
let diffSeconds = (now.getTime() - storedDate.getTime()) / 1000;
let storedCount += diffSeconds;
var countEl = document.querySelector('.counter');
var countBar = document.querySelector('.progress-bar');
var x = storedCount - 1 || 1;
var y = countEl.dataset.to;
var z = countBar.dataset.to;
}
I'm sure there are some more changes required to make it work with your code, but the idea is to store the current time so that when the page is closed and reopened, you can 'adjust' the count to catch up to what it should be.
What you want here is not possible just from the client-side code, there is no way for 2 different machines to share that information at all.
Here's the thing though, you can do this with a backend where the database gets updated every time a new IP hits the server. Note with this approach, a user here is one system and not different browsers or sessions.
To update this real-time for someone who is already on the website, run a timer and call an API that specifically gives you the count. Therefore the page gets updated frequently. You can also do this with react-query as it comes with inbuilt functions to do all this.
Working on a simple game, using delta time for the first time.
Delta time (dt) is created in this function:
function main() {
var now = Date.now();
var dt = (now - lastTime) / 1000.00;
update(dt);
render();
lastTime = now;
requestAnimationFrame(main);
};
gameTime (my second variable) is just created as a var.
var gameTime = 0;
The problem comes when I try to add dt to gameTime, here:
function update(dt){
gameTime += dt;
};
this returns NaN, whatever I seem to do to it. I can display gameTime, and add to it using ++, and I can display dt (0.017 usually), but as soon as I add one to the other, I get NaN.
How can I fix this?
Does your lastTime contain anything before running main() for the first time?
If not, then this code var dt = (now - lastTime) / 1000.00; can't work because lastTime is undefined
First of all, if you return you can see your result which is not NaN, basically you write it like this :
function update(dt)
{
return gameTime += dt;
};
Second of all,if you are not using this code in vanilla javascript and it's related to unity, try to initiate your variables. like how you defined var gameTime = 0;, check other variables and initiate them.
I had a task to make a progress bar and a process duration timer along with it. So, not thinking twice I did this:
<div class="mainInfo">
<div id="timer"><span id="elapsedText">0:00</span>/<span id="durationText">3:00</span></div>
<div id="progressBar"><div id="progress" style="width:0;"></div></div>
</div>
And the JS:
var time = 1000;
var duration = 180;
var $progress = $("#progress");
var $elapsedText = $("#elapsedText");
updateTime();
function updateTime() {
var elapsed = time / 1000;
$elapsedText.text(Math.floor(elapsed / 60) + ":" + Math.floor(elapsed % 60));
$progress.css('width', (elapsed * 100 / duration) + "%");
time = time + 1000;
setTimeout("updateTime()", 1000);
}
Time is actually retrieved from another variable - this ones for the demo (to illustrate that I actually have the value in miliseconds).
And it worked (not only on my PC), and still does, but the procmon shows a CPU spike on browser (chrome, ff) process when this cycle is running - 30-40% instead of regular 0,5%.
Is there a more efficient way to do this?
There is a standard function for that: SetInterval(function, delay_in_ms).
It calls a function in millisecond intervals.
Instead of
setTimeout("updateTime()", 1000);
use
setTimeout(updateTime, 1000);
The fact that you're invoking the compiler each second could really hurt performance. Passing a string to setTimeout is basically causing an eval within the setTimeout.
There is a default for that, and that is setInterval.
Be careful, the function passed as the first argument to setInterval is always executed in global scope.
Number two, a progress bar is usually created along-side expensive processes. You are using it for display purposes only and forcing a delay, which I don't particularly find useful, but if you like the layout, I guess you can go for it.
The way you would usually use it is:
executeFirstPotentiallyExpensiveProcess();// this is a call to a big function.
// then update the value of the progress bar in percentage style.
executeSecondPotentiallyExpensiveFunction()// this is the second part of your process.
// then again update..
// repeat until you have 100%.
// Basically, you logically divide the expenses of your various executions
// into numerable bits, preferably equal to one another for your convenience,
// but you chunk your loading process or whatever type of process and increment
// the progress after each chunk is complete.
Your use of jQuery disturbs me...
var time = 1000;
var duration = 180;
var $progress = document.getElementById("progress");
var $elapsedText = document.getElementById("elapsedText");
var beginTimestamp = new Date().getTime();
updateTime();
setInterval(updateTime,1000);
function updateTime() {
var now = new Date().getTime();
var elapsed = now-beginTimeStamp + time;
$elapsedText.firstChild.nodeValue = Math.floor(elapsed / 60) + ":" + Math.floor(elapsed % 60);
$progress.style.width = (elapsed * 100 / duration) + "%";
}
Maybe without jQuery your browser might run better ;)
Try with the function setInterval.
I'm trying to make a countdown timer in JS that will change the value of a field every one minute (in the begining there is 20, and then change it to 19,18,17 etc), but it's not working correctly. It's changing value not every 60sec but I have a feel that it works random (sometimes it change value first time after 15 sec, another time it's 53). Any idea what I'm doing wrong? Here is the code:
function getTimeNow(){
var Time = new Date;
return Time.getHours()*60*60+Time.getMinutes()*60 + Time.getSeconds();
}
var start = getTimeNow();
var start_point = start%60;
var target = start+60*20;
function TimeOut(){
if((getTimeNow()-start)%60 == start_point && target>getTimeNow()){
var temp = jQuery('.Timer').html();
temp-=1;
jQuery('.Timer').html(temp);
}
setTimeout(TimeOut,1000);
}
You cannot count on the exact moment a timer function will be called. You need to change your logic to something more resilient to time shifts...
setInterval(function(){count.innerText = count.innerText - 1;},
60*1000);
this is also a lot shorter...
$(function() {
var count = 20;
countdown = setInterval(function() {
$("p.countdown").html(count + "seconds remailing!");
if (count == 0) {
window.location = 'http://stackoverflow.com/';
}
count--;
}, 1000);
});
<p class="countdown">
Each time when i refresh the browser, the count down is beginning at 20. i want to when i refresh the browser. the count number not beginning at 20 each time. it begins from the actually time it beginning, how to do some changes to the code?
Probably the best method would be to store the current time in a cookie (or some other local storage), and check for it on page load. If it's present, use it. If it's not, start from 20.
To avoid the complexities of managing cross-browser storage, you could use amplify.store. Simply update the value with each iteration of your interval.
Setting values is pretty trivial:
amplify.store( 'countdown', count );
As is getting them at a later time:
amplify.store( 'countdown' );
Your code would look something like this:
$(function() {
// Pick up where we left off, or start from 20
var count = amplify.store('count') || 20;
countdown = setInterval(function() {
$("p.countdown").html(count + " seconds remailing!");
if (count <= 0) {
// Clear our stored value
amplify.store('count', null);
window.location = 'http://stackoverflow.com/';
}
// Update stored value
amplify.store('count', count--);
}, 1000);
});
Demo: http://jsfiddle.net/yWTR7/ ( Hit 'Run' after a few seconds )
first save time (max time) in php session variable or in datbase, and fire ajax query each 1 second or any interval you like that will decrease the php variable's value. When new page is loaded, load the php variables value in javascript...
alternative
You can use cookies to store timer values.
Here's one with localstorage:
$(function() {
var count = localStorage.getItem('count') || 20,
countdown = setInterval(function() {
localStorage.setItem('count', count);
$("p.countdown").html(count + " seconds remaining!");
if (count === 0) {
clearInterval(countdown);
localStorage.removeItem('count');
window.location = 'http://stackoverflow.com/';
}
count--;
}, 1000);
});
FIDDLE