function isEmail(str) {

	var invalidChars = new Array(" ", "`", "!", "#", "$", "%", "^", "&", "*", "(", ")", "+", "=", "|", "/", "<", ">", ",", "?");

	if (str.indexOf("@") == -1 || str.indexOf(".") == -1 || str.indexOf("@") != str.lastIndexOf("@")) {
		return false;
	} else if (str.charAt(str.lastIndexOf(".") - 1) == "@" || str.charAt(str.lastIndexOf(".") + 1) == "" || str.charAt(str.lastIndexOf("@") - 1) == "" || str.charAt(str.lastIndexOf("@") - 1) == ".") {
		return false;
	} else if (((str.length) - (str.lastIndexOf(".") + 1)) > 4 || ((str.length) - (str.lastIndexOf(".") + 1)) < 2) {
		return false;
	}

	for (var i = 0; i < invalidChars.length; i++) {

		if (str.indexOf(invalidChars[i]) > -1) {
			return false;
		}
	}

	return true;

}

function isPhone(str) {

	if (str.length != 10) return false;
	if (isNaN(str)) return false;

	return true;

}

function isZip(str) {

	if (str.length != 10) {
		if (str.length != 5) return false;
	}

	if (str.indexOf("-") > -1) {
		if (isNaN(str.substring(0, 5)) || isNaN(str.substring(6))) return false;
	} else {
		if (isNaN(str)) return false;
	}

	return true;

}

function isState(str) {

	var state = str.toUpperCase();
	var states = new Array("AL", "AK", "AS", "AZ", "AR", "CA", "CO", "CT", "DE", "DC", "FM", "FL", "GA", "GU", "HI", "ID", "IL", "IN", "IA", "KS", "KY", "LA", "ME", "MH", "MD", "MA", "MI", "MN", "MS", "MO", "MT", "NE", "NV", "NH", "NJ", "NM", "NY", "NC", "ND", "MP", "OH", "OK", "OR", "PA", "PR", "RI", "SC", "SD", "TN", "TX", "UT", "VT", "VA", "VI", "WA", "WV", "WI", "WY", "AA", "AE", "AP");

	for (var i = 0; i < states.length; i++) {
		if (state == states[i]) {
			return true;
		}
	}

	return false;

}

function isCC(str, cc) {

	// find rules for validation
	if (cc.toLowerCase() == "visa") {
		var lengths = new Array(13,16);
		var prefixes = new Array('4');
	} else if (cc.toLowerCase() == "mc") {
		var lengths = new Array(16);
		var prefixes = new Array('51','52','53','54','55');
	} else if (cc.toLowerCase() == "amex") {
		var lengths = new Array(15);
		var prefixes = new Array('34','37');
	} else if (cc.toLowerCase() == "discover") {
		var lengths = new Array(16);
		var prefixes = new Array('6011');
	} else if (cc.toLowerCase() == "enroute") {
		var lengths = new Array(15);
		var prefixes = new Array('2014','2149');
	} else if (cc.toLowerCase() == "jcb") {
		var lengths = new Array(15,16);
		var prefixes = new Array('3','2131','1800');
	} else if (cc.toLowerCase() == "diners") {
		var lengths = new Array(14);
		var prefixes = new Array('300','301','302','303','304','305','36','38');
	} else {
		// if no cc was specified return false
		return false;
	}

	// validate
	var foundLength = new Boolean(false);
	var foundPre = new Boolean(false);

	for (var h = 0; h < lengths.length; h++) {
		if (str.length == lengths[h]) {
			foundLength = true;
			break;
		}
	}

	for (var i = 0; i < prefixes.length; i++) {
		if (str.substring(0, prefixes[i].length) == prefixes[i]) {
			foundPre = true;
			break;
		}
	}

	return (foundLength && foundPre && isLuhn(str));

}

function isLuhn(str) {

	if (isNaN(str) || str.length == 0) return false;

	var noDigit = str.length;
	var oddOEven = noDigit & 1;
	var sum = 0;
	var digit = 0;

	for (var i = 0; i < noDigit; i++) {
		digit = parseInt(str.charAt(i));

		if (!((i & 1) ^ oddOEven)) {
			digit *= 2;
			if (digit > 9) digit -= 9;
		}

		sum += digit;
	}

	return (sum % 10 == 0);

}