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.
Related
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>
I am working on specific mobile wireframe web page, where after loading of web content body for user starts timer and during this time user is about to answer question. There are two cases how the question can be answered. 1. User couldn´t answer in time and server will evaulate answer as failure. 2. User answered earlier than question time expired.
I need to prevent user to rerun script for counting seconds left. I refuse solution that after question page load frontend could communicate with database, no, communication with database is allowed for me only before and after question answering, because I want to avoid problems with lost connection during answering. Due to this, I have JS script for timing like follows:
iterator= 0;
secondsMax = 15;
elem = document.getElementById("secLeft");
elem.innerHTML = secondsMax ;
function timer() {
setTimeout(function(){
iterator++;
elem.innerHTML = secondsMax - iterator;
if(iterator == secondsMax ) {
// progress bar move... 1 question from 5
move();
iterator= 0;
//give signal to evaluate question ...
return;
}
timer();
}, 1000);
}
Resembling StackOverflow questions like this contain only answer to use ajax for not giving respond from server to reload page. But I need to programmatically prevent user to refresh on frontend to prevent cheating (but maybe ajax is good solution, but I maybe don´t understand it´s usage in this case). Do you have any idea, or solution how to do it? I am open for any criticism, well, if this solution is really bad(I am new in web technologies), please be free to advise me better one.
Thank you in advance for your time.
First of all, you must to make server-side validation to exclude cheating scenarios.
For example, any question asked has unique hash with start time linked, When you receive answer related to that hash, you can to compare time was spent...
On client-side, you can to store start time for that question in localstorage, and if page loaded finds a localstorage entry for current question hash - initialize timer with found start value.
const TIME_ALLOWED = 10e3; // 10 sec
const QUESTION_HASH = '1fc3a9903';
// start = localStorage.getItem(QUESTION_HASH) else
let start = Date.now();
let timeleft = document.getElementById('timeleft');
let timer = setInterval(() => {
let timepass = Date.now() - start;
if (timepass >= TIME_ALLOWED) {
clearInterval(timer);
timeleft.innerText = 'Time is over';
// localStorage.setItem(QUESTION_HASH, null)
return;
}
let secs = (TIME_ALLOWED-timepass) / 1000 | 0;
let mins = secs / 60 | 0;
secs = secs % 60;
if (secs < 10) secs = '0' + secs;
timeleft.innerText = `${mins}:${secs}`;
}, 500);
const answer = e => {
if (Date.now() - start >= TIME_ALLOWED) return; // disallow to answer
clearInterval(timer);
timeleft.innerText = 'Answer received';
// localStorage.setItem(QUESTION_HASH, null)
}
Time left: <span id="timeleft"></span><br/>
<button onclick="answer()">Answer</button>
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.
I am developing a website that has two back to back web broadcasts. I have used PHP to display the time that the buttons should be enabled and disabled. Now I need to use Javascript to automatically refresh the page before the first broadcast, before the second broadcast and after the second broadcast. I implemented the following script and it does refresh the page at the given time, however, it doesn't work exactly as I need it to. I need to alter the script so that it refreshes the page on Sundays at 7:45pm, 8pm and 8:30pm EST only.
I'm using a modified script from this answered question
function refreshAt(hours, minutes, seconds) {
var now = new Date();
var then = new Date();
if(now.getUTCHours() > hours ||
(now.getUTCHours() == hours && now.getUTCMinutes() > minutes) ||
now.getUTCHours() == hours && now.getUTCMinutes() == minutes && now.getUTCSeconds() >= seconds) {
then.setUTCDate(now.getUTCDate() + 1);
}
then.setUTCHours(hours);
then.setUTCMinutes(minutes);
then.setUTCSeconds(seconds);
var timeout = (then.getTime() - now.getTime());
setTimeout(function() { window.location.reload(true); }, timeout);
}
Then I call the refreshAt() function.
refreshAt(19,45,0); //Will refresh the page at 7:45pm
refreshAt(20,00,0); //Will refresh the page at 8:00pm
refreshAt(20,30,0); //Will refresh the page at 8:30pm
Where I get confused is how to alter this script to only implement the refresh for EST on Sundays.
I figured it out. Here's the script:
function refreshAt(hours, minutes, seconds, day) {
var now = new Date();
var then = new Date();
var dayUTC = new Date();
if(dayUTC.getUTCDay() == day) {
if(now.getUTCHours() > hours ||
(now.getUTCHours() == hours && now.getUTCMinutes() > minutes) ||
now.getUTCHours() == hours && now.getUTCMinutes() == minutes && now.getUTCSeconds() >= seconds) {
then.setUTCDate(now.getUTCDate() + 1);
}
then.setUTCHours(hours);
then.setUTCMinutes(minutes);
then.setUTCSeconds(seconds);
var timeout = (then.getTime() - now.getTime());
setTimeout(function() { window.location.reload(true); }, timeout);
}
}
And then I just call the refreshAt() function:
refreshAt(20,00,0,1); //Will refresh the page at 8:00pm on Monday UTC or 3:00pm EST
An alternative approach would be to use Pusher. This keeps an open connection to receiving events.
Include the Pusher javascript:
<script src="http://js.pusher.com/1.11/pusher.min.js"></script>
Bind to a pusher event of "refresh" with this code:
var pusher = new Pusher('abc123'); // Get a key when you sign up and replace this
var refreshChannel = pusher.subscribe('refreshing');
refreshChannel.bind('refresh', function(thing) {
location.reload(true);
});
Then at 8pm (or whenever you want) manually issue a pusher event on the Pusher control panel page, and all of the people currently viewing the page would be reloaded.
You can add the test even for the day of the week, for example :
now.getDay() == "Sunday"
function refreshAt(day, hours, minutes, seconds)
{
Date.getDay() = day
...
}
0 is Sunday, 6 is Saturday.
I had the same problem as you. I'm building a site that sounds a lot like yours, also using PHP to enable and disable page elements before and after the broadcast time. Your solution seemed promising, but ultimately I was dissatisfied using pure Javascript for the page reload. Javascript gets its time from the client's machine, whereas PHP gets it from the server, and even a small difference between the two could wreck the whole system. (i.e. the page could refresh 30 seconds before the PHP enabled the buttons, causing some viewers to assume the whole thing is down.)
I solved the problem by using PHP to tell the Javascript function what time it is, and it works like a charm. The only issue is that it runs every day, instead of just on one day of the week, but that doesn't bother me- users will have no reason to be viewing the page other than the broadcast day.
This is all you need- I put this right after the <body> tag:
<script type="text/javascript">
setTimeout(function() { window.location.reload(true); }, 1000*<?php
$then = mktime(15,00,0);
$tomorrow = mktime(15, 00, 0, date("m") , date("d")+1);
$now = time();
if ($now > $then) {echo $tomorrow - $now;}
else {echo $then - $now;}?>); </script>
Basically, I am designing a quiz application with limited time. Use selects answer to a question and the next question loads using an Ajax request. All questions must be answered within a time frame of, say 2 minutes.
A clock ticks away to show how much time is left and as soon as it hits 0, results are shown. Now since the timer will be implemented using window.setTimeout(), it is possible that the value of timer variable be modified using an external bookmarklet or something like that. Anyway I can prevent this? I think this is implemented on file sharing sites like megaupload. Any forgery on the timer variable results in request for file being rejected.
Have .setTimeout() call an AJAX method on your server to synch time. Don't rely on the client time. You could also store the start time on the server for a quiz, and then check the end time when the quiz is posted.
You need to add a validation in your server side. When the client want to load the next question using an Ajax request, check whether deadline arrived.
The timer in client side js just a presention layer.
If the function runs as a immediately called function expression, then there are no global variables and nothing for a local script to subvert. Of course there's nothing to stop a user from reading your code and formulating a spoof, but anything to do with javascript is open to such attacks.
As others have said, use the server to validate requests based on the clock, do not rely on it to guarantee anything. Here's a simple count down that works from a start time so attempts to dealy execution won't work. There are no global variables to reset or modify either.
e.g.
(function (){
// Place to write count down
var el = document.getElementById('secondsLeft');
var starttime,
timeout,
limit = 20; // Timelimit in seconds
// Function to run about every second
function nextTick() {
var d = new Date();
// Set start time the first time
if (!starttime) starttime = d.getTime();
var diff = d.getTime() - starttime;
// Only run for period
if (diff < (limit * 1000)) {
el.innerHTML = limit - (diff/1000 | 0);
} else {
// Time's up
el.innerHTML = 0;
clearTimeout(timeout);
}
}
// Kick it off
timeout = window.setInterval(nextTick, 1000);
}());