Creating a Countdown
Sooner or later, you'll want to put a countdown on your pages that tells the user how many days or hours until a particular event. Script 13.8 (HTML) and Script 13.9 (JavaScript) lets one of the authors know his responsibilities, in no uncertain terms, as you can see in Figure 13.6. 
Script 13.8. The HTML for the countdown script.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
     <title>Dynamic Countdown</title>
     <script language="Javascript" type="text/ javascript" src="script06.js">
     </script>
</head>
<body bgcolor="#FFFFFF">
     <p>Dori says:</p>
     <p>It's only <span class="daysTill" id="bday"> </span> days until my birthday and 
 <span class="daysTill" id="xmas"> </span> days until Christmas, so you'd better start 
 shopping now!</p>
     <p>And it's only <span class="daysTill" id="anniv"> </span> days until our 
 anniversary...</p>
</body>
</html>
 
 |   
Script 13.9. This script counts down the number of days Tom stays out of the doghouse.
window.onload = showDays;
function showDays() {
     var allTags = document.getElementsByTagName("*");
     for (var i=0;i<allTags.length; i++) {
        if (allTags[i].className.indexOf("daysTill") > -1) {
           allTags[i].innerHTML = showTheDaysTill(allTags[i].id);
        }
     }
     function showTheDaysTill(thisDate) {
        var theDays;
        switch(thisDate) {
           case "anniv":
              theDays = daysTill(5,6);
              break;
           case "bday":
              theDays = daysTill(8,7);
              break;
           case "xmas":
              theDays = daysTill(12,25);
              break;
           default:
        }
        return theDays + " ";
     }
     function daysTill(mm,dd) {
        var now = new Date();
        var inDate = new Date(now.getFullYear(),mm-1,dd);
        if (inDate.getTime() < now.getTime()) {
           inDate.setYear(now.getFullYear()+1);
        }
        return (Math.ceil(dayToDays(inDate) - dayToDays(now)));
     }
     function dayToDays(inTime) {
        return (inTime.getTime() / (1000 * 60 * 60 * 24));
     }
}
 
 |   
 
 
To create a countdown: 
1.   | 
var allTags = document. getElementsByTagName("*");
Create a new  allTags array, and fill it with every tag on the page.
   |  2.   | 
for (var i=0;i<allTags.length; i++) {
  if (allTags[i].className. indexOf("daysTill") > -1) {
    allTags[i].innerHTML = showTheDaysTill(allTags[i].id);
  }
This loop scans through  allTags to see if the string  daysTill is found in the  class attribute of any tags on the page. Remember that a tag could have multiple  class attributes (i.e.,  class="firstClass daysTill somethingElse fourthThing"). 
If we found  daysTill, we call the  showTheDaysTill() function, which is passed one parameter: that tag's id (which stores what date to put up on the page). That function returns a value that is then put into  innerHTML.
   |   |  |  3.   | 
switch(thisDate) {
  case "anniv":
     theDays = daysTill(5,6);
     break;
  case "bday":
     theDays = daysTill(8,7);
     break;
  case "xmas":
     theDays = daysTill(12,25);
     break;
     default:
If you don't remember the  switch/case multi-level conditionals, you can review the discussion in  Chapter 3. Here, we are using the value of  thisDate to test against the three  case statements. For the  anniv case, we're setting  theDays to May 6 (5,6 is the numerical representation, much like you would write it in the real world); for  bday, we're setting it to August 7; and for  xmas,  theDays gets set to December 25.
   |  4.   | 
The  showTheDays() function ends by returning the number of days followed by a space. This is to work around a problem in IE: it eats the spaces in the HTML. If the script doesn't return a space at the end, the number runs into the word "days". If you just stuck the word "days" into this function, then there'd need to be a space after that, and so on.
   |  5.   | 
function daysTill(mm,dd) {
  var now = new Date();
  var inDate = new Date (now.getFullYear(),mm-1,dd);
This step shows the  daysTill() function, which receives the dates from the  case statements in step 3. Then, we create the  now and  inDate variables. The latter variable is filled with the current year, but with the month (with 1 subtracted from it to get it right; see the "More Weird Time Stuff" sidebar) and the day that were passed in.
   |   |  |  6.   | 
if (inDate.getTime() <> now.getTime()) {
  inDate.setYear (now.getFullYear()+1);
}
 
We then check that date against today. If that date in this year has already passed, we increment the year, going for next year's instead.
   |  7.   | 
return (Math.ceil(dayToDays(inDate) - dayToDays(now)));
 
Here, we're calculating the number of days between  inDate and the current date. The  Math.ceil() method makes sure that our result is a whole number.
   |  8.   | 
function dayToDays(inTime) {
  return (inTime.getTime() / (1000 * 60 * 60 * 24));
JavaScript stores dates in milliseconds since January 1, 1970. In order to compare two dates, change this to be the number of days since January 1, 1970. First, get the number of milliseconds in a day by multiplying 1000 (the number of milliseconds in a second) by 60 (number of seconds in a minute), by 60 again (number of minutes in an hour), and then by 24 (number of hours in a day). Dividing the number of milliseconds returned by  getTime() by this number gives the number of days since January 1, 1970.
   |   
| 
 Month numbering in JavaScript begins with 0 and day numbering with 1, and JavaScript deals inconsistently with years prior to 1970, depending on the version of JavaScript your browser is using. 
Navigator 2 (using JavaScript 1.0) couldn't deal with years before 1970 at all and had a Year 2000 Problem, as it returned the wrong answer for dates in or after 2000. Navigator 3 (which used JavaScript 1.1) supposedly changed the value returned by the getYear() method to be two digits if the year is in the 1900s and four digits if the year was before 1900 or after 2000. However, this is not true for all versions of Netscape; for example, Netscape Navigator 4 for Mac returns 100 for the year 2000. And to make things even worse, this still occurs in Firefoxthe current version (1.5) still returns numbers in the hundreds (versus in the 2000s) for getYear(). 
JavaScript 1.2 (in Navigator 4, and also in ECMAScript-compatible browsers such as Internet Explorer 4 and later) introduced a new method, getFullYear(), which always returns four-digit years. We recommend that you use getFullYear() any time you know that you'll only be working with version 4 and later browsers, so that's what we're using throughout this book. 
The getTime() method in JavaScript, for reasons probably best left unexplored, returns a number that is the number of milliseconds since January 1, 1970. Luckily, we hardly ever have to look at that number, as there have been a whopping number of milliseconds in the past three decades. 
 |  
  
  |