I created a test page for using the validate plugin and date picker. Everything works great except for one test case.
I have a required field which is a date. If I go in and enter a bunch of numbers I get one of my error messages. If I go to another field and return to the field with the error, the datepicker pops up. If I select a date, I now see I have a valid date, however if I leave by tabbing the error message still shows. If I change the value by hand it works correctly.
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>New Web Project</title>
<link href="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8/themes/base/jquery-ui.css" rel="stylesheet" type="text/css"/>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4/jquery.min.js" type="text/javascript">
</script>
<script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8/jquery-ui.min.js" type="text/javascript">
</script>
<script src="http://jquery-ui.googlecode.com/svn/trunk/ui/i18n/jquery.ui.datepicker-fr.js" type="text/javascript">
</script>
<script src="http://ajax.microsoft.com/ajax/jquery.validate/1.6/jquery.validate.min.js" type="text/javascript">
</script>
<link REL="StyleSheet" HREF="lib/test.css" TYPE="text/css">
</head>
<body>
<form action="index.html" id="myform">
<script type="text/javascript">
$.validator.setDefaults({
submitHandler: function(){
alert("submitted!");
}
});
$(document).ready(function(){
// Handler for .ready() called.
window.onbeforeunload = confirmExit;
var isdirty = false;
//$( ".selector" ).datepicker( "option", "buttonImage", '/images/datepicker.gif' );
$.datepicker.setDefaults($.datepicker.regional['']);
//$.datepicker.setDefaults($.datepicker.regional['fr']);
$.datepicker.setDefaults({
// showOn: 'both',
gotoCurrent: true,
dateFormat: 'yy-mm-dd',
autoSize: true,
numberOfMonths: 2,
// buttonImageOnly: true,
changeYear: true,
changeMonth: true
// buttonImage: 'images/icon_calendar.gif',
//regional: 'fr'
//regional: ''
});
$('input.datepicker').datepicker();
jQuery.validator.addMethod("gooddate", function(value, element, params){
return isValidDate2(value);
}, jQuery.format("Please enter a valid date"));
$(function(){
var dates = $('#from, #to').datepicker({
onSelect: function(selectedDate){
var option = this.id == dates[0].id ? "minDate" : "maxDate";
var instance = $(this).data("datepicker");
var date = $.datepicker.parseDate(instance.settings.dateFormat || $.datepicker._defaults.dateFormat, selectedDate, instance.settings);
dates.not(this).datepicker("option", option, date);
}
});
});
$("#myform").validate({
rules: {
xx: {
dateISO: true,
minlength: 8,
gooddate: true
}
},
messages: {
xx: {
dateISO: '* Date format is YYYY-MM-DD',
minlength: 'Dates need at least 8 characters'
},
errorPlacement: function(error, element){
error.insertAfter(element);
},
debug: true
}
});
});
function markDirty(){
isdirty = true;
}
function confirmExit(e){
if (!e) {
e = window.event;
}
if (isdirty === false) {
e = window.event;
}
//e.cancelBubble is supported by IE - this will kill the bubbling process.
e.cancelBubble = true;
e.returnValue = 'You sure you want to leave?'; //This is displayed on the dialog
//e.stopPropagation works in Firefox.
if (e.stopPropagation) {
e.stopPropagation();
e.preventDefault();
}
}
// My date validation function
function isValidDate2(value){
var sdt = value.split(" ");
var userDate = sdt[0];
// Checks for the following valid date formats:
// Also separates date into month, day, and year variables
// MM/DD/YY MM/DD/YYYY MM-DD-YY MM-DD-YYYY
//var datePat = /^(\d{1,2})(\/|-)(\d{1,2})\2(\d{2}|\d{4})$/;
// YYYY-MM-DD, YYYY/MM/DD, YYYY.MM.DD
// To require a 4 digit year entry, use this line instead:
var datePat = /^(\d{4})(\/|-|.|\s|\\)(\d{1,2})\2(\d{1,2})$/;
var result = true;
var matchArray = userDate.match(datePat); // is the format ok?
if (matchArray === null) {
//alert("Date is not in a valid format.");
result = false;
}
try {
month = matchArray[3]; // parse date into variables
}
catch (err) {
month = 0;
}
try {
day = matchArray[4];
}
catch (err) {
day = 0;
}
try {
year = matchArray[1];
}
catch (err) {
year = 0;
}
if (month < 1 || month > 12) { // check month range
result = false;
}
if (day < 1 || day > 31) {
result = false;
}
if ((month == 4 || month == 6 || month == 9 || month == 11) && day == 31) {
result = false;
}
if (month == 2) { // check for february 29th
var isleap = (year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0));
if (day > 29 || (day == 29 && !isleap)) {
result = false;
}
}
if (result === true && userDate.length > 0) {
result = isDate(userDate);
}
return result;
}
// existing function from aansims
var dtCh = "-";
var minYear = 1900;
var maxYear = 2100;
function isDate(dtStr){
var daysInMonth = DaysArray(12);
var pos1 = dtStr.indexOf(dtCh);
var pos2 = dtStr.indexOf(dtCh, pos1 + 1);
var strMonth = dtStr.substring(pos1 + 1, pos2);
var strDay = dtStr.substring(pos2 + 1);
var strYear = dtStr.substring(0, pos1);
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, 10);
day = parseInt(strDay, 10);
year = parseInt(strYr, 10);
if (pos1 == -1 || pos2 == -1) {
return false;
}
if (strMonth.length < 1 || month < 1 || month > 12) {
return false;
}
if (strDay.length < 1 || day < 1 || day > 31 || (month == 2 && day > daysInFebruary(year)) || day > daysInMonth[month]) {
return false;
}
if (strYear.length != 4 || year === 0 || year < minYear || year > maxYear) {
return false;
}
if (dtStr.indexOf(dtCh, pos2 + 1) !== -1 || isInteger(stripCharsInBag(dtStr, dtCh)) === false) {
return false;
}
return true;
}
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 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;
}
</script>
<h1>New Web Project Page</h1>
<h2>Single Date</h2>
<div>
<input id="singledate" class="datepicker" type="text" maxlength="10" onchange="markDirty();">
</div>
<br/>
<select>
<option value="volvo">Volvo</option>
<option value="saab">Saab</option>
<option value="mercedes">Mercedes</option>
<option value="audi">Audi</option>
</select>
<h2>Simple text</h2>
<input id="mytb" type="text" onchange="markDirty();"><h2>Default Date</h2>
<h2>Single Date Read only</h2>
<input id="singledate2" type="text" class="datepicker" maxlength="10" value="1963-01-05" disabled="true" onchange="markDirty();"><h2>Default Date</h2>
<input id="singledate3" type="text" class="datepicker" maxlength="10" value="2009-09-29" onchange="markDirty();"><h2>Required date</h2>
<input id="singledate4" type="text" class="datepicker" name="xx" title="Invalid Date" maxlength="10" onchange="markDirty();"><h2>Date Range</h2>
<div>
<input type="text" maxlength="10" id="from" onchange="markDirty();">to <input type="text" id="to" maxlength="10" onchange="markDirty();">
</div><h2>Exit tests</h2>
<a href="http://www.adga.ca">ADGA</a>
<input type="submit" value="test" />
</form>
</body>
</html>