// 
//  Validates form fields
//
//  attribute syntax:
//
//      required="true(default)|false"
//      validate="string|number|alpha|alphanumeric|year|date|time|email|emaillist|phone|checked|selected"
//      caption="description of field to display to user indicating a problem"
//      captioniscustom="true|false(default)"
//
//      form validation:    checkForm(objForm)
//                          checkForm(objForm,pPromptEach)
//
//                          pPromptEach controls whether multiple errors are accumulated or reported one at a time
//
function attachFormHandlers()
{
    // Ensure we're working with a 'relatively' new browser
    if (document.getElementsByTagName)
    {
        var objForm = document.getElementsByTagName('form');

        for (var iCounter=0; iCounter<objForm.length; iCounter++)
            objForm[iCounter].onsubmit = function(){return checkForm(this);}
    }
}

// used to dynamically add/remove validation rule form element
function addFormValidationRule(iElementName,iCaption,ivalRule,iIsRequired,iCaptionIsCustom) {
    var node = document.getElementsByName(iElementName);
    
    if (node.length ==  1) {
        node[0].setAttribute('caption', iCaption);
        node[0].setAttribute('validate', ivalRule);
        
        if (iIsRequired != undefined)
            node[0].setAttribute('required', iIsRequired);
        if (iCaptionIsCustom)
            node[0].setAttribute('captioniscustom', iCaptionIsCustom);
    } else if (node.length > 1) {
        alert('addFormValidationRule failed: too many choices.');
    } else {
        alert('addFormValidationRule failed: not found.');
    }
}

function removeFormValidationRule(iElementName) {
    var node = document.getElementsByName(iElementName);
    
    if (node.length ==  1) {
        node[0].removeAttribute('validate');
        node[0].removeAttribute('required');
        node[0].removeAttribute('caption');
        node[0].removeAttribute('captioniscustom');
    } else if (node.length > 1) {
        alert('removeFormValidationRule failed: too many choices.');
    } else {
        alert('removeFormValidationRule failed: not found.');
    }
}

function checkForm(objForm,pPromptEach)
{
    var bValid;
    var arClass;
    var objTag = objForm.getElementsByTagName('*');
    var bDeferPrompt = (pPromptEach ? pPromptEach : false);
    var sDeferredMsg = "";
    
    for (var iFieldCounter=0; iFieldCounter<objTag.length; iFieldCounter++)
    {
        if (!objTag[iFieldCounter].name)  // element has to be named
            continue;
        
        // Allow for multiple values being assigned to the class attribute
        var valRules = getAttributeByName(objTag[iFieldCounter],"validate");
        if (valRules) 
        {
            // check for other attributes
            var required = getAttributeByName(objTag[iFieldCounter],"required");
            required = (required == null) ? true : eval(required);
            
            var captionIsCustom = getAttributeByName(objTag[iFieldCounter],"captioniscustom");
            captionIsCustom = (captionIsCustom == null) ? false : eval(captionIsCustom);
            
            arClass = valRules.split(' ');
            for (var iClassCounter=0; iClassCounter<arClass.length; iClassCounter++)
            {
				// add the regex to trim the value
                var value = objTag[iFieldCounter].value.replace(/^\s+|\s+$/g,"");
                
                switch (arClass[iClassCounter])
                {
                    // backward compatability
                    case 'required':
                        required = true;
                        bValid = true;
                        break;
                    case 'notrequired':
                        required = false;
                        bValid = true;
                        break;
                        
                    case 'number' :
                        bValid = isNumber(value);
                        break;
                    case 'string':
                        bValid = isString(value);
                        break;
                    case 'alpha':
                        bValid = isAlpha (value);
                        break;
                    case 'alphanumeric':
                        bValid = isAlphaNumeric (value);
                        break;
                        
                    case 'password':
                        bValid = isPassword (value);
                        break;
                    case 'username':
                        bValid = isUsername (value);
                        break;
                        
                    case 'date':
                        bValid = isDate(value);
                        break;
                    case 'time':
                        bValid = isTime(value);
                        break;
                    case 'timehundredth':
                        bValid = isTimeHundredth(value);                        
                        break;
                    case 'timetenth':
                        bValid = isTimeTenth(value);                        
                        break;
                    case 'distancehundredth':
                        bValid = isDistanceHundredth(value);                        
                        break;
                        
                    case 'year':
                        bValid = isYear(value);
                        break;
                        
                    case 'email' :
                        bValid = isEmail(value);
                        break;
                    case 'emaillist' :
                        bValid = isEmailList(value);
                        break;
                        
                    case 'phone' :
                        bValid = isPhone(value);
                        break;
                        
                    case 'checked' :
                        bValid = isCheckboxChecked(objTag[iFieldCounter]);
                        break;
                    case 'selected' :
                        bValid = isRadioSelected(objTag[iFieldCounter]);
                        break;
                    default:
                        bValid = true;
                }
                
                // logic allows for a field to be validated but not be required
                if ((required && (value.length==0 ||!bValid)) || (value.length > 0 && !bValid))
                {
                    var caption = getAttributeByName(objTag[iFieldCounter],"caption");
                    if (!caption)
                    {
                        caption = objTag[iFieldCounter].name;
                    }  
                    
                    objTag[iFieldCounter].style.borderColor='red';
                    
                    if (!bDeferPrompt)
                    {
                        var undefined;
                        
                        if (captionIsCustom)
                            alert(caption);
                        else
                            alert('Please review ' + (required ? 'required ' : '')  + 'field "' + caption + '"');

                        if (objTag[iFieldCounter].select != undefined)
                            objTag[iFieldCounter].select();

                    // buggy on ie7, not sure we need this - pab
                    //    if (objTag[iFieldCounter].focus != undefined)
                    //        objTag[iFieldCounter].focus();

                        return false;
                    }
                    else
                    {
                        sDeferredMsg += (caption + (required ? ' (required)' : '') + '\n');
                    }
                } 
                else
                {
                    objTag[iFieldCounter].style.borderColor="";
                }
            }
        }
    }
    
    if (sDeferredMsg != "")
    {
        alert('Please review the value(s) you provided for the following fields:\n' + sDeferredMsg);
        return false;
    }
    else
    {
        return true;
    }
}

// internal functions
function getAttributeByName(node, attributeName)
{
    if (typeof NamedNodeMap != "undefined")
    {
        if (node.attributes.getNamedItem(attributeName))
            return node.attributes.getNamedItem(attributeName).value;
    }
    else
    {
        return node.getAttribute(attributeName);
    }
}

// ### Number and String Tests ###

// alternatively could use: check_integer ( n ) { return RegExp ( "^[-+]?[0-9]+$" ).test( n ); }
function isNumber(strValue)
{
    return (strValue != '' && !isNaN(strValue));
}

// alternatively could use: check_string ( s ) { return RegExp ( "^[a-zA-Z]+$" ).test( s ); }
function isString(strValue)
{
    return (strValue != '' && typeof strValue == 'string');
}

function isAlpha ( strValue ) 
{ 
    var objRE = /^[a-zA-Z]+$/;

    return (strValue != '' && objRE.test(strValue));
} 

function isAlphaNumeric ( strValue ) 
{ 
    var objRE = /^[a-zA-Z0-9]+$/;

    return (strValue != '' && objRE.test(strValue));
} 

function isPassword ( strValue ) 
{ 
    //var objRE = /^\S{6,}$/;
    var objRE = /^[^\s;\\]{6,}$/

    return ( strValue != '' && objRE.test(strValue) && (strValue.indexOf('--') == -1) );
} 

function isUsername ( strValue ) 
{ 
    var objRE = /^[0-9A-Za-z]{6,}$/;

    return (strValue != '' && objRE.test(strValue));
}
 
// ### Email Tests ###

function isEmail(strValue)
{
    var objRE = /^[\w\.\-\_]*@[\w\.\-\_]*\.[a-zA-Z]{2,3}$/;

    return (strValue != '' && objRE.test(strValue));
}

// assume comma delimited, convert to semi-colon
function isEmailList(strValue)
{
    var addresses = strValue.replace (/,/g,";").split (";");
    
    for (var i=0; i<addresses.length; i++)
    {
        if (!isEmail(addresses[i])) {
            return false;
        }
    }
                
    return (strValue != '');
}

// ### Distance Tests ###

// distance as mm.dd or mm.d
function isDistanceHundredth(strValue)
{
    var objRE = /^([1-9]{1,})(\.\d{1,2})?$/;

    return (strValue != '' && objRE.test(strValue));
}

// ### Date Time Tests ###

// alternatively could use: check_date ( s ) { return RegExp ( "^[0-9]{4,4}.[0-9]{2,2}.[0-9]{2,2}$" ).test( s ); }
function isDate(strValue)
{
    var parsedDate = strValue.split("/");
    
    if (parsedDate.length != 3) return false;
    
    var month = parseInt(parsedDate[0],10) - 1;
    var day = parseInt(parsedDate[1],10);
    var year = parseInt(parsedDate[2],10);
    
    var objDate = new Date(strValue);
    
    var fullYear = objDate.getFullYear();
    
    return (month == objDate.getMonth()) && (day == objDate.getDate()) && (year == fullYear) && (fullYear > 1800) && (fullYear < 2200);
}

// HH:MM or HH:MM:SS or HH:MM:SS.mmm
function isTime(strValue)
{
    var objRE = /^([1-9]|1[0-2]):[0-5]\d(:[0-5]\d(\.\d{1,3})?)?$/;

    return (strValue != '' && objRE.test(strValue));
}

//  If decimal point is found, requires two decimal numbers for fractional second: (H)H:MM:SS.dd
function isTimeHundredth(strValue)
{    
    var objRE = /^([0-9]{1,2})?:?[0-5]?\d:[0-5]\d(?:\.\d{1,2})?$/;
    return (strValue != '' && objRE.test(strValue));
}

//  If decimal point is found, requires one decimal number for fractional second: (H)H:MM:SS.d
function isTimeTenth(strValue)
{
    var objRE = /^[0-9]{1,2}?:?[0-5]?\d:[0-5]\d(?:\.(\d{1}))?$/;

    return (strValue != '' && objRE.test(strValue));
}

function isYear(strValue)
{
    var objDate = new Date ("1/1/" + strValue);

    return (strValue != '' && (strValue == objDate.getFullYear()) && (strValue > 1800));
}

// ### Phone Tests ###

function isPhone(strValue)
{
	if (strValue != '')
	{
		var objRE = strValue.replace(/[\(\)\.\-\ ]/g,""); //strip out acceptable non-numeric characters

		return (!isNaN(parseInt(objRE)) && objRE.length == 10);
	}
	else    
	{
	    return false;
	}
}

// ### Form checkbox and radio button select Tests ###

function isCheckboxChecked(objElem)
{
    return (objElem && objElem.checked);
}

function isRadioSelected(objElem)
{
    var objTag = document.getElementsByName(objElem.name);
    for (var i=0;i<objTag.length;i++) 
    {
        if (objTag[i].checked) 
            return true;
    }
    return false;
}


