views:

80

answers:

2

I'm working on a countdown timer for my website, but can't get the script to work. The creator of the script, PHP F1, hasn't been able to help with it.

Question is: Why is the year in the target date ($targetDate) variable not making it through to the HTML/JavaScript implement?

I'm using the mktime() function. No matter whether I put the actual date into the last attribute position (for the year) or whether I put in the date function (like how I've done it in the code below) I just can't get it to display correctly on the front end.

I'm not a PHP/JavaScript guru by any means, so this may seem like a really noobie problem, but if anyone can help me with this it'd be greatly appreciated!

Here is a live implementation of the code below: http://tripdealio.com/countdown/countdown5.php

Here is the code:

<?php
/* Define your target date here
    $targetYear  = 2011;
    $targetMonth = 09;
    $targetDay   = 30;
    $targetHour  = 23;
    $targetMinute= 59;
    $targetSecond= 59;
End target date definition */ 

// Define date format
$dateFormat = "Y-m-d H:i:s";

$targetDate = mktime(23,59,59,09,30,date("Y"));
$actualDate = time();

$secondsDiff = $targetDate - $actualDate;

$remainingDay     = floor($secondsDiff/60/60/24);
$remainingHour    = floor(($secondsDiff-($remainingDay*60*60*24))/60/60);
$remainingMinutes = floor(($secondsDiff-($remainingDay*60*60*24)-($remainingHour*60*60))/60);
$remainingSeconds = floor(($secondsDiff-($remainingDay*60*60*24)-($remainingHour*60*60))-($remainingMinutes*60));

$targetDateDisplay = date($dateFormat,$targetDate);
$actualDateDisplay = date($dateFormat,$actualDate);

?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&gt;
<html xmlns="http://www.w3.org/1999/xhtml"&gt;
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Max's Countdown System</title>
<link href="style/style.css" rel="stylesheet" type="text/css" />
<script type="text/javascript">
  var days = <?php echo $remainingDay; ?>  
  var hours = <?php echo $remainingHour; ?>  
  var minutes = <?php echo $remainingMinutes; ?>  
  var seconds = <?php echo $remainingSeconds; ?>  

function setCountDown ()
{
  seconds--;
  if (seconds < 0){
      minutes--;
      seconds = 59
  }
  if (minutes < 0){
      hours--;
      minutes = 59
  }
  if (hours < 0){
      days--;
      hours = 23
  }
  document.getElementById("remain").innerHTML = days+" days, "+hours+" hours, "+minutes+" minutes, "+seconds+" seconds";
  setTimeout ( "setCountDown()", 1000 );
}

</script>
</head>

<body onload="setCountDown();">
<div id="container">
    <div id="header"><div id="header_left"></div>
    <div id="header_main">Max's Countdown System</div><div id="header_right"></div></div>
    <div id="content">
        <table class="countTable">
           <tr><td>Target date:</td><td><?php echo $targetDateDisplay; ?></td></tr>
           <tr><th colspan="2" id="remain"><?php echo "$remainingDay days, $remainingHour hours, $remainingMinutes minutes, $remainingSeconds seconds";?></th></tr>
           <tr><td>Actual date:</td><td><?php echo $actualDateDisplay; ?></td></tr>
       </table>
    </div>
    <div id="footer"><a href="http://www.phpf1.com" target="_blank">Powered by PHP F1</a></div>
</div>
</body>
</html>
+1  A: 

I don't see anything particularly wrong with the algorithm, there are only syntax errors (missing semicolons) in the JS code. This is the fixed code:

var days = <?php echo $remainingDay; ?>;
var hours = <?php echo $remainingHour; ?>;  
var minutes = <?php echo $remainingMinutes; ?>;  
var seconds = <?php echo $remainingSeconds; ?>;

function setCountDown ()
{
  seconds--;
  if (seconds < 0){
      minutes--;
      seconds = 59;
  }
  if (minutes < 0){
      hours--;
      minutes = 59;
  }
  if (hours < 0){
      days--;
      hours = 23;
  }
  document.getElementById("remain").innerHTML = days+" days, "+hours+" hours, "+minutes+" minutes, "+seconds+" seconds";
  setTimeout ( "setCountDown()", 1000 );
}

You could also use setInterval instead of setTimeout but that's just a cosmetic change.

dark_charlie
Don't use string values to `setTimeout` when not necessary; use function references instead (`setTimeout(setCountDown, 1000)`).
Marcel Korpel
or better setTimeout(function(){ ..}, 1000)
shox
@shox: What's the advantage of using an anonymous wrapper function?
Marcel Korpel
Nope, there's one (rather inconspicuous, but significant) error in his PHP code, see my answer.
Marcel Korpel
@Marcel Korpel: Very nice catch!
dark_charlie
+1  A: 

You're calculating the target time using

$targetDate = mktime(23,59,59,09,30,date("Y"));
    // be careful:            ↑

but numbers beginning with a 0 are treated as octal in PHP; moreover, to quote the documentation:

If an invalid digit is given in an octal integer (i.e. 8 or 9), the rest of the number is ignored.

So 09 will actually be parsed as 0 and, as example #3 of mktime shows

The last day of any given month can be expressed as the "0" day of the next month, not the -1 day.

So month 0 will cause the year number to decrement, at this moment to 2009.

As you'll guess by now, the solution is simple: drop the 0

$targetDate = mktime(23,59,59,9,30,2011);

(date("Y") will return 2010 at the moment, but according to your comment you want 2011).

BTW, I think you want to use setInterval instead of setTimeout; see setTimeout or setInterval?

Marcel Korpel