
    // $Id: countdowntimer.module,v 1.8.2.22.2.4.2.11 2008/04/06 22:05:26 jvandervort Exp $
    if (Drupal.jsEnabled) {
      $(document).ready(countdown_auto_attach);
    }

    var formats = ['<em>(%dow% %moy%%day%)</em><br>%days% days + %hours%:%mins%:%secs%','%days% days, %hours% hours, %mins% mins %secs% secs', '%days% shopping days left', '<em>(%dow% %moy%%day%)</em><br>%days% days + %hours%:%mins%:%secs%'];

    function jstimer(timer_element) {
      /* defaults */
      var d = {dir:"down",format_num:0, format_txt:"", timer_complete:new String('<em>Timer Completed</em>'), highlight:new String('style="color:red"').split(/=/), threshold:new Number('5')};
      /* jstimer.properties */
      this.element = timer_element;
      this.d = d;
      /* jstimer.methods */
      this.parse_microformat = parse_microformat;
      this.update_timer = update_timer;

      /* bootstrap, parse microformat, load object */
      this.parse_microformat();

      if ( d.format_txt != "" ) {
          this.outformat = d.format_txt;
      } else {
        this.outformat = formats[d.format_num];
      }

      // replace the static stuff in the format string
      // this only needs to be done once, so here is a good spot.
      this.outformat = this.outformat.replace(/%day%/,   this.to_date.getDate());
      this.outformat = this.outformat.replace(/%month%/, this.to_date.getMonth() + 1);
      this.outformat = this.outformat.replace(/%year%/,  this.to_date.getFullYear());
      this.outformat = this.outformat.replace(/%moy%/,   this.to_date.get_moy());
      this.outformat = this.outformat.replace(/%dow%/,   this.to_date.get_dow());
    }

    function parse_microformat() {
      var strdate = $(this.element).children("span[@class=datetime]").html();
      var str_current_server_time = $(this.element).children("span[@class=current_server_time]").html();

      if ( String(strdate) != 'null' ) {
        var date = new Date();
        date.set_iso8601_date(strdate);
        this.to_date = date;

        if ( String(str_current_server_time) != 'null' ) {
          // this is a feedback time from the server to correct for small server-client time differences.
          // not used for normal block and node timers.
          var date_server = new Date();
          date_server.set_iso8601_date(str_current_server_time);
          var date_client = new Date();
          var adj = date_client.getTime() - date_server.getTime();
          // adjust target date to clients domain
          this.to_date.setTime(this.to_date.getTime() + adj); 
        }

        this.d.dir = $(this.element).children("span[@class=dir]").html() || this.d.dir;
        this.d.format_num = $(this.element).children("span[@class=format_num]").html() || this.d.format_num;
        this.d.format_txt = $(this.element).children("span[@class=format_txt]").html() || "";
        if ( String(this.d.format_txt).match("'") ) {
          this.d.format_txt = "<span style=\"color:red;\">Format may not contain single quotes(').</span>";
        }
        this.d.threshold = $(this.element).children("span[@class=threshold]").html() || this.d.threshold;
        this.d.timer_complete = $(this.element).children("span[@class=complete]").html() || this.d.timer_complete;
        this.d.tc_redir = $(this.element).children("span[@class=tc_redir]").html() || '';
        this.d.tc_msg = $(this.element).children("span[@class=tc_msg]").html() || '';
        
      } else {
        this.parse_microformat_success = 0;
        return 0;
      }
      this.parse_microformat_success = 1;
      return 1;
    }

    // update_timer: returns false if the timer is done.
    function update_timer() {
      var now_date = new Date();
      var diff_secs;
      if ( this.d.dir == "down" ) {
        diff_secs = Math.floor((this.to_date.getTime() - now_date.getTime()) / 1000);
      } else {
        diff_secs = Math.floor((now_date.getTime() - this.to_date.getTime()) / 1000);
      }

      if ( this.d.dir == "down" && diff_secs < 0 ) {
        /* timer complete */
        $(this.element).html(this.d.timer_complete.valueOf());
        
        if ( this.d.tc_msg != '' && diff_secs > -3 ) {
          alert(this.d.tc_msg);
          if ( this.d.tc_redir != '' ) {
            window.location = this.d.tc_redir;
          }
        } else if ( this.d.tc_redir != '' && diff_secs > -3) {
          window.location = this.d.tc_redir;
        }
        
        return false;
      } else {
        /* timer still counting */
        var years = Math.floor(diff_secs / 60 / 60 / 24 / 365.25);
        var days = Math.floor(diff_secs / 60 / 60 / 24);
        var ydays = Math.ceil(days - (years * 365.25));
        var hours = Math.floor(diff_secs / 60 / 60) - (days * 24);
        var minutes = Math.floor(diff_secs / 60) - (hours * 60) - (days * 24 * 60);
        var seconds = diff_secs - (minutes * 60) - (hours * 60 * 60) - (days * 24 * 60 * 60);

        var outhtml = new String(this.outformat);
        outhtml = outhtml.replace(/%years%/,years);
        outhtml = outhtml.replace(/%ydays%/,ydays);
        outhtml = outhtml.replace(/%days%/,days);
        outhtml = outhtml.replace(/%hours%/,LZ(hours));
        outhtml = outhtml.replace(/%mins%/,LZ(minutes));
        outhtml = outhtml.replace(/%secs%/,LZ(seconds));

        if ( days == 1 ) {
          outhtml = outhtml.replace(/days/,'day'); //kludge, find a better way
        }
        if ( years == 1 ) {
          outhtml = outhtml.replace(/years/,'year'); //kludge, find a better way
        }

        if ( this.d.dir == "down" && (diff_secs <= (this.d.threshold * 60)) ) {
          $(this.element).html('<span ' + this.d.highlight[0] + '=' + this.d.highlight[1] + '>' +  outhtml + '</span>');
        } else {
          $(this.element).html(outhtml);
        }

        return true;
      }
    }


    var running = 0;
    var timer_stack = new Array();
    function countdown_auto_attach() {
      $(".countdowntimer").each(
        function(i) {  // arg i is the position in the each fieldset
          var t = new jstimer(this,1);
          if ( t.parse_microformat_success == 1 ) {
            timer_stack[timer_stack.length] = t;
          }
          if ( running == 0 ) {
            running = 1;
            timer_loop();
          }
        }
      );
    }
    function timer_loop() {
      for (var i = timer_stack.length - 1; i >= 0; i--) {
        if ( timer_stack[i].update_timer() == false ) {
          timer_stack.splice(i, 1);
        }
      }
      setTimeout('timer_loop()',999);
    }
    function LZ(x) {
      return (x >= 10 || x < 0 ? "" : "0") + x;
    }

    Date.prototype.set_iso8601_date = function (string) {
      var iso8601_re = /^(?:(\d{4})(?:-(\d{2})(?:-(\d{2}))?)?)?(?:T(\d{2}):(\d{2})(?::(\d{2})(.\d+)?)?((?:[+-](\d{2}):(\d{2}))|Z)?)?$/;
      var date_bits = iso8601_re.exec(string);
      var date_obj = null;
      if ( date_bits ) {
        date_bits.shift();
        date_bits[1] && date_bits[1]--; // normalize month
        date_bits[6] && (date_bits[6] *= 1000); // convert mils
        date_obj = new Date(date_bits[0]||1970, date_bits[1]||0, date_bits[2]||0, date_bits[3]||0, date_bits[4]||0, date_bits[5]||0, date_bits[6]||0);
        //timezone handling
        var zone_offset = 0;  // in minutes
        var zone_plus_minus = date_bits[7] && date_bits[7].charAt(0);
        // get offset from isostring time to Z time
        if ( zone_plus_minus != 'Z' ) {
          zone_offset = ((date_bits[8] || 0) * 60) + (Number(date_bits[9]) || 0);
          if ( zone_plus_minus != '-' ) {
            zone_offset *= -1;
          }
        }
        // convert offset to localtime offset, will include daylight savings
        if ( zone_plus_minus ) {
          zone_offset -= date_obj.getTimezoneOffset();
        }
        if ( zone_offset ) {
          date_obj.setTime(date_obj.getTime() + zone_offset * 60000);
        }
      }
      // set this object to current localtime representation
      this.setTime(date_obj.getTime());
    }
    Date.prototype.get_moy = function () {
      var myMonths=new Array("Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec");
      return myMonths[this.getMonth()];
    }
    Date.prototype.get_dow = function () {
      var myDays=["Sun","Mon","Tue","Wed","Thu","Fri","Sat","Sun"];
      return myDays[this.getDay()];
    }

