﻿/* --------------------------------------------------------------------------------
 Filename: ValidationInfo                                                   

 Description:

 This file contains the ValidationInfo class, which is used to validate form information.   

 Here is an example of how to create an object of this class:
     
 g_validationInfo    = new ValidationInfo([
    {"szName": "szFirstName",       "szType": "input",  "szValidationType": "exists", "szMessageLevel2": "Please supply a first name."},
    {"szName": "szLastName",        "szType": "input",  "szValidationType": "exists", "szMessageLevel2": "Please supply a last name."},
    {"szName": "szTitle",           "szType": "input",  "szValidationType": "exists", "szMessageLevel2": "Please supply a job title."},
    {"szName": "szSchoolDistrict",  "szType": "input",  "szValidationType": "exists", "szMessageLevel2": "Please supply a district name."},
    {"szName": "szSchoolName",      "szType": "input",  "szValidationType": "exists", "szMessageLevel2": "Please supply a school name."},
    {"szName": "szPhone",           "szType": "input",  "szValidationType": "phone",  "szMessageLevel2": "Invalid format - Use: (999)999-9999"},
    {"szName": "szPhone",           "szType": "input",  "szValidationType": "exists", "szMessageLevel2": "Please supply a phone number."}
    ],
    "validateMessageHidden",
    "validateMessageLevel1",
    "validateMessageLevel2"
 ); // Create an instance of the ValidationInfo class.

 Then on load of the page call the Initialize method, passing in a reference to the document and the form. Like this:
 g_validationInfo.Initialize(document, document.forms[0]);
 
 Then validate the form by calling the Validate method. Like this:
 g_validationInfo.Validate();       // Returns true if the form validates, false if it doesn't.
     
 History:                                                                        
   Ver         Inits   Date        Comments                                        
   1.00.00     jwl     02/19/08    Created

-------------------------------------------------------------------------------- */


// ValidationInfo:
//
// This is the constructor for the ValidationInfo class.
//
function ValidationInfo(objFormInfo, szHiddenClass, szLevel1Class, szLevel2Class)
{
    // DATA:    
    var m_pDoc          = null;             // A reference to the document.               
    var m_pForm         = null;             // A reference to the form that we will validate.   
    var m_pFormInfo     = objFormInfo;      // The array of information we will use to validate the form.
    var m_szHiddenClass = szHiddenClass;    // The class when the validation messages are hidden.
    var m_szLevel1Class = szLevel1Class;    // The class when the validation message is at alert level 1.
    var m_szLevel2Class = szLevel2Class;    // The class when the validation message is at alert level 2.
    var m_szDefaultDatePrefix = '19';
               
    // PRIVATE METHODS:               
                             
               
    // ValidationInfo::validateTheElement:
    //
    // Validate the element based on the type of element it is.
    //
    function validateTheElement(pInput, pFormInfo)
    {                      
        if(!pInput || !pFormInfo) 
            return false;
        
        switch(pFormInfo.szType)
        {
            case "input":             
                return handleValidationInput(pInput, pFormInfo);                                   
		    break;
		    
            case "select":
                // If the selected value matches what we said is the unselected value, then it doesn't validate.
                if(pInput.options.length > 0)
                {
		            if(pInput.options[pInput.selectedIndex].value === pFormInfo.szUnselectedValue)
		                return false;
		            else
		                return true;
                }
                else
                    return false;	                                		                		    
		    break;		
		    default:
		        return false;		            
        }  
        return false;  
                    
    } // validateTheElement                   
           
               
    // ValidationInfo::handleValidationInput:
    //
    // Handle the various kinds of validation on input form fields.
    //
    function handleValidationInput(pInput, pFormInfo)
    {                      
        if(!pInput || !pFormInfo || !pFormInfo.szValidationType) 
            return false;   
            
        switch(pFormInfo.szValidationType)
        {
            case "exists":
                if(pInput.value.length > 0)
                    return true;
            break;        
            case "match":
                if(pFormInfo.pMatchInputElement)
                {
                    if(pInput.value === pFormInfo.pMatchInputElement.value)
                        return true;
                } 
            break; 
            case "date":
                if(pInput.value.length < 1)                     // Weird...but we're allowing a blank...                
                    return true;                                // ...date to be valid.
            
                if(validateDate(pInput.value))                  // If the date validates...
                {
                    pInput.value = formatDate(pInput.value);    // ...do a little formatting on it.
                    return true;
                }
                else
                    return false;
            break;     
            case "email":            
                if(validateEmail(pInput.value))                 
                    return true;
                else
                    return false;
            break;      
            case "phone":            
                if(validatePhone(pInput.value))                 
                    return true;
                else
                    return false;
            break;                                        
            case "prompt":
                if(pFormInfo.nMessageLevel === 0)
                {
                    pFormInfo.pMessageElement.innerHTML = pFormInfo.szMessageLevel0;  
                    pFormInfo.pMessageElement.className = "validateMessageLevel1";  
                }        
                return true;    // Validation type of prompt always returns true.
            break;        
            default:
	            return false;		                             
        }
        return false;             
            
    } // ValidationInfo::handleValidationInput                    
           
            
    // ValidationInfo::validateDate  
    //
    // This is a date validation method I got from this website:
    // http://www.expertsrt.com/scripts/Rod/validate_date.php
    //
    // Date as month, day, and four digit year. You may use a slash, hyphen or period to separate the values.
    // The date must be a real date. 2-30-2000 would not be accepted.
    // Format mm/dd/yyyy
    //         
    function validateDate(pInputValue)
    {    
        var RegExPattern = /^(?=\d)(?:(?:(?:(?:(?:0?[13578]|1[02])(\/|-|\.)31)\1|(?:(?:0?[1,3-9]|1[0-2])(\/|-|\.)(?:29|30)\2))(?:(?:1[6-9]|[2-9]\d)?\d{2})|(?:0?2(\/|-|\.)29\3(?:(?:(?:1[6-9]|[2-9]\d)?(?:0[48]|[2468][048]|[13579][26])|(?:(?:16|[2468][048]|[3579][26])00))))|(?:(?:0?[1-9])|(?:1[0-2]))(\/|-|\.)(?:0?[1-9]|1\d|2[0-8])\4(?:(?:1[6-9]|[2-9]\d)?\d{2}))($|\ (?=\d)))?(((0?[1-9]|1[012])(:[0-5]\d){0,2}(\ [AP]M))|([01]\d|2[0-3])(:[0-5]\d){1,2})?$/;
        if ((pInputValue.match(RegExPattern)) && (pInputValue != '')) 
            return true;
        else
            return false;
        
    } //ValidationInfo::validateDate    
    
    
    // ValidationInfo::validatePhone  
    //
    // This strips out the parens, slashes, and dots and then makes sure that all that's left is numbers.
    //         
    function validatePhone(pInputValue)
    {    
        if(!pInputValue || pInputValue.length < 1)
            return false;
    
         var RegExPattern = /^\([1-9]\d{2}\)\s?\d{3}\-\d{4}$/;
         if(pInputValue.match(RegExPattern)) 
           return true;   
         else
           return false; 
        
    } //ValidationInfo::validatePhone               
    
    
    // ValidationInfo::validateEmail  
    //
    // Returns true if the email is in a valid format and false if it isn't.
    //         
    function validateEmail(pInputValue)
    {    
        if(!pInputValue || pInputValue.length < 1)
            return false;
    
         var RegExPattern  =  /(^[a-z]([a-z_\.]*)@([a-z_\.]*)([.][a-z]{3})$)|(^[a-z]([a-z_\.]*)@([a-z_\.]*)(\.[a-z]{3})(\.[a-z]{2})*$)/i;        
         if(pInputValue.match(RegExPattern)) 
           return true;   
         else
             return true;    // 05-18-2010 jwl - This should be false, however the regular expression above is tossing out email addresses that
                             // end with 2 characters after the dot such as ".us", so I'm disabling it until I fix it.
        
    } //ValidationInfo::validateEmail                             
            

    // ValidationInfo::formatDate  
    //
    // Help get the date into the format that we want, which is mm/dd/yyyy
    // Format mm/dd/yyyy
    //         
    function formatDate(pInputValue)
    {
        if (!pInputValue)
            return;

        pInputValue = pInputValue.replace(/-/g, "/");   // Change dashes to slashes.
        pInputValue = pInputValue.replace(/\./g, "/");  // Change periods, to slashes.

        // If they only entered a 2-digit year, make it "19" + whatever.
        if (pInputValue.charAt(pInputValue.length - 3) === '/') {
            var szYear = "20";
            var nYear = parseInt(pInputValue.substring(pInputValue.length - 2));
            if (nYear >= 30)
                szYear = "19";
            pInputValue = pInputValue.substring(0, (pInputValue.length - 2)) + szYear + pInputValue.substring(pInputValue.length - 2);
        }

        if (pInputValue.charAt(1) == '/')        // Add leading zero to month if it needs it.
            pInputValue = '0' + pInputValue;

        if (pInputValue.charAt(4) == '/')        // Add leading zero to day if it needs it.
            pInputValue = pInputValue.substr(0, 3) + '0' + pInputValue.substr(3, 6);

        return pInputValue;
        
    } //ValidationInfo::formatDate              
            
               
    // ValidationInfo::getElementUsingId:  
    //
    // Utility function to safely hide or show an element.
    //  
    function getElementUsingId(szID)
    {        
        if(!szID || szID.length < 1)
            return null;
                                                
        var pElement = m_pDoc.getElementById(szID);
        if(pElement)
            return pElement;
        else
            return null;
                    
    } // getElementUsingId                                    
      
      
    // ValidationInfo::setDefaultMessageLevelInfo:  
    //
    // This creates default message level information, if more specific information wasn't
    // included when the object was initialized.
    //
    function setDefaultMessageLevelInfo(pFormInfo)
    {   
        if(!pFormInfo)                                                 // We need this to continue.
            return;        
                     
        if(!pFormInfo.hasOwnProperty("nMessageLevel"))                  // If we don't specifically assign a message level...
            pFormInfo.nMessageLevel = 1;                                // ...assign a level of 1.
                 
        if(!pFormInfo.hasOwnProperty("szMessageLevel1"))                // If we didn't specify one on creation...   
            pFormInfo.szMessageLevel1 = setDefaultMessage(pFormInfo);   // ...then specify a default message.
          
        if(!pFormInfo.hasOwnProperty("szMessageLevel2"))                // If we didn't specify one on creation...   
            pFormInfo.szMessageLevel2 = setDefaultMessage(pFormInfo);   // ...then specify a default message.
                                                          
    } // setDefaultpMessageLevelInfo              
               
          
    // ValidationInfo::setDefaultMessage:  
    //
    // Use the information passed in to come up with a default message and return it.
    //
    function setDefaultMessage(pFormInfo)
    {           
        if(!pFormInfo || !pFormInfo.hasOwnProperty("szValidationType")) // We need these to continue.
            return "";        
                     
        switch(pFormInfo.szValidationType)
        {
            case "exists":
                return "required";
            break;
            case "match":
                return pFormInfo.szName + " must match " + pFormInfo.szMatchName;
            break;   
            default:
                return "required"; 
        }
                                         
    } // setDefaultMessage                   
               
               
    // PUBLIC METHODS:    
                       
    // ValidationInfo::GetFormInfo
    //
    // Allows public access to the private member variable m_pFormInfo
    //
    function GetFormInfo()
    {
        return m_pFormInfo;
               
    }   // GetFormInfo    
    this.GetFormInfo = GetFormInfo;     // Make this a public method.              
    
               
    // ValidationInfo::Initialize
    //
    // After the page is loaded you must call this method, passing in a reference to the form object.
    // This method will establish pointers to the elements that we will validate and that will receive
    // the validation messages.
    //
    function Initialize(pDoc, pForm)
    {
        if(!pDoc || !pForm || !m_pFormInfo)    // We need these to continue.
            return;                 
               
        m_pForm = pForm;                       // Set the member variables.   
        m_pDoc  = pDoc;     
                
        for(var i=0; i<m_pFormInfo.length; i++)
        {        
            if(m_pFormInfo[i]) {                    // Odd error where m_pFormInfo.length is more than the number of members in the array.
                m_pFormInfo[i].bValidate = true;    // Add this property and init it to true.              
            
                setDefaultMessageLevelInfo(m_pFormInfo[i]);
            
                var pInput = getElementUsingId(m_pFormInfo[i].szName); // Get the form input element.     
                if(pInput)
                {   
                    if(pInput.readOnly)                         // If this input element is set to readyOnly...
                        m_pFormInfo[i].bValidate = false;       // ...then we don't want to validate it. 
                
                    m_pFormInfo[i].pInputElement = pInput;                
                    var objMessage = m_pDoc.getElementById("val" + m_pFormInfo[i].szName);// Get the span that holds the message.
                    if(objMessage)
                        m_pFormInfo[i].pMessageElement = objMessage;  
                         
                    if(m_pFormInfo[i].szMatchName)                      // See if we have a match name 
                    {
                        pInput = getElementUsingId(m_pFormInfo[i].szMatchName);
                        if(pInput)
                            m_pFormInfo[i].pMatchInputElement = pInput; // Set the element we must match with.
                    }                     
                }         
            }       
        }                        
                           
    }   // Initialize    
    this.Initialize = Initialize;   //  Make this a public method.                    
                   
               
    // ValidationInfo::SetValidation
    //
    // Pass in true or false to set validation on or off for the passed in form element name.
    //
    function SetValidation(szName, bSetToValue)
    {    
        for(var i=0; i<m_pFormInfo.length; i++)     // There could be more than one with the same name.
        {                                           // So go through them all.
            if(m_pFormInfo[i]) {                    // Odd error where m_pFormInfo.length is more than the number of members in the array.        
                if(m_pFormInfo[i].szName == szName)
                {                        
                    m_pFormInfo[i].bValidate = bSetToValue;
                    if(m_pFormInfo[i].pMessageElement)    
                    {
                        m_pFormInfo[i].pMessageElement.className  = m_szHiddenClass;
                        m_pFormInfo[i].pMessageElement.innerHTML   = "";   // blank out the validation message.                                        
                    }
                    if(m_pFormInfo[i].pInputElement)
                    {
                        if(m_pFormInfo[i].pInputElement.readOnly)          // If this input element is set to readOnly... 
                            m_pFormInfo[i].bValidate = false;              // ...we don't want to validate it. 
                    }                           
                }
            }
        }                       
    }   // SetValidation    
    this.SetValidation = SetValidation; //  Make this a public method.                
           
           
    // ValidationInfo::SetAllWarningsToThisLevel
    //
    // Set the message level of all message to the one passed in.
    //
    function SetAllWarningsToThisLevel(nMessageLevel)
    {
        if(!m_pFormInfo)              // We need these to continue.
            return;     
                                           
        for(var i=0; i<m_pFormInfo.length; i++) {
            if(m_pFormInfo[i])                     // Odd error where m_pFormInfo.length is more than the number of members in the array.                
                m_pFormInfo[i].nMessageLevel = nMessageLevel;
        }            
               
    }   // SetAllWarningsToThisLevel   
    this.SetAllWarningsToThisLevel = SetAllWarningsToThisLevel; //  Make this a public method.                   
           
           
    // ValidationInfo::Validate
    //
    // This validates all the form elements that are in the m_pFormInfo array.
    //
    function Validate()
    {
        if(!m_pFormInfo)            // If we don't have form info, that's a problem.
            return false;         

        // First, turn off all the validation messages.
        for(var i=0; i<m_pFormInfo.length; i++)
        {
            if(m_pFormInfo[i]) {    // Odd error where m_pFormInfo.length is more than the number of members in the array.                
                if(m_pFormInfo[i].pInputElement && m_pFormInfo[i].pMessageElement)  // These pointers should already be established.
                {
                    m_pFormInfo[i].pMessageElement.className = m_szHiddenClass;
                    m_pFormInfo[i].pMessageElement.innerHTML = "";                              
                }   
            } 
        }  

        var bReturn = true;        
        for(var i=0; i<m_pFormInfo.length; i++)
        {        
            if(m_pFormInfo[i]) {        // Odd error where m_pFormInfo.length is more than the number of members in the array.                
                if(m_pFormInfo[i].pInputElement && m_pFormInfo[i].pMessageElement)  // These pointers should already be established.
                {
                    if(m_pFormInfo[i].bValidate)                                    // We're validating this element.
                    {
                        if(!validateTheElement(m_pFormInfo[i].pInputElement, m_pFormInfo[i]))     // Validate the element based on it's type.
                        {
                            if(m_pFormInfo[i].nMessageLevel === 2)
                            {
                                m_pFormInfo[i].pMessageElement.innerHTML = m_pFormInfo[i].szMessageLevel2;  
                                m_pFormInfo[i].pMessageElement.className = "validateMessageLevel2";  
                            }
                            else  
                            {  
                                m_pFormInfo[i].pMessageElement.innerHTML = m_pFormInfo[i].szMessageLevel1;                          
                                m_pFormInfo[i].pMessageElement.className = "validateMessageLevel1"; 
                            }                                                                           
                            bReturn = false;
                        }    
                    }     
                } 
            }                      
        }  
        return bReturn;      
               
    }   // Validation    
    this.Validate = Validate;   //  Make this a public method.


    // ValidationInfo::SetDatePrefix
    //
    // This sets the date prefix equal to the passed-in string.
    //
    function SetDatePrefix(szDatePrefix) {
        m_szDefaultDatePrefix = szDatePrefix;

    }   // SetDatePrefix
    this.SetDatePrefix = SetDatePrefix; //  Make this a public method.         
    
                                   
} // ValidationInfo:       


