MobiScroll datePicker reset value 00-000-0000 - javascript

Mobiscroll date picker
every year should ends with reset value 00-000-0000, the reset value is achieved when i click the reset button. how to achieve this.
+----+-----+------+
| 31 | dec | 2014 |
| 00 | 000 | 0000 | ----->reset value
| 01 | jan | 2015 |
| 02 | jan | 2015 |
+----+-----+------+
--------------------
|ok| |reset| |cancel|
--------------------

To add reset value in the date picker scroll view. modify few lines of code in
mobiscroll.util.datetime.js, mobiscroll.datetimebase.js
In mobiscroll.datetimebase.js,
under variable defaults={}, add partialDate : false,
add reset values in a wheel generating loop: for (k = 0; k < 3; k++) {},
if (s.partialDate)
{
keys.push(-1);
values.push('0000');
}
replace following codes in a mobiscroll.datetimebase.js
formatValue: function (d) {
//return datetime.formatDate(format, getDate(d), s);
//KKN
if (d[o["m"]] != "-1" && d[o["d"]] != "0" )
{
datetime.partialDate = false;
return datetime.formatDate(format, getDate(d), s);
}
else
{
datetime.partialDate = true;
var tempDate = [],
hideDate = false,
hideMonth = false;
$.each(['y', 'm', 'd', 'a', 'h', 'i', 's'], function (x, i) {
tempDate[o[i]] = d[o[i]];
});
if (d[o["m"]] == "-1")
{
//datetime.partialDateFormat = yy;
tempDate[o["m"]] = "0";
tempDate[o["d"]] = "1";
hideMonth = true;
hideDate = true;
}else if (d[o["d"]] == "0"){
//datetime.partialDateFormat = MM-yy;
tempDate[o["d"]] = "1";
hideDate = true;
}
//var dt = getDate (tempDate);
var newDt = datetime.formatDate(format, getDate(tempDate), s, hideDate, hideMonth);
datetime.partialDateFormat = s.partialDateFormat;
return newDt;
}
//return datetime.formatPartialDate(format, d, s ,o);
},
parseValue: function (val) {
if (!val) {
innerValues = {};
}
var datValue = getArray(val ? datetime.parseDate(format, val, s) : (s.defaultValue || new Date()), !!val && !!val.getTime);
var seperator = "-";
if (format.indexOf ('/') > 0){
seperator = "/";
}
var dateArray = val.split(seperator);
switch (dateArray.length)
{
case 1: //Year Only
datValue[o["d"]] = 0;
datValue[o["m"]] = -1;
break;
case 2: //Month & Year
datValue[o["d"]] = 0;
break;
}
return datValue;
},
validate: function (dw, i, time, dir) {
//KKN
var temp = [],
hideDate = false,
hideMonth = false;
var d = inst.getArrayVal(true);
if (s.partialDate)
{
hideDate = false,
hideMonth = false;
$.each(['y', 'm', 'd', 'a', 'h', 'i', 's'], function (x, i) {
temp[o[i]] = d[o[i]];
});
if (d[o["m"]] == "-1")
{
temp[o["m"]] = "0";
temp[o["d"]] = "1";
hideMonth = true;
hideDate = true;
}else if (d[o["d"]] == "0"){
//datetime.partialDateFormat = MM-yy;
temp[o["d"]] = "1";
hideDate = true;
}
//return true;
}
else
{
var validated = getClosestValidDate(getDate(inst.getArrayVal(true)), dir),
temp = getArray(validated);
}
y = get(temp, 'y'),
m = get(temp, 'm'),
minprop = true,
maxprop = true;
$.each(['y', 'm', 'd', 'a', 'h', 'i', 's'], function (x, i) {
if (o[i] !== undefined) {
var min = mins[i],
max = maxs[i],
maxdays = 31,
val = get(temp, i),
t = $('.dw-ul', dw).eq(o[i]);
if (i == 'd') {
maxdays = s.getMaxDayOfMonth(y, m);
max = maxdays;
if (regen) {
$('.dw-li', t).each(function () {
var that = $(this),
d = that.data('val'),
w = s.getDate(y, m, d).getDay(),
str = dord.replace(/[my]/gi, '').replace(/dd/, (d < 10 ? '0' + d : d) + (s.daySuffix || '')).replace(/d/, d + (s.daySuffix || ''));
$('.dw-i', that).html(str.match(/DD/) ? str.replace(/DD/, '<span class="dw-day">' + s.dayNames[w] + '</span>') : str.replace(/D/, '<span class="dw-day">' + s.dayNamesShort[w] + '</span>'));
});
}
}
if (minprop && mind) {
min = f[i](mind);
}
if (maxprop && maxd) {
max = f[i](maxd);
}
if (i != 'y') {
var i1 = getIndex(t, min),
i2 = getIndex(t, max);
$('.dw-li', t).removeClass('dw-v').slice(i1, i2 + 1).addClass('dw-v');
if (i == 'd') { // Hide days not in month
//$('.dw-li', t).removeClass('dw-h').slice(maxdays).addClass('dw-h');
if (s.partialDate){
if (hideMonth)
{
$('.dw-li', t).removeClass('dw-h').slice(1).addClass('dw-h');
}
else{
$('.dw-li', t).removeClass('dw-h').slice(maxdays + 1).addClass('dw-h');
}
}
else
{
$('.dw-li', t).removeClass('dw-h').slice(maxdays).addClass('dw-h');
}
}
}
if (val < min) {
val = min;
}
if (val > max) {
val = max;
}
if (minprop) {
minprop = val == min;
}
if (maxprop) {
maxprop = val == max;
}
// Disable some days
if (i == 'd') {
var first = s.getDate(y, m, 1).getDay(),
idx = {};
// Set invalid indexes
validateDates(invalid, y, m, first, maxdays, idx, 1);
// Delete indexes which are valid
validateDates(valid, y, m, first, maxdays, idx, 0);
$.each(idx, function (i, v) {
if (v) {
$('.dw-li', t).eq(i).removeClass('dw-v');
}
});
}
}
});
// Invalid times
if (hasTime) {
$.each(['a', 'h', 'i', 's'], function (i, v) {
var val = get(temp, v),
d = get(temp, 'd'),
t = $('.dw-ul', dw).eq(o[v]);
if (o[v] !== undefined) {
validateTimes(invalid, i, v, temp, y, m, d, t, 0);
validateTimes(valid, i, v, temp, y, m, d, t, 1);
// Get valid value
validValues[i] = +inst.getValidCell(val, t, dir).val;
}
});
}
if (hideMonth)
{
temp[o["m"]] = "-1";
temp[o["d"]] = "0";
}else if (hideDate){
//datetime.partialDateFormat = MM-yy;
temp[o["d"]] = "0";
}
inst._tempWheelArray = temp;
}
and in mobiscroll.util.datetime.js, replace following lines
(function ($, undefined) {
var ms = $.mobiscroll;
ms.datetime = {
defaults: {
shortYearCutoff: '+10',
monthNames: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
monthNamesShort: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
dayNames: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'],
dayNamesShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
dayNamesMin: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
amText: 'am',
pmText: 'pm',
getYear: function (d) { return d.getFullYear(); },
getMonth: function (d) { return d.getMonth(); },
getDay: function (d) { return d.getDate(); },
getDate: function (y, m, d, h, i, s, u) { return new Date(y, m, d, h || 0, i || 0, s || 0, u || 0); },
getMaxDayOfMonth: function (y, m, o) { return 32 - new Date(y, m, 32).getDate(); },
getWeekNumber: function (d) {
// Copy date so don't modify original
d = new Date(d);
d.setHours(0, 0, 0);
// Set to nearest Thursday: current date + 4 - current day number
// Make Sunday's day number 7
d.setDate(d.getDate() + 4 - (d.getDay() || 7));
// Get first day of year
var yearStart = new Date(d.getFullYear(), 0, 1);
// Calculate full weeks to nearest Thursday
return Math.ceil((((d - yearStart) / 86400000) + 1) / 7);
}
},
/**
* Format a date into a string value with a specified format.
* #param {String} format Output format.
* #param {Date} date Date to format.
* #param {Object} [settings={}] Settings.
* #return {String} Returns the formatted date string.
*/
formatDate: function (format, date, settings, hideDate, hideMonth) {
var newformat = format;
if (!date) {
return null;
}
var s = $.extend({}, ms.datetime.defaults, settings),
look = function (m) { // Check whether a format character is doubled
var n = 0;
while (i + 1 < format.length && format.charAt(i + 1) == m) {
n++;
i++;
}
return n;
},
f1 = function (m, val, len) { // Format a number, with leading zero if necessary
var n = '' + val;
if (look(m)) {
while (n.length < len) {
n = '0' + n;
}
}
return n;
},
f2 = function (m, val, s, l) { // Format a name, short or long as requested
return (look(m) ? l[val] : s[val]);
},
f3 = function (m){
look(m);
if (newformat.indexOf('/') > 0 ){
newformat = newformat.replace( m +'/', '');
}
else
{
newformat = newformat.replace( m +'-', '');
}
newformat = newformat.replace( m, '');
if (format.charAt(i+1) == "/" ||format.charAt(i+1) == "-"){//Skip Separator
i++;
}
return '';
},
i,
year,
output = '',
literal = false;
//return s.getPartialMonth(date, format);
for (i = 0; i < format.length; i++) {
if (literal) {
if (format.charAt(i) == "'" && !look("'")) {
literal = false;
} else {
output += format.charAt(i);
}
} else {
switch (format.charAt(i)) {
case 'd':
if (hideDate)
{
output += f3('d');
}
else
{
output += f1('d', s.getDay(date), 2);
}
break;
case 'D':
if (hideDate)
{
output += f3('D');
}
else
{
output += f2('D', date.getDay(), s.dayNamesShort, s.dayNames);
}
break;
case 'o':
output += f1('o', (date.getTime() - new Date(date.getFullYear(), 0, 0).getTime()) / 86400000, 3);
break;
case 'm':
if (hideMonth)
{
output += f3('m');
}
else
{
output += f1('m', s.getMonth(date) + 1, 2);
}
break;
case 'M':
if (hideMonth)
{
output += f3('M');
}
else
{
output += f2('M', s.getMonth(date), s.monthNamesShort, s.monthNames);
}
break;
case 'y':
year = s.getYear(date);
output += (look('y') ? year : (year % 100 < 10 ? '0' : '') + year % 100);
//output += (look('y') ? date.getFullYear() : (date.getYear() % 100 < 10 ? '0' : '') + date.getYear() % 100);
break;
case 'h':
var h = date.getHours();
output += f1('h', (h > 12 ? (h - 12) : (h === 0 ? 12 : h)), 2);
break;
case 'H':
output += f1('H', date.getHours(), 2);
break;
case 'i':
output += f1('i', date.getMinutes(), 2);
break;
case 's':
output += f1('s', date.getSeconds(), 2);
break;
case 'a':
output += date.getHours() > 11 ? s.pmText : s.amText;
break;
case 'A':
output += date.getHours() > 11 ? s.pmText.toUpperCase() : s.amText.toUpperCase();
break;
case "'":
if (look("'")) {
output += "'";
} else {
literal = true;
}
break;
default:
output += format.charAt(i);
}
}
}
ms.partialDateFormat = newformat;
return output;
},
/**
* Format a date into a string value with a specified format.
* #param {String} format Output format.
* #param {Date} date Date to format.
* #param {Object} [settings={}] Settings.
* #return {String} Returns the formatted date string.
*/
formatPartialDate: function (format, date, settings, o) {
if (!date) {
return null;
}
var tempDate = [],
hideDate = false,
hideMonth = false;
$.each(['y', 'm', 'd', 'a', 'h', 'i', 's'], function (x, i) {
tempDate[o[i]] = date[o[i]];
});
if (date[o["m"]] == "-1")
{
tempDate[o["m"]] = "0";
tempDate[o["d"]] = "1";
hideMonth = true;
hideDate = true;
}else if (date[o["d"]] == "0"){
tempDate[o["d"]] = "1";
hideDate = true;
}
var t2 = ms.getDate(tempDate);
var t1 = new Date();
//var output = ms.formatDate(format, settings.getDate(tempDate), settings, hideDate, hideMonth);
var output = ms.formatDate(format, tempDate, settings, hideDate, hideMonth);
return output;
},
/**
* Extract a date from a string value with a specified format.
* #param {String} format Input format.
* #param {String} value String to parse.
* #param {Object} [settings={}] Settings.
* #return {Date} Returns the extracted date.
*/
parseDate: function (format, value, settings) {
var s = $.extend({}, ms.datetime.defaults, settings),
def = s.defaultValue || new Date();
if (!format || !value) {
return def;
}
// If already a date object
if (value.getTime) {
return value;
}
value = (typeof value == 'object' ? value.toString() : value + '');
var seperator = "-";
if (format.indexOf ('/') > 0){
seperator = "/";
}
var dateArray = value.split(seperator);
//else (value)
var shortYearCutoff = s.shortYearCutoff,
year = s.getYear(def),
month = s.getMonth(def) + 1,
day = s.getDay(def),
doy = -1,
hours = def.getHours(),
minutes = def.getMinutes(),
seconds = 0, //def.getSeconds(),
ampm = -1,
literal = false, // Check whether a format character is doubled
lookAhead = function (match) {
var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match);
if (matches) {
iFormat++;
}
return matches;
},
getNumber = function (match) { // Extract a number from the string value
lookAhead(match);
var size = (match == '#' ? 14 : (match == '!' ? 20 : (match == 'y' ? 4 : (match == 'o' ? 3 : 2)))),
digits = new RegExp('^\\d{1,' + size + '}'),
num = value.substr(iValue).match(digits);
if (!num) {
return 0;
}
iValue += num[0].length;
return parseInt(num[0], 10);
},
getName = function (match, s, l) { // Extract a name from the string value and convert to an index
var names = (lookAhead(match) ? l : s),
i;
for (i = 0; i < names.length; i++) {
if (value.substr(iValue, names[i].length).toLowerCase() == names[i].toLowerCase()) {
iValue += names[i].length;
return i + 1;
}
}
return 0;
},
checkLiteral = function () {
if (value.charAt(iValue) == '/' || value.charAt(iValue) == '-')
iValue++;
},
iValue = 0,
iFormat;
for (iFormat = 0; iFormat < format.length; iFormat++) {
if (literal) {
if (format.charAt(iFormat) == "'" && !lookAhead("'")) {
literal = false;
} else {
checkLiteral();
}
} else {
switch (format.charAt(iFormat)) {
case 'd':
if (dateArray.length <= 2){
day = 1;
//iValue++;
}
else{
day = getNumber('d');
}
break;
case 'D':
getName('D', s.dayNamesShort, s.dayNames);
break;
case 'o':
doy = getNumber('o');
break;
case 'm':
if (dateArray.length == 1){
month = 1;
//iValue++;
}
else
{
month = getNumber('m');
}
break;
case 'M':
if (dateArray.length == 1){
month = 1;
//iValue++;
}
else
{
month = getName('M', s.monthNamesShort, s.monthNames);
}
break;
case 'y':
year = getNumber('y');
break;
case 'H':
hours = getNumber('H');
break;
case 'h':
hours = getNumber('h');
break;
case 'i':
minutes = getNumber('i');
break;
case 's':
seconds = getNumber('s');
break;
case 'a':
ampm = getName('a', [s.amText, s.pmText], [s.amText, s.pmText]) - 1;
break;
case 'A':
ampm = getName('A', [s.amText, s.pmText], [s.amText, s.pmText]) - 1;
break;
case "'":
if (lookAhead("'")) {
checkLiteral();
} else {
literal = true;
}
break;
default:
checkLiteral();
}
}
}
if (year < 100) {
year += new Date().getFullYear() - new Date().getFullYear() % 100 +
(year <= (typeof shortYearCutoff != 'string' ? shortYearCutoff : new Date().getFullYear() % 100 + parseInt(shortYearCutoff, 10)) ? 0 : -100);
}
if (doy > -1) {
month = 1;
day = doy;
do {
var dim = 32 - new Date(year, month - 1, 32).getDate();
if (day <= dim) {
break;
}
month++;
day -= dim;
} while (true);
}
hours = (ampm == -1) ? hours : ((ampm && hours < 12) ? (hours + 12) : (!ampm && hours == 12 ? 0 : hours));
var date = s.getDate(year, month - 1, day, hours, minutes, seconds);
if (s.getYear(date) != year || s.getMonth(date) + 1 != month || s.getDay(date) != day) {
return def; // Invalid date
}
return date;
}
};
// #deprecated since 2.11.0, backward compatibility code
// ---
ms.formatDate = ms.datetime.formatDate;
ms.parseDate = ms.datetime.parseDate;
ms.formatPartialDate = ms.datetime.formatPartialDate;
ms.getDate = ms.datetime.getDate;
ms.partialDate = true;
ms.partialDateFormat = ms.datetime.partialDateFormat; })(jQuery);
to enable a partial date picker add partialDate: true, whenever you want to enable a partial date picker.

Related

Get date range string from array of days in javascript

I have an array of days
[0,1,4,5,6]
How do I get these days to print in a format like
"Sun-Mon, Thu-Sat"
var hours = {
firstSet: {
days: [0,1,4,5,6]
},
secondSet: {
days: [1,4,6]
}
};
var prevDay = null;
var counter = 0;
function loadHours() {
$.each(hours,function(id,val){
prevDay = null;
counter = 0;
var dayString = "";
$.each(val.days, function(day){
counter += 1;
if (counter == 1) {
dayString += checkDayString(prevDay, day);
} else if (counter == val.days.length) {
dayString += "-"+getDayName(day);
}
});
});
}
function checkDayString(prevDay, day) {
if (prevDay == null) {
prevDay = day;
return getDayName(day);
}
}
function getDayName(day) {
switch(day) {
case 0:
return "Sun";
break;
case 1:
return "Mon";
break;
case 2:
return "Tue";
break;
case 3:
return "Wed";
break;
case 4:
return "Thu";
break;
case 5:
return "Fri";
break;
case 6:
return "Sat";
break;
}
}
You can use reduce to group consecutive days that appear in the array and then convert that into word ranges using the first and last index of the number groups using map.
var days = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
var ranges = [0, 1, 4, 5, 6];
var words = ranges
.reduce((acc, curr) => {
if (acc.length === 0) {
acc.push([curr]);
return acc;
}
let r = acc[acc.length - 1];
if (curr - r[r.length - 1] === 1) r.push(curr);
else acc.push([curr]);
return acc;
}, [])
.map(range => range.length === 1 ?
days[range[0]] :
days[range[0]] + "-" + days[range[range.length - 1]])
console.log(words.join(', '));

Days name in order in Jquery

I have a array like
var abc = ["mon","Thu","Fri","Tue","Wed","Sun","Sat"]
So next I want these days in order like
["mon","Tue","Wed","Thu","Fri","Sat","Sun"]
Is there any inbuilt functions or any logic for it?
I used a map object to be used along with a sort function .. pretty easy.
var arrayOfDays = ["Mon","Thu","Fri","Tue","Wed","Sun","Sat"]; //array to be sorted
//int this map, define the "correct" order of days
var map = {
"Sun" : 0,
"Mon" : 1,
"Tue" : 2,
"Wed" : 3,
"Thu" : 4,
"Fri" : 5,
"Sat" : 6,
}
function dateSort(array) //function to sort the array
{
for(i = 0 ; i < array.length ; i++)
for(j = i + 1 ; j < array.length ; j++)
{
if(map[array[i]] > map[array[j]])
{
temp = array[i];
array[i] = array[j];
array[j] = temp;
}
}
}
It can be invoked as follows:
datesort(arrayOfDays);
I tested it by printing the values of array of dates before calling the function and after:
Before: Mon Thu Fri Tue Wed Sun Sat
After: Sun Mon Tue Wed Thu Fri Sat
EDIT: As suggested by others, a version using Array.sort() - though avoid it if you are a beginner.
Define a custom compare function:
function dateCompare(d1, d2)
{
if(map[d1] == map[d2])
return 0;
return (map[d1] < map[d2]) ? -1 : 1;
}
Invoke as:
arrayOfDays.sort(dateCompare);
As indicated by others, you need to use square brackets for arrays, not curly ones:
var abc = ["mon","Thu","Fri","Tue","Wed","Sun","Sat"];
There is no predefined method that recognizes weekdays, but you can just compare given day names to a list that is in the correct order, like this:
function compareDayNames(day1, day2) {
var weekdays = ',monday,tuesday,wednesday,thursday,friday,saturday,sunday';
return weekdays.indexOf(',' + day1.toLowerCase())
- weekdays.indexOf(',' + day2.toLowerCase());
}
var abc = ["mon","Thu","Fri","Tue","Wed","Sun","Sat"];
abc.sort(compareDayNames);
console.log('Sorted: ' + abc.join(','));
Output in the console is:
Sorted: mon,Tue,Wed,Thu,Fri,Sat,Sun
This function also sorts longer and shorter names well:
var abc = ['Satur','Tu', 'W', 'M', 'Thurs'];
abc.sort(compareDayNames);
console.log('Sorted: ' + abc.join(','));
Output:
Sorted: M,Tu,W,Thurs,Satur
EDIT:
If you want to throw an error when an invalid day name is provided, or a name that is less than 2 characters (because T and S are ambiguous), then rewrite the compare function as follows:
function compareDayNames(day1, day2) {
var weekdays = ',monday,tuesday,wednesday,thursday,friday,saturday,sunday';
function dayNumber(day) {
var pos = weekdays.indexOf(',' + day.toLowerCase());
if (pos === -1 || day.length < 2) {
throw '"' + day + '" is not a valid day name';
}
return pos;
}
return dayNumber(day1) - dayNumber(day2);
}
$(document).ready(function () {
var ndays = "";
var days = "Sat,Fri,mon,Thu,Tue,Wed,Sun";
var dys = days.split(",");
debugger;
for (var i = 0; i < dys.length; i++) {
switch (dys[i]) {
case "mon":
ndays = ndays + ",1";
break;
case "Tue":
ndays = ndays + ",2";
break;
case "Wed":
ndays = ndays + ",3";
break;
case "Thu":
ndays = ndays + ",4";
break;
case "Fri":
ndays = ndays + ",5";
break;
case "Sat":
ndays = ndays + ",6";
break;
default:
ndays = ndays + ",7";
break;
}
alert(ndays);
}
var cDays = "";
var wdays = ndays.split(",").sort();
for (var s = 0; s < wdays.length; s++) {
//alert(wdays[s]);
debugger;
if (wdays[s] === "1") {
cDays = "Mon";
}
else if (wdays[s] === "2") {
cDays = cDays + ",Tue";
}
else if (wdays[s] === "3") {
cDays = cDays + ",Wed";
}
else if (wdays[s] === "4") {
cDays = cDays + ",Thu";
}
else if (wdays[s] === "5") {
cDays = cDays + ",Fri";
}
else if (wdays[s] === "6") {
cDays = cDays + ",Sat";
}
else {
cDays = cDays + ",Sun";
}
}
});
There is no inbuilt function for it, you need to write your own logic as suggested in other answers. You can create one common function to compare two array's as...
function compareDays(wrongSquence , rightSequence) {
var i=0;
for(i=0;i<wrongSquence.length;i++) {
if(wrongSquence [i] != rightSequence[i]) {
wrongSquence [i] = rightSequence[i];
}
}
return wrongSquence;
}
//e.g....
var abc = ["mon","Thu","Fri","Tue","Wed","Sun","Sat"],
outputFormat = ["mon","Tue","Wed","Thu","Fri","Sat","Sun"];
var correctArray = compareDays(abc, outputFormat);
console.log(correctArray); // check output...

Which part is responsible on the animation in this script?

this code is from a jquery countdown counter , I am trying to eliminate the animation (flip) as you can see in the demo, I succeed to remove the main one, but if you notice at the end when a digit is at 0 you see a quick animation back to 9, and I could not figure which part is responsible for that, this is the code again here.
/*
* jquery-countdown plugin
*
* Copyright (c) 2009 Martin Conte Mac Donell <Reflejo#gmail.com>
* Dual licensed under the MIT and GPL licenses.
* http://docs.jquery.com/License
*
*/
// Draw digits in given container
var createDigits = function(where, options) {
var counter = 0;
// Iterate each startTime digit, if it is not a digit
// we'll asume that it's a separator
var mFirstPos, sFirstPos;
// reset digits and intervals array.
digits = [];
intervals = [];
for (var i = 0; i < options.startTime.length; i++) {
if (parseInt(options.startTime[i]) >= 0) {
elem = $('<div id="cnt_' + counter + '" class="cntDigit" />').css({
height: options.digitHeight,
float: 'left',
background: 'url(\'' + options.image + '\')',
width: options.digitWidth
});
elem.current = parseInt(options.startTime[i]);
digits.push(elem);
margin(counter, -elem.current * options.digitHeight * options.digitImages);
if (options.continuous === true) {
digits[counter]._max = function() { return 9; };
} else {
// Add max digits, for example, first digit of minutes (mm) has
// a max of 5. Conditional max is used when the left digit has reach
// the max. For example second "hours" digit has a conditional max of 4
switch (options.format[i]) {
case 'h':
digits[counter]._max = function(pos, isStart) {
if (pos % 2 == 0)
return 2;
else
return (isStart) ? 3: 9;
};
break;
case 'd':
digits[counter]._max = function() { return 9; };
break;
case 'm':
digits[counter]._max = function(pos) {
if(!mFirstPos) { mFirstPos = pos; }
return pos == mFirstPos ? 9 : 5;
};
break;
case 's':
digits[counter]._max = function(pos) {
if(!sFirstPos) { sFirstPos = pos; }
return pos == sFirstPos ? 9 : 5;
};
}
}
counter += 1;
} else {
elem = $('<div class="cntSeparator"/>').css({float: 'left'})
.text(options.startTime[i]);
}
where.append(elem)
}
};
var makeMovement = function(elem, steps, isForward, options) {
// Stop any other movement over the same digit.
if (intervals[elem])
window.clearInterval(intervals[elem]);
// Move to the initial position (We force that because in chrome
// there are some scenarios where digits lost sync)
var initialPos = -(options.digitHeight * options.digitImages *
digits[elem].current);
margin(elem, initialPos);
digits[elem].current = digits[elem].current + ((isForward) ? steps: -steps);
var x = 0;
intervals[elem] = setInterval(function() {
if (x++ === options.digitImages * steps) {
window.clearInterval(intervals[elem]);
delete intervals[elem];
return;
}
var diff = isForward ? -options.digitHeight: options.digitHeight;
margin(elem, initialPos + (x * diff));
}, options.stepTime / steps);
};
// Set or get element margin
var margin = function(elem, val) {
if (val !== undefined) {
digits[elem].margin = val;
return digits[elem].css({'backgroundPosition': '0 ' + val + 'px'});
}
return digits[elem].margin || 0;
};
// Makes the movement. This is done by "digitImages" steps.
var moveDigit = function(elem, options) {
if (digits[elem].current == 0) {
// Is there still time left?
if (elem > 0) {
var isStart = (digits[elem - 1].current == 0);
makeMovement(elem, digits[elem]._max(elem, isStart), true, options);
moveDigit(elem - 1, options);
} else { // That condition means that we reach the end! 00:00.
for (var i = 0; i < digits.length; i++) {
clearInterval(intervals[i]);
clearInterval(intervals.main);
margin(i, 0);
}
options.timerEnd();
}
return;
}
makeMovement(elem, 1, false, options);
};
// parses a date of the form hh:mm:ss, for example, where
// ... precision is the same as the format.
var parseRelativeDate = function(form, options) {
// give the date the values of now by default
var now = new Date();
var d = now.getDate();
var m = now.getMonth() + 1;
var y = now.getFullYear();
var h = now.getHours(), mm, s;
// read in components and render based on format
var format = options.format;
var parts = form.split(':');
if( format.indexOf('dd') == 0 ) {
d = parts[0];
parts = parts.slice(1);
format = format.substr(3);
}
if( format.indexOf('hh') == 0 ) {
h = parts[0];
parts = parts.slice(1);
format = format.substr(3);
}
if( format.indexOf('mm') == 0 ) {
mm = parts[0];
parts = parts.slice(1);
format = format.substr(3);
}
if( format.indexOf('ss') == 0 ) {
s = parts[0];
parts = parts.slice(1);
format = format.substr(3);
}
// return our constructed date object
return new Date([m, d, y].join('/') + ' ' + [h, mm, s].map(pad).join(':') + ' GMT-0900');
};
// convert a date object to the format specified
var formatCompute = function(d, options) {
var format = options.format;
var parse = {
d: d.getUTCDate() - 1,
h: d.getUTCHours(),
m: d.getUTCMinutes(),
s: d.getUTCSeconds()
};
return format.replace(/(dd|hh|mm|ss)/g, function($0, form) {
return pad(parse[form[0]]);
});
};
// add leading zeros
var pad = function(x){return (1e15+""+x).slice(-2)};
var digits = [];
var intervals = [];
jQuery.fn.countdown = function(userOptions) {
// Default options
var options = {
stepTime: 60,
// startTime and format MUST follow the same format.
// also you cannot specify a format unordered (e.g. hh:ss:mm is wrong)
format: "dd:hh:mm:ss",
startTime: "01:12:32:55",
digitImages: 6,
digitWidth: 67,
digitHeight: 90,
timerEnd: function(){},
image: "digits.png",
continuous: false
};
$.extend(options, userOptions);
// if an endTime is provided...
if( userOptions.endTime ) {
// calculate the difference between endTime and present time
var endDate = userOptions.endTime instanceof Date ? userOptions.endTime : parseRelativeDate(userOptions.endTime, options);
var diff = endDate.getTime() - (new Date()).getTime();
// and set that as the startTime
userOptions.startTime = formatCompute(new Date(diff), options);
delete userOptions.endTime;
}
$.extend(options, userOptions);
if (this.length) {
clearInterval(intervals.main);
createDigits(this, options);
intervals.main = setInterval(function(){ moveDigit(digits.length - 1, options); },
1000);
}
};
Is this:
setInterval(function(){ moveDigit(digits.length - 1, options); },
1000);
your animation has a duration of one second and this runs the function moveDigit()

Jquery Countdown... time is running out

I am trying to change the end of the countdown so it displays a countdown till the end date of 22nd of May 2014 on the below countdown, any idea how I do that?
Here is the webiste nordicitsourcing.com you will see it currently is counting down to a date I cannot even seem to find
Please help
Code here:
(function ($) {
function Countdown() {
this.regional = [];
this.regional[''] = {
labels: ['Years', 'Months', 'Weeks', 'Days', 'Hours', 'Minutes', 'Seconds'],
labels1: ['Year', 'Month', 'Week', 'Day', 'Hour', 'Minute', 'Second'],
compactLabels: ['y', 'm', 'w', 'd'],
whichLabels: null,
digits: ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'],
timeSeparator: ':',
isRTL: false
};
this._defaults = {
until: null,
since: null,
timezone: null,
serverSync: null,
format: 'dHMS',
layout: '',
compact: false,
significant: 0,
description: '',
expiryUrl: '',
expiryText: '',
alwaysExpire: false,
onExpiry: null,
onTick: null,
tickInterval: 1
};
$.extend(this._defaults, this.regional['']);
this._serverSyncs = [];
var c = (typeof Date.now == 'function' ? Date.now : function () {
return new Date().getTime()
});
var d = (window.performance && typeof window.performance.now == 'function');
function timerCallBack(a) {
var b = (a < 1e12 ? (d ? (performance.now() + performance.timing.navigationStart) : c()) : a || c());
if (b - f >= 1000) {
x._updateTargets();
f = b
}
e(timerCallBack)
}
var e = window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame || null;
var f = 0;
if (!e || $.noRequestAnimationFrame) {
$.noRequestAnimationFrame = null;
setInterval(function () {
x._updateTargets()
}, 980)
} else {
f = window.animationStartTime || window.webkitAnimationStartTime || window.mozAnimationStartTime || window.oAnimationStartTime || window.msAnimationStartTime || c();
e(timerCallBack)
}
}
var Y = 0;
var O = 1;
var W = 2;
var D = 3;
var H = 4;
var M = 5;
var S = 6;
$.extend(Countdown.prototype, {
markerClassName: 'hasCountdown',
propertyName: 'countdown',
_rtlClass: 'countdown_rtl',
_sectionClass: 'countdown_section',
_amountClass: 'countdown_amount',
_rowClass: 'countdown_row',
_holdingClass: 'countdown_holding',
_showClass: 'countdown_show',
_descrClass: 'countdown_descr',
_timerTargets: [],
setDefaults: function (a) {
this._resetExtraLabels(this._defaults, a);
$.extend(this._defaults, a || {})
},
UTCDate: function (a, b, c, e, f, g, h, i) {
if (typeof b == 'object' && b.constructor == Date) {
i = b.getMilliseconds();
h = b.getSeconds();
g = b.getMinutes();
f = b.getHours();
e = b.getDate();
c = b.getMonth();
b = b.getFullYear()
}
var d = new Date();
d.setUTCFullYear(b);
d.setUTCDate(1);
d.setUTCMonth(c || 0);
d.setUTCDate(e || 1);
d.setUTCHours(f || 0);
d.setUTCMinutes((g || 0) - (Math.abs(a) < 30 ? a * 60 : a));
d.setUTCSeconds(h || 0);
d.setUTCMilliseconds(i || 0);
return d
},
periodsToSeconds: function (a) {
return a[0] * 31557600 + a[1] * 2629800 + a[2] * 604800 + a[3] * 86400 + a[4] * 3600 + a[5] * 60 + a[6]
},
_attachPlugin: function (a, b) {
a = $(a);
if (a.hasClass(this.markerClassName)) {
return
}
var c = {
options: $.extend({}, this._defaults),
_periods: [0, 0, 0, 0, 0, 0, 0]
};
a.addClass(this.markerClassName).data(this.propertyName, c);
this._optionPlugin(a, b)
},
_addTarget: function (a) {
if (!this._hasTarget(a)) {
this._timerTargets.push(a)
}
},
_hasTarget: function (a) {
return ($.inArray(a, this._timerTargets) > -1)
},
_removeTarget: function (b) {
this._timerTargets = $.map(this._timerTargets, function (a) {
return (a == b ? null : a)
})
},
_updateTargets: function () {
for (var i = this._timerTargets.length - 1; i >= 0; i--) {
this._updateCountdown(this._timerTargets[i])
}
},
_optionPlugin: function (a, b, c) {
a = $(a);
var d = a.data(this.propertyName);
if (!b || (typeof b == 'string' && c == null)) {
var e = b;
b = (d || {}).options;
return (b && e ? b[e] : b)
}
if (!a.hasClass(this.markerClassName)) {
return
}
b = b || {};
if (typeof b == 'string') {
var e = b;
b = {};
b[e] = c
}
if (b.layout) {
b.layout = b.layout.replace(/</g, '<').replace(/>/g, '>')
}
this._resetExtraLabels(d.options, b);
var f = (d.options.timezone != b.timezone);
$.extend(d.options, b);
this._adjustSettings(a, d, b.until != null || b.since != null || f);
var g = new Date();
if ((d._since && d._since < g) || (d._until && d._until > g)) {
this._addTarget(a[0])
}
this._updateCountdown(a, d)
},
_updateCountdown: function (a, b) {
var c = $(a);
b = b || c.data(this.propertyName);
if (!b) {
return
}
c.html(this._generateHTML(b)).toggleClass(this._rtlClass, b.options.isRTL);
if ($.isFunction(b.options.onTick)) {
var d = b._hold != 'lap' ? b._periods : this._calculatePeriods(b, b._show, b.options.significant, new Date());
if (b.options.tickInterval == 1 || this.periodsToSeconds(d) % b.options.tickInterval == 0) {
b.options.onTick.apply(a, [d])
}
}
var e = b._hold != 'pause' && (b._since ? b._now.getTime() < b._since.getTime() : b._now.getTime() >= b._until.getTime());
if (e && !b._expiring) {
b._expiring = true;
if (this._hasTarget(a) || b.options.alwaysExpire) {
this._removeTarget(a);
if ($.isFunction(b.options.onExpiry)) {
b.options.onExpiry.apply(a, [])
}
if (b.options.expiryText) {
var f = b.options.layout;
b.options.layout = b.options.expiryText;
this._updateCountdown(a, b);
b.options.layout = f
}
if (b.options.expiryUrl) {
window.location = b.options.expiryUrl
}
}
b._expiring = false
} else if (b._hold == 'pause') {
this._removeTarget(a)
}
c.data(this.propertyName, b)
},
_resetExtraLabels: function (a, b) {
var c = false;
for (var n in b) {
if (n != 'whichLabels' && n.match(/[Ll]abels/)) {
c = true;
break
}
}
if (c) {
for (var n in a) {
if (n.match(/[Ll]abels[02-9]|compactLabels1/)) {
a[n] = null
}
}
}
},
_adjustSettings: function (a, b, c) {
var d;
var e = 0;
var f = null;
for (var i = 0; i < this._serverSyncs.length; i++) {
if (this._serverSyncs[i][0] == b.options.serverSync) {
f = this._serverSyncs[i][1];
break
}
}
if (f != null) {
e = (b.options.serverSync ? f : 0);
d = new Date()
} else {
var g = ($.isFunction(b.options.serverSync) ? b.options.serverSync.apply(a, []) : null);
d = new Date();
e = (g ? d.getTime() - g.getTime() : 0);
this._serverSyncs.push([b.options.serverSync, e])
}
var h = b.options.timezone;
h = (h == null ? -d.getTimezoneOffset() : h);
if (c || (!c && b._until == null && b._since == null)) {
b._since = b.options.since;
if (b._since != null) {
b._since = this.UTCDate(h, this._determineTime(b._since, null));
if (b._since && e) {
b._since.setMilliseconds(b._since.getMilliseconds() + e)
}
}
b._until = this.UTCDate(h, this._determineTime(b.options.until, d));
if (e) {
b._until.setMilliseconds(b._until.getMilliseconds() + e)
}
}
b._show = this._determineShow(b)
},
_destroyPlugin: function (a) {
a = $(a);
if (!a.hasClass(this.markerClassName)) {
return
}
this._removeTarget(a[0]);
a.removeClass(this.markerClassName).empty().removeData(this.propertyName)
},
_pausePlugin: function (a) {
this._hold(a, 'pause')
},
_lapPlugin: function (a) {
this._hold(a, 'lap')
},
_resumePlugin: function (a) {
this._hold(a, null)
},
_hold: function (a, b) {
var c = $.data(a, this.propertyName);
if (c) {
if (c._hold == 'pause' && !b) {
c._periods = c._savePeriods;
var d = (c._since ? '-' : '+');
c[c._since ? '_since' : '_until'] = this._determineTime(d + c._periods[0] + 'y' + d + c._periods[1] + 'o' + d + c._periods[2] + 'w' + d + c._periods[3] + 'd' + d + c._periods[4] + 'h' + d + c._periods[5] + 'm' + d + c._periods[6] + 's');
this._addTarget(a)
}
c._hold = b;
c._savePeriods = (b == 'pause' ? c._periods : null);
$.data(a, this.propertyName, c);
this._updateCountdown(a, c)
}
},
_getTimesPlugin: function (a) {
var b = $.data(a, this.propertyName);
return (!b ? null : (b._hold == 'pause' ? b._savePeriods : (!b._hold ? b._periods : this._calculatePeriods(b, b._show, b.options.significant, new Date()))))
},
_determineTime: function (k, l) {
var m = function (a) {
var b = new Date();
b.setTime(b.getTime() + a * 1000);
return b
};
var n = function (a) {
a = a.toLowerCase();
var b = new Date();
var c = b.getFullYear();
var d = b.getMonth();
var e = b.getDate();
var f = b.getHours();
var g = b.getMinutes();
var h = b.getSeconds();
var i = /([+-]?[0-9]+)\s*(s|m|h|d|w|o|y)?/g;
var j = i.exec(a);
while (j) {
switch (j[2] || 's') {
case 's':
h += parseInt(j[1], 10);
break;
case 'm':
g += parseInt(j[1], 10);
break;
case 'h':
f += parseInt(j[1], 10);
break;
case 'd':
e += parseInt(j[1], 10);
break;
case 'w':
e += parseInt(j[1], 10) * 7;
break;
case 'o':
d += parseInt(j[1], 10);
e = Math.min(e, x._getDaysInMonth(c, d));
break;
case 'y':
c += parseInt(j[1], 10);
e = Math.min(e, x._getDaysInMonth(c, d));
break
}
j = i.exec(a)
}
return new Date(c, d, e, f, g, h, 0)
};
var o = (k == null ? l : (typeof k == 'string' ? n(k) : (typeof k == 'number' ? m(k) : k)));
if (o) o.setMilliseconds(0);
return o
},
_getDaysInMonth: function (a, b) {
return 32 - new Date(a, b, 32).getDate()
},
_normalLabels: function (a) {
return a
},
_generateHTML: function (c) {
var d = this;
c._periods = (c._hold ? c._periods : this._calculatePeriods(c, c._show, c.options.significant, new Date()));
var e = false;
var f = 0;
var g = c.options.significant;
var h = $.extend({}, c._show);
for (var i = Y; i <= S; i++) {
e |= (c._show[i] == '?' && c._periods[i] > 0);
h[i] = (c._show[i] == '?' && !e ? null : c._show[i]);
f += (h[i] ? 1 : 0);
g -= (c._periods[i] > 0 ? 1 : 0)
}
var j = [false, false, false, false, false, false, false];
for (var i = S; i >= Y; i--) {
if (c._show[i]) {
if (c._periods[i]) {
j[i] = true
} else {
j[i] = g > 0;
g--
}
}
}
var k = (c.options.compact ? c.options.compactLabels : c.options.labels);
var l = c.options.whichLabels || this._normalLabels;
var m = function (a) {
var b = c.options['compactLabels' + l(c._periods[a])];
return (h[a] ? d._translateDigits(c, c._periods[a]) + (b ? b[a] : k[a]) + ' ' : '')
};
var n = function (a) {
var b = c.options['labels' + l(c._periods[a])];
return ((!c.options.significant && h[a]) || (c.options.significant && j[a]) ? '<span class="' + x._sectionClass + '">' + '<span class="' + x._amountClass + '">' + d._translateDigits(c, c._periods[a]) + '</span><br/>' + (b ? b[a] : k[a]) + '</span>' : '')
};
return (c.options.layout ? this._buildLayout(c, h, c.options.layout, c.options.compact, c.options.significant, j) : ((c.options.compact ? '<span class="' + this._rowClass + ' ' + this._amountClass + (c._hold ? ' ' + this._holdingClass : '') + '">' + m(Y) + m(O) + m(W) + m(D) + (h[H] ? this._minDigits(c, c._periods[H], 2) : '') + (h[M] ? (h[H] ? c.options.timeSeparator : '') + this._minDigits(c, c._periods[M], 2) : '') + (h[S] ? (h[H] || h[M] ? c.options.timeSeparator : '') + this._minDigits(c, c._periods[S], 2) : '') : '<span class="' + this._rowClass + ' ' + this._showClass + (c.options.significant || f) + (c._hold ? ' ' + this._holdingClass : '') + '">' + n(Y) + n(O) + n(W) + n(D) + n(H) + n(M) + n(S)) + '</span>' + (c.options.description ? '<span class="' + this._rowClass + ' ' + this._descrClass + '">' + c.options.description + '</span>' : '')))
},
_buildLayout: function (c, d, e, f, g, h) {
var j = c.options[f ? 'compactLabels' : 'labels'];
var k = c.options.whichLabels || this._normalLabels;
var l = function (a) {
return (c.options[(f ? 'compactLabels' : 'labels') + k(c._periods[a])] || j)[a]
};
var m = function (a, b) {
return c.options.digits[Math.floor(a / b) % 10]
};
var o = {
desc: c.options.description,
sep: c.options.timeSeparator,
yl: l(Y),
yn: this._minDigits(c, c._periods[Y], 1),
ynn: this._minDigits(c, c._periods[Y], 2),
ynnn: this._minDigits(c, c._periods[Y], 3),
y1: m(c._periods[Y], 1),
y10: m(c._periods[Y], 10),
y100: m(c._periods[Y], 100),
y1000: m(c._periods[Y], 1000),
ol: l(O),
on: this._minDigits(c, c._periods[O], 1),
onn: this._minDigits(c, c._periods[O], 2),
onnn: this._minDigits(c, c._periods[O], 3),
o1: m(c._periods[O], 1),
o10: m(c._periods[O], 10),
o100: m(c._periods[O], 100),
o1000: m(c._periods[O], 1000),
wl: l(W),
wn: this._minDigits(c, c._periods[W], 1),
wnn: this._minDigits(c, c._periods[W], 2),
wnnn: this._minDigits(c, c._periods[W], 3),
w1: m(c._periods[W], 1),
w10: m(c._periods[W], 10),
w100: m(c._periods[W], 100),
w1000: m(c._periods[W], 1000),
dl: l(D),
dn: this._minDigits(c, c._periods[D], 1),
dnn: this._minDigits(c, c._periods[D], 2),
dnnn: this._minDigits(c, c._periods[D], 3),
d1: m(c._periods[D], 1),
d10: m(c._periods[D], 10),
d100: m(c._periods[D], 100),
d1000: m(c._periods[D], 1000),
hl: l(H),
hn: this._minDigits(c, c._periods[H], 1),
hnn: this._minDigits(c, c._periods[H], 2),
hnnn: this._minDigits(c, c._periods[H], 3),
h1: m(c._periods[H], 1),
h10: m(c._periods[H], 10),
h100: m(c._periods[H], 100),
h1000: m(c._periods[H], 1000),
ml: l(M),
mn: this._minDigits(c, c._periods[M], 1),
mnn: this._minDigits(c, c._periods[M], 2),
mnnn: this._minDigits(c, c._periods[M], 3),
m1: m(c._periods[M], 1),
m10: m(c._periods[M], 10),
m100: m(c._periods[M], 100),
m1000: m(c._periods[M], 1000),
sl: l(S),
sn: this._minDigits(c, c._periods[S], 1),
snn: this._minDigits(c, c._periods[S], 2),
snnn: this._minDigits(c, c._periods[S], 3),
s1: m(c._periods[S], 1),
s10: m(c._periods[S], 10),
s100: m(c._periods[S], 100),
s1000: m(c._periods[S], 1000)
};
var p = e;
for (var i = Y; i <= S; i++) {
var q = 'yowdhms'.charAt(i);
var r = new RegExp('\\{' + q + '<\\}([\\s\\S]*)\\{' + q + '>\\}', 'g');
p = p.replace(r, ((!g && d[i]) || (g && h[i]) ? '$1' : ''))
}
$.each(o, function (n, v) {
var a = new RegExp('\\{' + n + '\\}', 'g');
p = p.replace(a, v)
});
return p
},
_minDigits: function (a, b, c) {
b = '' + b;
if (b.length >= c) {
return this._translateDigits(a, b)
}
b = '0000000000' + b;
return this._translateDigits(a, b.substr(b.length - c))
},
_translateDigits: function (b, c) {
return ('' + c).replace(/[0-9]/g, function (a) {
return b.options.digits[a]
})
},
_determineShow: function (a) {
var b = a.options.format;
var c = [];
c[Y] = (b.match('y') ? '?' : (b.match('Y') ? '!' : null));
c[O] = (b.match('o') ? '?' : (b.match('O') ? '!' : null));
c[W] = (b.match('w') ? '?' : (b.match('W') ? '!' : null));
c[D] = (b.match('d') ? '?' : (b.match('D') ? '!' : null));
c[H] = (b.match('h') ? '?' : (b.match('H') ? '!' : null));
c[M] = (b.match('m') ? '?' : (b.match('M') ? '!' : null));
c[S] = (b.match('s') ? '?' : (b.match('S') ? '!' : null));
return c
},
_calculatePeriods: function (c, d, e, f) {
c._now = f;
c._now.setMilliseconds(0);
var g = new Date(c._now.getTime());
if (c._since) {
if (f.getTime() < c._since.getTime()) {
c._now = f = g
} else {
f = c._since
}
} else {
g.setTime(c._until.getTime());
if (f.getTime() > c._until.getTime()) {
c._now = f = g
}
}
var h = [0, 0, 0, 0, 0, 0, 0];
if (d[Y] || d[O]) {
var i = x._getDaysInMonth(f.getFullYear(), f.getMonth());
var j = x._getDaysInMonth(g.getFullYear(), g.getMonth());
var k = (g.getDate() == f.getDate() || (g.getDate() >= Math.min(i, j) && f.getDate() >= Math.min(i, j)));
var l = function (a) {
return (a.getHours() * 60 + a.getMinutes()) * 60 + a.getSeconds()
};
var m = Math.max(0, (g.getFullYear() - f.getFullYear()) * 12 + g.getMonth() - f.getMonth() + ((g.getDate() < f.getDate() && !k) || (k && l(g) < l(f)) ? -1 : 0));
h[Y] = (d[Y] ? Math.floor(m / 12) : 0);
h[O] = (d[O] ? m - h[Y] * 12 : 0);
f = new Date(f.getTime());
var n = (f.getDate() == i);
var o = x._getDaysInMonth(f.getFullYear() + h[Y], f.getMonth() + h[O]);
if (f.getDate() > o) {
f.setDate(o)
}
f.setFullYear(f.getFullYear() + h[Y]);
f.setMonth(f.getMonth() + h[O]);
if (n) {
f.setDate(o)
}
}
var p = Math.floor((g.getTime() - f.getTime()) / 1000);
var q = function (a, b) {
h[a] = (d[a] ? Math.floor(p / b) : 0);
p -= h[a] * b
};
q(W, 604800);
q(D, 86400);
q(H, 3600);
q(M, 60);
q(S, 1);
if (p > 0 && !c._since) {
var r = [1, 12, 4.3482, 7, 24, 60, 60];
var s = S;
var t = 1;
for (var u = S; u >= Y; u--) {
if (d[u]) {
if (h[s] >= t) {
h[s] = 0;
p = 1
}
if (p > 0) {
h[u]++;
p = 0;
s = u;
t = 1
}
}
t *= r[u]
}
}
if (e) {
for (var u = Y; u <= S; u++) {
if (e && h[u]) {
e--
} else if (!e) {
h[u] = 0
}
}
}
return h
}
});
var w = ['getTimes'];
function isNotChained(a, b) {
if (a == 'option' && (b.length == 0 || (b.length == 1 && typeof b[0] == 'string'))) {
return true
}
return $.inArray(a, w) > -1
}
$.fn.countdown = function (a) {
var b = Array.prototype.slice.call(arguments, 1);
if (isNotChained(a, b)) {
return x['_' + a + 'Plugin'].apply(x, [this[0]].concat(b))
}
return this.each(function () {
if (typeof a == 'string') {
if (!x['_' + a + 'Plugin']) {
throw 'Unknown command: ' + a;
}
x['_' + a + 'Plugin'].apply(x, [this].concat(b))
} else {
x._attachPlugin(this, a || {})
}
})
};
var x = $.countdown = new Countdown()
})(jQuery);
There is a javascript file called custom.js
Here is the code to find you will see the date you have to modify,
Additional information regarding this plugin can be found http://keith-wood.name/countdown.html
// Countdown //
$('#countdown').countdown({
until: new Date(2014, 10 - 1, 9), // new Date(year, mth - 1, day, hr, min, sec) - date/time to count down to
// or numeric for seconds offset, or string for unit offset(s):
// 'Y' years, 'O' months, 'W' weeks, 'D' days, 'H' hours, 'M' minutes, 'S' seconds
timezone: -4, // The timezone (hours or minutes from GMT) for the target times, or null for client local
layout: '{d<}<div class="span3"><div class="digit-container">{dn}<span class="label-container">{dl}</span></div></div>{d>}{h<}<div class="span3"><div class="digit-container">{hn}<span class="label-container">{hl}</span></div></div>{h>}{m<}<div class="span3"><div class="digit-container">{mn}<span class="label-container">{ml}</span></div></div>{m>}{s<}<div class="span3"><div class="digit-container">{sn}<span class="label-container">{sl}</span></div></div>{s>}',
timeSeparator: '', // Separator for time periods
isRTL: false, // True for right-to-left languages, false for left-to-right
format: 'dHMS', // Format for display - upper case for always, lower case only if non-zero,
// 'Y' years, 'O' months, 'W' weeks, 'D' days, 'H' hours, 'M' minutes, 'S' seconds
alwaysExpire: true, // True to trigger onExpiry even if never counted down
onExpiry: liftOff // Callback when the countdown expires -
// receives no parameters and 'this' is the containing division
});

Check SSL certificate Expiration Date

I need to check local computer's SSl certificate expiry DATE and compare it with current date and notify user that his/her certificate is going to expire in X days. All this I need to do in JavaScript.
Your certificate should look like this:
-----BEGIN CERTIFICATE-----
MIIGoDCCBIigAwIBAgIJAICRY3cWdgK1MA0GCSqGSIb3DQEBCwUAMIGeMQswCQYD
VQQGEwJCRzERMA8GA1UECAwIQnVsZ2FyaWExDjAMBgNVBAcMBVNvZmlhMQ8wDQYD
..
ud5Nja8+xycA/Jk7bSvB1jJjpc3oL0G9j0HOcxqQKd4e1IQXuss5V7FnQxSOVCq4
GVK0r3LkAxtl/EGmQC1DRlHAUWg=
-----END CERTIFICATE-----
You need to strip the -----BEGIN CERTIFICATE----- header and the -----END CERTIFICATE----- trailer from the certificate data, the rest is a Base64 encoded byte array.
You need to decode it to an array of bytes (in this example represented as array of number, where each number represents a byte - number between 0 and 255 inclusive).
That byte array is a DER encoded ASN.1 structure as defined in RFC-5280.
The below example will parse the content of the certificate after the -----BEGIN CERTIFICATE----- and -----END CERTIFICATE----- traile has already been stripped.
Usage:
var pem =
"MIIGijCCBXKgAwIBAgIQEpI/gkvDS6idH2m2Zwn7ZzANBgkqhkiG9w0BAQsFADCB\n"
...
+"VQ+o34uWo7z19I8eXWSXN6P+Uj1OvHn8zNM1G/ddjQXBwMvzwwJEdVBhdK1uQw==\n";
var bytes = fromBase64(pem);
var validity = getValidity(bytes);
var notBefore = validity.notBefore;
var notAfter = validity.notAfter;
var now = new Date();
if ( notBefore.getTime() < now.getTime()
&& now.getTime() < notAfter.getTime())
{
// Certificate is withing its validity days
} else {
// Certificate is either not yet valid or has already expired.
}
Parsing:
var TYPE_INTEGER = 0x02;
var TYPE_SEQUENCE = 0x10;
var TYPE_UTC_TIME = 0x17;
var TYPE_GENERALIZED_TIME = 0x18;
function subArray(original, start, end) {
var subArr = [];
var index = 0;
for (var i = start; i < end; i++) {
subArr[index++] = original[i];
}
return subArr;
}
function getDigit(d) {
switch (d) {
default:
case 0x30: case '0': return 0;
case 0x31: case '1': return 1;
case 0x32: case '2': return 2;
case 0x33: case '3': return 3;
case 0x34: case '4': return 4;
case 0x35: case '5': return 5;
case 0x36: case '6': return 6;
case 0x37: case '7': return 7;
case 0x38: case '8': return 8;
case 0x39: case '9': return 9;
}
}
function enterTag(bytes, start, requiredTypes, name) {
if (start + 1 > bytes.length) {
throw new Error("Too short certificate input");
}
var typeByte = bytes[start ] & 0x0FF;
var lenByte = bytes[start +1] & 0x0FF;
var type = typeByte & 0x1F;
var len = lenByte;
var index = start + 2;
if (requiredTypes.length > 0 && requiredTypes.indexOf(type) == -1) {
throw new Error("Invalid type");
}
var lengthOfLength = 0;
if (len > 0x07F) {
lengthOfLength = len & 0x7F;
len = 0;
for (var i =0; i < lengthOfLength && index < bytes.length; i++) {
len = (len << 8 ) | (bytes[index] & 0x00FF);
index++;
}
}
if (index >= bytes.length) {
throw new Error("Too short certificate input");
}
return {index: index, type: type, length: len}
}
function processTag(bytes, start, requiredTypes, name) {
var result = enterTag(bytes, start, requiredTypes, name);
var index = result.index + result.length;
if (index >= bytes.length) {
throw new Error("Too short certificate input");
}
var valueStart = result.index;
var valueEnd = result.index + result.length;
var value = subArray(bytes, valueStart, valueEnd);
return { index: index, type: result.type, value: value};
}
function readDate(bytes, start, name) {
var date = new Date();
var result = processTag(bytes, start,
[TYPE_UTC_TIME, TYPE_GENERALIZED_TIME], name);
var index, year;
if (result.type == 0x17) { // UTCTime
if (result.value.length < 12) {
throw new Error("Invalid type");
}
var yearHigh = getDigit(result.value[0]);
var yearLow = getDigit(result.value[1]);
var year2Digits = (yearHigh * 10 ) + (yearLow)
if (year2Digits >= 50) {
year = 1900 + year2Digits;
} else {
year = 2000 + year2Digits;
}
index = 2;
} else if (result.type = 0x18) { // GeneralizedTime
if (result.value.length < 14) {
throw new Error("Invalid type");
}
var year1 = getDigit(result.value[0]);
var year2 = getDigit(result.value[1]);
var year3 = getDigit(result.value[2]);
var year4 = getDigit(result.value[3]);
year = (year1 * 1000) + (year2 * 100) + (year3*10) + year4;
index = 4;
}
var monthHigh = getDigit(result.value[index++]);
var monthLow = getDigit(result.value[index++]);
var dayHigh = getDigit(result.value[index++]);
var dayhLow = getDigit(result.value[index++]);
var hourHigh = getDigit(result.value[index++]);
var hourLow = getDigit(result.value[index++]);
var minuteHigh = getDigit(result.value[index++]);
var minuteLow = getDigit(result.value[index++]);
var secondHigh = getDigit(result.value[index++]);
var secondLow = getDigit(result.value[index]);
var month = (monthHigh * 10) + monthLow;
var day = (dayHigh * 10) + dayhLow;
var hour = (hourHigh * 10) + hourLow;
var minute = (minuteHigh * 10) + minuteLow;
var second = (secondHigh * 10) + secondLow;
if (month < 1 || month > 12) {
throw new Error("Invalid month");
}
if (day < 1 || day > 31) {
throw new Error("Invalid day");
}
if (hour < 0 || hour > 24) {
throw new Error("Invalid hour");
}
if (minute < 0 || minute > 59) {
throw new Error("Invalid minute");
}
if (second < 0 || second > 59) {
throw new Error("Invalid second ");
}
date.setUTCFullYear(year);
date.setUTCMonth(month-1);
date.setUTCDate(day);
date.setUTCHours(hour);
date.setUTCMinutes(minute);
date.setUTCSeconds(second);
return {
index: result.index,
type: result.type,
length: result.length,
value: result.value,
date: date
};
}
function getValidity(bytes) {
if (bytes == null || bytes.length <= 0) {
return null;
}
var index = 0;
index = enterTag(bytes, index, [TYPE_SEQUENCE], "Certificate").index;
index = enterTag(bytes, index, [TYPE_SEQUENCE], "TBSCertificate").index;
var result = processTag(bytes, index, [0x00, 0x02],
"Version or SerialNumber");
if (result.type == 0) {
index = result.index;
result = processTag(bytes, index, [TYPE_INTEGER], "SerialNumber")
}
index = result.index;
result = processTag(bytes, index, [TYPE_SEQUENCE],
"Signature AlgorithmIdentifier");
index = result.index;
result = processTag(bytes, index, [], "Issuer Name");
index = result.index;
index = enterTag(bytes, index, [TYPE_SEQUENCE], "Validity").index;
result = readDate(bytes, index, "Not Before");
var notBefore = result.date;
index = result.index;
result = readDate(bytes, index, "Not After");
var notAfter = result.date;
return {notBefore: notBefore, notAfter: notAfter};
}
function getNextBase64Chr(str, index, equalSignReceived, alpha) {
var chr = null;
var code = 0;
var padding = equalSignReceived;
while (index < str.length) {
chr = str.charAt(index);
if (chr == " " || chr == "\r" || chr == "\n" || chr == "\t") {
index++;
continue;
}
if (chr == "=") {
padding = true;
} else {
if (equalSignReceived) {
throw new Error("Invalid Base64 Endcoding.");
}
code = alpha.indexOf(chr);
if (code == -1) {
throw new Error("Invalid Base64 Encoding .");
}
}
break;
}
return { character: chr, code: code, padding: padding, nextIndex: ++index};
}
function fromBase64(str) {
var alpha = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
var value = [];
var index = 0;
var destIndex = 0;
var padding = false;
while (true) {
var first = getNextBase64Chr(str, index, padding, alpha);
var second = getNextBase64Chr(str, first .nextIndex, first .padding, alpha);
var third = getNextBase64Chr(str, second.nextIndex, second.padding, alpha);
var fourth = getNextBase64Chr(str, third .nextIndex, third .padding, alpha);
index = fourth.nextIndex;
padding = fourth.padding;
// ffffffss sssstttt ttffffff
var base64_first = first.code == null ? 0 : first.code;
var base64_second = second.code == null ? 0 : second.code;
var base64_third = third.code == null ? 0 : third.code;
var base64_fourth = fourth.code == null ? 0 : fourth.code;
var a = (( base64_first << 2 ) & 0xFC ) | ((base64_second >> 4) & 0x03);
var b = (( base64_second << 4 ) & 0xF0 ) | ((base64_third >> 2) & 0x0F);
var c = (( base64_third << 6 ) & 0xC0 ) | ((base64_fourth >> 0) & 0x3F);
value [destIndex++] = a;
if (!third.padding) {
value [destIndex++] = b;
} else {
break;
}
if (!fourth.padding) {
value [destIndex++] = c;
} else {
break;
}
if (index >= str.length) {
break;
}
}
return value;
}
Used resources:
A Layman's Guide to a Subset of ASN.1, BER, and DER
Encoding of ASN.1 UTC Time and GeneralizedTime
RFC-5280
The only available option so far is forge - https://github.com/digitalbazaar/forge/blob/master/README.md or some sort of custom extension for the client.
Client side does not know nothing about other than DOM elements thus it cannot inspect SSL layer.
More on this Within a web browser, is it possible for JavaScript to obtain information about the SSL Certificate being used for the current page?
This is not possible from the client, but you could do something like this with node / shell combo.
Assuming you have access to the server the cert is running on you could do something like this on the host:
var execSync = require('child_process').execSync
var cmd = "echo | openssl s_client -connect 127.0.0.1:443 2>/dev/null | openssl x509 -noout -dates"
var stdout = execSync(cmd).toString()
// "notBefore=Feb 16 15:33:00 2017 GMT\nnotAfter=May 17 15:33:00 2017 GMT"
From there you could parse the dates reported by stdout and write them to a public resource or json file so they are readable from the client, and from there do your date comparison.

Categories

Resources