// some javascript Validation functions to be included into pages.


//////////////////////////////////////////////////////////////////////////////////
//                        Validate
//
// This function will Validate data.  Pass in the type, and the Value.
// It will pop up an alert box for invalid data.
//
function Validate( _val, _type )
{
    if( _type == "date" )
    {
        if( !ValidateDate( _val ) )
        {
            alert("invalid date : " + _val);
        }
    } 
    else if( _type == "alpha" )
    {
        if( !ValidateAlpha( _val ) )
        {
            alert("invalid alphanumeric : " + _val);
        }
    } 
    else if( _type == "number" )
    {
        if( !ValidateNumber( _val ) )
        {
            alert("invalid number : " + _val);
        }
    } 
    else if( _type == "email" )
    {
        if( !ValidateEmail( _val ) )
        {
            alert("invalid email address : " + _val);
        }
    } 
    else if( _type == "phone" )
    {
        if( !ValidatePhone( _val ) )
        {
            alert("invalid phone number : " + _val);
        }
    }
    else // unknown type.
    {
        // do nothing..
    }
} 
// end Validate


//////////////////////////////////////////////////////////////////////////////////
//                        ValidateDate
//
// This function will Validate dates. returns true for valid date.
//
function ValidateDate( _val )
{
    if( _val.charAt(2) == '/' && _val.charAt(5) == '/' && _val.length == 10 )
    {
        // alright we have the slashes where they should be, and its the right length..       
        // but do we have numbers?

        month = _val.substring(0, 2);
        day = _val.substring(3, 5);
        year = _val.substring(6);

        if( ValidateNumber(month) && ValidateNumber(day) && ValidateNumber(year) )
        {
            // ok they are all numbers. it must be a good date then.
            return true;
        }
    }
    return false;
} 
// end ValidateDate


//////////////////////////////////////////////////////////////////////////////////
//                        ValidateAlpha
//
// This function will Validate alphanumeric strings. returns true if valid.
//
function ValidateAlpha( _val )
{
    for( i = 0; i < _val.length; i++ )
    {
        ch = _val.charAt(i);
        if(!( (ch >= 0 && ch <= 9) || (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') ))
            return false;
    }        
    return true;
} 
// end ValidateAlpha


//////////////////////////////////////////////////////////////////////////////////
//                        ValidateChar
//
// This function will Validate character strings.  a-z & A-Z
//
function ValidateChar( _val )
{
    for( i = 0; i < _val.length; i++ )
    {
        ch = _val.charAt(i);
        if(!( (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') ))
            return false;
    }        
    return true;
} 
// end ValidateChar


//////////////////////////////////////////////////////////////////////////////////
//                        ValidateNumber
//
// This function will Validate numbers. returns true for all numeric string.
//
function ValidateNumber( _val )
{
    for( i = 0; i < _val.length; i++ )
    {
        num = _val.charAt(i);
        if( !(num >= 0 && num <= 9) )
            return false;
    }        
    return true;
} 
// end ValidateNumber


//////////////////////////////////////////////////////////////////////////////////
//                        ValidateEmail
//
// This function will Validate email addresses. returns true if vaild.
//
function ValidateEmail( _val )
{
    // we gotta check if the email is in valid format..
    goodEmail = true;
    atLocation = 0;
    dotLocation = 0;

    for(i = 0; i < _val.length; i++)
    {
        if(_val.charAt(i) == '@')
        {
            if(atLocation == 0)
                atLocation = i;
            else // we have found two @ chars.. no email I know has two..
            {
                goodEmail = false;
                break;
            }
        }
        else if(_val.charAt(i) == '.')
        {
            // we dont need to worry.. there can be lots of '.''s in an address...
            dotLocation = i;
        }
    }
    // just so long as there is a dot after the @, we should be ok.
    if( !goodEmail || (dotLocation <= atLocation) || (dotLocation >= (_val.length - 1)) || (atLocation == 0) )
    {
        return false;
    }

    return true;
} 
// end ValidateEmail


//////////////////////////////////////////////////////////////////////////////////
//                        ValidatePhone
//
// This function will Validate phone numbers. returns true if valid.
//
function ValidatePhone( _val )
{
    if( _val.charAt(3) == '-' && _val.charAt(7) == '-' && _val.length == 12 )
    {
        // alright we have the slashes where they should be, and its the right length..       
        // but do we have numbers?

        area = _val.substring(0, 3);
        ext = _val.substring(4, 7);
        num = _val.substring(8);

        if( ValidateNumber(area) && ValidateNumber(ext) && ValidateNumber(num) )
        {
            // ok they are all numbers. it must be a good phone# then.
            return true;
        }
    }
    return false;
} 
// end ValidatePhone


//////////////////////////////////////////////////////////////////////////////////
//                        ValidateZipCode
//
// This function will Validate US Zip codes
//
function ValidateZipCode( _val )
{
    if(_val.length == 5 && ValidateNumber(_val))
    {
	return true;
    }

    if(_val.length == 9 && ValidateNumber(_val))
    {
	return true;
    }

    if(_val.length == 10)
    {
	first_part = _val.substring(0,5);
	middle = _val.charAt(5);
	last_part = _val.substring(6);
	
	if(ValidateNumber(first_part) && ValidateNumber(last_part) && middle == "-")
	{
	    return true;
	}
    }
    return false;
} 
// end ValidateZipCode


//////////////////////////////////////////////////////////////////////////////////
//                        ValidatePostalCode
//
// This function will Validate Canadian postal codes
//
function ValidatePostalCode( _val )
{
    if(_val.length == 6)
    {
	if(
	    ValidateChar(_val.charAt(0)) &&
	    ValidateNumber(_val.charAt(1)) &&
	    ValidateChar(_val.charAt(2)) &&
	    ValidateNumber(_val.charAt(3)) &&
	    ValidateChar(_val.charAt(4)) &&
	    ValidateNumber(_val.charAt(5))
	    )
	{
	    return true;	    
	}
    }

    if(_val.length == 7)
    {
	
	if(
	    ValidateChar(_val.charAt(0)) &&
	    ValidateNumber(_val.charAt(1)) &&
	    ValidateChar(_val.charAt(2)) &&
	    _val.charAt(3) == " " &&
	    ValidateNumber(_val.charAt(4)) &&
	    ValidateChar(_val.charAt(5)) &&
	    ValidateNumber(_val.charAt(6))
	    )
	{
	    return true;	    
	}
    }
    return false;
} 
// end ValidatePostalCode



/*
There are three functions in this set for credit card validation.
The main function is:

// taking out the date checking for now
validateCard(cardNumber,cardType)
        parameters:
                all paramaters are string values.
                Month & Year come from the select input fields in the form, so they are defined.
                cardType can be:
                        'a' for American Express
                        'd' for Discover
                        'm' for MasterCard
                        'v' for Visa
        description:
                This function will check string length, valid characters, specific credit card prefixes and test
                the Mod 10 (LUHN Formula) for validating possible credit card numbers. This function can only
                authorize that the given card data is potentially valid. You would still need to run actual
                card validation routines to verify the actual account.
        returns:
                this function returns true if the card number could be valid for the card type and expiration date.
                false otherwise.        
supporting functions:
mod10( cardNumber )
        parameters:
                this function takes the text string card number and runs the Mod 10 formula on its respective digits.
        description:
                Mod 10 is the check digit formula for the supported cards these functions attempt to validate.
        returns:
                this function returns true if the number passes the check digit test.
                false otherwise.
expired( cardMonth, cardYear )
        parameters:
                this function takes the text string values given by the html form.
        description:
                this function basically will check to make sure todays date is less than the expiration date the user inputs.
                this function is not locked into using 2 digit dates.
        returns:
                this fucntion returns true if the card is expired.
                false otherwise.
*/

function mod10( cardNumber ) 
{ 
    // LUHN Formula for validation of credit card numbers.
    var ar = new Array( cardNumber.length );
    var i = 0,sum = 0;

    for( i = 0; i < cardNumber.length; ++i ) 
    {
	ar[i] = parseInt(cardNumber.charAt(i));
    }
    for( i = ar.length -2; i >= 0; i-=2 ) 
    { 
        // you have to start from the right, and work back.
	ar[i] *= 2; // every second digit starting with the right most (check digit)
	if( ar[i] > 9 ) ar[i]-=9;// will be doubled, and summed with the skipped digits.
        // if the double digit is > 9, add those individual digits together 
    }
    
    // add it all up.
    for( i = 0; i < ar.length; ++i ){ sum += ar[i]; }

    // if the sum is divisible by 10 mod10 succeeds
    return (((sum % 10) == 0) ? true : false);
}


function expired( month, year ) 
{
    var now = new Date(); // this function is designed to be Y2K compliant.
    // create an expired on date object with valid thru expiration date
    var expiresIn = new Date(year,month,0,0,0); 
    // adjust the month, to first day, hour, minute & second of expired month
    expiresIn.setMonth(expiresIn.getMonth()+1); 
    // then we get the miliseconds, and do a long integer comparison
    if( now.getTime() < expiresIn.getTime() )
	return false;
    else
	return true;
}


function validateCard(cardNumber,cardType)
{
    if( cardNumber.length == 0 ) 
    {
	//most of these checks are self explanitory
	alert("Please enter a valid card number.");
	return false;                           
    }
    for( var i = 0; i < cardNumber.length; ++i ) 
    {
	// make sure the number is all digits.. (by design)
	var c = cardNumber.charAt(i);
	
	if( c < '0' || c > '9' ) 
	{
	    alert("Please enter a valid card number. Use only digits. Do not use spaces or hyphens.");
	    return false;
	}
    }
    
    //perform card specific length and prefix tests
    var length = cardNumber.length;
    
    switch( cardType ) 
    {
	case 'a':
	    if( length != 15 ) 
	    {
		alert("Please enter a valid American Express Card number.");
		return;
	    }
	    var prefix = parseInt( cardNumber.substring(0,2));
	    if( prefix != 34 && prefix != 37 ) 
	    {
		alert("Please enter a valid American Express Card number.");
		return;
	    }
	    break;
	case 'd':
	    if( length != 16 ) 
	    {
		alert("Please enter a valid Discover Card number.");
		return;
	    }
	    var prefix = parseInt( cardNumber.substring(0,4));
	    
	    if( prefix != 6011 ) 
	    {
		alert("Please enter a valid Discover Card number.");
		return;
	    }
	    break;
	case 'm':
	    if( length != 16 ) 
	    {
		alert("Please enter a valid MasterCard number.");
		return;
	    }
	    var prefix = parseInt( cardNumber.substring(0,2));
	    if( prefix < 51 || prefix > 55) 
	    {
		alert("Please enter a valid MasterCard Card number.");
		return;
	    }
	    break;
	case 'v':
	    if( length != 16 && length != 13 ) 
	    {
		alert("Please enter a valid Visa Card number.");
		return;
	    }
	    var prefix = parseInt( cardNumber.substring(0,1));
	    if( prefix != 4 ) 
	    {
		alert("Please enter a valid Visa Card number.");
		return;
	    }
	    break;
    }
    if( !mod10( cardNumber ) ) 
    {            
	// run the check digit algorithm
	alert("Sorry! This is not a valid credit card number.");
	return false;
    }

    // for now we are not checking the exipry...
    //if( expired( cardMonth, cardYear ) )
    //{
    // check if entered date is already expired.
    //alert("Sorry! The expiration date you have entered would make this card invalid.");
    //return false;
    //}

    // at this point card has not been proven to be invalid
    return true; 
}

