I have a code that needs to run a count-down timer, the counter needs to count down 15 min per user even if he\she leaves the page.
this is the cookie initialize line:
document.cookie = "name=timerCookie; timeLeft=" + initialTime + "; expires=" + expires;
and this is how I update the cookie:
document.cookie = "name=timerCookie; timeLeft=" + timeLeft + "; expires=" + expires;
when I try to read the cookie I get "name=timerCookie"
am I setting the cookie correctly?
can I use cookie this way?
EDIT****:
apparently, cookie can contain only 1 segment(aka timeLeft) by removing the name value the issue was solved.
Well, I came up with this solution while I was offline and before I learned what your use case actually is.
I was thinking it would be better to use localStorage since MDN says:
"Cookies were once used for general client-side storage. While this was
legitimate when they were the only way to store data on the client, it
is recommended nowadays to prefer modern storage APIs."
Since your server needs to know about the user's "time remaining", you probably want cookies after all (unless you can just have the browser update the server at unload time), but maybe you can adapt this idea to your purpose.
I was also thinking that "even if he/she leaves the page" meant that the timer should keep ticking while they're away -- but this part should be relatively easy to fix.
I'm including this as HTML (to copy/paste) because SO snippets are sandboxed and won't run code that uses localStorage.
<!DOCTYPE html><html><head></head><body>
<p id="display">__:__</p>
<script>
let expires = localStorage.getItem("expires"); // Gets the stored expiration time
const display = document.querySelector("#display"); // Identifies our HTML element
// Makes a helper function to treat dates as accumulated seconds
const getSecondsSinceEpoch = ((date) => Math.floor(date.getTime()/1000));
// Sets the expiration time if countdown is not already running
if(!expires){
expires = getSecondsSinceEpoch(new Date()) + (60 * 15); // 15 minutes from now
localStorage.setItem("expires", expires);
}
// Calculates how long until expiration
let pageLoadedAt = getSecondsSinceEpoch(new Date());
let secondsRemaining = parseInt(expires) - pageLoadedAt;
// Starts the countdown (which repeats once per second)
setInterval(countdown, 1000);
function countdown(){
// When time expires, stops counting and clears storage for the user's next visit
if(secondsRemaining === 0){
clearInterval();
localStorage.clear(); // You don't want this here -- it resets the clock
}
else{
// Until time expires, updates the display with reduced time each second
display.textContent = formatTime(--secondsRemaining);
}
}
function formatTime(time){
let mins = Math.floor(time/60).toString();
let secs = Math.floor(time%60).toString();
secs = secs.length == 2 ? secs : "0" + secs; // Ensures two-digit seconds
return `${mins}:${secs}`
}
</script>
</body></html>
Related
I have an app that requires countdown timer. Due date comes from my back-end with rest api. I need to coundown remaining time in my react native app. But I can't use smart phone's time. Because user can be in different timezone / country etc. How i can use server's due date response for react native?
Should I send also remaining time in seconds to user? So I can countdown that remaining time every second?
https://www.example.com/getDueDate [POST]
returns:
Y-m-d H:i:s (future) time like 2021-05-20 23:40:40
If I use classic countdown approach for javascript, I need to use smart phone's time. But I don't want to use that.
NTP server approach can be tricky for react-native side. It just simple counter.
Why not send both the server's current time and the due date? Then start your timer from there?
That being said, the time will still be off by the roundtrip time between your user and the server (which will depend on their internet connection and your server's response time).
Yes, it is possible to get time. I'm also using rest api (token base authentication and expiry token after certain time). I'm checking as given below
var l_currentDateTimeSeconds;
l_currentDateTimeSeconds=((new Date().getTime() - "your_time_from_api") / 1000);
if (parseInt(l_CurrentDateTimeSeconds) < parseInt(your_time_from_api))
{
//failure case ;
}
else
{
//Success case;
}
output of time (in variable) will be in seconds. Visit given below link, it may be help
https://aboutreact.com/react-native-get-current-date-time/
This is the technique i use and it's really effective.
Step 1.
Send due date from server (5pm)
Send current time from server (4pm)
Step 2.
Check clients current time (3pm)
Subtract currentTime(server) - currentTime(client) and call it timeOffset
Step 3.
setInterval to run every second using the code example below.
//import useState, useEffect from react-native
const [timer,setTimer]=useState();
var serverExpiryDate="'the time the event will expire gotten from server";
var currentTimeAtServer="the time you got from server via api";
var currentTimeAtDevice=new Date().getTime();
const timeOffset= currentTimeAtServer - currentTimeAtDevice;
//timeOffset is the time difference between the user's clock and the server clock. Calculated when user received response from server.
useEffect(() => {
let interval = setInterval(() => {
setTimer(() => {
let endT = new Date(serverExpiryDate).getTime(); //time from server;
let nowT = new Date().getTime(); //current time on user've device
nowT = nowT + timeOffset; //VERY IMPORTANT, helps to sync user's time with server.
let remaining = endT >= nowT ? Math.floor((endT - nowT) / 1000) : 0;
let stopCheck = remaining === 0 ? clearInterval(interval) : null;
return remaining;
});
}, 1000); //each count lasts for a second
return () => {
clearInterval(interval);
};
}, []);
console.log(timer) //this will be decreasing every second
I'm writing a countdown timer using javascript in a php-mysql project, the countdown timer works correctly, but the problem is that when the user interacts with the game, the timer restarts. Should I do something with php sessions?
Any ideas?
<div>Time left = <span id="timer"></span></div>
<script>
document.getElementById('timer').innerHTML = 01 + ":" + 00;
startTimer();
function startTimer() {
var presentTime = document.getElementById('timer').innerHTML;
var timeArray = presentTime.split(/[:]+/);
var m = timeArray[0];
var s = checkSecond((timeArray[1] - 1));
if(s==59){m=m-1}
if(m<0){alert('You lose,click reset')}
document.getElementById('timer').innerHTML =m + ":" + s;
setTimeout(startTimer, 1000);
}
function checkSecond(sec) {
if (sec < 10 && sec >= 0) {sec = "0" + sec}; // add zero in front
of numbers < 10
if (sec < 0) {sec = "59"};
return sec;
}
</script>
Based on your comments to the main question, there are ways you can "jury rig" this, but I'm not entirely sure its the perfect solution for you.
When the user first initiates the game and you redirect them with a php action, I'm guessing this starts the initial timer, and subsequent interactions with the game also resets the timer also.
You could initiate a php session and save the start time of the game into a php session variable. Then when the page loads again, check for the existence of the session/variable, if it is set, then us it to do whatever you need it to as the difference between the current time and the start time of the game will tell you how long the game has been going for.
You can pass variables from php to JS with:
let js_start_time_variable = "<?=php_start_time_variable?>";
This solution is not pretty. I would recommend using something like vuejs to keep the entire game in a single page application without using page refreshes to php.
I want to realize timer using performance.now because Date.now depends on users clock (performance.now doesn't), and "Date.now-way" may crash the timer, when user changes system clock.
And I want to store timer in localStorage. When user close tab or browser and open it, timer have to resume.
Important condition: I want to take into account the time, when the browser/tab was closed. For example, user close browser, when timer value is 10 sec. After 10 sec user open the browser - timer value should be 20 sec.
This is the problem, that I faced.
This is code without using localStorage:
const timerNode = document.getElementById('timer');
const initialTimestamp = performance.now();
setInterval(() => {
const seconds = getSeconds(initialTimestamp);
timerNode.innerHTML = seconds;
}, 200);
function getSeconds(initialTimestamp) {
return Math.round((performance.now() - initialTimestamp) / 1000);
}
<div id='timer'></div>
Is there any way to store timer in localStorage using performance.now and resume it in cases, that I mentioned above (and observing the condition)?
Or maybe there is another way to get UNIX timestamp, that is not depends on system clock?
To demonstrate problem with Date.now() run this code and change system time, for example, set date to few days ago. You will see, that value of the timer is negative.
const timerNode = document.getElementById('timer');
const initialTimestamp = Date.now();
setInterval(() => {
const seconds = getSeconds(initialTimestamp);
timerNode.innerHTML = seconds;
}, 200);
function getSeconds(initialTimestamp) {
return Math.round((Date.now() - initialTimestamp) / 1000);
}
<div id='timer'></div>
Yes, you would use localStorage for this to persist across browser sessions.
You would use setItem to set the initial time and getItem to access it in new browser sessions. When the new browser session starts, you would check if a previous initial time existed. If it did, use it; if it didn't, create it.
var initialTimestamp = localStorage.getItem('initialTimestamp');
// If we previously set an initialTimestamp, convert it from string to number.
if (initialTimestamp) {
initialTimestamp = parseInt(initialTimestamp);
}
// If we never previously set an initial timestamp, create one now.
else {
initialTimestamp = performance.now();
localStorage.setItem('initialTimestamp', initialTimestamp);
}
This is the code for countdown I am using . If the user reloads the page the countdown starts again .
I want the countdown to keep on running after the first time user has visited that page irrespective whether he closes the page or not . Please suggest a method . I think creating sessions might help but I have no idea about sessions .
<span id="countdown" class="timer"></span>
<script>
var seconds =120;
function secondPassed() {
var minutes = Math.round((seconds - 30)/60);
var remainingSeconds = seconds % 60;
if (remainingSeconds < 10) {
remainingSeconds = "0" + remainingSeconds;
}
document.getElementById('countdown').innerHTML = minutes + ":" + remainingSeconds;
if (seconds == 0) {
clearInterval(countdownTimer);
document.getElementById('bonus').innerHTML = "Buzz Buzz";
} else {
seconds--;
}
}
var countdownTimer = setInterval('secondPassed()', 1000);
</script>
The question is not entirely complete. You want a counter for "forever" or for "a while after he accessed page first time".
For the first one, you need to count on the server side (you can for example create a db - or a file, or whatever you are comfortable with for saving things), and somehow identify the user, and get the first time he accessed. Then send back this info each time user logs, and count on client side in js, just like you do.
For the second one, you can either send a cookie with the timestamp he accessed first time, either save this info in session and use it each time user access the page.
onClick="javascript:document.cookie='n=1'"
Im new in javascript
I have a btn click will set cookie, how can I set expire time 1 hour on this cookie?
When you write the cookie to the browser, you need to specify an expiration date or a max age. However, note that max-age is ignored by Interent Explorer 8 and below. So if you're expecting to get usage from that browser, you can just rely on expires.
Example:
<script type="text/javascript">
function setMyCookie() {
var now = new Date();
var expires = new Date(now.setTime(now.getTime() + 60 * 60 * 1000)); //Expire in one hour
document.cookie = 'n=1;path=/;expires='+expires.toGMTString()+';';
}
</script>
And your button can call this function like so:
<input type="button" onclick="setMyCookie();">Set Cookie</input>
Note that I've also included the path to indicate that this cookie is site-wide.
You can read more about expiring cookies with the date or max-age here:
http://mrcoles.com/blog/cookies-max-age-vs-expires/
You can do:
onClick="setupCookie();"
function setupCookie() {
document.cookie = "n=1";
setTimeout(function() {
document.cookie = "n=0";
}, 3600000); // 1 hour
}
On click you can call some javascript function and while creating cookie itself you can set expire time please refer this
javascript set cookie with expire time