Diff for /loncom/html/adm/countdown/jquery.countdown.js between versions 1.1 and 1.2

version 1.1, 2012/03/18 13:51:11 version 1.2, 2014/01/15 14:45:11
Line 1 Line 1
 /* http://keith-wood.name/countdown.html  /* http://keith-wood.name/countdown.html
    Countdown for jQuery v1.5.11.     Countdown for jQuery v1.6.3.
    Written by Keith Wood (kbwood{at}iinet.com.au) January 2008.     Written by Keith Wood (kbwood{at}iinet.com.au) January 2008.
    Dual licensed under the GPL (http://dev.jquery.com/browser/trunk/jquery/GPL-LICENSE.txt) and      Available under the MIT (https://github.com/jquery/jquery/blob/master/MIT-LICENSE.txt) license. 
    MIT (http://dev.jquery.com/browser/trunk/jquery/MIT-LICENSE.txt) licenses.   
    Please attribute the author if you use it. */     Please attribute the author if you use it. */
   
 /* Display a countdown timer.  /* Display a countdown timer.
Line 22  function Countdown() { Line 21  function Countdown() {
  labels1: ['Year', 'Month', 'Week', 'Day', 'Hour', 'Minute', 'Second'],   labels1: ['Year', 'Month', 'Week', 'Day', 'Hour', 'Minute', 'Second'],
  compactLabels: ['y', 'm', 'w', 'd'], // The compact texts for the counters   compactLabels: ['y', 'm', 'w', 'd'], // The compact texts for the counters
  whichLabels: null, // Function to determine which labels to use   whichLabels: null, // Function to determine which labels to use
    digits: ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'], // The digits to display
  timeSeparator: ':', // Separator for time periods   timeSeparator: ':', // Separator for time periods
  isRTL: false // True for right-to-left languages, false for left-to-right   isRTL: false // True for right-to-left languages, false for left-to-right
  };   };
Line 53  function Countdown() { Line 53  function Countdown() {
  };   };
  $.extend(this._defaults, this.regional['']);   $.extend(this._defaults, this.regional['']);
  this._serverSyncs = [];   this._serverSyncs = [];
    var now = (typeof Date.now == 'function' ? Date.now :
    function() { return new Date().getTime(); });
    var perfAvail = (window.performance && typeof window.performance.now == 'function');
  // Shared timer for all countdowns   // Shared timer for all countdowns
  function timerCallBack(timestamp) {   function timerCallBack(timestamp) {
  var drawStart = (timestamp || new Date().getTime());   var drawStart = (timestamp < 1e12 ? // New HTML5 high resolution timer
    (perfAvail ? (performance.now() + performance.timing.navigationStart) : now()) :
    // Integer milliseconds since unix epoch
    timestamp || now());
  if (drawStart - animationStartTime >= 1000) {   if (drawStart - animationStartTime >= 1000) {
  $.countdown._updateTargets();   plugin._updateTargets();
  animationStartTime = drawStart;   animationStartTime = drawStart;
  }   }
  requestAnimationFrame(timerCallBack);   requestAnimationFrame(timerCallBack);
  }   }
  var requestAnimationFrame = window.requestAnimationFrame || window.webkitRequestAnimationFrame ||   var requestAnimationFrame = window.requestAnimationFrame ||
  window.mozRequestAnimationFrame || window.oRequestAnimationFrame ||   window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame ||
  window.msRequestAnimationFrame || null; // this is when we expect a fall-back to setInterval as it's much more fluid   window.oRequestAnimationFrame || window.msRequestAnimationFrame || null;
    // This is when we expect a fall-back to setInterval as it's much more fluid
  var animationStartTime = 0;   var animationStartTime = 0;
  if (!requestAnimationFrame) {   if (!requestAnimationFrame || $.noRequestAnimationFrame) {
  setInterval(function() { $.countdown._updateTargets(); }, 980); // Fall back to good old setInterval   $.noRequestAnimationFrame = null;
    setInterval(function() { plugin._updateTargets(); }, 980); // Fall back to good old setInterval
  }   }
  else {   else {
  animationStartTime = window.mozAnimationStartTime || new Date().getTime();   animationStartTime = window.animationStartTime ||
    window.webkitAnimationStartTime || window.mozAnimationStartTime ||
    window.oAnimationStartTime || window.msAnimationStartTime || now();
  requestAnimationFrame(timerCallBack);   requestAnimationFrame(timerCallBack);
  }   }
 }  }
   
 var PROP_NAME = 'countdown';  
   
 var Y = 0; // Years  var Y = 0; // Years
 var O = 1; // Months  var O = 1; // Months
 var W = 2; // Weeks  var W = 2; // Weeks
Line 88  var S = 6; // Seconds Line 96  var S = 6; // Seconds
 $.extend(Countdown.prototype, {  $.extend(Countdown.prototype, {
  /* Class name added to elements to indicate already configured with countdown. */   /* Class name added to elements to indicate already configured with countdown. */
  markerClassName: 'hasCountdown',   markerClassName: 'hasCountdown',
    /* Name of the data property for instance settings. */
    propertyName: 'countdown',
   
    /* Class name for the right-to-left marker. */
    _rtlClass: 'countdown_rtl',
    /* Class name for the countdown section marker. */
    _sectionClass: 'countdown_section',
    /* Class name for the period amount marker. */
    _amountClass: 'countdown_amount',
    /* Class name for the countdown row marker. */
    _rowClass: 'countdown_row',
    /* Class name for the holding countdown marker. */
    _holdingClass: 'countdown_holding',
    /* Class name for the showing countdown marker. */
    _showClass: 'countdown_show',
    /* Class name for the description marker. */
    _descrClass: 'countdown_descr',
   
  /* List of currently active countdown targets. */   /* List of currently active countdown targets. */
  _timerTargets: [],   _timerTargets: [],
Line 96  $.extend(Countdown.prototype, { Line 121  $.extend(Countdown.prototype, {
    @param  options  (object) the new settings to use as defaults */     @param  options  (object) the new settings to use as defaults */
  setDefaults: function(options) {   setDefaults: function(options) {
  this._resetExtraLabels(this._defaults, options);   this._resetExtraLabels(this._defaults, options);
  extendRemove(this._defaults, options || {});   $.extend(this._defaults, options || {});
  },   },
   
  /* Convert a date/time to UTC.   /* Convert a date/time to UTC.
Line 141  $.extend(Countdown.prototype, { Line 166  $.extend(Countdown.prototype, {
  periods[3] * 86400 + periods[4] * 3600 + periods[5] * 60 + periods[6];   periods[3] * 86400 + periods[4] * 3600 + periods[5] * 60 + periods[6];
  },   },
   
  /* Retrieve one or more settings values.  
    @param  name  (string, optional) the name of the setting to retrieve  
                  or 'all' for all instance settings or omit for all default settings  
    @return  (any) the requested setting(s) */  
  _settingsCountdown: function(target, name) {  
  if (!name) {  
  return $.countdown._defaults;  
  }  
  var inst = $.data(target, PROP_NAME);  
  return (name == 'all' ? inst.options : inst.options[name]);  
  },  
   
  /* Attach the countdown widget to a div.   /* Attach the countdown widget to a div.
    @param  target   (element) the containing division     @param  target   (element) the containing division
    @param  options  (object) the initial settings for the countdown */     @param  options  (object) the initial settings for the countdown */
  _attachCountdown: function(target, options) {   _attachPlugin: function(target, options) {
  var $target = $(target);   target = $(target);
  if ($target.hasClass(this.markerClassName)) {   if (target.hasClass(this.markerClassName)) {
  return;   return;
  }   }
  $target.addClass(this.markerClassName);   var inst = {options: $.extend({}, this._defaults), _periods: [0, 0, 0, 0, 0, 0, 0]};
  var inst = {options: $.extend({}, options),   target.addClass(this.markerClassName).data(this.propertyName, inst);
  _periods: [0, 0, 0, 0, 0, 0, 0]};   this._optionPlugin(target, options);
  $.data(target, PROP_NAME, inst);  
  this._changeCountdown(target);  
  },   },
   
  /* Add a target to the list of active ones.   /* Add a target to the list of active ones.
Line 197  $.extend(Countdown.prototype, { Line 208  $.extend(Countdown.prototype, {
  }   }
  },   },
   
    /* Reconfigure the settings for a countdown div.
      @param  target   (element) the control to affect
      @param  options  (object) the new options for this instance or
                       (string) an individual property name
      @param  value    (any) the individual property value (omit if options
                       is an object or to retrieve the value of a setting)
      @return  (any) if retrieving a value */
    _optionPlugin: function(target, options, value) {
    target = $(target);
    var inst = target.data(this.propertyName);
    if (!options || (typeof options == 'string' && value == null)) { // Get option
    var name = options;
    options = (inst || {}).options;
    return (options && name ? options[name] : options);
    }
   
    if (!target.hasClass(this.markerClassName)) {
    return;
    }
    options = options || {};
    if (typeof options == 'string') {
    var name = options;
    options = {};
    options[name] = value;
    }
    if (options.layout) {
    options.layout = options.layout.replace(/&lt;/g, '<').replace(/&gt;/g, '>');
    }
    this._resetExtraLabels(inst.options, options);
    var timezoneChanged = (inst.options.timezone != options.timezone);
    $.extend(inst.options, options);
    this._adjustSettings(target, inst,
    options.until != null || options.since != null || timezoneChanged);
    var now = new Date();
    if ((inst._since && inst._since < now) || (inst._until && inst._until > now)) {
    this._addTarget(target[0]);
    }
    this._updateCountdown(target, inst);
    },
   
  /* Redisplay the countdown with an updated display.   /* Redisplay the countdown with an updated display.
    @param  target  (jQuery) the containing division     @param  target  (jQuery) the containing division
    @param  inst    (object) the current settings for this instance */     @param  inst    (object) the current settings for this instance */
  _updateCountdown: function(target, inst) {   _updateCountdown: function(target, inst) {
  var $target = $(target);   var $target = $(target);
  inst = inst || $.data(target, PROP_NAME);   inst = inst || $target.data(this.propertyName);
  if (!inst) {   if (!inst) {
  return;   return;
  }   }
  $target.html(this._generateHTML(inst));   $target.html(this._generateHTML(inst)).toggleClass(this._rtlClass, inst.options.isRTL);
  $target[(this._get(inst, 'isRTL') ? 'add' : 'remove') + 'Class']('countdown_rtl');   if ($.isFunction(inst.options.onTick)) {
  var onTick = this._get(inst, 'onTick');  
  if (onTick) {  
  var periods = inst._hold != 'lap' ? inst._periods :   var periods = inst._hold != 'lap' ? inst._periods :
  this._calculatePeriods(inst, inst._show, this._get(inst, 'significant'), new Date());   this._calculatePeriods(inst, inst._show, inst.options.significant, new Date());
  var tickInterval = this._get(inst, 'tickInterval');   if (inst.options.tickInterval == 1 ||
  if (tickInterval == 1 || this.periodsToSeconds(periods) % tickInterval == 0) {   this.periodsToSeconds(periods) % inst.options.tickInterval == 0) {
  onTick.apply(target, [periods]);   inst.options.onTick.apply(target, [periods]);
  }   }
  }   }
  var expired = inst._hold != 'pause' &&   var expired = inst._hold != 'pause' &&
Line 222  $.extend(Countdown.prototype, { Line 271  $.extend(Countdown.prototype, {
  inst._now.getTime() >= inst._until.getTime());   inst._now.getTime() >= inst._until.getTime());
  if (expired && !inst._expiring) {   if (expired && !inst._expiring) {
  inst._expiring = true;   inst._expiring = true;
  if (this._hasTarget(target) || this._get(inst, 'alwaysExpire')) {   if (this._hasTarget(target) || inst.options.alwaysExpire) {
  this._removeTarget(target);   this._removeTarget(target);
  var onExpiry = this._get(inst, 'onExpiry');   if ($.isFunction(inst.options.onExpiry)) {
  if (onExpiry) {   inst.options.onExpiry.apply(target, []);
  onExpiry.apply(target, []);   }
  }   if (inst.options.expiryText) {
  var expiryText = this._get(inst, 'expiryText');   var layout = inst.options.layout;
  if (expiryText) {   inst.options.layout = inst.options.expiryText;
  var layout = this._get(inst, 'layout');  
  inst.options.layout = expiryText;  
  this._updateCountdown(target, inst);   this._updateCountdown(target, inst);
  inst.options.layout = layout;   inst.options.layout = layout;
  }   }
  var expiryUrl = this._get(inst, 'expiryUrl');   if (inst.options.expiryUrl) {
  if (expiryUrl) {   window.location = inst.options.expiryUrl;
  window.location = expiryUrl;  
  }   }
  }   }
  inst._expiring = false;   inst._expiring = false;
Line 245  $.extend(Countdown.prototype, { Line 291  $.extend(Countdown.prototype, {
  else if (inst._hold == 'pause') {   else if (inst._hold == 'pause') {
  this._removeTarget(target);   this._removeTarget(target);
  }   }
  $.data(target, PROP_NAME, inst);   $target.data(this.propertyName, inst);
  },  
   
  /* Reconfigure the settings for a countdown div.  
    @param  target   (element) the containing division  
    @param  options  (object) the new settings for the countdown or  
                     (string) an individual property name  
    @param  value    (any) the individual property value  
                     (omit if options is an object) */  
  _changeCountdown: function(target, options, value) {  
  options = options || {};  
  if (typeof options == 'string') {  
  var name = options;  
  options = {};  
  options[name] = value;  
  }  
  var inst = $.data(target, PROP_NAME);  
  if (inst) {  
  this._resetExtraLabels(inst.options, options);  
  extendRemove(inst.options, options);  
  this._adjustSettings(target, inst);  
  $.data(target, PROP_NAME, inst);  
  var now = new Date();  
  if ((inst._since && inst._since < now) ||  
  (inst._until && inst._until > now)) {  
  this._addTarget(target);  
  }  
  this._updateCountdown(target, inst);  
  }  
  },   },
   
  /* Reset any extra labelsn and compactLabelsn entries if changing labels.   /* Reset any extra labelsn and compactLabelsn entries if changing labels.
Line 289  $.extend(Countdown.prototype, { Line 307  $.extend(Countdown.prototype, {
  }   }
  if (changingLabels) {   if (changingLabels) {
  for (var n in base) { // Remove custom numbered labels   for (var n in base) { // Remove custom numbered labels
  if (n.match(/[Ll]abels[0-9]/)) {   if (n.match(/[Ll]abels[02-9]|compactLabels1/)) {
  base[n] = null;   base[n] = null;
  }   }
  }   }
Line 298  $.extend(Countdown.prototype, { Line 316  $.extend(Countdown.prototype, {
   
  /* Calculate interal settings for an instance.   /* Calculate interal settings for an instance.
    @param  target  (element) the containing division     @param  target  (element) the containing division
    @param  inst    (object) the current settings for this instance */     @param  inst    (object) the current settings for this instance
  _adjustSettings: function(target, inst) {     @param  recalc  (boolean) true if until or since are set */
    _adjustSettings: function(target, inst, recalc) {
  var now;   var now;
  var serverSync = this._get(inst, 'serverSync');  
  var serverOffset = 0;   var serverOffset = 0;
  var serverEntry = null;   var serverEntry = null;
  for (var i = 0; i < this._serverSyncs.length; i++) {   for (var i = 0; i < this._serverSyncs.length; i++) {
  if (this._serverSyncs[i][0] == serverSync) {   if (this._serverSyncs[i][0] == inst.options.serverSync) {
  serverEntry = this._serverSyncs[i][1];   serverEntry = this._serverSyncs[i][1];
  break;   break;
  }   }
  }   }
  if (serverEntry != null) {   if (serverEntry != null) {
  serverOffset = (serverSync ? serverEntry : 0);   serverOffset = (inst.options.serverSync ? serverEntry : 0);
  now = new Date();   now = new Date();
  }   }
  else {   else {
  var serverResult = (serverSync ? serverSync.apply(target, []) : null);   var serverResult = ($.isFunction(inst.options.serverSync) ?
    inst.options.serverSync.apply(target, []) : null);
  now = new Date();   now = new Date();
  serverOffset = (serverResult ? now.getTime() - serverResult.getTime() : 0);   serverOffset = (serverResult ? now.getTime() - serverResult.getTime() : 0);
  this._serverSyncs.push([serverSync, serverOffset]);   this._serverSyncs.push([inst.options.serverSync, serverOffset]);
  }   }
  var timezone = this._get(inst, 'timezone');   var timezone = inst.options.timezone;
  timezone = (timezone == null ? -now.getTimezoneOffset() : timezone);   timezone = (timezone == null ? -now.getTimezoneOffset() : timezone);
  inst._since = this._get(inst, 'since');   if (recalc || (!recalc && inst._until == null && inst._since == null)) {
  if (inst._since != null) {   inst._since = inst.options.since;
  inst._since = this.UTCDate(timezone, this._determineTime(inst._since, null));   if (inst._since != null) {
  if (inst._since && serverOffset) {   inst._since = this.UTCDate(timezone, this._determineTime(inst._since, null));
  inst._since.setMilliseconds(inst._since.getMilliseconds() + serverOffset);   if (inst._since && serverOffset) {
    inst._since.setMilliseconds(inst._since.getMilliseconds() + serverOffset);
    }
    }
    inst._until = this.UTCDate(timezone, this._determineTime(inst.options.until, now));
    if (serverOffset) {
    inst._until.setMilliseconds(inst._until.getMilliseconds() + serverOffset);
  }   }
  }  
  inst._until = this.UTCDate(timezone, this._determineTime(this._get(inst, 'until'), now));  
  if (serverOffset) {  
  inst._until.setMilliseconds(inst._until.getMilliseconds() + serverOffset);  
  }   }
  inst._show = this._determineShow(inst);   inst._show = this._determineShow(inst);
  },   },
   
  /* Remove the countdown widget from a div.   /* Remove the countdown widget from a div.
    @param  target  (element) the containing division */     @param  target  (element) the containing division */
  _destroyCountdown: function(target) {   _destroyPlugin: function(target) {
  var $target = $(target);   target = $(target);
  if (!$target.hasClass(this.markerClassName)) {   if (!target.hasClass(this.markerClassName)) {
  return;   return;
  }   }
  this._removeTarget(target);   this._removeTarget(target[0]);
  $target.removeClass(this.markerClassName).empty();   target.removeClass(this.markerClassName).empty().removeData(this.propertyName);
  $.removeData(target, PROP_NAME);  
  },   },
   
  /* Pause a countdown widget at the current time.   /* Pause a countdown widget at the current time.
    Stop it running but remember and display the current time.     Stop it running but remember and display the current time.
    @param  target  (element) the containing division */     @param  target  (element) the containing division */
  _pauseCountdown: function(target) {   _pausePlugin: function(target) {
  this._hold(target, 'pause');   this._hold(target, 'pause');
  },   },
   
  /* Pause a countdown widget at the current time.   /* Pause a countdown widget at the current time.
    Stop the display but keep the countdown running.     Stop the display but keep the countdown running.
    @param  target  (element) the containing division */     @param  target  (element) the containing division */
  _lapCountdown: function(target) {   _lapPlugin: function(target) {
  this._hold(target, 'lap');   this._hold(target, 'lap');
  },   },
   
  /* Resume a paused countdown widget.   /* Resume a paused countdown widget.
    @param  target  (element) the containing division */     @param  target  (element) the containing division */
  _resumeCountdown: function(target) {   _resumePlugin: function(target) {
  this._hold(target, null);   this._hold(target, null);
  },   },
   
Line 372  $.extend(Countdown.prototype, { Line 392  $.extend(Countdown.prototype, {
    @param  target  (element) the containing division     @param  target  (element) the containing division
    @param  hold    (string) the new hold setting */     @param  hold    (string) the new hold setting */
  _hold: function(target, hold) {   _hold: function(target, hold) {
  var inst = $.data(target, PROP_NAME);   var inst = $.data(target, this.propertyName);
  if (inst) {   if (inst) {
  if (inst._hold == 'pause' && !hold) {   if (inst._hold == 'pause' && !hold) {
  inst._periods = inst._savePeriods;   inst._periods = inst._savePeriods;
Line 386  $.extend(Countdown.prototype, { Line 406  $.extend(Countdown.prototype, {
  }   }
  inst._hold = hold;   inst._hold = hold;
  inst._savePeriods = (hold == 'pause' ? inst._periods : null);   inst._savePeriods = (hold == 'pause' ? inst._periods : null);
  $.data(target, PROP_NAME, inst);   $.data(target, this.propertyName, inst);
  this._updateCountdown(target, inst);   this._updateCountdown(target, inst);
  }   }
  },   },
Line 394  $.extend(Countdown.prototype, { Line 414  $.extend(Countdown.prototype, {
  /* Return the current time periods.   /* Return the current time periods.
    @param  target  (element) the containing division     @param  target  (element) the containing division
    @return  (number[7]) the current periods for the countdown */     @return  (number[7]) the current periods for the countdown */
  _getTimesCountdown: function(target) {   _getTimesPlugin: function(target) {
  var inst = $.data(target, PROP_NAME);   var inst = $.data(target, this.propertyName);
  return (!inst ? null : (!inst._hold ? inst._periods :   return (!inst ? null : (inst._hold == 'pause' ? inst._savePeriods : (!inst._hold ? inst._periods :
  this._calculatePeriods(inst, inst._show, this._get(inst, 'significant'), new Date())));   this._calculatePeriods(inst, inst._show, inst.options.significant, new Date()))));
  },  
   
  /* Get a setting value, defaulting if necessary.  
    @param  inst  (object) the current settings for this instance  
    @param  name  (string) the name of the required setting  
    @return  (any) the setting's value or a default if not overridden */  
  _get: function(inst, name) {  
  return (inst.options[name] != null ?  
  inst.options[name] : $.countdown._defaults[name]);  
  },   },
   
  /* A time may be specified as an exact value or a relative one.   /* A time may be specified as an exact value or a relative one.
Line 440  $.extend(Countdown.prototype, { Line 451  $.extend(Countdown.prototype, {
  case 'w': day += parseInt(matches[1], 10) * 7; break;   case 'w': day += parseInt(matches[1], 10) * 7; break;
  case 'o':   case 'o':
  month += parseInt(matches[1], 10);    month += parseInt(matches[1], 10); 
  day = Math.min(day, $.countdown._getDaysInMonth(year, month));   day = Math.min(day, plugin._getDaysInMonth(year, month));
  break;   break;
  case 'y':   case 'y':
  year += parseInt(matches[1], 10);   year += parseInt(matches[1], 10);
  day = Math.min(day, $.countdown._getDaysInMonth(year, month));   day = Math.min(day, plugin._getDaysInMonth(year, month));
  break;   break;
  }   }
  matches = pattern.exec(offset);   matches = pattern.exec(offset);
Line 477  $.extend(Countdown.prototype, { Line 488  $.extend(Countdown.prototype, {
    @param  inst  (object) the current settings for this instance     @param  inst  (object) the current settings for this instance
    @return  (string) the new HTML for the countdown display */     @return  (string) the new HTML for the countdown display */
  _generateHTML: function(inst) {   _generateHTML: function(inst) {
    var self = this;
  // Determine what to show   // Determine what to show
  var significant = this._get(inst, 'significant');  
  inst._periods = (inst._hold ? inst._periods :   inst._periods = (inst._hold ? inst._periods :
  this._calculatePeriods(inst, inst._show, significant, new Date()));   this._calculatePeriods(inst, inst._show, inst.options.significant, new Date()));
  // Show all 'asNeeded' after first non-zero value   // Show all 'asNeeded' after first non-zero value
  var shownNonZero = false;   var shownNonZero = false;
  var showCount = 0;   var showCount = 0;
  var sigCount = significant;   var sigCount = inst.options.significant;
  var show = $.extend({}, inst._show);   var show = $.extend({}, inst._show);
  for (var period = Y; period <= S; period++) {   for (var period = Y; period <= S; period++) {
  shownNonZero |= (inst._show[period] == '?' && inst._periods[period] > 0);   shownNonZero |= (inst._show[period] == '?' && inst._periods[period] > 0);
Line 504  $.extend(Countdown.prototype, { Line 515  $.extend(Countdown.prototype, {
  }   }
  }   }
  }   }
  var compact = this._get(inst, 'compact');   var labels = (inst.options.compact ? inst.options.compactLabels : inst.options.labels);
  var layout = this._get(inst, 'layout');   var whichLabels = inst.options.whichLabels || this._normalLabels;
  var labels = (compact ? this._get(inst, 'compactLabels') : this._get(inst, 'labels'));  
  var whichLabels = this._get(inst, 'whichLabels') || this._normalLabels;  
  var timeSeparator = this._get(inst, 'timeSeparator');  
  var description = this._get(inst, 'description') || '';  
  var showCompact = function(period) {   var showCompact = function(period) {
  var labelsNum = $.countdown._get(inst,   var labelsNum = inst.options['compactLabels' + whichLabels(inst._periods[period])];
  'compactLabels' + whichLabels(inst._periods[period]));   return (show[period] ? self._translateDigits(inst, inst._periods[period]) +
  return (show[period] ? inst._periods[period] +  
  (labelsNum ? labelsNum[period] : labels[period]) + ' ' : '');   (labelsNum ? labelsNum[period] : labels[period]) + ' ' : '');
  };   };
  var showFull = function(period) {   var showFull = function(period) {
  var labelsNum = $.countdown._get(inst, 'labels' + whichLabels(inst._periods[period]));   var labelsNum = inst.options['labels' + whichLabels(inst._periods[period])];
  return ((!significant && show[period]) || (significant && showSignificant[period]) ?   return ((!inst.options.significant && show[period]) ||
  '<span class="countdown_section"><span class="countdown_amount">' +   (inst.options.significant && showSignificant[period]) ?
  inst._periods[period] + '</span><br/>' +   '<span class="' + plugin._sectionClass + '">' +
    '<span class="' + plugin._amountClass + '">' +
    self._translateDigits(inst, inst._periods[period]) + '</span><br/>' +
  (labelsNum ? labelsNum[period] : labels[period]) + '</span>' : '');   (labelsNum ? labelsNum[period] : labels[period]) + '</span>' : '');
  };   };
  return (layout ? this._buildLayout(inst, show, layout, compact, significant, showSignificant) :   return (inst.options.layout ? this._buildLayout(inst, show, inst.options.layout,
  ((compact ? // Compact version   inst.options.compact, inst.options.significant, showSignificant) :
  '<span class="countdown_row countdown_amount' +   ((inst.options.compact ? // Compact version
  (inst._hold ? ' countdown_holding' : '') + '">' +    '<span class="' + this._rowClass + ' ' + this._amountClass +
    (inst._hold ? ' ' + this._holdingClass : '') + '">' + 
  showCompact(Y) + showCompact(O) + showCompact(W) + showCompact(D) +    showCompact(Y) + showCompact(O) + showCompact(W) + showCompact(D) + 
  (show[H] ? this._minDigits(inst._periods[H], 2) : '') +   (show[H] ? this._minDigits(inst, inst._periods[H], 2) : '') +
  (show[M] ? (show[H] ? timeSeparator : '') +   (show[M] ? (show[H] ? inst.options.timeSeparator : '') +
  this._minDigits(inst._periods[M], 2) : '') +   this._minDigits(inst, inst._periods[M], 2) : '') +
  (show[S] ? (show[H] || show[M] ? timeSeparator : '') +   (show[S] ? (show[H] || show[M] ? inst.options.timeSeparator : '') +
  this._minDigits(inst._periods[S], 2) : '') :   this._minDigits(inst, inst._periods[S], 2) : '') :
  // Full version   // Full version
  '<span class="countdown_row countdown_show' + (significant || showCount) +   '<span class="' + this._rowClass + ' ' + this._showClass + (inst.options.significant || showCount) +
  (inst._hold ? ' countdown_holding' : '') + '">' +   (inst._hold ? ' ' + this._holdingClass : '') + '">' +
  showFull(Y) + showFull(O) + showFull(W) + showFull(D) +   showFull(Y) + showFull(O) + showFull(W) + showFull(D) +
  showFull(H) + showFull(M) + showFull(S)) + '</span>' +   showFull(H) + showFull(M) + showFull(S)) + '</span>' +
  (description ? '<span class="countdown_row countdown_descr">' + description + '</span>' : '')));   (inst.options.description ? '<span class="' + this._rowClass + ' ' + this._descrClass + '">' +
    inst.options.description + '</span>' : '')));
  },   },
   
  /* Construct a custom layout.   /* Construct a custom layout.
Line 550  $.extend(Countdown.prototype, { Line 560  $.extend(Countdown.prototype, {
    @param  showSignificant  (boolean[7]) other periods to show for significance     @param  showSignificant  (boolean[7]) other periods to show for significance
    @return  (string) the custom HTML */     @return  (string) the custom HTML */
  _buildLayout: function(inst, show, layout, compact, significant, showSignificant) {   _buildLayout: function(inst, show, layout, compact, significant, showSignificant) {
  var labels = this._get(inst, (compact ? 'compactLabels' : 'labels'));   var labels = inst.options[compact ? 'compactLabels' : 'labels'];
  var whichLabels = this._get(inst, 'whichLabels') || this._normalLabels;   var whichLabels = inst.options.whichLabels || this._normalLabels;
  var labelFor = function(index) {   var labelFor = function(index) {
  return ($.countdown._get(inst,   return (inst.options[(compact ? 'compactLabels' : 'labels') +
  (compact ? 'compactLabels' : 'labels') + whichLabels(inst._periods[index])) ||   whichLabels(inst._periods[index])] || labels)[index];
  labels)[index];  
  };   };
  var digit = function(value, position) {   var digit = function(value, position) {
  return Math.floor(value / position) % 10;   return inst.options.digits[Math.floor(value / position) % 10];
  };   };
  var subs = {desc: this._get(inst, 'description'), sep: this._get(inst, 'timeSeparator'),   var subs = {desc: inst.options.description, sep: inst.options.timeSeparator,
  yl: labelFor(Y), yn: inst._periods[Y], ynn: this._minDigits(inst._periods[Y], 2),   yl: labelFor(Y), yn: this._minDigits(inst, inst._periods[Y], 1),
  ynnn: this._minDigits(inst._periods[Y], 3), y1: digit(inst._periods[Y], 1),   ynn: this._minDigits(inst, inst._periods[Y], 2),
    ynnn: this._minDigits(inst, inst._periods[Y], 3), y1: digit(inst._periods[Y], 1),
  y10: digit(inst._periods[Y], 10), y100: digit(inst._periods[Y], 100),   y10: digit(inst._periods[Y], 10), y100: digit(inst._periods[Y], 100),
  y1000: digit(inst._periods[Y], 1000),   y1000: digit(inst._periods[Y], 1000),
  ol: labelFor(O), on: inst._periods[O], onn: this._minDigits(inst._periods[O], 2),   ol: labelFor(O), on: this._minDigits(inst, inst._periods[O], 1),
  onnn: this._minDigits(inst._periods[O], 3), o1: digit(inst._periods[O], 1),   onn: this._minDigits(inst, inst._periods[O], 2),
    onnn: this._minDigits(inst, inst._periods[O], 3), o1: digit(inst._periods[O], 1),
  o10: digit(inst._periods[O], 10), o100: digit(inst._periods[O], 100),   o10: digit(inst._periods[O], 10), o100: digit(inst._periods[O], 100),
  o1000: digit(inst._periods[O], 1000),   o1000: digit(inst._periods[O], 1000),
  wl: labelFor(W), wn: inst._periods[W], wnn: this._minDigits(inst._periods[W], 2),   wl: labelFor(W), wn: this._minDigits(inst, inst._periods[W], 1),
  wnnn: this._minDigits(inst._periods[W], 3), w1: digit(inst._periods[W], 1),   wnn: this._minDigits(inst, inst._periods[W], 2),
    wnnn: this._minDigits(inst, inst._periods[W], 3), w1: digit(inst._periods[W], 1),
  w10: digit(inst._periods[W], 10), w100: digit(inst._periods[W], 100),   w10: digit(inst._periods[W], 10), w100: digit(inst._periods[W], 100),
  w1000: digit(inst._periods[W], 1000),   w1000: digit(inst._periods[W], 1000),
  dl: labelFor(D), dn: inst._periods[D], dnn: this._minDigits(inst._periods[D], 2),   dl: labelFor(D), dn: this._minDigits(inst, inst._periods[D], 1),
  dnnn: this._minDigits(inst._periods[D], 3), d1: digit(inst._periods[D], 1),   dnn: this._minDigits(inst, inst._periods[D], 2),
    dnnn: this._minDigits(inst, inst._periods[D], 3), d1: digit(inst._periods[D], 1),
  d10: digit(inst._periods[D], 10), d100: digit(inst._periods[D], 100),   d10: digit(inst._periods[D], 10), d100: digit(inst._periods[D], 100),
  d1000: digit(inst._periods[D], 1000),   d1000: digit(inst._periods[D], 1000),
  hl: labelFor(H), hn: inst._periods[H], hnn: this._minDigits(inst._periods[H], 2),   hl: labelFor(H), hn: this._minDigits(inst, inst._periods[H], 1),
  hnnn: this._minDigits(inst._periods[H], 3), h1: digit(inst._periods[H], 1),   hnn: this._minDigits(inst, inst._periods[H], 2),
    hnnn: this._minDigits(inst, inst._periods[H], 3), h1: digit(inst._periods[H], 1),
  h10: digit(inst._periods[H], 10), h100: digit(inst._periods[H], 100),   h10: digit(inst._periods[H], 10), h100: digit(inst._periods[H], 100),
  h1000: digit(inst._periods[H], 1000),   h1000: digit(inst._periods[H], 1000),
  ml: labelFor(M), mn: inst._periods[M], mnn: this._minDigits(inst._periods[M], 2),   ml: labelFor(M), mn: this._minDigits(inst, inst._periods[M], 1),
  mnnn: this._minDigits(inst._periods[M], 3), m1: digit(inst._periods[M], 1),   mnn: this._minDigits(inst, inst._periods[M], 2),
    mnnn: this._minDigits(inst, inst._periods[M], 3), m1: digit(inst._periods[M], 1),
  m10: digit(inst._periods[M], 10), m100: digit(inst._periods[M], 100),   m10: digit(inst._periods[M], 10), m100: digit(inst._periods[M], 100),
  m1000: digit(inst._periods[M], 1000),   m1000: digit(inst._periods[M], 1000),
  sl: labelFor(S), sn: inst._periods[S], snn: this._minDigits(inst._periods[S], 2),   sl: labelFor(S), sn: this._minDigits(inst, inst._periods[S], 1),
  snnn: this._minDigits(inst._periods[S], 3), s1: digit(inst._periods[S], 1),   snn: this._minDigits(inst, inst._periods[S], 2),
    snnn: this._minDigits(inst, inst._periods[S], 3), s1: digit(inst._periods[S], 1),
  s10: digit(inst._periods[S], 10), s100: digit(inst._periods[S], 100),   s10: digit(inst._periods[S], 10), s100: digit(inst._periods[S], 100),
  s1000: digit(inst._periods[S], 1000)};   s1000: digit(inst._periods[S], 1000)};
  var html = layout;   var html = layout;
  // Replace period containers: {p<}...{p>}   // Replace period containers: {p<}...{p>}
  for (var i = Y; i <= S; i++) {   for (var i = Y; i <= S; i++) {
  var period = 'yowdhms'.charAt(i);   var period = 'yowdhms'.charAt(i);
  var re = new RegExp('\\{' + period + '<\\}(.*)\\{' + period + '>\\}', 'g');   var re = new RegExp('\\{' + period + '<\\}([\\s\\S]*)\\{' + period + '>\\}', 'g');
  html = html.replace(re, ((!significant && show[i]) ||   html = html.replace(re, ((!significant && show[i]) ||
  (significant && showSignificant[i]) ? '$1' : ''));   (significant && showSignificant[i]) ? '$1' : ''));
  }   }
Line 606  $.extend(Countdown.prototype, { Line 622  $.extend(Countdown.prototype, {
  },   },
   
  /* Ensure a numeric value has at least n digits for display.   /* Ensure a numeric value has at least n digits for display.
      @param  inst   (object) the current settings for this instance
    @param  value  (number) the value to display     @param  value  (number) the value to display
    @param  len    (number) the minimum length     @param  len    (number) the minimum length
    @return  (string) the display text */     @return  (string) the display text */
  _minDigits: function(value, len) {   _minDigits: function(inst, value, len) {
  value = '' + value;   value = '' + value;
  if (value.length >= len) {   if (value.length >= len) {
  return value;   return this._translateDigits(inst, value);
  }   }
  value = '0000000000' + value;   value = '0000000000' + value;
  return value.substr(value.length - len);   return this._translateDigits(inst, value.substr(value.length - len));
    },
   
    /* Translate digits into other representations.
      @param  inst   (object) the current settings for this instance
      @param  value  (string) the text to translate
      @return  (string) the translated text */
    _translateDigits: function(inst, value) {
    return ('' + value).replace(/[0-9]/g, function(digit) {
    return inst.options.digits[digit];
    });
  },   },
   
  /* Translate the format into flags for each period.   /* Translate the format into flags for each period.
Line 623  $.extend(Countdown.prototype, { Line 650  $.extend(Countdown.prototype, {
    @return  (string[7]) flags indicating which periods are requested (?) or     @return  (string[7]) flags indicating which periods are requested (?) or
             required (!) by year, month, week, day, hour, minute, second */              required (!) by year, month, week, day, hour, minute, second */
  _determineShow: function(inst) {   _determineShow: function(inst) {
  var format = this._get(inst, 'format');   var format = inst.options.format;
  var show = [];   var show = [];
  show[Y] = (format.match('y') ? '?' : (format.match('Y') ? '!' : null));   show[Y] = (format.match('y') ? '?' : (format.match('Y') ? '!' : null));
  show[O] = (format.match('o') ? '?' : (format.match('O') ? '!' : null));   show[O] = (format.match('o') ? '?' : (format.match('O') ? '!' : null));
Line 665  $.extend(Countdown.prototype, { Line 692  $.extend(Countdown.prototype, {
  var periods = [0, 0, 0, 0, 0, 0, 0];   var periods = [0, 0, 0, 0, 0, 0, 0];
  if (show[Y] || show[O]) {   if (show[Y] || show[O]) {
  // Treat end of months as the same   // Treat end of months as the same
  var lastNow = $.countdown._getDaysInMonth(now.getFullYear(), now.getMonth());   var lastNow = plugin._getDaysInMonth(now.getFullYear(), now.getMonth());
  var lastUntil = $.countdown._getDaysInMonth(until.getFullYear(), until.getMonth());   var lastUntil = plugin._getDaysInMonth(until.getFullYear(), until.getMonth());
  var sameDay = (until.getDate() == now.getDate() ||   var sameDay = (until.getDate() == now.getDate() ||
  (until.getDate() >= Math.min(lastNow, lastUntil) &&   (until.getDate() >= Math.min(lastNow, lastUntil) &&
  now.getDate() >= Math.min(lastNow, lastUntil)));   now.getDate() >= Math.min(lastNow, lastUntil)));
Line 682  $.extend(Countdown.prototype, { Line 709  $.extend(Countdown.prototype, {
  // Adjust for months difference and end of month if necessary   // Adjust for months difference and end of month if necessary
  now = new Date(now.getTime());   now = new Date(now.getTime());
  var wasLastDay = (now.getDate() == lastNow);   var wasLastDay = (now.getDate() == lastNow);
  var lastDay = $.countdown._getDaysInMonth(now.getFullYear() + periods[Y],   var lastDay = plugin._getDaysInMonth(now.getFullYear() + periods[Y],
  now.getMonth() + periods[O]);   now.getMonth() + periods[O]);
  if (now.getDate() > lastDay) {   if (now.getDate() > lastDay) {
  now.setDate(lastDay);   now.setDate(lastDay);
Line 737  $.extend(Countdown.prototype, { Line 764  $.extend(Countdown.prototype, {
  }   }
 });  });
   
 /* jQuery extend now ignores nulls!  // The list of commands that return values and don't permit chaining
    @param  target  (object) the object to update  var getters = ['getTimes'];
    @param  props   (object) the new settings  
    @return  (object) the updated object */  /* Determine whether a command is a getter and doesn't permit chaining.
 function extendRemove(target, props) {     @param  command    (string, optional) the command to run
  $.extend(target, props);     @param  otherArgs  ([], optional) any other arguments for the command
  for (var name in props) {     @return  true if the command is a getter, false if not */
  if (props[name] == null) {  function isNotChained(command, otherArgs) {
  target[name] = null;   if (command == 'option' && (otherArgs.length == 0 ||
  }   (otherArgs.length == 1 && typeof otherArgs[0] == 'string'))) {
    return true;
  }   }
  return target;   return $.inArray(command, getters) > -1;
 }  }
   
 /* Process the countdown functionality for a jQuery selection.  /* Process the countdown functionality for a jQuery selection.
    @param  command  (string) the command to run (optional, default 'attach')     @param  options  (object) the new settings to use for these instances (optional) or
    @param  options  (object) the new settings to use for these countdown instances                      (string) the command to run (optional)
    @return  (jQuery) for chaining further calls */     @return  (jQuery) for chaining further calls or
               (any) getter value */
 $.fn.countdown = function(options) {  $.fn.countdown = function(options) {
  var otherArgs = Array.prototype.slice.call(arguments, 1);   var otherArgs = Array.prototype.slice.call(arguments, 1);
  if (options == 'getTimes' || options == 'settings') {   if (isNotChained(options, otherArgs)) {
  return $.countdown['_' + options + 'Countdown'].   return plugin['_' + options + 'Plugin'].
  apply($.countdown, [this[0]].concat(otherArgs));   apply(plugin, [this[0]].concat(otherArgs));
  }   }
  return this.each(function() {   return this.each(function() {
  if (typeof options == 'string') {   if (typeof options == 'string') {
  $.countdown['_' + options + 'Countdown'].apply($.countdown, [this].concat(otherArgs));   if (!plugin['_' + options + 'Plugin']) {
    throw 'Unknown command: ' + options;
    }
    plugin['_' + options + 'Plugin'].
    apply(plugin, [this].concat(otherArgs));
  }   }
  else {   else {
  $.countdown._attachCountdown(this, options);   plugin._attachPlugin(this, options || {});
  }   }
  });   });
 };  };
   
 /* Initialise the countdown functionality. */  /* Initialise the countdown functionality. */
 $.countdown = new Countdown(); // singleton instance  var plugin = $.countdown = new Countdown(); // Singleton instance
   
 })(jQuery);  })(jQuery);

Removed from v.1.1  
changed lines
  Added in v.1.2


FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>