/* 'Magic' date parsing, by Simon Willison (6th October 2003)
http://simon.incutio.com/archive/2003/10/06/betterDateInput

Modifications By Tanny O'Haley
24 Feb 2006 Changed order of setting date items from day, month, year
to year, month, day. When a user put in "31 jan" and the 
current month did not end in 31 the date first be put to the
next month then the entered date. If today was 27 Feb and
the user put in 31 jan the date first be changed to 3 Mar,
then the month would be set to Jan. The date displayed
would be 3 Jan instead of 31 Jan. By changing the order
the date is set correctly.
27 Feb 2006 Added code to display the dates in formats other than mm/dd/yyyy.
03 Jul 2006 Added code to automatically add magicDate behavior to input fields 
with a className that includes the word dateparse.
*/

/* Finds the index of the first occurence of item in the array, or -1 if not found */
Array.prototype.indexOf = function(item) {
    for (var i = 0; i < this.length; i++) {
        if (this[i] == item) {
            return i;
        }
    }
    return -1;
};
/* Returns an array of items judged 'true' by the passed in test function */
Array.prototype.filter = function(test) {
    var matches = [];
    for (var i = 0; i < this.length; i++) {
        if (test(this[i])) {
            matches[matches.length] = this[i];
        }
    }
    return matches;
};

var monthNames = "January February March April May June July August September October November December".split(" ");
var weekdayNames = "Sunday Monday Tuesday Wednesday Thursday Friday Saturday".split(" ");

/* Takes a string, returns the index of the month matching that string, throws
an error if 0 or more than 1 matches
*/
function parseMonth(month) {
    var matches = monthNames.filter(function(item) {
        return new RegExp("^" + month, "i").test(item);
    });

    if (matches.length == 0) {
        throw new Error("Invalid month string");
    }
    if (matches.length > 1) {
        throw new Error("Ambiguous month");
    }
    return monthNames.indexOf(matches[0]);
}
/* Same as parseMonth but for days of the week */
function parseWeekday(weekday) {
    var matches = weekdayNames.filter(function(item) {
        return new RegExp("^" + weekday, "i").test(item);
    });

    if (matches.length == 0) {
        throw new Error("Invalid day string");
    }
    if (matches.length > 1) {
        throw new Error("Ambiguous weekday");
    }
    return weekdayNames.indexOf(matches[0]);
}

/* Array of objects, each has 're', a regular expression and 'handler', a 
function for creating a date from something that matches the regular 
expression. Handlers may throw errors if string is unparseable. 
*/
var dateParsePatterns = [
// Today
	{re: /^tod/i,
	handler: function() {
	    return new Date();
	}
},
// Tomorrow
	{re: /^tom/i,
	handler: function() {
	    var d = new Date();
	    d.setDate(d.getDate() + 1);
	    return d;
	}
},
// Yesterday
	{re: /^yes/i,
	handler: function() {
	    var d = new Date();
	    d.setDate(d.getDate() - 1);
	    return d;
	}
},
// 4th
	{re: /^(\d{1,2})(st|nd|rd|th)?$/i,
	handler: function(bits) {
	    var d = new Date();
	    d.setDate(parseInt(bits[1], 10));
	    return d;
	}
},
// 4th Jan
	{re: /^(\d{1,2})(?:st|nd|rd|th)? (\w+)$/i,
	handler: function(bits) {
	    var d = new Date();
	    d.setDate(1);
	    d.setMonth(parseMonth(bits[2]));
	    d.setDate(parseInt(bits[1], 10));
	    return d;
	}
},
// 4th Jan 2003
	{re: /^(\d{1,2})(?:st|nd|rd|th)? (\w+),? (\d{4})$/i,
	handler: function(bits) {
	    var d = new Date();
	    d.setDate(1);
	    d.setYear(bits[3]);
	    d.setMonth(parseMonth(bits[2]));
	    d.setDate(parseInt(bits[1], 10));
	    return d;
	}
},
// Jan 4th
	{re: /^(\w+) (\d{1,2})(?:st|nd|rd|th)?$/i,
	handler: function(bits) {
	    var d = new Date();
	    d.setDate(1);
	    d.setMonth(parseMonth(bits[1]));
	    d.setDate(parseInt(bits[2], 10));
	    return d;
	}
},
// Jan 4th 2003
	{re: /^(\w+) (\d{1,2})(?:st|nd|rd|th)?,? (\d{4})$/i,
	handler: function(bits) {
	    var d = new Date();
	    d.setDate(1);
	    d.setYear(bits[3]);
	    d.setMonth(parseMonth(bits[1]));
	    d.setDate(parseInt(bits[2], 10));
	    return d;
	}
},
// next Tuesday - this is suspect due to weird meaning of "next"
	{re: /^ne(?:xt)* (\w+)$/i,
	handler: function(bits) {
	    var d = new Date();
	    var wd = d.getDay();
	    var nwd = parseWeekday(bits[1]);
	    var addDays = nwd - wd;

	    // It can't be before today or this week.
	    if (nwd <= wd || (addDays + wd < 7)) {
	        addDays += 7;
	    }

	    // Next is not tomorrow.
	    if (1 == addDays) {
	        addDays += 7;
	    }

	    d.setDate(d.getDate() + addDays);
	    return d;
	}
},
// last Tuesday
	{re: /^la(?:st)* (\w+)$/i,
	handler: function(bits) {
	    var d = new Date();
	    var wd = d.getDay();
	    var nwd = parseWeekday(bits[1]);

	    // determine the number of days to subtract to get last weekday
	    var addDays = (-1 * (wd + 7 - nwd)) % 7;
	    // above calculate 0 if weekdays are the same so we have to change this to 7
	    if (0 == addDays) {
	        addDays = -7;
	    } else if (-1 == addDays) {	// Last is not yesterday.
	        addDays -= 7;
	    }

	    // adjust date and return
	    d.setDate(d.getDate() + addDays);
	    return d;
	}
},
// this coming Tuesday
	{re: /^th(?:is)* (\w+)$/i,
	handler: function(bits) {
	    var d = new Date();
	    var wd = d.getDay();
	    var nwd = parseWeekday(bits[1]);
	    var addDays = nwd - wd;

	    // It can't be before today.
	    if (nwd <= wd) {
	        addDays += 7;
	    }

	    d.setDate(d.getDate() + addDays);
	    return d;
	}
},
// first Tuesday
	{re: /^fir(?:st)* (\w+)$/i,
	handler: function(bits) {
	    var d = new Date();
	    d.setDate(1);
	    var day = d.getDay();
	    var newDay = parseWeekday(bits[1]);
	    if (day == newDay) {
	        return d;
	    }

	    var addDays = newDay - day;
	    if (newDay < day) {
	        addDays += 7;
	    }
	    d.setDate(d.getDate() + addDays);
	    return d;
	}
},
// second Tuesday
	{re: /^sec(?:ond)* (\w+)$/i,
	handler: function(bits) {
	    var d = new Date();
	    d.setDate(1);
	    var day = d.getDay();
	    var newDay = parseWeekday(bits[1]);
	    var addDays = newDay - day;
	    if (newDay < day) {
	        addDays += 7;
	    }
	    addDays += 7;
	    d.setDate(d.getDate() + addDays);
	    return d;
	}
},
// third Tuesday
	{re: /^thi(?:rd)* (\w+)$/i,
	handler: function(bits) {
	    var d = new Date();
	    d.setDate(1);
	    var day = d.getDay();
	    var newDay = parseWeekday(bits[1]);
	    var addDays = newDay - day;
	    if (newDay < day) {
	        addDays += 7;
	    }
	    addDays += 14;
	    d.setDate(d.getDate() + addDays);
	    return d;
	}
},
// fourth Tuesday
	{re: /^fo(?:urth)* (\w+)$/i,
	handler: function(bits) {
	    var d = new Date();
	    d.setDate(1);
	    var day = d.getDay();
	    var newDay = parseWeekday(bits[1]);
	    var addDays = newDay - day;
	    if (newDay < day) {
	        addDays += 7;
	    }
	    addDays += 21;
	    d.setDate(d.getDate() + addDays);
	    return d;
	}
},
// fifth Tuesday
	{re: /^fi(?:fth)* (\w+)$/i,
	handler: function(bits) {
	    var d = new Date();
	    d.setDate(1);
	    var day = d.getDay();
	    var newDay = parseWeekday(bits[1]);
	    var addDays = newDay - day;
	    if (newDay < day) {
	        addDays += 7;
	    }
	    addDays += 28;
	    d.setDate(d.getDate() + addDays);
	    return d;
	}
},
// mm/dd/yyyy (American style)
	{re: /(\d{1,2})\/(\d{1,2})\/(\d{4})/,
	handler: function(bits) {
	    var d = new Date();
	    d.setDate(1);
	    if (!dp_dateFormat || dp_dateFormat.substr(0, 1) == 'm') {
	        d.setYear(bits[3]);
	        d.setMonth(parseInt(bits[1], 10) - 1); // Because months indexed from 0
	        d.setDate(parseInt(bits[2], 10));
	    } else {
	        d.setYear(bits[3]);
	        d.setMonth(parseInt(bits[2], 10) - 1); // Because months indexed from 0
	        d.setDate(parseInt(bits[1], 10));
	    }
	    return d;
	}
},
// mm-dd-yyyy (American style) or dd-mm-yyyy
	{re: /(\d{1,2})-(\d{1,2})-(\d{4})/,
	handler: function(bits) {
	    var d = new Date();
	    d.setDate(1);
	    if (!dp_dateFormat || dp_dateFormat.substr(0, 1) == 'm') {
	        d.setYear(bits[3]);
	        d.setMonth(parseInt(bits[1], 10) - 1); // Because months indexed from 0
	        d.setDate(parseInt(bits[2], 10));
	    } else {
	        d.setYear(bits[3]);
	        d.setMonth(parseInt(bits[2], 10) - 1); // Because months indexed from 0
	        d.setDate(parseInt(bits[1], 10));
	    }
	    return d;
	}
},
// mm.dd.yyyy (American style) or dd.mm.yyyy
	{re: /(\d{1,2})\.(\d{1,2})\.(\d{4})/,
	handler: function(bits) {
	    var d = new Date();
	    d.setDate(1);
	    if (!dp_dateFormat || dp_dateFormat.substr(0, 1) == 'm') {
	        d.setYear(bits[3]);
	        d.setMonth(parseInt(bits[1], 10) - 1); // Because months indexed from 0
	        d.setDate(parseInt(bits[2], 10));
	    } else {
	        d.setYear(bits[3]);
	        d.setMonth(parseInt(bits[2], 10) - 1); // Because months indexed from 0
	        d.setDate(parseInt(bits[1], 10));
	    }
	    return d;
	}
},
// yyyy-mm-dd (ISO style)
	{re: /(\d{4})-(\d{1,2})-(\d{1,2})/,
	handler: function(bits) {
	    var d = new Date();
	    d.setDate(1);
	    d.setYear(parseInt(bits[1], 10));
	    d.setMonth(parseInt(bits[2], 10) - 1);
	    d.setDate(parseInt(bits[3], 10));
	    return d;
	}
}
];

function parseDateString(s) {
    for (var i = 0; i < dateParsePatterns.length; i++) {
        var re = dateParsePatterns[i].re;
        var handler = dateParsePatterns[i].handler;
        var bits = re.exec(s);
        if (bits) {
            return handler(bits);
        }
    }
    throw new Error("Invalid date string");
}

var dp_dateFormat;

function dp_DateString(d) {
    var dateDelim, delim;

    dp_dateFormat = dp_dateFormat || 'm/d/yyyy';
    if (dp_dateFormat.indexOf('/') != -1) {
        delim = eval('/\\//g');
        dateDelim = '/';
    } else if (dp_dateFormat.indexOf('-') != -1) {
        delim = eval('/\\-/g');
        dateDelim = '-';
    } else if (dp_dateFormat.indexOf('.') != -1) {
        delim = eval('/\\./g');
        dateDelim = '.';
    } else {
        delim = eval('/\\ /g');
        dateDelim = ' ';
    }

    var month, day, year;

    month = d.getMonth();
    day = d.getDate();
    year = d.getFullYear();

    switch (dp_dateFormat.replace(delim, "")) {
        case 'ddmmmyyyy':
            return dp_padZero(day) + dateDelim + monthNames[month].substr(0, 3) + dateDelim + year;
        case 'dmmmyyyy':
            return day + dateDelim + monthNames[month].substr(0, 3) + dateDelim + year;
        case 'ddmmyyyy':
            return dp_padZero(day) + dateDelim + dp_padZero(month + 1) + dateDelim + year;
        case 'dmmyyyy':
            return day + dateDelim + dp_padZero(month + 1) + dateDelim + year;
        case 'mmddyyyy':
            return dp_padZero((month + 1)) + dateDelim + dp_padZero(day) + dateDelim + year;
        case 'mddyyyy':
            return (month + 1) + dateDelim + dp_padZero(day) + dateDelim + year;
        case 'mdyyyy':
            return (month + 1) + dateDelim + day + dateDelim + year;
        case 'yyyymmdd':
            return year + dateDelim + dp_padZero(month + 1) + dateDelim + dp_padZero(day);
        default:
            return (month + 1) + dateDelim + day + dateDelim + year;
    }
}

function dp_padZero(n) {
    return ((n <= 9) ? ("0" + n) : n);
}

function magicDate(input, required) {
    if (!required && input.value == '') {
        return true;
    }
    var bRet = true;
    var messagespan = input.id + 'Msg';
    try {
        var d = parseDateString(input.value);
        input.value = dp_DateString(d);
        //		input.className='';
        // Human readable date
        var el = document.getElementById(messagespan);
        if (el) {
            el.firstChild.nodeValue = d.toDateString();
            el.className = 'normal';
        } else {
            d.toDateString();
        }
    }
    catch (e) {
        input.className = 'error';
        var message = e.message;

        // Fix for IE6 bug
        if (!message.length || message.indexOf('is null or not an object') > -1) {
            message = 'Invalid date string';
        }
        var el = document.getElementById(messagespan);
        if (el) {
            el.firstChild.nodeValue = message;
            el.className = 'error';
        } else {
          //  alert(message);
        }
        bRet = false;
    }
    //	if(!bRet)
    //		input.focus();
    return bRet;
}

// If there is an addEvent function add an event to add the dateparse functions to
// an input field with a className of dateparse. If you don't have an addEvent function,
// please use mine at http://tanny.ica.com, search for DOMContentLoaded.
try {
    if (addEvent) {
        // If there is an addDOMLoadEvent function use it as it runs as soon as the
        // DOM (html) has loaded. This is faster than load (onload) since it doesn't
        // have to wait for images and other stuff (technical term).
        var sEventType; ;
        try {
            if (addDOMLoadEvent)
                sEventType = "DOMContentLoaded";
        }
        catch (e) {
            sEventType = "load";
        }

        // Let's add an event to run the add date parse behavior function.
        addEvent(window, sEventType, function() {
            // Get an array of input elements.
            var els = document.getElementsByTagName("input");

            // Check each input element.
            for (var i = 0; i < els.length; i++) {
                // If the className has the word dateparse in it, add the behavior.
                if (/\bdateparse\b/.test(els[i].className)) {
                    addEvent(els[i], "blur", function() { magicDate(this); });
                    addEvent(els[i], "focus", function() { if (this.className != 'error') this.select(); });
                }
            }
        });
    }
}
catch (e) {
    // We could add the function to the onload event here, but the user might overright it
    // in body onload attribute. Therefore, we're not going to add the functionality.
}

function validateFuture(date, errorId, hfId) {
    //alert(date);
    //alert(date.value);
    //alert(errorId);
    //alert(errorId.value);
    //alert(hfId);
    //alert(hfId.value);
    var tempDate = date.value;
    if (tempDate == "")
        return true;
    var currentDate = new Date();
    restrictFuture(tempDate, currentDate, errorId, hfId);
}
function restrictFuture(tempDate, currentDate, errorId, hfId) {
    //         alert('in restrict');
    if (isDate(tempDate, errorId, hfId)) {
        var SysDate = currentDate.getDate();
        var SysMonth = currentDate.getMonth() + 1; //January is 0!
        var SysYear = currentDate.getFullYear();
        var ArrDob = tempDate.split("/");

        if (ArrDob.length == 3) {
            var DobMonth = ArrDob[0];
            var DobDate = ArrDob[1];
            var DobYear = ArrDob[2];
            //      alert(DobDate+"__"+"__"+SysMonth+"__"+DobMonth+"__"+SysDate);
            if (DobYear > SysYear) {
                document.getElementById(errorId).innerHTML = "<span class='errordisplay'>Date Should not be Greater than Current Date</span>";
                var tmp = eval(document.getElementById(hfId));
                tmp.value = 'true';
                return false;
            } else if ((DobYear == SysYear) && (DobDate > SysMonth)) {
                document.getElementById(errorId).innerHTML = "<span class='errordisplay'>Date Should not be Greater than Current Date</span>";
                var tmp = eval(document.getElementById(hfId));
                tmp.value = 'true';
                return false;
            } else if ((DobYear == SysYear) && (DobDate == SysMonth) && (DobMonth > SysDate)) {
                document.getElementById(errorId).innerHTML = "<span class='errordisplay'>Date Should not be Greater than Current Date</span>";
                var tmp = eval(document.getElementById(hfId));
                tmp.value = 'true';
                return false;
            }
            //        else if ((DobYear == SysYear) && (DobDate == SysMonth) && (DobMonth <= SysDate)) {
            //            document.getElementById(errorId).innerHTML = '';
            //            var tmp = eval(document.getElementById(hfId));
            //            tmp.value = 'false';
            //            return;

            //        } else if ((DobYear <= SysYear) && (DobDate <= SysMonth) && (DobMonth <= SysDate)) {
            //            document.getElementById(errorId).innerHTML = '';
            //            var tmp = eval(document.getElementById(hfId));
            //            tmp.value = 'false';
            //            return;

            //        } else if ((DobYear <= SysYear) && (DobDate >= SysMonth) && (DobMonth >= SysDate)) {

            //            document.getElementById(errorId).innerHTML = '';
            //            var tmp = eval(document.getElementById(hfId));
            //            tmp.value = 'false';
            //            return;
            //        }
            //        //        else if ((DobYear == SysYear) && (DobDate == SysMonth) && (DobMonth > SysDate)) {
            //            var tmp = eval(document.getElementById('ctl00_HomePageContent_dtFact'));
            //            tmp.value = 'true';
            //            document.getElementById('ctl00_HomePageContent_lblerrFactclosed').innerHTML = "<span class='errordisplay'>Date Should be less than current date</span>";
            //            return;
            //        }
            else {
                //            var tmp = eval(document.getElementById(hfId));
                //            tmp.value = 'false';
                //            document.getElementById(errorId).innerHTML = '';
                return true;
            }
        }
    }
    else
        return true;
}

function isInteger(s) {
    var i;
    for (i = 0; i < s.length; i++) {
        // Check that current character is number.
        var c = s.charAt(i);
        if (((c < "0") || (c > "9"))) return false;
    }
    // All characters are numbers.
    return true;
}

function stripCharsInBag(s, bag) {
    var i;
    var returnString = "";
    // Search through string's characters one by one.
    // If character is not in bag, append to returnString.
    for (i = 0; i < s.length; i++) {
        var c = s.charAt(i);
        if (bag.indexOf(c) == -1) returnString += c;
    }
    return returnString;
}

function daysInFebruary(year) {
    // February has 29 days in any year evenly divisible by four,
    // EXCEPT for centurial years which are not also divisible by 400.
    return (((year % 4 == 0) && ((!(year % 100 == 0)) || (year % 400 == 0))) ? 29 : 28);
}
function DaysArray(n) {
    for (var i = 1; i <= n; i++) {
        this[i] = 31
        if (i == 4 || i == 6 || i == 9 || i == 11) { this[i] = 30 }
        if (i == 2) { this[i] = 29 }
    }
    return this
}

function isDate(dtStr, errorId, hfId) {
    var dtCh = "/";
    var minYear = 1900;
    var maxYear = 9999;
    var daysInMonth = DaysArray(12)
    var pos1 = dtStr.indexOf(dtCh)
    var pos2 = dtStr.indexOf(dtCh, pos1 + 1)
    var strDay = dtStr.substring(0, pos1)
    var strMonth = dtStr.substring(pos1 + 1, pos2)
    var strYear = dtStr.substring(pos2 + 1)
    strYr = strYear
    if (strDay.charAt(0) == "0" && strDay.length > 1) strDay = strDay.substring(1)
    if (strMonth.charAt(0) == "0" && strMonth.length > 1) strMonth = strMonth.substring(1)
    for (var i = 1; i <= 3; i++) {
        if (strYr.charAt(0) == "0" && strYr.length > 1) strYr = strYr.substring(1)
    }
    month = parseInt(strMonth)
    day = parseInt(strDay)
    year = parseInt(strYr)
    if (pos1 == -1 || pos2 == -1) {
        document.getElementById(errorId).innerHTML = "<span class='errordisplay'>The date format should be : dd/mm/yyyy</span>";
        var tmp = eval(document.getElementById(hfId));
        tmp.value = 'true';
        return false;
    }
    if (strDay.length < 1 || day < 1 || day > 31 || (month == 2 && day > daysInFebruary(year)) || day > daysInMonth[month]) {
        document.getElementById(errorId).innerHTML = "<span class='errordisplay'>Please enter a valid day</span>";
        var tmp = eval(document.getElementById(hfId));
        tmp.value = 'true';
        return false;
    }
    if (strMonth.length < 1 || month < 1 || month > 12) {
        document.getElementById(errorId).innerHTML = "<span class='errordisplay'>Please enter a valid month</span>";
        var tmp = eval(document.getElementById(hfId));
        tmp.value = 'true';
        return false;
    }
    if (strYear.length != 4 || year == 0 || year < minYear || year > maxYear) {
        document.getElementById(errorId).innerHTML = "<span class='errordisplay'>Please enter a valid 4 digit year between ' + minYear + ' and ' + maxYear+ ' </span> "
        var tmp = eval(document.getElementById(hfId));
        tmp.value = 'true';
        return false;
    }
    if (dtStr.indexOf(dtCh, pos2 + 1) != -1 || isInteger(stripCharsInBag(dtStr, dtCh)) == false) {
        document.getElementById(errorId).innerHTML = "<span class='errordisplay'>Please enter a valid date</span>";
        var tmp = eval(document.getElementById(hfId));
        tmp.value = 'true';
        return false
    }
    return true
} /* 'Magic' date parsing, by Simon Willison (6th October 2003)
   http://simon.incutio.com/archive/2003/10/06/betterDateInput

Modifications By Tanny O'Haley
24 Feb 2006 Changed order of setting date items from day, month, year
		to year, month, day. When a user put in "31 jan" and the 
		current month did not end in 31 the date first be put to the
		next month then the entered date. If today was 27 Feb and
		the user put in 31 jan the date first be changed to 3 Mar,
		then the month would be set to Jan. The date displayed
		would be 3 Jan instead of 31 Jan. By changing the order
		the date is set correctly.
27 Feb 2006 Added code to display the dates in formats other than mm/dd/yyyy.
03 Jul 2006 Added code to automatically add magicDate behavior to input fields 
		with a className that includes the word dateparse.
*/

/* Finds the index of the first occurence of item in the array, or -1 if not found */
Array.prototype.indexOf = function(item) {
	for (var i = 0; i < this.length; i++) {
		if (this[i] == item) {
			return i;
		}
	}
	return -1;
};
/* Returns an array of items judged 'true' by the passed in test function */
Array.prototype.filter = function(test) {
	var matches = [];
	for (var i = 0; i < this.length; i++) {
		if (test(this[i])) {
			matches[matches.length] = this[i];
		}
	}
	return matches;
};

var monthNames = "January February March April May June July August September October November December".split(" ");
var weekdayNames = "Sunday Monday Tuesday Wednesday Thursday Friday Saturday".split(" ");

/* Takes a string, returns the index of the month matching that string, throws
an error if 0 or more than 1 matches
*/
function parseMonth(month) {
	var matches = monthNames.filter(function(item) { 
		return new RegExp("^" + month, "i").test(item);
	});

	if (matches.length == 0) {
		throw new Error("Invalid month string");
	}
	if (matches.length > 1) {
		throw new Error("Ambiguous month");
	}
	return monthNames.indexOf(matches[0]);
}
/* Same as parseMonth but for days of the week */
function parseWeekday(weekday) {
	var matches = weekdayNames.filter(function(item) {
		return new RegExp("^" + weekday, "i").test(item);
	});

	if (matches.length == 0) {
		throw new Error("Invalid day string");
	}
	if (matches.length > 1) {
		throw new Error("Ambiguous weekday");
	}
	return weekdayNames.indexOf(matches[0]);
}

/* Array of objects, each has 're', a regular expression and 'handler', a 
function for creating a date from something that matches the regular 
expression. Handlers may throw errors if string is unparseable. 
*/
var dateParsePatterns = [
	// Today
	{   re: /^tod/i,
		handler: function() { 
			return new Date();
		} 
	},
	// Tomorrow
	{   re: /^tom/i,
		handler: function() {
			var d = new Date(); 
			d.setDate(d.getDate() + 1); 
			return d;
		}
	},
	// Yesterday
	{   re: /^yes/i,
		handler: function() {
			var d = new Date();
			d.setDate(d.getDate() - 1);
			return d;
		}
	},
	// 4th
	{   re: /^(\d{1,2})(st|nd|rd|th)?$/i, 
		handler: function(bits) {
			var d = new Date();
			d.setDate(parseInt(bits[1], 10));
			return d;
		}
	},
	// 4th Jan
	{   re: /^(\d{1,2})(?:st|nd|rd|th)? (\w+)$/i, 
		handler: function(bits) {
			var d = new Date();
			d.setDate(1);
			d.setMonth(parseMonth(bits[2]));
			d.setDate(parseInt(bits[1], 10));
			return d;
		}
	},
	// 4th Jan 2003
	{   re: /^(\d{1,2})(?:st|nd|rd|th)? (\w+),? (\d{4})$/i,
		handler: function(bits) {
			var d = new Date();
			d.setDate(1);
			d.setYear(bits[3]);
			d.setMonth(parseMonth(bits[2]));
			d.setDate(parseInt(bits[1], 10));
			return d;
		}
	},
	// Jan 4th
	{   re: /^(\w+) (\d{1,2})(?:st|nd|rd|th)?$/i, 
		handler: function(bits) {
			var d = new Date();
			d.setDate(1);
			d.setMonth(parseMonth(bits[1]));
			d.setDate(parseInt(bits[2], 10));
			return d;
		}
	},
	// Jan 4th 2003
	{   re: /^(\w+) (\d{1,2})(?:st|nd|rd|th)?,? (\d{4})$/i,
		handler: function(bits) {
			var d = new Date();
			d.setDate(1);
			d.setYear(bits[3]);
			d.setMonth(parseMonth(bits[1]));
			d.setDate(parseInt(bits[2], 10));
			return d;
		}
	},
	// next Tuesday - this is suspect due to weird meaning of "next"
	{   re: /^ne(?:xt)* (\w+)$/i,
		handler: function(bits) {
			var d = new Date();
			var wd = d.getDay();
			var nwd = parseWeekday(bits[1]);
			var addDays = nwd - wd;

			// It can't be before today or this week.
			if (nwd <= wd || (addDays + wd < 7) ) {
				addDays += 7;
			}
			
			// Next is not tomorrow.
			if (1 == addDays) {
				addDays += 7;
			}

			d.setDate(d.getDate() + addDays);
			return d;
		}
	},
	// last Tuesday
	{   re: /^la(?:st)* (\w+)$/i,
		handler: function(bits) {
			var d = new Date();
			var wd = d.getDay();
			var nwd = parseWeekday(bits[1]);

			// determine the number of days to subtract to get last weekday
			var addDays = (-1 * (wd + 7 - nwd)) % 7;
			// above calculate 0 if weekdays are the same so we have to change this to 7
			if (0 == addDays) {
				addDays = -7;
			} else if (-1 == addDays) {	// Last is not yesterday.
				addDays -= 7;
			}

			// adjust date and return
			d.setDate(d.getDate() + addDays);
			return d;
			}
	},
	// this coming Tuesday
	{   re: /^th(?:is)* (\w+)$/i,
		handler: function(bits) {
			var d = new Date();
			var wd = d.getDay();
			var nwd = parseWeekday(bits[1]);
			var addDays = nwd - wd;

			// It can't be before today.
			if (nwd <= wd) {
				addDays += 7;
			}
			
			d.setDate(d.getDate() + addDays);
			return d;
		}
	},
	// first Tuesday
	{   re: /^fir(?:st)* (\w+)$/i,
		handler: function(bits) {
			var d = new Date();
			d.setDate(1);
			var day = d.getDay();
			var newDay = parseWeekday(bits[1]);
			if(day == newDay) {
				return d;
			}
			
			var addDays = newDay - day;
			if (newDay < day) {
				addDays += 7;
			}
			d.setDate(d.getDate() + addDays);
			return d;
		}
	},
	// second Tuesday
	{   re: /^sec(?:ond)* (\w+)$/i,
		handler: function(bits) {
			var d = new Date();
			d.setDate(1);
			var day = d.getDay();
			var newDay = parseWeekday(bits[1]);
			var addDays = newDay - day;
			if (newDay < day) {
				addDays += 7;
			}
			addDays += 7;
			d.setDate(d.getDate() + addDays);
			return d;
		}
	},
	// third Tuesday
	{   re: /^thi(?:rd)* (\w+)$/i,
		handler: function(bits) {
			var d = new Date();
			d.setDate(1);
			var day = d.getDay();
			var newDay = parseWeekday(bits[1]);
			var addDays = newDay - day;
			if (newDay < day) {
				addDays += 7;
			}
			addDays += 14;
			d.setDate(d.getDate() + addDays);
			return d;
		}
	},
	// fourth Tuesday
	{   re: /^fo(?:urth)* (\w+)$/i,
		handler: function(bits) {
			var d = new Date();
			d.setDate(1);
			var day = d.getDay();
			var newDay = parseWeekday(bits[1]);
			var addDays = newDay - day;
			if (newDay < day) {
				addDays += 7;
			}
			addDays += 21;
			d.setDate(d.getDate() + addDays);
			return d;
		}
	},
	// fifth Tuesday
	{   re: /^fi(?:fth)* (\w+)$/i,
		handler: function(bits) {
			var d = new Date();
			d.setDate(1);
			var day = d.getDay();
			var newDay = parseWeekday(bits[1]);
			var addDays = newDay - day;
			if (newDay < day) {
				addDays += 7;
			}
			addDays += 28;
			d.setDate(d.getDate() + addDays);
			return d;
		}
	},
	// mm/dd/yyyy (American style)
	{   re: /(\d{1,2})\/(\d{1,2})\/(\d{4})/,
		handler: function(bits) {
			var d = new Date();
			d.setDate(1);
			if(!dp_dateFormat || dp_dateFormat.substr(0,1) == 'm') {
				d.setYear(bits[3]);
				d.setMonth(parseInt(bits[1], 10) - 1); // Because months indexed from 0
				d.setDate(parseInt(bits[2], 10));
			} else {
				d.setYear(bits[3]);
				d.setMonth(parseInt(bits[2], 10) - 1); // Because months indexed from 0
				d.setDate(parseInt(bits[1], 10));
			}
			return d;
		}
	},
	// mm-dd-yyyy (American style) or dd-mm-yyyy
	{   re: /(\d{1,2})-(\d{1,2})-(\d{4})/,
		handler: function(bits) {
			var d = new Date();
			d.setDate(1);
			if(!dp_dateFormat || dp_dateFormat.substr(0,1) == 'm') {
				d.setYear(bits[3]);
				d.setMonth(parseInt(bits[1], 10) - 1); // Because months indexed from 0
				d.setDate(parseInt(bits[2], 10));
			} else {
				d.setYear(bits[3]);
				d.setMonth(parseInt(bits[2], 10) - 1); // Because months indexed from 0
				d.setDate(parseInt(bits[1], 10));
			}
			return d;
		}
	},
	// mm.dd.yyyy (American style) or dd.mm.yyyy
	{   re: /(\d{1,2})\.(\d{1,2})\.(\d{4})/,
		handler: function(bits) {
			var d = new Date();
			d.setDate(1);
			if(!dp_dateFormat || dp_dateFormat.substr(0,1) == 'm') {
				d.setYear(bits[3]);
				d.setMonth(parseInt(bits[1], 10) - 1); // Because months indexed from 0
				d.setDate(parseInt(bits[2], 10));
			} else {
				d.setYear(bits[3]);
				d.setMonth(parseInt(bits[2], 10) - 1); // Because months indexed from 0
				d.setDate(parseInt(bits[1], 10));
			}
			return d;
		}
	},
	// yyyy-mm-dd (ISO style)
	{   re: /(\d{4})-(\d{1,2})-(\d{1,2})/,
		handler: function(bits) {
			var d = new Date();
			d.setDate(1);
			d.setYear(parseInt(bits[1],10));
			d.setMonth(parseInt(bits[2], 10) - 1);
			d.setDate(parseInt(bits[3], 10));
			return d;
		}
	}
];

function parseDateString(s) {
	for (var i = 0; i < dateParsePatterns.length; i++) {
		var re = dateParsePatterns[i].re;
		var handler = dateParsePatterns[i].handler;
		var bits = re.exec(s);
		if (bits) {
			return handler(bits);
		}
	}
	throw new Error("Invalid date string");
}

var dp_dateFormat;

function dp_DateString(d) {
	var dateDelim, delim;

	dp_dateFormat = dp_dateFormat || 'm/d/yyyy';
	if(dp_dateFormat.indexOf('/') != -1) {
		delim = eval('/\\//g');
		dateDelim = '/';
	} else if(dp_dateFormat.indexOf('-') != -1) {
		delim = eval('/\\-/g');
		dateDelim = '-';
	} else if(dp_dateFormat.indexOf('.') != -1) {
		delim = eval('/\\./g');
		dateDelim = '.';
	} else {
		delim = eval('/\\ /g');
		dateDelim = ' ';
	}

	var month, day, year;
	
	month = d.getMonth();
	day = d.getDate();
	year = d.getFullYear();

	switch (dp_dateFormat.replace(delim,"")){
	case 'ddmmmyyyy':
		return dp_padZero(day) + dateDelim + monthNames[month].substr(0,3) + dateDelim + year;
	case 'dmmmyyyy':
		return day + dateDelim + monthNames[month].substr(0,3) + dateDelim + year;
	case 'ddmmyyyy':
		return dp_padZero(day) + dateDelim + dp_padZero(month+1) + dateDelim + year;
	case 'dmmyyyy':
		return day + dateDelim + dp_padZero(month+1) + dateDelim + year;
	case 'mmddyyyy':
		return dp_padZero((month+1)) + dateDelim + dp_padZero(day) + dateDelim + year;
	case 'mddyyyy':
		return (month+1) + dateDelim + dp_padZero(day) + dateDelim + year;
	case 'mdyyyy':
		return (month+1) + dateDelim + day + dateDelim + year;
	case 'yyyymmdd':
		return year + dateDelim + dp_padZero(month+1) + dateDelim + dp_padZero(day);
	default:
		return (month+1) + dateDelim + day + dateDelim + year;
	}
}

function dp_padZero(n) {
	return ((n <= 9) ? ("0" + n) : n);
}

function magicDate(input, required) {
	if(!required && input.value == '') {
		return true;
	}
	var bRet = true;
	var messagespan = input.id + 'Msg';
	try {
		var d = parseDateString(input.value);
		input.value = dp_DateString(d);
//		input.className='';
		// Human readable date
		var el = document.getElementById(messagespan);
		if(el) {
			el.firstChild.nodeValue = d.toDateString();
			el.className = 'normal';
		} else {
			d.toDateString();
		}
	}
	catch (e) {
		input.className = 'error';
		var message = e.message;

		// Fix for IE6 bug
		if (!message.length || message.indexOf('is null or not an object') > -1) {
			message = 'Invalid date string';
		}
		var el = document.getElementById(messagespan);
		if(el) {
			el.firstChild.nodeValue = message;
			el.className = 'error';
		} else {
		//	alert(message);
		}
		bRet = false;
	}
//	if(!bRet)
//		input.focus();
	return bRet;
}

// If there is an addEvent function add an event to add the dateparse functions to
// an input field with a className of dateparse. If you don't have an addEvent function,
// please use mine at http://tanny.ica.com, search for DOMContentLoaded.
try {
	if(addEvent){
		// If there is an addDOMLoadEvent function use it as it runs as soon as the
		// DOM (html) has loaded. This is faster than load (onload) since it doesn't
		// have to wait for images and other stuff (technical term).
		var sEventType;;
		try {
			if(addDOMLoadEvent)
				sEventType = "DOMContentLoaded";
		}
		catch(e) {
			sEventType = "load";
		}

		// Let's add an event to run the add date parse behavior function.
		addEvent(window, sEventType, function() {
			// Get an array of input elements.
			var els = document.getElementsByTagName("input");

			// Check each input element.
			for(var i = 0; i < els.length; i++) {
				// If the className has the word dateparse in it, add the behavior.
				if(/\bdateparse\b/.test(els[i].className)) {
					addEvent(els[i], "blur", function() { magicDate(this); });
					addEvent(els[i], "focus", function() { if (this.className != 'error') this.select(); });
				}
			}
		});
	}
}
catch(e) {
	// We could add the function to the onload event here, but the user might overright it
	// in body onload attribute. Therefore, we're not going to add the functionality.
}

function validateFuture(date, errorId, hfId) {
    //           alert(date);
    //         alert(errorId);
    var tempDate = document.getElementById(date).value;
    if (tempDate == "")
        return true;
    var currentDate = new Date();
    restrictFuture(tempDate, currentDate, errorId, hfId);    
}
function restrictFuture(tempDate, currentDate, errorId, hfId) {
    //         alert('in restrict');
    if (isDate(tempDate, errorId, hfId)) {
        var SysDate = currentDate.getDate();
        var SysMonth = currentDate.getMonth() + 1; //January is 0!
        var SysYear = currentDate.getFullYear();
        var ArrDob = tempDate.split("/");

        if (ArrDob.length == 3) {
            var DobMonth = ArrDob[0];
            var DobDate = ArrDob[1];
            var DobYear = ArrDob[2];
            //      alert(DobDate+"__"+"__"+SysMonth+"__"+DobMonth+"__"+SysDate);
            if (DobYear > SysYear) {
                document.getElementById(errorId).innerHTML = '<span class="errordisplay">Date Should not be Greater than Current Date</span>';
                var tmp = eval(document.getElementById(hfId));
                tmp.value = 'true';
                return false;
            } else if ((DobYear == SysYear) && (DobDate > SysMonth)) {
            document.getElementById(errorId).innerHTML = '<span class="errordisplay">Date Should not be Greater than Current Date</span>';
                var tmp = eval(document.getElementById(hfId));
                tmp.value = 'true';
                return false;
            } else if ((DobYear == SysYear) && (DobDate == SysMonth) && (DobMonth > SysDate)) {
            document.getElementById(errorId).innerHTML = '<span class="errordisplay">Date Should not be Greater than Current Date</span>';
                var tmp = eval(document.getElementById(hfId));
                tmp.value = 'true';
                return false;
            }
            //        else if ((DobYear == SysYear) && (DobDate == SysMonth) && (DobMonth <= SysDate)) {
            //            document.getElementById(errorId).innerHTML = '';
            //            var tmp = eval(document.getElementById(hfId));
            //            tmp.value = 'false';
            //            return;

            //        } else if ((DobYear <= SysYear) && (DobDate <= SysMonth) && (DobMonth <= SysDate)) {
            //            document.getElementById(errorId).innerHTML = '';
            //            var tmp = eval(document.getElementById(hfId));
            //            tmp.value = 'false';
            //            return;

            //        } else if ((DobYear <= SysYear) && (DobDate >= SysMonth) && (DobMonth >= SysDate)) {

            //            document.getElementById(errorId).innerHTML = '';
            //            var tmp = eval(document.getElementById(hfId));
            //            tmp.value = 'false';
            //            return;
            //        }
            //        //        else if ((DobYear == SysYear) && (DobDate == SysMonth) && (DobMonth > SysDate)) {
            //            var tmp = eval(document.getElementById('ctl00_HomePageContent_dtFact'));
            //            tmp.value = 'true';
            //            document.getElementById('ctl00_HomePageContent_lblerrFactclosed').innerHTML = 'Date Should be less than current date';
            //            return;
            //        }
            else {
                //            var tmp = eval(document.getElementById(hfId));
                //            tmp.value = 'false';
                //            document.getElementById(errorId).innerHTML = '';
                return true;
            }
        }
    }
    else
        return true;
}

function isInteger(s) {
    var i;
    for (i = 0; i < s.length; i++) {
        // Check that current character is number.
        var c = s.charAt(i);
        if (((c < "0") || (c > "9"))) return false;
    }
    // All characters are numbers.
    return true;
}

function stripCharsInBag(s, bag) {
    var i;
    var returnString = "";
    // Search through string's characters one by one.
    // If character is not in bag, append to returnString.
    for (i = 0; i < s.length; i++) {
        var c = s.charAt(i);
        if (bag.indexOf(c) == -1) returnString += c;
    }
    return returnString;
}

function daysInFebruary(year) {
    // February has 29 days in any year evenly divisible by four,
    // EXCEPT for centurial years which are not also divisible by 400.
    return (((year % 4 == 0) && ((!(year % 100 == 0)) || (year % 400 == 0))) ? 29 : 28);
}
function DaysArray(n) {
    for (var i = 1; i <= n; i++) {
        this[i] = 31
        if (i == 4 || i == 6 || i == 9 || i == 11) { this[i] = 30 }
        if (i == 2) { this[i] = 29 }
    }
    return this
}

function isDate(dtStr, errorId, hfId) {
    var dtCh = "/";
    var minYear = 1900;
    var maxYear = 9999;
    var daysInMonth = DaysArray(12);
    var pos1 = dtStr.indexOf(dtCh);
    var pos2 = dtStr.indexOf(dtCh, pos1 + 1);
    var strDay = dtStr.substring(0, pos1);
   // alert("D" + strDay);
    var strMonth = dtStr.substring(pos1 + 1, pos2);
   // alert("M" + strMonth);
    var strYear = dtStr.substring(pos2 + 1);
    //alert("Y" + strYear);
    
    strYr = strYear;
    if (strDay.charAt(0) == "0" && strDay.length > 1) strDay = strDay.substring(1);
    if (strMonth.charAt(0) == "0" && strMonth.length > 1) strMonth = strMonth.substring(1);
    for (var i = 1; i <= 3; i++) {
        if (strYr.charAt(0) == "0" && strYr.length > 1) strYr = strYr.substring(1);
    }
    //month = parseInt.strMonth;
    //day = parseInt.strDay;
    //year = parseInt.strYr;
   
    if (pos1 == -1 || pos2 == -1) {
        document.getElementById(errorId).innerHTML = '<span class="errordisplay">The date format should be : dd/mm/yyyy</span>';
        var tmp = eval(document.getElementById(hfId));
        tmp.value = 'true';
        return false;
    }
    if (strDay.length < 1 || strDay < 1 || strDay > 31 || (strMonth == 2 && strDay > daysInFebruary(strYr)) || strDay > daysInMonth[strMonth]) {
        document.getElementById(errorId).innerHTML = '<span class="errordisplay">Please enter a valid day</span>';
        var tmp = eval(document.getElementById(hfId));
        tmp.value = 'true';
        return false;
    }
    if (strMonth.length < 1 || strMonth < 1 || strMonth > 12) {
        document.getElementById(errorId).innerHTML = '<span class="errordisplay">Please enter a valid month</span>';
        var tmp = eval(document.getElementById(hfId));
        tmp.value = 'true';
        return false;
    }
    if (strYear.length != 4 || strYr == 0 || strYr < minYear || strYr > maxYear) {
        document.getElementById(errorId).innerHTML = '<span class="errordisplay">Please enter a valid 4 digit year between ' + minYear + ' and ' + maxYear + '</span>'
        var tmp = eval(document.getElementById(hfId));
        tmp.value = 'true';
        return false;
    }
    if (dtStr.indexOf(dtCh, pos2 + 1) != -1 || isInteger(stripCharsInBag(dtStr, dtCh)) == false) {
        document.getElementById(errorId).innerHTML = '<span class="errordisplay">Please enter a valid date</span>';
        var tmp = eval(document.getElementById(hfId));
        tmp.value = 'true';
        return false
    }
    return true
}
