Jump to content

count down a specific period to zero time


Go to solution Solved by jodunno,

Recommended Posts

i have this timer:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Countdown</title>
    <script type="text/javascript">
        var hours;
        var mins
        var secs;
        function cd() {
            // below count down for 2 hours and 10 mins and 10 seconds
            // Or you could provide a string such as => [var time = "10:10:10";] 
            // And construct a function to fetch values from correct parts

            hours =  2;
            mins =  10;
            secs =  10;
	    progr_ess=130;
	    //document.getElementById("progressBar").setAttribute('max','130');
            redo();
        }
        

        function dis(hours, mins, secs) {
            var disp;

            if (hours <= 9) {
                disp = " 0";
            } else {
                disp = " ";
            }
            disp += hours + ":";

            if (mins <= 9) {
                disp += " 0";
            } else {
                disp += " ";
            }
            disp += mins + ":";
            if (secs <= 9) {
                disp += "0" + secs;
            } else {
                disp += secs;
            }
            return (disp);
        }
        function redo() {
            secs--;
            if (secs == -1) {
                secs = 59;
                mins--;
		document.getElementById("progressBar").value = 130-progr_ess ;
                progr_ess -= 1;
            }

            if (mins == -1) {
                mins = 59;
                hours--;
            }

            document.getElementById("txt").value = dis(hours, mins, secs);
            if ((mins == 0) && (secs == 0) && (hours == 0)) {
                window.alert("Time is up. Press OK to continue.");
                //  window.open("module.aspx", "_parent ")
            } else {
                cd = setTimeout("redo()", 1000);
            }
	    	
        }

        function init() {
            cd();
        }
        window.onload = init;
    </script>

    <style>
        #txt {
            border: none;
            font-family: verdana;
            font-size: 16pt;
            font-weight: bold;
            border-right-color: #FFFFFF
        }
    </style>
</head>
<body>
    <form id="form1" >
        <div>
            <div>
                <input id="txt" type="text" value="00:00:00" name="disp" />
            </div>
	    <progress value="0" max="130"  id="progressBar"></progress>
        </div>
    </form>
</body>
</html>

how can i make sure it does not go back to start time duration on page refresh?

how can i accustom it to recieve the count down duration using php variable?

1 hour ago, shadd said:

how can i make sure it does not go back to start time duration on page refresh?

Store the completion time instead of the duration. Count down until the end time is reached.

 

1 hour ago, shadd said:

how can i accustom it to recieve the count down duration using php variable?

My usual method is to store a variable in a hidden input field in PHP  then access that field's value from javascript.

An alternative to using HTML markup for the value would be to put it directly into the Javascript code.

const END_TIMESTAMP_MS = <?= $whatever_end_time ?> * 1000;

You need to consider the same sorts of things you would with putting values into HTML, in that you should make sure the value is safe - safe for Javascript, that is.
(But since I'm assuming $whatever_end_time is a number, it's naturally safe without needing any escaping.)

And tip: don't literally count down to the time, as in do things like "seconds--". Because you won't be able to get to-the-second accuracy with Javascript, and it will drift as it runs: for example, you'll find you did "seconds--" 60 times but it's actually been 61 seconds, and now the timer is off by a second.
It may sound weird, but instead of counting down, recalculate how much time is left on every "tick". As in

function update() {
  const remaining = END_TIMESTAMP_MS - Date.now();
  if (remaining > 0) {
    // calculate hours/minutes/seconds and display
  } else {
    // count down complete
  }
}

The drift will still happen, and you'll notice that occasionally the timer will skip a second because of it, but (a) some drift is unavoidable and (b) it's probably more important that you provide an accurate timer than you provide a "smooth" count down.

On 9/15/2024 at 10:52 PM, Barand said:

Store the completion time instead of the duration. Count down until the end time is reached.

 

My usual method is to store a variable in a hidden input field in PHP  then access that field's value from javascript.

an example of this will be great thanks

1 hour ago, maxxd said:

You've gotten quite a bit of good advice here - what have you looked up or tried after reading it?

i have tried this by putting the end time

<!DOCTYPE HTML>
<html>
<body>

<p id="demo"></p>
<!--button onclick="countdownTimeStart()">Start Timer</button-->

<script>
// Set the date we're counting down to
function strToMins(t) {
  var s = t.split(":");
  return Number(s[0]) * 60 + Number(s[1]);
}
function countdownTimeStart(){
        let currentTime = new Date().getTime();
         let countDownTime = new Date(currentTime + 2 * 60 * 60 * 1000);

//var countDownTime = strToMins(" 06:45:00");

// Update the count down every 1 second
var x = setInterval(function() {

    // Get todays date and time
    var now = new Date().getTime();
    
    // Find the distance between now an the count down date
    var distance = countDownTime - now;
    
    // Time calculations for days, hours, minutes and seconds
    var hours = Math.floor((distance % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
    var minutes = Math.floor((distance % (1000 * 60 * 60)) / (1000 * 60));
    var seconds = Math.floor((distance % (1000 * 60)) / 1000);
    
    // Output the result in an element with id="demo"
    document.getElementById("demo").innerHTML = hours + "h "
    + minutes + "m " + seconds + "s ";
    
    // If the count down is over, write some text 
    if (distance < 0) {
        clearInterval(x);
        document.getElementById("demo").innerHTML = "EXPIRED";
    }
}, 1000);
}
window.onload = function () {
    //var timeLeft = 3600*1,
     //   display = document.querySelector('#time');
    countdownTimeStart()
};
</script>

</body>
</html>

but  still i get the page refreshing the timer to start

Timeout! How do you intend to prevent server-side regeneration? id est, where do you retrieve that hidden input timestamp from?

one must create persistent/long-term storage such as a database entry or a one-time usage text file entry. The server side storage is most important because any timestamp generating code will create a new timestamp per GET request (here, a synonym for refresh), thus ! solving your problem.

ip addresses can be changed and cookies can be deleted (edited or spoofed for that matter).

UPDATE auctions SET timer = :generated_timestamp WHERE user_id = :userid
execute(array('generated_timestamp' => $ttl, ':userid' => $userid));

example where $ttl = (int) 180; for three minutes.
* example does not implement db or text file storage and retrieval.
 

<?php
$ttl = (int) 180; $ttl += time();
echo $ttl;
?>
<!DOCTYPE HTML>
<html>
<body>

<p id="demo">0h 3m 00s</p>
<!--button onclick="countdownTimeStart()">Start Timer</button-->

<script>
function countdownTimeStart(){
  var x = setInterval(function() {
  let currentTime = new Date().getTime();
  let countDownTime = new Date(<?php echo $ttl; ?>*1000).getTime();
  let timeElapsed = countDownTime - currentTime;
   
    // Time calculations for days, hours, minutes and seconds
    var hours = Math.floor((timeElapsed % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
    var minutes = Math.floor((timeElapsed % (1000 * 60 * 60)) / (1000 * 60));
    var seconds = Math.floor((timeElapsed % (1000 * 60)) / 1000);
    
    // Output the result in an element with id="demo"
    document.getElementById("demo").innerHTML = hours + "h "
    + minutes + "m " + seconds + "s ";
    
    // If the count down is over, write some text 
    if (timeElapsed < 0) {
        clearInterval(x);
        document.getElementById("demo").innerHTML = "EXPIRED";
    }
}, 1000);
}
window.onload = function () {
    countdownTimeStart()
};
</script>

</body>
</html>

plus what Barand and Requinix mentioned. Otherwise, Barand or Requinix posted your solution.

Best wishes.

1 hour ago, jodunno said:

Timeout! How do you intend to prevent server-side regeneration? id est, where do you retrieve that hidden input timestamp from?

one must create persistent/long-term storage such as a database entry or a one-time usage text file entry. The server side storage is most important because any timestamp generating code will create a new timestamp per GET request (here, a synonym for refresh), thus ! solving your problem.

ip addresses can be changed and cookies can be deleted (edited or spoofed for that matter).

UPDATE auctions SET timer = :generated_timestamp WHERE user_id = :userid
execute(array('generated_timestamp' => $ttl, ':userid' => $userid));

example where $ttl = (int) 180; for three minutes.
* example does not implement db or text file storage and retrieval.
 

<?php
$ttl = (int) 180; $ttl += time();
echo $ttl;
?>
<!DOCTYPE HTML>
<html>
<body>

<p id="demo">0h 3m 00s</p>
<!--button onclick="countdownTimeStart()">Start Timer</button-->

<script>
function countdownTimeStart(){
  var x = setInterval(function() {
  let currentTime = new Date().getTime();
  let countDownTime = new Date(<?php echo $ttl; ?>*1000).getTime();
  let timeElapsed = countDownTime - currentTime;
   
    // Time calculations for days, hours, minutes and seconds
    var hours = Math.floor((timeElapsed % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
    var minutes = Math.floor((timeElapsed % (1000 * 60 * 60)) / (1000 * 60));
    var seconds = Math.floor((timeElapsed % (1000 * 60)) / 1000);
    
    // Output the result in an element with id="demo"
    document.getElementById("demo").innerHTML = hours + "h "
    + minutes + "m " + seconds + "s ";
    
    // If the count down is over, write some text 
    if (timeElapsed < 0) {
        clearInterval(x);
        document.getElementById("demo").innerHTML = "EXPIRED";
    }
}, 1000);
}
window.onload = function () {
    countdownTimeStart()
};
</script>

</body>
</html>

plus what Barand and Requinix mentioned. Otherwise, Barand or Requinix posted your solution.

Best wishes.

180 is 3hours and not 3minutes. And after hard coding the 180 in, the timer does not count down it simply displays for aroun 3 sec and shows expired

Edited by shadd
clarity

Unix timestamps utilize seconds. 60s * 3 = 180s
three hours = 10800s. hello?

https://www.php.net/manual/en/function.time.php
"time(): int
Returns the current time measured in the number of seconds since the Unix Epoch (January 1 1970 00:00:00 GMT). "

you should start your research with unix timestamps.

https://www.unixtimestamp.com/
https://unixtime.org/
https://developer.mozilla.org/en-US/docs/Glossary/Unix_time

I wonder, "why did i write a script with corrected JavaScript code when shadd ignores it?"
your code is problematic. use the modified code and throw it in xampp.

24 minutes ago, jodunno said:

Unix timestamps utilize seconds. 60s * 3 = 180s
three hours = 10800s. hello?

https://www.php.net/manual/en/function.time.php
"time(): int
Returns the current time measured in the number of seconds since the Unix Epoch (January 1 1970 00:00:00 GMT). "

you should start your research with unix timestamps.

https://www.unixtimestamp.com/
https://unixtime.org/
https://developer.mozilla.org/en-US/docs/Glossary/Unix_time

I wonder, "why did i write a script with corrected JavaScript code when shadd ignores it?"
your code is problematic. use the modified code and throw it in xampp.

thanks for the job butit still resets the timer to 3 seconds on page refresh which is not required.it is supposed to count down continuously

  • Solution
3 minutes ago, shadd said:

butit still resets the timer to 3 seconds on page refresh

 

2 hours ago, jodunno said:

Timeout! How do you intend to prevent server-side regeneration? id est, where do you retrieve that hidden input timestamp from?

one must create persistent/long-term storage such as a database entry or a one-time usage text file entry. The server side storage is most important because any timestamp generating code will create a new timestamp per GET request (here, a synonym for refresh), thus ! solving your problem.

so you have some code to write...

jodunno is correct - you need some sort of persistence to make this work. The web is an inherently stateless medium, which means that by default any work a visitor does on a page (start a timer, set a variable, write a book, etc) is gone as soon as they navigate away from or refresh the page - nothing on that page remembers what was done on it before the refresh. I don't see any php in either of your code samples so I assume you'd rather stay in javascript. Look at sessions (https://developer.mozilla.org/en-US/docs/Web/API/Window/sessionStorage) because it's gonna be the easiest way to do what you want. You'll save the expiration time to a session variable when the timer is started, and on every page load check to see if that session variable is set. If it is, check to see if it's expired - if it's set but not expired, don't re-initialize the countdown. If it's not set, initialize the countdown. If it's set but expired, tell the user that.

Dear shadd, i sense that you are making this a publicly accessible script. Thus, i will agree that allowing anyone, bot, scraper, alien, dog or cat to run db code is a bad idea. if your script is in fact available to the public, then what else could we do?

hmm. waiting for a lightbulb. still dark... still dark... wait, i see a flash... aha!

maybe we can use a folder with a timestamp to illustrate persistence. You could make timestamps an event id. so i made a folder with a timestamp and added some cheap php code to show you how it works. You must think about what it is that you are trying to accomplish and attack it from every point-of-view. Eventually, you will come up with something that works.  example folder name: 1726649294, which is a UNIX timestamp.

<?php
/* $ttl = (int) 7200; $ttl += time();
   a formula for naming your folder. 7200 seconds = two hours
   the current name, 1726649294, is based upon the time that i created this example.
   1726649294 may be expired when you test the code.
   so change the name of the folder to your current time using the aforementioned formula.
*/
echo 'event id: ' . basename(__DIR__) . '<br>';
?>

<!DOCTYPE HTML>
<html>
<body>

<p id="demo"></p>
<!--button onclick="countdownTimeStart()">Start Timer</button-->

<script>
// Set the date we're counting down to

function countdownTimeStart(){
  var x = setInterval(function() {
  let currentTime = new Date().getTime();
  let countDownTime = new Date(<?php echo basename(__DIR__); ?>*1000);
  let timeElapsed = countDownTime - currentTime;
   
    // Time calculations for days, hours, minutes and seconds
    var hours = Math.floor((timeElapsed % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
    var minutes = Math.floor((timeElapsed % (1000 * 60 * 60)) / (1000 * 60));
    var seconds = Math.floor((timeElapsed % (1000 * 60)) / 1000);
    
    // Output the result in an element with id="demo"
    document.getElementById("demo").innerHTML = hours + "h "
    + minutes + "m " + seconds + "s ";
    
    // If the count down is over, write some text 
    if (timeElapsed < 0) {
        clearInterval(x);
        document.getElementById("demo").innerHTML = "EXPIRED";
    }
}, 1000);
}
window.onload = function () {
    countdownTimeStart()
};
</script>

</body>
</html>

otherwise, if your script is only available to logged in users, then follow the advice provided by maxxd and use the session storage.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.