Jack Andrews
asked on
How do fix calendar date validation
The popup calendar in a form is requiring a date within the current year. Is there something in this script that controls that? What would I change?
The js for the calendar itself is set 1999/2099
The js for the calendar itself is set 1999/2099
<SCRIPT type=text/javascript>
<!--
function collapseElem(obj)
{
var el = document.getElementById(obj);
el.style.display = 'none';
}
function expandElem(obj)
{
var el = document.getElementById(obj);
el.style.display = '';
}
//-->
</SCRIPT>
<!-- expand/collapse function -->
<!-- expand/collapse function -->
<SCRIPT type=text/javascript>
<!--
// collapse all elements, except the first one
function collapseAll()
{
var numFormPages = 3;
for(i=2; i <= numFormPages; i++)
{
currPageId = ('page_' + i);
collapseElem(currPageId);
}
}
//-->
</SCRIPT>
<!-- expand/collapse function -->
<!-- validate -->
<SCRIPT type=text/javascript>
<!--
function validateField(fieldId, fieldBoxId, fieldType, required)
{
fieldBox = document.getElementById(fieldBoxId);
fieldObj = document.getElementById(fieldId);
if(fieldType == 'text' || fieldType == 'textarea' || fieldType == 'password' || fieldType == 'file' || fieldType == 'phone' || fieldType == 'website')
{
if(required == 1 && fieldObj.value == '')
{
fieldObj.setAttribute("class","mainFormError");
fieldObj.setAttribute("className","mainFormError");
fieldObj.focus();
return false;
}
}
else if(fieldType == 'menu' || fieldType == 'country' || fieldType == 'state')
{
if(required == 1 && fieldObj.selectedIndex == 0)
{
fieldObj.setAttribute("class","mainFormError");
fieldObj.setAttribute("className","mainFormError");
fieldObj.focus();
return false;
}
}
else if(fieldType == 'email')
{
if((required == 1 && fieldObj.value=='') || (fieldObj.value!='' && !validate_email(fieldObj.value)))
{
fieldObj.setAttribute("class","mainFormError");
fieldObj.setAttribute("className","mainFormError");
fieldObj.focus();
return false;
}
}
}
function validate_email(emailStr)
{
apos=emailStr.indexOf("@");
dotpos=emailStr.lastIndexOf(".");
if (apos<1||dotpos-apos<2)
{
return false;
}
else
{
return true;
}
}
function validateDate(fieldId, fieldBoxId, fieldType, required, minDateStr, maxDateStr)
{
retValue = true;
fieldBox = document.getElementById(fieldBoxId);
fieldObj = document.getElementById(fieldId);
dateStr = fieldObj.value;
if(required == 0 && dateStr == '')
{
return true;
}
if(dateStr.charAt(2) != '/' || dateStr.charAt(5) != '/' || dateStr.length != 10)
{
retValue = false;
}
else // format's okay; check max, min
{
currDays = parseInt(dateStr.substr(0,2),10) + parseInt(dateStr.substr(3,2),10)*30 + parseInt(dateStr.substr(6,4),10)*365;
//alert(currDays);
if(maxDateStr != '')
{
maxDays = parseInt(maxDateStr.substr(0,2),10) + parseInt(maxDateStr.substr(3,2),10)*30 + parseInt(maxDateStr.substr(6,4),10)*365;
//alert(maxDays);
if(currDays > maxDays)
retValue = false;
}
if(minDateStr != '')
{
minDays = parseInt(minDateStr.substr(0,2),10) + parseInt(minDateStr.substr(3,2),10)*30 + parseInt(minDateStr.substr(6,4),10)*365;
//alert(minDays);
if(currDays < minDays)
retValue = false;
}
}
if(retValue == false)
{
fieldObj.setAttribute("class","mainFormError");
fieldObj.setAttribute("className","mainFormError");
fieldObj.focus();
return false;
}
}
function MM_openBrWindow(theURL,winName,features) { //v2.0
if(window.screen)if(isCenter)if(isCenter=="true"){
var myLeft = (screen.width-myWidth)/2;
var myTop = (screen.height-myHeight)/2;
features+=(features!='')?',':'';
features+=',left='+myLeft+',top='+myTop;
}
window.open(theURL,winName,features);
}
//-->
</SCRIPT>
currDays is the number of days since the year zero, some large number eg 13 Dec 2013 would be 1485594
minDateStr is the earliest the date can be, while maxDateStr is the maximum. If it is for this year then they're set to something like "01/01/2013" and "31/12/2013" respectively.
minDays / maxDays are the conversion to a number so that currDays can be compared with and whether it falls between minDays and maxDays
So all you need to change is the strings: minDateStr and maxDateStr. You have to make sure you follow the dd/mm/yyyy format or it won't calculate properly. Note the double digits for day and month and the four digits for year.
There is an element of error in the calculation as the number of days assumes each month is 30 days and each year is 365 so you may find some dates that are in the range may say they're not close to the minimum or maximum.
minDateStr is the earliest the date can be, while maxDateStr is the maximum. If it is for this year then they're set to something like "01/01/2013" and "31/12/2013" respectively.
minDays / maxDays are the conversion to a number so that currDays can be compared with and whether it falls between minDays and maxDays
So all you need to change is the strings: minDateStr and maxDateStr. You have to make sure you follow the dd/mm/yyyy format or it won't calculate properly. Note the double digits for day and month and the four digits for year.
There is an element of error in the calculation as the number of days assumes each month is 30 days and each year is 365 so you may find some dates that are in the range may say they're not close to the minimum or maximum.
ASKER
Thanks for the fast response but I'm really ignorant here.
I see the mindate and maxdate code but I don't know what to change. I want a max of 90 days between two dates and a message when it exceeds that. There would be no min since the same day is ok.
Does this code control all that?
I see the mindate and maxdate code but I don't know what to change. I want a max of 90 days between two dates and a message when it exceeds that. There would be no min since the same day is ok.
Does this code control all that?
then you don't need the mindatestr. You would calculate minDays based on the maxDays-90 so just combine into the condition testing if there is a maxDateStr
currDays = parseInt(dateStr.substr(0,2),10) + parseInt(dateStr.substr(3,2),10)*30 + parseInt(dateStr.substr(6,4),10)*365;
if(maxDateStr != '')
{
maxDays = parseInt(maxDateStr.substr(0,2),10) + parseInt(maxDateStr.substr(3,2),10)*30 + parseInt(maxDateStr.substr(6,4),10)*365;
//alert(maxDays);
if(currDays > maxDays)
retValue = false;
minDays = maxDays - 90;
//alert(minDays);
if(currDays < minDays)
retValue = false;
}
ASKER
I copied what you have above and pasted it into the script in the page replacing what was there. It still will not validate the date selected in Jan 2014. I probably missed something but the validation seems to be functioning.
Here is the complete script:
Here is the complete script:
<SCRIPT type=text/javascript>
<!--
function validateField(fieldId, fieldBoxId, fieldType, required)
{
fieldBox = document.getElementById(fieldBoxId);
fieldObj = document.getElementById(fieldId);
if(fieldType == 'text' || fieldType == 'textarea' || fieldType == 'password' || fieldType == 'file' || fieldType == 'phone' || fieldType == 'website')
{
if(required == 1 && fieldObj.value == '')
{
fieldObj.setAttribute("class","mainFormError");
fieldObj.setAttribute("className","mainFormError");
fieldObj.focus();
return false;
}
}
else if(fieldType == 'menu' || fieldType == 'country' || fieldType == 'state')
{
if(required == 1 && fieldObj.selectedIndex == 0)
{
fieldObj.setAttribute("class","mainFormError");
fieldObj.setAttribute("className","mainFormError");
fieldObj.focus();
return false;
}
}
else if(fieldType == 'email')
{
if((required == 1 && fieldObj.value=='') || (fieldObj.value!='' && !validate_email(fieldObj.value)))
{
fieldObj.setAttribute("class","mainFormError");
fieldObj.setAttribute("className","mainFormError");
fieldObj.focus();
return false;
}
}
}
function validate_email(emailStr)
{
apos=emailStr.indexOf("@");
dotpos=emailStr.lastIndexOf(".");
if (apos<1||dotpos-apos<2)
{
return false;
}
else
{
return true;
}
}
function validateDate(fieldId, fieldBoxId, fieldType, required, minDateStr, maxDateStr)
{
retValue = true;
fieldBox = document.getElementById(fieldBoxId);
fieldObj = document.getElementById(fieldId);
dateStr = fieldObj.value;
if(required == 0 && dateStr == '')
{
return true;
}
if(dateStr.charAt(2) != '/' || dateStr.charAt(5) != '/' || dateStr.length != 10)
{
retValue = false;
}
else // format's okay; check max, min
{
currDays = parseInt(dateStr.substr(0,2),10) + parseInt(dateStr.substr(3,2),10)*30 + parseInt(dateStr.substr(6,4),10)*365;
//alert(currDays);
if(maxDateStr != '')
{
maxDays = parseInt(maxDateStr.substr(0,2),10) + parseInt(maxDateStr.substr(3,2),10)*30 + parseInt(maxDateStr.substr(6,4),10)*365;
//alert(maxDays);
if(currDays > maxDays)
retValue = false;
}
if(minDateStr != '')
{
minDays = maxDays - 90;
//alert(minDays);
if(currDays < minDays)
retValue = false;
}
}
if(retValue == false)
{
fieldObj.setAttribute("class","mainFormError");
fieldObj.setAttribute("className","mainFormError");
fieldObj.focus();
return false;
}
}
function MM_openBrWindow(theURL,winName,features) { //v2.0
if(window.screen)if(isCenter)if(isCenter=="true"){
var myLeft = (screen.width-myWidth)/2;
var myTop = (screen.height-myHeight)/2;
features+=(features!='')?',':'';
features+=',left='+myLeft+',top='+myTop;
}
window.open(theURL,winName,features);
}
//-->
</SCRIPT>
I'd edited my comment before you posted so I suspect you got an old copy of the code. My thoughts were to remove the minDateStr and combine the condition code into the maxDateStr:
if(maxDateStr != '')
{
maxDays = parseInt(maxDateStr.substr(0,2),10) + parseInt(maxDateStr.substr(3,2),10)*30 + parseInt(maxDateStr.substr(6,4),10)*365;
//alert(maxDays);
if(currDays > maxDays)
retValue = false;
minDays = maxDays - 90;
//alert(minDays);
if(currDays < minDays)
retValue = false;
}
That way you only set the maxDateStr and the rest calculates automatically. Does that make sense?
ASKER
Not really cuz I tried what I understood and it won't submit now. Here is the part I changed:
function validateDate(fieldId, fieldBoxId, fieldType, required, minDateStr, maxDateStr)
{
retValue = true;
fieldBox = document.getElementById(fieldBoxId);
fieldObj = document.getElementById(fieldId);
dateStr = fieldObj.value;
if(required == 0 && dateStr == '')
{
return true;
}
if(dateStr.charAt(2) != '/' || dateStr.charAt(5) != '/' || dateStr.length != 10)
{
retValue = false;
}
else // format's okay; check max, min
{
currDays = parseInt(dateStr.substr(0,2),10) + parseInt(dateStr.substr(3,2),10)*30 + parseInt(dateStr.substr(6,4),10)*365;
//alert(currDays);
if(maxDateStr != '')
{
maxDays = parseInt(maxDateStr.substr(0,2),10) + parseInt(maxDateStr.substr(3,2),10)*30 + parseInt(maxDateStr.substr(6,4),10)*365;
//alert(maxDays);
if(currDays > maxDays)
retValue = false;
minDays = maxDays - 90;
//alert(minDays);
if(currDays < minDays)
retValue = false;
}
if(retValue == false)
{
fieldObj.setAttribute("class","mainFormError");
fieldObj.setAttribute("className","mainFormError");
fieldObj.focus();
return false;
}
}
function MM_openBrWindow(theURL,winName,features) { //v2.0
if(window.screen)if(isCenter)if(isCenter=="true"){
var myLeft = (screen.width-myWidth)/2;
var myTop = (screen.height-myHeight)/2;
features+=(features!='')?',':'';
features+=',left='+myLeft+',top='+myTop;
}
window.open(theURL,winName,features);
}
You're missing a closing parenthesis } after the maxDateStr != '' condition. It needs to be:
function validateDate(fieldId, fieldBoxId, fieldType, required, minDateStr, maxDateStr)
{
retValue = true;
fieldBox = document.getElementById(fieldBoxId);
fieldObj = document.getElementById(fieldId);
dateStr = fieldObj.value;
if(required === 0 && dateStr === '')
{
return true;
}
if(dateStr.charAt(2) != '/' || dateStr.charAt(5) != '/' || dateStr.length != 10)
{
retValue = false;
}
else // format's okay; check max, min
{
currDays = parseInt(dateStr.substr(0,2),10) + parseInt(dateStr.substr(3,2),10)*30 + parseInt(dateStr.substr(6,4),10)*365;
//alert(currDays);
if(maxDateStr !== '')
{
maxDays = parseInt(maxDateStr.substr(0,2),10) + parseInt(maxDateStr.substr(3,2),10)*30 + parseInt(maxDateStr.substr(6,4),10)*365;
//alert(maxDays);
if(currDays > maxDays)
retValue = false;
minDays = maxDays - 90;
//alert(minDays);
if(currDays < minDays)
retValue = false;
}
}
if(retValue === false)
{
fieldObj.setAttribute("class","mainFormError");
fieldObj.setAttribute("className","mainFormError");
fieldObj.focus();
return false;
}
}
function MM_openBrWindow(theURL,winName,features) { //v2.0
if(window.screen)if(isCenter)if(isCenter=="true"){
var myLeft = (screen.width-myWidth)/2;
var myTop = (screen.height-myHeight)/2;
features+=(features!=='')?',':'';
features+=',left='+myLeft+',top='+myTop;
}
window.open(theURL,winName,features);
}
Note that I've updated the equality to use === and !== to make sure that type conversion isn't happening.
ASKER
I'm sorry. I checked it all and it still will not validate. I now have:
else // format's okay; check max, min
{
currDays = parseInt(dateStr.substr(0,2),10) + parseInt(dateStr.substr(3,2),10)*30 + parseInt(dateStr.substr(6,4),10)*365; //alert(currDays);
if(maxDateStr !== '')
{
maxDays = parseInt(maxDateStr.substr(0,2),10) + parseInt(maxDateStr.substr(3,2),10)*30 + parseInt(maxDateStr.substr(6,4),10)*365;
//alert(maxDays);
if(currDays > maxDays)
retValue = false;
minDays = maxDays - 90; //alert(minDays);
if(currDays < minDays)
retValue = false;
}
}
if(retValue == false)
{
fieldObj.setAttribute("class","mainFormError");
fieldObj.setAttribute("className","mainFormError");
fieldObj.focus();
return false;
}
}
Can you show the code that is calling the validate script please.
ASKER
I guess it would be the first submit button (code below). This is a three part form collapsed/expanded to paginate the user experience.
the form
The problem occurs on the first submit on the first "page" of the form. That is the only "page" that requires validation. There is a simple security script on the last page. The entire form can be found here. If you want to test it yourself, please use "test" in name and email fields and 000-000-0000 in the phone field.
Once the first step validates there shouldn't be further messages except for not filling in the security question.
the form
The problem occurs on the first submit on the first "page" of the form. That is the only "page" that requires validation. There is a simple security script on the last page. The entire form can be found here. If you want to test it yourself, please use "test" in name and email fields and 000-000-0000 in the phone field.
Once the first step validates there shouldn't be further messages except for not filling in the security question.
<input style="font-size: 16px;" type=button onClick="if (validatePage1()) { collapseElem('page_1'); expandElem('page_2');}" class="mainForm" value="Continue to Your Item List »"/>
ASKER
The validation script is in the page, not an external file.
ASKER
The calendar script we are using is found here
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
I've also tried to contact the calendar control site but it's down.
The calendar control should be able to restrict to certain dates. You can also make it so that the input textbox is unable to be typed in and the calendar icon has to be clicked. Alternatively clicking in the box displays the calendar.
If the calendar control you're using doesn't do this then use this jquery one. It's very good: http://jqueryui.com/datepicker/
A note on validation... This should be done in full on the server and not the client. To validate on the client is just a way of helping the user enter the right information but shouldn't be used to validate the form. I would be able to bypass all your javascript validation and submit what I like but using the console so you'd want to make sure that all inputs can be handled by your server.
The calendar control should be able to restrict to certain dates. You can also make it so that the input textbox is unable to be typed in and the calendar icon has to be clicked. Alternatively clicking in the box displays the calendar.
If the calendar control you're using doesn't do this then use this jquery one. It's very good: http://jqueryui.com/datepicker/
A note on validation... This should be done in full on the server and not the client. To validate on the client is just a way of helping the user enter the right information but shouldn't be used to validate the form. I would be able to bypass all your javascript validation and submit what I like but using the console so you'd want to make sure that all inputs can be handled by your server.
http://jsbin.com/otUTUlu/2/edit?js,console,output
This shows how easy it is to restrict the jquery calendar control to allow dates 90 days in the past and 1 month and 10 days into the future, as an example.
This shows how easy it is to restrict the jquery calendar control to allow dates 90 days in the past and 1 month and 10 days into the future, as an example.
$(function() {
$( "#field_1" ).datepicker({
minDate: "-90D",
maxDate: "+1M +10D"
});
});
ASKER
This one seems to have fixed it: ID: 39720406
I am curious what that parse line is actual specifying. It is cryptic to me. I wasn't sure where to put it, so I put it in two places... currDays and maxDays. Did I do this right?
The values from this form drop into another piece of management software. It reads the values from the email that the form send on submit. Apparently whatever was entered before was compatible, except for the date limitation. I implemented your parse function and it worked. I don't know if I entered it correctly and I don't yet know if the management app accepted it, but I expect that it did, since I was finally directed to the confirmation page at the end.
I am curious what that parse line is actual specifying. It is cryptic to me. I wasn't sure where to put it, so I put it in two places... currDays and maxDays. Did I do this right?
else // format's okay; check max, min
{
currDays = parseInt(maxDateStr.substr(0,2),10)*30 + parseInt(maxDateStr.substr(3,2),10) + parseInt(maxDateStr.substr(6,4),10)*365;
//alert(currDays);
if(maxDateStr != '')
{
maxDays = parseInt(maxDateStr.substr(0,2),10)*30 + parseInt(maxDateStr.substr(3,2),10) + parseInt(maxDateStr.substr(6,4),10)*365;
//alert(maxDays);
if(currDays > maxDays)
retValue = false;
}
if(minDateStr != '')
{
minDays = parseInt(minDateStr.substr(0,2),10) + parseInt(minDateStr.substr(3,2),10)*30 + parseInt(minDateStr.substr(6,4),10)*365;
//alert(minDays);
if(currDays < minDays)
retValue = false;
}
}
The values from this form drop into another piece of management software. It reads the values from the email that the form send on submit. Apparently whatever was entered before was compatible, except for the date limitation. I implemented your parse function and it worked. I don't know if I entered it correctly and I don't yet know if the management app accepted it, but I expect that it did, since I was finally directed to the confirmation page at the end.
SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
You are obviously very experienced at this. Wish I was. Reading your explanation, I get the feeling there is some prior knowledge necessary to grab what you so carefully explain. I'm just an empty bucket here. I had copied what your last post included in two places. But, your comment here:
"You're almost there but your currDays and minDays calculations aren't correct. You need to replace maxDateStr with dateStr for currDays and minDateStr for minDays. However this will make more sense when I explain it below:"
...seems to suggest that I either did not put them in the right places or there is more to be done. The strengs vs numbers difference is Greek to me.
Sorry.
If you can be a little more elementary, I would like to understand it, but I'm not sure it is worth your time or within my IQ.
To clarify since we first began this exercise, the client (my customer) does not care how far out the date is. However, at some point he might. My comment, not his.
That said, I see the 90 days might need to be something else?
Confused. Again, sorry.
"You're almost there but your currDays and minDays calculations aren't correct. You need to replace maxDateStr with dateStr for currDays and minDateStr for minDays. However this will make more sense when I explain it below:"
...seems to suggest that I either did not put them in the right places or there is more to be done. The strengs vs numbers difference is Greek to me.
Sorry.
If you can be a little more elementary, I would like to understand it, but I'm not sure it is worth your time or within my IQ.
To clarify since we first began this exercise, the client (my customer) does not care how far out the date is. However, at some point he might. My comment, not his.
That said, I see the 90 days might need to be something else?
Confused. Again, sorry.
SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
The customer does not care what date is entered. The calendar is working. We'll leave it at that. Maybe I'll learn this stuff some day. Thanks.
Open in new window