//Created By: Chris Campbell
//www.particletree.com

window.onload = attachFormHandlers;


function toggle(obj) {
	var el = document.getElementById(obj);
	if ( el.style.display != 'none' ) {
		el.style.display = 'none';
	}
	else {
		el.style.display = '';
	}
}

function changehidden(thehidden,obj) {	
      	document.getElementById(thehidden).value = obj.checked? "1":"0";	
}

function attachFormHandlers()
{
	var formcontactinformation = document.getElementById('contactinformation'); // get the form contactinformation
	
	attachFormHandlersTo('contactinformation');

	formcontactinformation.onsubmit = function(){

            if(document.pressed == "SEND REQUEST"){
              
              return validateContactInformation();

            }
            if(document.pressed == "CANCEL"){

              toggle('contactcontent');
              toggle('requestButton');
              
              return false;

            }
                                                      
        } 
}


function attachFormHandlersTo(formName)
{
	var TheForm = document.getElementById(formName); // get the form 
	
	var inputs = TheForm.getElementsByTagName("input");
	
	var total = inputs.length; // viejo truco para acelerar.

	for (var i=0; i < total; i++){				
		if(inputs[i].name != "Submit"){			
			if(inputs[i].className){				
				var sRules = inputs[i].className.split(' ');				
				if(sRules[0] == "validate"){
					inputs[i].onchange = function(){return attachValidator(this,formName);}
					inputs[i].onblur = function(){return attachValidator(this,formName);}
				}
			}
		}					
	}		
}


var gContinue = true;
function attachValidator(objInput,formName)
{
	
	var sVal = objInput.value; //get value inside of input field
	var sFeedBack; //feedback is the feedback message sent back to the user
	gContinue = true; 
	
	var sRules = objInput.className.split(' '); // get all the rules from the input box classname
	var sValidate = sRules[0]; //validate means we will validate the field
	var sRequired = sRules[1]; // required means field is required
	var sTypeCheck = sRules[2]; //typecheck are additional validation rules (ie. email, phone, date)
	var sFeedbackLoc = sRules[3]; //feedbackLoc is the td id where feedback is sent to.
	sFeedback = validateRequired (sRequired, sVal, sTypeCheck); //validateRequired() checks if it is required and then sends back feedback
		 	
	
	if (gContinue) //if it is required and blank gContinue is false and we don't validate anymore.  // this is done because if it is blank
	//it will also fail other tests.  We don't want to spam the user with INVALID EMAIL!! if the field is still blank.
	{		
		// check the different validation cases (ie: email, phone, etc.)
		switch (sTypeCheck)		
		{
			case "date":
				sFeedback = validateDate(sVal);
				break;
			case "email":
				sFeedback = validateEmail(sVal);
				break;
			case "phone":								
				sFeedback = validatePhone(sVal);				
				break;
			case "zip":
				sFeedback = validateZip(sVal);
				break;
			case "password":
				sFeedback = validatePassword(sVal);
				break;
			case "first":
				sFeedback = validateName(sVal);
				break;
			case "name":				
				sFeedback = validateName(sVal);				
				break;
			case "numeric":				
				sFeedback = validateNumeric(sVal);
				break;
			case "street":
				sFeedback = validateStreet(sVal);
				break;
			case "alnum":
				sFeedback = validateAlfaNumeric(sVal);
				break;
			case "whatever":
				sFeedback = whatever(sVal);
				break;
		}
	}
	// after validation is complete return the feedback
			
	var TheForm = document.getElementById(formName); 

	// To get all the elemets class name's are rules and select onlly sFeedbackLoc
	//if((var elem = TheForm.getElementsById(sFeedbackLoc))) elem.innerHTML = sFeedback;
	
	var cl = "rules";	
	var myclass = new RegExp('\\b'+cl+'\\b');
	var elem = TheForm.getElementsByTagName('*');
	for (var i = 0; i < elem.length; i++) {				
		if (myclass.test(elem[i].className)) {
			if(elem[i].id == sFeedbackLoc){
				elem[i].innerHTML = sFeedback;
			}
		}
	}
	
}




function validateRequired(sRequired, sVal, sTypecheck)
{	
	if (sRequired == "required")  //check if required if not, continue validation script
	{	
   		if (sVal == "") //if it is rquired and blank then it is an error and continues to be required
		{
			gContinue = false;			
			return  "Required";
	 	}
  		else if (sTypecheck == "none")  //if its not blank and has no other validation requirements the field passes
		{
			return "Thank You";
		}
	}
        if (sRequired == "notrequired")
        {
                if (sVal == "")
                {
                        gContinue = false;
                        return "Thank You";
                }

        }
}


function validateDate(sVal)
{
	// our date regular expression (http://www.regexlib.com)
 var regex=/(((0[13578]|10|12)([-.\/])(0[1-9]|[12][0-9]|3[01])([-.\/])(\d{4}))|((0[469]|11)([-.\/])([0][1-9]|[12][0-9]|30)([-.\/])(\d{4}))|((2)([-.\/])(0[1-9]|1[0-9]|2[0-8])([-.\/])(\d{4}))|((2)(\.|-|\/)(29)([-.\/])([02468][048]00))|((2)([-.\/])(29)([-.\/])([13579][26]00))|((2)([-.\/])(29)([-.\/])([0-9][0-9][0][48]))|((2)([-.\/])(29)([-.\/])([0-9][0-9][2468][048]))|((2)([-.\/])(29)([-.\/])([0-9][0-9][13579][26])))/;
 
	// do the comparison, if we have a match write thank you or else the date is invalid
	if (regex.test(sVal))
	{
      return "Thank You";
	}
	else 
	{
      return "Invalid Date";
	}

}


/*
OK, let's look at this in pieces. The ^ character indicates that the expression needs to start out with the group in parentheses. But that, in itself, is made of up two groups with a vertical bar ("or") between. So either grouping can be at the start of the email address. Let's take a look at the two groups independently:

([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)
The brackets indicate a group of characters. The + at the end says that the group of characters has to appear at least once, but it can appear as many times as you want. The group starts out with a carat (^) character, which indicates negation. So we are listing characters that CANNOT appear: greater than or less than signs, open or close parentheses, open or close brackets (the slash before the close bracket indicates that the character is literal instead of closing the group of characters), slash (needs to have a slash in front to indicate a literal character), period, comma, semicolon, colon, a whitespace character (space, tab, form feed, line feed), at sign, or quote. If any one of those characters appear one or more times, the address will be not valid. But all other characters not listed are valid and something outside of that group must appear at least once (because of the + sign following the group).

After one or more valid characters, there is parentheses around another group, followed by a star (*) character. The star idicates that the preceeding group can appear zero or more times. In other words, if it's omitted it's ok, but it can appear. That applies to the whole grouping of characters. Within this grouping, is a period followed by one or more valid characters (same listing as before).

All this means that there has to be one or more valid characters before the @ sign, and if there are any periods before the @ sign they must be followed by one or more valid characters. Since periods themselves are listed in the not valid characters, a period cannot be the first character and there cannot be consecutive periods before the @ sign.

(\".+\")
This grouping is a bit easier to understand. A literal quote character can appear, followed by one or more characters (here, the period indicates any single character) followed by another qoute. So, "johndoe"@ is a valid starting part of the email address. And if there truly was a case where consecutive periods were in the part before the @ sign, the whole thing could be enclosed in quotes to make it valid ("john..doe"@ would be a valid first part, but john..doe@ would not be valid).

After one of the first two groups of characters appears at the start of the email address, the @ character must appear. Then the next grouping must appear at the end of the email address (the $ after the big grouping indicates that). There are other "sub" groups that are "or"ed together to make up the big grouping. Let's go over each of the "sub" groups.

(\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])
This group looks for the IP address format of the domain. So this group says that a left bracket (the slash again indicates the literal character) must be followed by anywhere from 1 to 3 digits ([] indicates a group of characters, 0-9 indicate the allowed characters, {1,3} indicate a range of times the previous group of characters must appear - between 1 and 3). After the bracket and 1 to 3 digits must come a period, then another 1 to 3 digits, then another period, then another 1 to 3 digits, and then another period, then another 1 to 3 digits, and then the right bracket.

(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,})
The + at the end of the first group indicates that the preceeding grouping must appear one or more times. This grouping is one or more valid characters followed by a period. Valid characters are letters, numbers, or hyphens. Domain names can only contain letters, numbers, or hyphens (go to www.godaddy.com and attempt to register a domain name with any other character somewhere in it). So every period must be preceeded by one or more characters, but there can be as many groupings of character(s) followed by a period. At the very end must be a group of 2 or more letters. This handles the ending qualifiers of a domain name. It used to be a requirement that the ending qualifiers were anywhere from 2 to 4 characters (.tv has 2 characters, .name has 4) but recently state names have been introduced as qualifiers, so we just decided to make sure it was at least 2 characters and didn't put an upper limit on the length.

So those two groups are "or"ed together. So after the @ sign must appear one of those groups - either the IP address format, or the domain name format.
*/
	
function validateEmail(sVal)
{
 var regex= /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[(2([0-4]\d|5[0-5])|1?\d{1,2})(\.(2([0-4]\d|5[0-5])|1?\d{1,2})){3} \])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/
 
	// do the comparison, if we have a match write thank you or else the email is invalid
	if (regex.test(sVal))
	{
      return "Thank You";
	}
	else
	{
      return "Invalid Email Address";
	}
}

function validatePhone(sVal)
{
	var regex=/^\(?(\d{3})\)?[\.\-\/]?(\d{3})[\.\-\/]?(\d{4})$/;
 			
	
	// do the comparison, if we have a match write thank you or else the email is invalid
	if (regex.test(sVal))	
	{
      		return "Thank You";
	}
	else
	{
      		return "Invalid Phone";		
	}

}

function removeSpaces(string) {
	var tstring = "";
	string = '' + string;
	splitstring = string.split(" ");
	for(i = 0; i < splitstring.length; i++)
	tstring += splitstring[i];
	return tstring;
}

function validateZip(sVal)
{
	
// our email regular expression
//Javascript matches US zipcodes not allowing all zeros in first 5 or +4 (http://www.regexlib.com)
// Matches:  	 [12345], [12345-6789], [123456789]
 var regex=/(^(?!0{5})(\d{5})(?!-?0{4})(-?\d{4})?$)/;
 
	// do the comparison, if we have a match write thank you or else the email is invalid
	if (regex.test(sVal))
	{
      return "Thank You";
	}
	else
	{
      return "Invalid ZipCode";
	}
}

function validatePassword(sVal)
{ 
/*Description:the password length doesn't matter, but the password must contain at least 1 number, at least 1 lower case letter, and at least 1 upper case letter.
Again, the ^ and $ are looking for things at the start and end. The "\w*" combination is used at both the start and the end. \w means any alphanumeric character, and * means zero or more. You'll see why it's "zero or more" in a bit. Between are groupings in parentheses. The "(?" combination is a flag in regular expressions. Basically, they say "apply the following formula, but don't consume any of the string". In this example, instead of specifying the order that things should appear, it's saying that it must appear but we're not worried about the order.

The first grouping (called an "atom" in "regular expresion speak") uses the = sign. This means that there must be a match. Other choices are ! for a negative match (the string must not look like this). There are others (more complicated) for preceeding matches and stuff. We can refer you to a regular expression syntax web site for further details.

After the = sign comes "\w*\d". Again, any alphanumeric character can happen zero or more times, then any digit (\d means any digit from 0 to 9) can happen. So this checks to see if there is at least one number in the string. But since the string isn't comsumed, that one digit can appear anywhere in the string.

The next atom (grouping) is (?=\w*[a-z]). This is similar to the digit grouping, except it looks for a lower case letter. Again, the lower case letter can appear anywhere, but there has to be at least one.

The third atom is (?=\w*[A-Z]) which looks for an upper case letter somewhere in the string.

Finally, at the end is zero or more alphanumeric characters. To match this string, the minimum characters needed is 3 (one upper case letter, one lower case letter, and one number).
*/


 var regex= /^\w*(?=\w*\d)(?=\w*[a-z])(?=\w*[A-Z])\w*$/;	

	// do the comparison, if we have a match write thank you or else the email is invalid
	if (regex.test(sVal))
	{		
      		return "Thank You";	
	}
	else
	{		
      		return "Invalid Password";	
	}
}



function validateName(sVal)
{ 
//This is the simplest RegEx for validating someone's name. The name can contain only alphabets(in either case) & 
//should be of minimum length 4 & maximum length 32. Only white spaces are allowed apart from alphabets.
//Matches: 	[some body], [hey there], [hello] (http://www.regexlib.com)
 var regex=/^([a-zA-z\s]{4,32})$/;
 
	// do the comparison, if we have a match write thank you or else the email is invalid
	if (regex.test(sVal))
	{
      return "Thank You";
	}
	else
	{
      return "Invalid Name";
	}
}

function validateAlfaNumeric(sVal)
{ 
//This is the simplest RegEx for validating someone's name. The name can contain only alphabets(in either case) & 
//should be of minimum length 1 & maximum length 80. Only white spaces are allowed apart from alphabets.
//Matches: 	[some body 7878], [hey there], [hello] (http://www.regexlib.com)
 //var regex=/^([A-Za-z0-9]{1,80})$/;
var regex=/^\w+$/;
 
	// do the comparison, if we have a match write thank you or else the email is invalid
	if (regex.test(sVal))
	{
      return "Thank You";
	}
	else
	{
      return "Invalid Name";
	}
}

function validateStreet(sVal)
{ 
//This is the simplest RegEx for validating someone's name. The name can contain only alphabets(in either case) & 
//should be of minimum length 4 & maximum length 32. Only white spaces are allowed apart from alphabets.
//Matches: 	[some body], [hey there], [hello] (http://www.regexlib.com)
 var regex=/^([!"$%&'()*+,-./:;?@[\\\]_`{|}~A-Za-z0-9\s]{4,32})$/;
 
	// do the comparison, if we have a match write thank you or else the email is invalid
	if (regex.test(sVal))
	{
      return "Thank You";
	}
	else
	{
      return "Invalid Street Address";
	}
}

function validateNumeric(sVal)
{ 
/*
This is a quick JavaScript function using regular expressions to make sure a string is a number. It checks to see if a plus or minus sign (optional) is at the start of the string, then one or more digits, then an optional grouping of a decimal followed by one or more digits at the end of the string.
*/
 var regex=/^[-+]?\d+(\.\d+)?$/;
 
	// do the comparison, if we have a match write thank you or else the email is invalid
	if (regex.test(sVal))
	{
      return "Thank You";
	}
	else
	{
      return "Invalid Number";
	}
}

function whatever(sVal)
{
	return "Thank You";
}

/*
Many companies sell products over the internet. When doing that, getting credit card input over the internet becomes important. And then validating those credit card numbers becomes important. Here is a combination of regular expression validation and standard JavaScript to check to see if a credit card number is a valid number. The code below will do that validation. However, note that this doesn't check to see if the specific credit card number has really been issued by the bank, or if the owner of the credit card has enough credit available, etc. You'll still need to go through your merchant account software to validate all that information, but this initial check assures that the credit card number itself is one that could have been issued.

This code handles the most popular types of credit card: Visa, Master Card, Discover, American Express, and Diner's Club. Each of these cards start out with a different prefix and card number length. This information is used for the regular expression validation. After the card number has the right prefix and is the correct length, a "mod 10" validation is performed on the credit card number. This code is a bit strange and needs some explanation. Cards with an even number of digits go through differently than cards with an odd number of digits (American Express). Every other digit, starting with the second digit (first digit for American Express) is added together. Then a second pass is made, again with every other digit, starting this time with the first digit (second digit for American Express). During this second pass, each digit is multipled by 2. If the digit multiplied by 2 is greater than or equal to 10, the total minus 9 is added to the original sum from the first pass. If the digit multiplied by 2 is less than 10, that total is added to the original sum from the first pass. After the two passes, the total should be evenly divisible by 10. This is the check that the JavaScript code goes through to validate the credit card.

The code handles the different cases for cards of even length and cards for odd length (American Express) with the same code. That part is probably the most confusing part of the code when looking at it.

*/

function isValidCreditCard(type, ccnum) {


   if (type == "Visa") {
      // Visa: length 16, prefix 4, dashes optional.
      var re = /^4\d{3}-?\d{4}-?\d{4}-?\d{4}$/;
   } else if (type == "MC") {
      // Mastercard: length 16, prefix 51-55, dashes optional.
      var re = /^5[1-5]\d{2}-?\d{4}-?\d{4}-?\d{4}$/;
   } else if (type == "Disc") {
      // Discover: length 16, prefix 6011, dashes optional.
      var re = /^6011-?\d{4}-?\d{4}-?\d{4}$/;
   } else if (type == "AmEx") {
      // American Express: length 15, prefix 34 or 37.
      var re = /^3[4,7]\d{13}$/;
   } else if (type == "Diners") {
      // Diners: length 14, prefix 30, 36, or 38.
      var re = /^3[0,6,8]\d{12}$/;
   }
   if (!re.test(ccnum)) return false;
   // Remove all dashes for the checksum checks to eliminate negative numbers
   ccnum = ccnum.split("-").join("");
   // Checksum ("Mod 10")
   // Add even digits in even length strings or odd digits in odd length strings.
   var checksum = 0;
   for (var i=(2-(ccnum.length % 2)); i<=ccnum.length; i+=2) {
      checksum += parseInt(ccnum.charAt(i-1));
   }
   // Analyze odd digits in even length strings or even digits in odd length strings.
   for (var i=(ccnum.length % 2) + 1; i<ccnum.length; i+=2) {
      var digit = parseInt(ccnum.charAt(i-1)) * 2;
      if (digit < 10) { checksum += digit; } else { checksum += (digit-9); }
   }
   if ((checksum % 10) == 0) return true; else return false;
}

/*
The function takes an input string and an optional format string. The format string is only 3 characters long and determines the relative positions of the month, day, and year. If the format string is omitted, then it will be "MDY" (month first, then day, then year). There are three different types of dividers that can be used in the date string. These are the slash (/), the period (.) and the dash (-). Years can be either 2 digits (00-49 are assumed to be 21st century and 50-99 are assumed to be 20th century) or 4 digits.

The way the regular expression part of the function works is by using the "remember" capabilities of regular expressions. This assures that the same divider is used in both positions. (In other words, you couldn't do MM/DD-YYYY). The "\1" in the regular expression says "use the same thing you used in parentheses before (which is the check for a slash, period, or dash) and apply the check here".

If the string passes the regular expression (there are 2 checks since the year can be either 2 or 4 digits), then additional JavaScript is performed to check the validity of the date. Instead of doing all the checks for the day of the month being out of range and checking for leap years, a simple approach is taken. A new date object is created in JavaScript. If the numbers are out of range (like February 31), JavaScript will still create an object, it will just be adjusted to be a valid date. So create the date and then check to see if it was adjusted by JavaScript. If it was adjusted, then the original date is not a valid date.
The function returns true if the date is valid and false if it is not. So, your validation could look something like:

if (!isValidDate(myDateString, "DMY")) { alert("The date is not in the correct format."); }

*/

function isValidDate(dateStr, format) {
   if (format == null) { format = "MDY"; }
   format = format.toUpperCase();
   if (format.length != 3) { format = "MDY"; }
   if ( (format.indexOf("M") == -1) || (format.indexOf("D") == -1) || _
      (format.indexOf("Y") == -1) ) { format = "MDY"; }
   if (format.substring(0, 1) == "Y") { // If the year is first
      var reg1 = /^\d{2}(\-|\/|\.)\d{1,2}\1\d{1,2}$/
      var reg2 = /^\d{4}(\-|\/|\.)\d{1,2}\1\d{1,2}$/
   } else if (format.substring(1, 2) == "Y") { // If the year is second
      var reg1 = /^\d{1,2}(\-|\/|\.)\d{2}\1\d{1,2}$/
      var reg2 = /^\d{1,2}(\-|\/|\.)\d{4}\1\d{1,2}$/
   } else { // The year must be third
      var reg1 = /^\d{1,2}(\-|\/|\.)\d{1,2}\1\d{2}$/
      var reg2 = /^\d{1,2}(\-|\/|\.)\d{1,2}\1\d{4}$/
   }
   // If it doesn't conform to the right format (with either a 2 digit year or 4 digit year), fail
   if ( (reg1.test(dateStr) == false) && (reg2.test(dateStr) == false) ) { return false; }
   var parts = dateStr.split(RegExp.$1); // Split into 3 parts based on what the divider was
   // Check to see if the 3 parts end up making a valid date
   if (format.substring(0, 1) == "M") { var mm = parts[0]; } else _
      if (format.substring(1, 2) == "M") { var mm = parts[1]; } else { var mm = parts[2]; }
   if (format.substring(0, 1) == "D") { var dd = parts[0]; } else _
      if (format.substring(1, 2) == "D") { var dd = parts[1]; } else { var dd = parts[2]; }
   if (format.substring(0, 1) == "Y") { var yy = parts[0]; } else _
      if (format.substring(1, 2) == "Y") { var yy = parts[1]; } else { var yy = parts[2]; }
   if (parseFloat(yy) <= 50) { yy = (parseFloat(yy) + 2000).toString(); }
   if (parseFloat(yy) <= 99) { yy = (parseFloat(yy) + 1900).toString(); }
   var dt = new Date(parseFloat(yy), parseFloat(mm)-1, parseFloat(dd), 0, 0, 0, 0);
   if (parseFloat(dd) != dt.getDate()) { return false; }
   if (parseFloat(mm)-1 != dt.getMonth()) { return false; }
   return true;
}

