function validateFields(form, rules)
{
	for (var i=0; i<rules.length; i++)
	{
		var row = rules[i].split(",");
		
		var satisfiesIfConditions = true;
		while (row[0].match("^if:"))
		{
			var condition = row[0];
			condition = condition.replace("if:", "");
			var parts = condition.split("=");
			var fieldToCheck = parts[0];
			var valueToCheck = parts[1];

			// find value of FIELDNAME for conditional check
			var fieldnameValue = "";
			if (form[fieldToCheck].type == undefined) // RADIO
			{
				for (var j=0; j<form[fieldToCheck].length; j++)
				{
					if (form[fieldToCheck][j].checked)
						fieldnameValue = form[fieldToCheck][j].value;
				}
			}
			// single checkbox      
			else if (form[fieldToCheck].type == "checkbox")
			{
				if (form[fieldToCheck].checked)
					fieldnameValue = form[parts[0]].value;
			}      
			// all other field types
			else
				fieldnameValue = form[parts[0]].value;

			// if the VALUE is NOT the same, we don't need to validate this field. Return.
			if (fieldnameValue != valueToCheck)
			{
				satisfiesIfConditions = false;
				break;
			}
			else
				row.shift();
				// remove this if-condition from line, and continue validating line
    	}

		if (!satisfiesIfConditions)
			continue;

		var requirement = row[0];
		var fieldName   = row[1];
		
		// depending on the validation test, store the incoming strings for use later...
		if (row.length == 6)        // valid_date
		{
			var fieldName2   = row[2];
			var fieldName3   = row[3];
			var date_flag    = row[4];
			var errorMessage = row[5];
		}
		else if (row.length == 4)     // same_as
		{
			var fieldName2   = row[2];
			var errorMessage = row[3];
		}
		else
			var errorMessage = row[2];    // everything else.
		
		// if the requirement is "length...", rename requirement to "length" for switch statement
		if (requirement.match("^length"))
		{
			var lengthRequirements = requirement;
			requirement = "length";
		}
		
		// if the requirement is "range=...", rename requirement to "range" for switch statement
		if (requirement.match("^range"))
		{
			var rangeRequirements = requirement;
			requirement = "range";
		}

		// now, validate whatever is required of the field
		switch (requirement)
		{
			case "required":
				// if radio buttons or multiple checkboxes:
				if (form[fieldName].type == undefined)
				{
					var oneIsChecked = false;
					for (var j=0; j<form[fieldName].length; j++)
					{
						if (form[fieldName][j].checked)
						oneIsChecked = true;
					}
					if (!oneIsChecked)
					{
						alertMessage(form[fieldName], errorMessage);
						return false;           
					}
				}
				else if (form[fieldName].type == "select-multiple")
				{          
					var oneIsSelected = false;
					for (k=0; k<form[fieldName].length; k++)
					{
						if (form[fieldName][k].selected)
						oneIsSelected = true;
					}
				
					// if no options have been selected, or if there ARE no options in the multi-select 
					// dropdown, return false
					if (!oneIsSelected || form[fieldName].length == 0)
					{
						alertMessage(form[fieldName], errorMessage);
						return false;          
					}
				}
				// a single checkbox
				else if (form[fieldName].type == "checkbox")
				{
					if (!form[fieldName].checked)
					{
						alertMessage(form[fieldName], errorMessage);
						return false;           
					}
				}        
				// otherwise, just perform ordinary "required" check.
				else if (!form[fieldName].value)
				{
					alertMessage(form[fieldName], errorMessage);
					return false;
				}
				break;

			case "digits_only":       
				if (form[fieldName].value && form[fieldName].value.match(/\D/))
				{
					alertMessage(form[fieldName], errorMessage);
					return false;
				}
				break;

			case "is_alpha": 
				if (form[fieldName].value && form[fieldName].value.match(/\W/))
				{
					alertMessage(form[fieldName], errorMessage);
					return false;
				}
				break;
				
			case "is_alpha_numeric": 
				if (form[fieldName].value && form[fieldName].value.match(/[\W_]/))
				{
					alertMessage(form[fieldName], errorMessage);
					return false;
				}
				break;	
			case "is_underscore": 
				if (form[fieldName].value && !form[fieldName].value.match(/^[a-zA-Z0-9-/]+$/))
				{
					alertMessage(form[fieldName], errorMessage);
					return false;
				}
				break;
			case "valid_url": 
				if (form[fieldName].value && !form[fieldName].value.match(/(http|https):\/\/(www.|)([A-Za-z0-9-]{3,})\.([a-zA-Z]{3})/))
				{
					alertMessage(form[fieldName], errorMessage);
					return false;
				}
				break;
			case "length":		
				comparison_rule = "";
				rule_string = "";
		
				// if-else order is important here: needs to check for >= before >
				if(lengthRequirements.match(/length=/))
				{ 
					comparison_rule = "equal"; 
					rule_string = lengthRequirements.replace("length=", ""); 
				}
				else if (lengthRequirements.match(/length>=/))
				{
					comparison_rule = "greater_than_or_equal"; 
					rule_string = lengthRequirements.replace("length>=", "");
				}
				else if (lengthRequirements.match(/length>/))
				{
					comparison_rule = "greater_than"; 
					rule_string = lengthRequirements.replace("length>", "");
				}
				else if (lengthRequirements.match(/length<=/))
				{
					comparison_rule = "less_than_or_equal"; 
					rule_string = lengthRequirements.replace("length<=", "");
				}        
				else if (lengthRequirements.match(/length</))
				{
					comparison_rule = "less_than"; 
					rule_string = lengthRequirements.replace("length<", "");
				}
		
				// now perform the appropriate validation
				switch (comparison_rule)
				{
					case "greater_than_or_equal":
						if (!(form[fieldName].value.length >= parseInt(rule_string)))
						{
							alertMessage(form[fieldName], errorMessage);
							return false;
						}
						break;
					
					case "greater_than":
						if (!(form[fieldName].value.length > parseInt(rule_string)))
						{
							alertMessage(form[fieldName], errorMessage);
							return false;
						}
						break;
					
					case "less_than_or_equal":
						if (!(form[fieldName].value.length <= parseInt(rule_string)))
						{
							alertMessage(form[fieldName], errorMessage);
							return false;
						}
						break;
					
					case "less_than":
						if (!(form[fieldName].value.length < parseInt(rule_string)))
						{
							alertMessage(form[fieldName], errorMessage);
							return false;
						}
						break;
		
					case "equal":
						var range_or_exact_number = rule_string.match(/[^_]+/);
						var fieldCount = range_or_exact_number[0].split("-");
						
						// if the user supplied two length fields, make sure the field is within that range
						if (fieldCount.length == 2)
						{
							if (form[fieldName].value.length < fieldCount[0] || form[fieldName].value.length > fieldCount[1])
							{
							alertMessage(form[fieldName], errorMessage);
								return false;
							}
						}
						// otherwise, check it's EXACTLY the size the user specified 
						else
						{
							if (form[fieldName].value.length != fieldCount[0])
							{
								alertMessage(form[fieldName], errorMessage);
								return false;
							}
						}
						break;
				}
				break;
		
			// this is also true if field is empty [should be same for digits_only]
			case "valid_email":
				if (form[fieldName].value && !isValidEmail(form[fieldName].value))
				{
					alertMessage(form[fieldName], errorMessage);
					return false;         
				}
				break;
			
			case "valid_date":
				// this is written for future extensibility of isValidDate function to allow 
				// checking for dates BEFORE today, AFTER today, IS today and ANY day.
				var isLaterDate = false;
				if    (date_flag == "later_date")
					isLaterDate = true;
				else if (date_flag == "any_date")
					isLaterDate = false;
				if (!isValidDate(form[fieldName].value, form[fieldName2].value, form[fieldName3].value, isLaterDate))
				{
					alertMessage(form[fieldName], errorMessage);
					return false;
				}
				break;

			case "same_as":
				if (form[fieldName].value != form[fieldName2].value)
				{
					alertMessage(form[fieldName], errorMessage);
					return false;
				}       
				break;
		
		case "range":
		
		comparison_rule = "";
		rule_string = "";
		
		// if-else order is important here: needs to check for >= before >
		if      (rangeRequirements.match(/range=/))
		{ 
		comparison_rule = "equal";
		rule_string = rangeRequirements.replace("range=", ""); 
		}
		else if (rangeRequirements.match(/range>=/))
		{
		comparison_rule = "greater_than_or_equal";
		rule_string = rangeRequirements.replace("range>=", "");
		}
		else if (rangeRequirements.match(/range>/))
		{
		comparison_rule = "greater_than";
		rule_string = rangeRequirements.replace("range>", "");
		}
		else if (rangeRequirements.match(/range<=/))
		{
		comparison_rule = "less_than_or_equal";
		rule_string = rangeRequirements.replace("range<=", "");
		}        
		else if (rangeRequirements.match(/range</))
		{
		comparison_rule = "less_than";
		rule_string = rangeRequirements.replace("range<", "");
		}
		
		// now perform the appropriate validation
		switch (comparison_rule)
		{
		case "greater_than_or_equal":
		if (!(form[fieldName].value >= Number(rule_string)))
		{
		alertMessage(form[fieldName], errorMessage);
		return false;
		}
		break;
		
		case "greater_than":
		if (!(form[fieldName].value > Number(rule_string)))
		{
			alertMessage(form[fieldName], errorMessage);
			return false;
		}
		break;
		
		case "less_than_or_equal":
		if (!(form[fieldName].value <= Number(rule_string)))
		{
		alertMessage(form[fieldName], errorMessage);
		return false;
		}
		break;
		
		case "less_than":
		if (!(form[fieldName].value < Number(rule_string)))
		{
		alertMessage(form[fieldName], errorMessage);
		return false;
		}
		break;
		
		case "equal":
		var rangeValues = rule_string.split("-");
		
		// if the user supplied two length fields, make sure the field is within that range
		if ((form[fieldName].value < Number(rangeValues[0])) || (form[fieldName].value > Number(rangeValues[1])))
		{
		alertMessage(form[fieldName], errorMessage);
		return false;
		}
		break;
		}
		case "valid_phone":
		var numericExpression = /^[.0-9-_ ()]+$/;
		if ((form[fieldName].value != ''))
		{
			if (!(form[fieldName].value.match(numericExpression)))
			{
				alertMessage(form[fieldName], errorMessage);
				return false;
			}
		}
		break;
		case "valid_image":
		if ((form[fieldName].value != ''))
		{
				if(!checkImage(form[fieldName].value))
				{
					alertMessage(form[fieldName], errorMessage);
					return false;
				}
		}
		break;
		
		case "chk_index":
		if ((form[fieldName].value .indexOf("/") == 0))
		{
			alertMessage(form[fieldName], errorMessage);
			return false;
		}
		break;
		case "chk_domain":
		var link_redirect=form[fieldName].value;
		if(link_redirect!="")
		{
			var arr = new Array(
			'.com','.net','.org','.biz','.coop','.info','.museum','.name',
			'.pro','.edu','.gov','.int','.mil','.ac','.ad','.ae','.af','.ag',
			'.ai','.al','.am','.an','.ao','.aq','.ar','.as','.at','.au','.aw',
			'.az','.ba','.bb','.bd','.be','.bf','.bg','.bh','.bi','.bj','.bm',
			'.bn','.bo','.br','.bs','.bt','.bv','.bw','.by','.bz','.ca','.cc',
			'.cd','.cf','.cg','.ch','.ci','.ck','.cl','.cm','.cn','.co','.cr',
			'.cu','.cv','.cx','.cy','.cz','.de','.dj','.dk','.dm','.do','.dz',
			'.ec','.ee','.eg','.eh','.er','.es','.et','.fi','.fj','.fk','.fm',
			'.fo','.fr','.ga','.gd','.ge','.gf','.gg','.gh','.gi','.gl','.gm',
			'.gn','.gp','.gq','.gr','.gs','.gt','.gu','.gv','.gy','.hk','.hm',
			'.hn','.hr','.ht','.hu','.id','.ie','.il','.im','.in','.io','.iq',
			'.ir','.is','.it','.je','.jm','.jo','.jp','.ke','.kg','.kh','.ki',
			'.km','.kn','.kp','.kr','.kw','.ky','.kz','.la','.lb','.lc','.li',
			'.lk','.lr','.ls','.lt','.lu','.lv','.ly','.ma','.mc','.md','.mg',
			'.mh','.mk','.ml','.mm','.mn','.mo','.mp','.mq','.mr','.ms','.mt',
			'.mu','.mv','.mw','.mx','.my','.mz','.na','.nc','.ne','.nf','.ng',
			'.ni','.nl','.no','.np','.nr','.nu','.nz','.om','.pa','.pe','.pf',
			'.pg','.ph','.pk','.pl','.pm','.pn','.pr','.ps','.pt','.pw','.py',
			'.qa','.re','.ro','.rw','.ru','.sa','.sb','.sc','.sd','.se','.sg',
			'.sh','.si','.sj','.sk','.sl','.sm','.sn','.so','.sr','.st','.sv',
			'.sy','.sz','.tc','.td','.tf','.tg','.th','.tj','.tk','.tm','.tn',
			'.to','.tp','.tr','.tt','.tv','.tw','.tz','.ua','.ug','.uk','.um',
			'.us','.uy','.uz','.va','.vc','.ve','.vg','.vi','.vn','.vu','.ws',
			'.wf','.ye','.yt','.yu','.za','.zm','.zw','.co.uk','.com.pk');
			var domain=document.myform.domain.value;
			var mai = link_redirect+domain;////
			var val = true;
			var dot = mai.lastIndexOf(".");
			var dname = mai.substring(0,dot);
			var ext = mai.substring(dot,mai.length);
			//alert(ext);
			if(dot>2 && dot<57)
			{
				for(var i=0; i<arr.length; i++)
				{
				  if(ext == arr[i])
				  {
					val = true;
					break;
				  }	
				  else
				  {
					val = false;
				  }
				}
				if(val == false)
				{
					 alert("Your domain extension "+ext+" is not correct");
					 return false;
				}
				else
				{
					for(var j=0; j<dname.length; j++)
					{
					  var dh = dname.charAt(j);
					  var hh = dh.charCodeAt(0);
					  if((hh > 47 && hh<59) || (hh > 64 && hh<91) || (hh > 96 && hh<123) || hh==45 || hh==46)
					  {
						 if((j==0 || j==dname.length-1) && hh == 45)	
						 {
							 alert("Domain name should not begin are end with '-'");
							  return false;
						 }
					  }
					else	{
						 alert("Your domain name should not have special characters");
						 return false;
					  }
					}
				}
			}
			else
			{
			 alert("Your Domain name is too short/long");
			 return false;
			}
		}
		break;
		
		break;
		
					default:
					alert("Unknown requirement flag in validateFields(): " + requirement);
					return false;
				}
			}
			return true;
		}
		
		
		/*--------------------------------------------------------------------------------------------*\
		Function: alertMessage()
		Purpose:  simple helper function which alerts a message, then focuses on and highlights 
		a particular field.
		\*--------------------------------------------------------------------------------------------*/
		function alertMessage(obj, message)
		{ 
			var backgroundColor = "#F2F9FF";
			
			alert(message);
			
			// if "obj" is an array: it's a radio button. Focus on the first element.
			if (obj.type == undefined)
				obj[0].focus();
			else
			{
				obj.style.background = backgroundColor;
				obj.focus();
			}
			return false;
		}
		
		/*--------------------------------------------------------------------------------------------*\
		Function: isValidEmail
		Purpose:  tests a string is a valid email
		\*--------------------------------------------------------------------------------------------*/
		function isValidEmail(str)
		{
			// trim starting / ending whitespace
			str = str.replace(/^\s*/, "");
			str = str.replace(/\s*$/, "");
			
			var at="@"
			var dot="."
			var lat=str.indexOf(at)
			var lstr=str.length
			var ldot=str.indexOf(dot)
			
			if (str.indexOf(at)==-1)
				return false
			
			if (str.indexOf(at)==-1 || str.indexOf(at)==0 || str.indexOf(at)==lstr)
				return false
			
			if (str.indexOf(dot)==-1 || str.indexOf(dot)==0 || str.indexOf(dot)==lstr)
				return false
			
			if (str.indexOf(at,(lat+1))!=-1)
				return false
			
			if (str.substring(lat-1,lat)==dot || str.substring(lat+1,lat+2)==dot)
			return false
			
			if (str.indexOf(dot,(lat+2))==-1)
				return false
			
			if (str.indexOf(" ")!=-1)
				return false
			
				return true;
		}
		
		
		// helper function to check to see if a string is empty
		function isEmpty(str)
		{  
			return ((str == null) || (str.length == 0));
		}
		
		
		/*--------------------------------------------------------------------------------------------*\
		Function: isWhitespace()
		Purpose:  Returns true if string parameter is empty or whitespace characters only.
		\*--------------------------------------------------------------------------------------------*/
		function isWhitespace(s)
		{
			var i;
			// Is s empty?
			if (isEmpty(s))
				return true;
			
			for (var i=0; i<s.length; i++)
			{   
				var c = s.charAt(i);
				if (whitespace.indexOf(c) == -1)
					return false;
			}
		
			return true;
		}

		function checkImage(sFile)
		{
			var iDotPosition = sFile.lastIndexOf(".");
			
			if (iDotPosition == -1)
				return false;
		
			var sExtension = sFile.substring((iDotPosition + 1)).toLowerCase( );
		
			if (sExtension != "jpg" && sExtension != "jpeg" && sExtension != "gif" && sExtension != "png")
				return false;
		
			return true;
		}
		
		/*----------------------------------------------------------------------------*\
		Function:   isValidDate()
		Purpose:    to check an incoming date is valid. If any of the date parameters  
		fail, it returns a string message denoting the problem.
		Parameters: month       - an integer between 1 and 12
		day         - an integer between 1 and 31 (depending on month)
		year        - a 4-digit integer value
		isLaterDate - a boolean value. If true, the function verifies the 
		date being passed in is LATER than the current date.
		\*----------------------------------------------------------------------------*/
		function isValidDate(month, day, year, isLaterDate)
		{
		// depending on the year, calculate the number of days in the month
		if (year % 4 == 0)      // LEAP YEAR 
			var daysInMonth = new Array(31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);
		else
			var daysInMonth = new Array(31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);
		
		
		// first, check the incoming month and year are valid. 
		if (!month || !day || !year)
			return false;

		if (1 > month || month > 12)
			return false;

		if (year < 0)
			return false;

		if (1 > day || day > daysInMonth[month-1])
			return false;
		
		// if required, verify the incoming date is LATER than the current date.
		if (isLaterDate)
		{
		// get current date
		var today = new Date();
		var currMonth = today.getMonth() + 1; // since returns 0-11
		var currDay   = today.getDate();
		var currYear  = today.getFullYear();
		
		// zero-pad today's month & day
		if (String(currMonth).length == 1)  currMonth = "0" + currMonth;
		if (String(currDay).length == 1)  currDay   = "0" + currDay;    
		currDate = String(currYear) + String(currMonth) + String(currDay);
		
		// zero-pad incoming month & day
		if (String(month).length == 1)  month = "0" + month;
		if (String(day).length == 1)
			day   = "0" + day;
		incomingDate = String(year) + String(month) + String(day);
		
		if (Number(currDate) > Number(incomingDate))
			return false;
		}
	return true;
}
