Link to home
Start Free TrialLog in
Avatar of Jack Andrews
Jack AndrewsFlag for United States of America

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

<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>

Open in new window

Avatar of Rob
Rob
Flag of Australia image

yes, it's set here:

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;
                    }

                    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;
                    }

Open in new window

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.
Avatar of Jack Andrews

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?
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;

}

Open in new window

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:

<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>

Open in new window

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;
                    }

Open in new window

That way you only set the maxDateStr and the rest calculates automatically.  Does that make sense?
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);
}

Open in new window

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);
}

Open in new window

Note that I've updated the equality to use === and !== to make sure that type conversion isn't happening.
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;
                }
            }

Open in new window

Can you show the code that is calling the validate script please.
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.
<input style="font-size: 16px;" type=button onClick="if (validatePage1()) { collapseElem('page_1'); expandElem('page_2');}" class="mainForm" value="Continue to Your Item List »"/>

Open in new window

The validation script is in the page, not an external file.
The calendar script we are using is found here
ASKER CERTIFIED SOLUTION
Avatar of Rob
Rob
Flag of Australia image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
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.
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.

$(function() {
    $( "#field_1" ).datepicker({ 
minDate: "-90D", 
maxDate: "+1M +10D" 
});
  });

Open in new window

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?

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;
                    }
                }

Open in new window


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
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
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.
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
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.