function doValidation(formName)
{
	//create a new validation object
	var validation = new Validation(formName);
	var errorString;
	var elementName
	
	//call the validateForm method of the object
	validation.validateForm();
	
	//if the validation has failed then display the error message and
	//change the colour of the failed fields
	if (!validation.passed)
	{	
		//loop through the form and reset the colours of the failed fields.  They will be made
		//failed again if they have not been rectified.
		for(z = 0; z < findObj(formName).length; z++)
		{
			findObj(formName).elements[z].className = findObj(formName).elements[z].className.replace("error", "");
			elementName = findObj(formName).elements[z].name.replace("textbox", "").replace("textbox", "").replace("textarea", "") + "label";

			if(findObj(elementName)!=null)
			{
				findObj(elementName).className = findObj(elementName).className.replace("error", "");
			}

			//radio buttons and checkboxes cannot be styled by firefox
			//style the containing <td> instead
			if(findObj(formName).elements[z].className == "radio")
			{
			  //radio buttons and dropdowns will come through as arrays
		    if(findObj(formName).elements[z].length != null)
		    {
		      document.getElementById(findObj(formName).elements[z] + "_control").className = document.getElementById(findObj(formName).elements[z] + "_control").className.replace("error", "")
		    }
		    else
		    {		      
			    if(document.getElementById(findObj(formName).elements[z].id.replace("_1", "") + "_control") != null)
			    {
			      if(document.getElementById(findObj(formName).elements[z].id.replace("_1", "") + "_control").className != "")
			      {
			        document.getElementById(findObj(formName).elements[z].id.replace("_1", "") + "_control").className = document.getElementById(findObj(formName).elements[z].id.replace("_1", "") + "_control").className.replace("error", "")      
			      }
			      else
			      {
			        document.getElementById(findObj(formName).elements[z].id.replace("_1", "") + "_control").className = "radio"
			      }
			    }
			    if(document.getElementById(findObj(formName).elements[z].id + "_control") != null)
			    {
			      document.getElementById(findObj(formName).elements[z].id + "_control").className = document.getElementById(findObj(formName).elements[z].id + "_control").className.replace("error", "")	      
			    }
			  }
			}
		}		
    
		//display the message in the error layer
		errorString = "The highlighted field(s) are mandatory \nor have errors and must be filled in.\n\nDates should be formatted dd/mm/yyyy";
		
		//loop through the failedFields array and display the
		//text boxes to change		    
		for(y = 0; y < validation.failedFields.length; y++)
		{
		  //radio buttons and dropdowns will come through as arrays
		  if(findObj(validation.failedFields[y]).length != null)
		  {
		    //radio buttons and checkboxes will not have a control style
		    if(findObj(validation.failedFields[y]).className != null)
		    {
			    findObj(validation.failedFields[y]).className = findObj(validation.failedFields[y]).className.replace("error", "") + "error";
		    }
		    else
		    {
		      var myarray = findObj(validation.failedFields[y])
  		    
  		    //loop through each item and set its containing <td> to radioerror style 
		      for(var i = 0; i < myarray.length; i++)
		      {
		        if(document.getElementById(myarray[i].id + "_control") != null)
		        {
		          if(document.getElementById(myarray[i].id + "_control").className != "")
		          {
		            document.getElementById(myarray[i].id + "_control").className = document.getElementById(myarray[i].id + "_control").className.replace("error", "") + "error";
		          }
		          else
		          {
		            document.getElementById(myarray[i].id + "_control").className = "radioerror";
		          }
		        }
		      }
		    }
		  }
		  else
		  {
		    findObj(validation.failedFields[y]).className = findObj(validation.failedFields[y]).className.replace("error", "") + "error";
		    
		    //1st checkbox
		    if(findObj(validation.failedFields[y].replace("_1","") + "_control") != null)
		    {
		      findObj(validation.failedFields[y].replace("_1","") + "_control").className = findObj(validation.failedFields[y].replace("_1","") + "_control").className.replace("error", "") + "error";
		    }
		  } 
		}
		alert(errorString);
	}
	
	//return the passed or failed
	return validation.passed;
}

function Validation(formName)
{  
	//initialise properties
	this.formName = formName;
	this.passed = true;
	this.failedFields = new Array();	
	
	//initialise methods
	this.validateMandatory = validateMandatory;
	this.validate = validate;
	this.validateRadio = validateRadio;
	this.validateForm = validateForm;
}

function validate(v, validationName, e)
{
	var validation = "";
	var regularExpression;
	
	//loop through the rulesArray and find the regular
	//expression associated with the rule name
	
	for (x = 0; x < validationsArray.length; x++)
	{
		if(validationsArray[x][0] == validationName)
		{
			//set the validation equal to the regular expression
			validation = validationsArray[x][1];
		}
	}
	
	//only check the element if the validation has been found
	if((validation != "") || (validation != null))
	{
		//create a new regular expression
		regularExpression = new RegExp(validation);
		if(!regularExpression.test(v))
		{
			this.passed = false;
			this.failedFields[this.failedFields.length] = e;
		}
	}
}

function validateMandatory(v, e)
{
	//check if v is blank, null or made entirely of spaces
	if ((v.replace(" ", "") == "") || (v == null))
	{
		this.passed = false;
		this.failedFields[this.failedFields.length] = e;
	}
}

function validate(v, validationName, e)
{
	var validation = "";
	var regularExpression;
	
	//loop through the validationsArray and find the regular
	//expression associated with the validation name
	
	for (x = 0; x < validationsArray.length; x++)
	{
		if(validationsArray[x][0] == validationName)
		{
			//set the rule equal to the regular expression
			validation = validationsArray[x][1];
		}
	}
	
	//only check the element if the validation has been found
	if((validation != "") || (validation != null))
	{
		//create a new regular expression
		regularExpression = new RegExp(validation);
		if(!regularExpression.test(v))
		{
			this.passed = false;
			this.failedFields[this.failedFields.length] = e;
		}
	}
}

//checks to see if at least one item has been checked
//valid for radio buttons and checkboxes
function validateRadio(f, e)
{
  var checked = false;
  var match = false
  
  //for each element in the form f
	for (var i = 0; i < f.length; i++)
	{
	  //checkboxes must have the trailing _1 _2 _3 etc split off first
		if(f.elements[i].name.split("_")[0] == e.split("_")[0])
		{
      if(f.elements[i].checked == true)
      {
        checked = true;
      }
		}
	}
	
  //if one item has been checked set all items in the collection to valid
	if(!checked)
	{
	  for(var j = 0; j < this.failedFields.length; j++)
	  {
	    if(this.failedFields[j] == e)
	    {
	      match = true	      
		  }
		}

		if(!match)
		{
		  this.passed = false;
		  this.failedFields[this.failedFields.length] = e;
		}
	}
}

function validateForm()
{
	var f = findObj(this.formName);
	var validation;
	var style
  var hiddenControl;
  
	//for each element in the form f
	for (i = 0; i < f.length; i++)
	{
		//re-enable all controls before validation and submit
		//f.elements[i].disabled = false;

		//check textareas maxlength attribute
		//built in IE textarea functionality does not have a maxlength attribute
    if(f.elements[i].type=='textarea' && f.elements[i].getAttribute('maxlength') != null)
    {
      hiddenControl = false
      var stringValue = f.elements[i].value
      
       //test visible controls
		  if(document.getElementById(f.elements[i].id + "_row") != null)
		  {
		    //if(document.getElementById(f.elements[i].id + "_row").style.visibility=='hidden')
		    if(document.getElementById(f.elements[i].id + "_row").className=='hiddenrow')
		    {
		      hiddenControl = true;
		    }
		  }
      
      if((stringValue.length > f.elements[i].getAttribute('maxlength')) && !hiddenControl)
      {
        this.passed = false;
			  this.failedFields[this.failedFields.length] = f.elements[i].name;
      }
    }

		//if there is a rule
		if((f.elements[i].getAttribute('mandatory') != null) && (f.elements[i].getAttribute('mandatory') != ""))
		{
		  hiddenControl = false
			//test normal controls
		  if(document.getElementById(f.elements[i].id + "_row") != null)
		  {
		    //if(document.getElementById(f.elements[i].id + "_row").style.visibility=='hidden')
		    if(document.getElementById(f.elements[i].id + "_row").className=='hiddenrow')
		    {
		      hiddenControl = true;
		    }		    
		  }
		  //checkboxes and radio buttons
      else if(document.getElementById(f.elements[i].id).getAttribute('type')=='checkbox')
      {
        //remove _1,_2,_3 etc and append "_row" to get parent row object to check visibility
        //if(document.getElementById(f.elements[i].id.split("_")[0] + "_row").style.visibility=='hidden')
        if(document.getElementById(f.elements[i].id.split("_")[0] + "_row").className == "hiddenrow")
		    {
		      hiddenControl = true;
		    }
      }
		  
		  //test grid controls
		  if(document.getElementById(f.elements[i].id.split("_row")[0].replace("_","-") + "_row") != null)
		  {		      
		    //if(document.getElementById(f.elements[i].id.split("_row")[0].replace("_","-") + "_row").style.visibility=='hidden')
		    if(document.getElementById(f.elements[i].id.split("_row")[0].replace("_","-") + "_row").className == "hiddenrow")
		    {
		      hiddenControl = true;
		    }
		  }
		  //test grid controls      
		  if(document.getElementById(f.elements[i].id).style.visibility=='hidden')
		  {
		    hiddenControl = true;
		  }
		  
		  //do not validate hidden controls
			if(!hiddenControl)
			{//alert(f.elements[i].id)
			  //split the validations up into an array using ; as the delimiter
			  validation = f.elements[i].getAttribute('mandatory').split(";");
  			
			  //loop through the array of validations for the element			
			  for (j = 0; j < validation.length; j++)
			  {
				  //check whether the validation is mandatory or a defined rule
				  switch(validation[j].replace(" ", ""))
				  {
					  case "true":
					    if(f.elements[i].getAttribute('type') == "radio" || f.elements[i].getAttribute('type') == "checkbox")
					    {
						    this.validateRadio(f, f.elements[i].name);
						  }
						  else
						  {						    
						    //check mandatory
						    this.validateMandatory(f.elements[i].value, f.elements[i].name);
						  }
						  break;
					  case "date":
						  //check date
						  this.validate(f.elements[i].value, validation[j].replace(" ", ""), f.elements[i].name);
						  break;
					  case "optionaldate":
						  //check optional dates
						  if(f.elements[i].value != "")
						  {
						    this.validate(f.elements[i].value, validation[j].replace(" ", "").replace("optional", ""), f.elements[i].name);
						  }
						  break;
					  case "number":
						  //check date
						  this.validate(f.elements[i].value, validation[j].replace(" ", ""), f.elements[i].name);
						  break;
						case "numbernonzero":
						  //check date
						  this.validate(f.elements[i].value, validation[j].replace(" ", ""), f.elements[i].name);
						  break;
						case "creditcardnumber":
						  //check date
						  this.validate(f.elements[i].value, validation[j].replace(" ", ""), f.elements[i].name);
						  break;
						case "decimal":
						  //check date
						  this.validate(f.elements[i].value, validation[j].replace(" ", ""), f.elements[i].name);
						  break;
						case "optionalnumber":
						  //check optional numbers
						  if(f.elements[i].value != "")
						  {
						    this.validate(f.elements[i].value, validation[j].replace(" ", "").replace("optional", ""), f.elements[i].name);
						  }
						  break;
					  case "phonenumber":
						  //check date
						  this.validate(f.elements[i].value, validation[j].replace(" ", ""), f.elements[i].name);
						  break;
						case "email":
						  //check email
						  this.validate(f.elements[i].value, validation[j].replace(" ", ""), f.elements[i].name);
						  break;
						case "optionalemail":
						  //check optional emails
						  if(f.elements[i].value != "")
						  {
						    this.validate(f.elements[i].value, validation[j].replace(" ", "").replace("optional", ""), f.elements[i].name);
						  }
						  break;
						 case "referenceno":
						    //check reference number
						    this.validate(f.elements[i].value, validation[j].replace(" ", ""), f.elements[i].name);
						    break;
					  default:
						  //check rule
						  //this.validate(f.elements[i].value, validation[j].replace(" ", ""), f.elements[i].name);
						  break;
					}
				}
			}			
		}		
	}
}

//Macromedia findObj method - finds any object reference from its name or id
function findObj(n, d) { //v4.0
  var p,i,x;  if(!d) d=document; if((p=n.indexOf("?"))>0&&parent.frames.length) {
    d=parent.frames[n.substring(p+1)].document; n=n.substring(0,p);}
  if(!(x=d[n])&&d.all) x=d.all[n]; for (i=0;!x&&i<d.forms.length;i++) x=d.forms[i][n];
  for(i=0;!x&&d.layers&&i<d.layers.length;i++) x=findObj(n,d.layers[i].document);
  if(!x && document.getElementById) x=document.getElementById(n); return x;
}

