function  validate ($form) {
	
	var $nodes = $form.elements;
	var $i, $j, $tag, $type, $name, $node, $optional, $optionalParts, $optionals, $parts, $fieldName, $refId, $cont;
	var $ckbNames = [];
	
	for ($i = 0; $i < $nodes.length; ++$i) {
		
		$node = $nodes [$i];
		$name = $node.name;
		$tag = $node.nodeName.toLowerCase (); // normalize type to lowercase
		
		if (($tag != 'fieldset')) {
			
			if ($name.lastIndexOf ('[]') != $name.length - 2) {
				
				if ($tag == 'input' || $tag == 'textarea') {
					
					$parts = $name.split ('__');
					
					if ($parts.length >= 2) {
						
						$cont = true;
						$optionals = ($parts [0] != undefined) ? $parts [0].split ('_') : [];
						$fieldName = ($parts [1] != undefined) ? $parts [1].split ('_').join (' ') : [];
						$refId = ($parts [2] != undefined) ? $parts.slice (2).join ('__') : null;
						
						if (($refId) && ($refId.indexOf ('-') == 0) && ($node.form.elements [$refId.substr (1)].value != '')) {
								//skip
						} else
						
						if (($optionals.toString() != '')) {
							
							if ((($refId == '') ) && ($node.value == '')) {
								
								$cont = false;
							}
							
							if (($cont)) {
								
								for ($j = 0; $j < $optionals.length; ++$j) {
									
									$optional = $optionals [$j];
									$optionalParts = $optional.split ('-');
									
									switch ($optionalParts [0]) {
										
										case 'date':
											if ((!validatDate ($node.value))) {
												alert ('The ' + $fieldName + ' field does not satisfy a valid date structure');
												$node.focus ();
												return false;
											} else break;
										case 'phone':
											if ((!validPhone ($node.value))) {
												alert ('The ' + $fieldName + ' field does not satisfy a valid phone structure');
												$node.focus ();
												return false;
											} else break;
										case 'email':
											if ((!validEmail ($node.value))) {
												alert ('The ' + $fieldName + ' field does not satisfy a valid email structure');
												$node.focus ();
												return false;
											} else break;
										case 'url':
											if ((!validURL ($node.value))) {
												alert ('The ' + $fieldName + ' field does not represent a valid URL string');
												$node.focus ();
												return false;
											} else break;
										case 'exact':
											if (($node.value.length != $optionalParts [1])) {
												alert ('The ' + $fieldName + ' requires exact number of ' + $optionalParts [1] + ' characters');
												$node.focus ();
												return false;
											} else break;
										case 'min':
											if (($node.value.length < $optionalParts [1])) {
												alert ('The ' + $fieldName + ' requires minimum number of ' + $optionalParts [1] + ' characters');
												$node.focus ();
												return false;
											} else break;
										case 'number':
											if ((isNaN (parseInt ($node.value)))) {
												alert ('The ' + $fieldName + ' must be a of a number format');
												$node.focus ();
												return false;
											} else if (($optionalParts.length == 2) && ($optionalParts [1] == 'unsigned') &&
													($node.value.charAt(0) == '-')) {
												alert ('The ' + $fieldName + ' must be a of a non-negative number format');
												$node.focus ();
												return false;
											} else break;
										case 'confirm':
											if (($node.value != $node.form.elements [$refId].value)) {
												alert ('The ' + $fieldName + ' does not match');
												$node.focus ();
												return false;
											} else break;
										default		: alert ('The option "' + $optionalParts [0] + '" is not a valid entry'); return false;
									}
								}
							}
						} else {
							
							if (($node.value == '')) {
								
								alert ('The ' + $fieldName + ' is a required field');
								$node.focus ();
								return false;
							}
						}
					}
				} else {
					if ($tag == 'select') {
						
						if (($name.indexOf ('__') == 0)) {
							
							$parts = $name.split ('__');
							$fieldName = ($parts [1] != undefined) ? $parts [1].split ('_').join (' ') : [];
							
							$refId = ($parts [2] != undefined) ? $parts.slice (2).join ('__') : null;
							
							if (($refId) && ($refId.indexOf ('-') == 0) && ($node.form.elements [$refId.substr (1)].value != '')) {
								// skip
							} else if (($node.selectedIndex == 0)) {
								alert ('Please select a ' + $fieldName);
								$node.focus ();
								return false;
							}
						}
					}
				}
			} else {
				
				if ($name.indexOf ('__') == 0) {
					
					$fieldName = $name.substring (2, $name.length - 2).split ('_').join(' ');
					
					$cont = false;
					for ($j = 0; $j < $nodes [$name].length; ++$j) {
						
						if ($nodes [$name][$j].checked) {
							$cont = true;
							break;
						}
					}
					
					if (!$cont) {
						alert ('The ' + $fieldName + ' need to have at least one (1) selection checked');
						return false;
					}
				}
			}
		}
	}
	
	/***********************************/
	//alert('form validated successfully');
	//return false;
	/***********************************/
	
	return true;
}

function validPhone ($phone) {
	$phoneRegExp = new RegExp ('^(1\\s*[-\/\.]?)?(\\((\\d{3})\\)|(\\d{3}))\\s*[-\/\.]?\\s*(\\d{3})\\s*[-\/\.]?\\s*(\\d{4})\\s*(([xX]|[eE][xX][tT])\\.?\\s*(\\d+))*$', 'g');
	
	return $phoneRegExp.test ($phone);
}

function validEmail ($email) {
	
	$emailRegExp = new RegExp ('\\w+([-+.]\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*([,;]\\s*\\w+([-+.]\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*)*', 'g');
	
	return $emailRegExp.test ($email);
}

function validURL ($url) {
	$urlRegExp = new RegExp ('^((http|ftp|https):\\/\\/)?[\\w\\-_]+(\.[\\w\\-_]+)+([\\w\\-\\.,@?^=%&amp;:/~\+#]*[\\w\\-\\@?^=%&amp;/~\\+#])?$', 'g');
	
	return $urlRegExp.test ($url);
}

function validatDate ($date) {
	var $dateRegExp = new RegExp ('^(?:0?[1-9]|1[0-2])\\/(?:0?[1-9]|[1-2][0-9]|3[0-1])\\/\\d{4}$', 'g');
	
	return $dateRegExp.test ($date);
}
