function w3FormValidation(arrInfoVal,strTitleMsgToUser,intPageTopDistance,boolEncobrirBody,boolFixMsgToUserInViewPort) {
	this.arrInfoVal = arrInfoVal;
	
	if ( typeof strTitleMsgToUser == "undefined" ) {
		this.strTitleMsgToUser = 'Observações!';
	} else {
		this.strTitleMsgToUser = strTitleMsgToUser;
	}
	
	if ( typeof intPageTopDistance == "undefined" ) {
		intPageTopDistance = 0;
	}
	this.top = intPageTopDistance;
	
	if ( typeof boolEncobrirBody == "undefined" ) {
		this.boolEncobrirBody = true;
	}
	
	var arrAtualScrollingPosition = this.getScrollingPosition();
	this.atualScrollingPositionY = arrAtualScrollingPosition[1];
	
	if ( typeof boolFixMsgToUserInViewPort == "undefined" ) {
		boolFixMsgToUserInViewPort = true;	
	}
	if ( boolFixMsgToUserInViewPort ) {
		addEvent(window, 'scroll', this.fixMsgToUserInViewPort, false, [this.top]);
	}
};

w3FormValidation.prototype.fixMsgToUserInViewPort = function(paramTopDistance) {
	var arrCorrenteScrollingPosition = w3FormValidation.prototype.getScrollingPosition();
	var correnteScrollingPositionY = arrCorrenteScrollingPosition[1];
	if ( $('w3ShowMsgToUser') ) {
		$('w3ShowMsgToUser').style.top = correnteScrollingPositionY + parseInt(paramTopDistance,'') + 'px';
	}
};

w3FormValidation.prototype.start = function() {
	var valida = this.validation(this.arrInfoVal);
	return valida;
};

w3FormValidation.prototype.validation = function(arrParams) {
	var arrMsgToUser = [];
	var arrFields = [];
	var boolResultVal = true;

	for ( i = 0; i < arrParams.length; i++ ) {
	
		var arrFieldVal = arrParams[i].split(',');
		var if_typeVal = true;
		var strCondition, arrCondition, strFieldToCheck, strValueToCheck, strFieldToCheckValue;
		while ( arrFieldVal[0].match("^if:") ) {
			strCondition = arrFieldVal[0].replace("if:",""); 
			if ( strCondition.match(":") ) {
				var arrFieldInfo = strCondition.split(":");
				var strFormID = arrFieldInfo[0];
				arrCondition = arrFieldInfo[1].split("=");
				strFieldToCheck = arrCondition[0];
				strValueToCheck = arrCondition[1];
				for ( var r = 0; r < $(strFormID)[strFieldToCheck].length; r++) {
					if ( $(strFormID)[strFieldToCheck][r].checked ) {
						strFieldToCheckValue = $(strFormID)[strFieldToCheck][r].value;
					}
				}
			} else {
				arrCondition = strCondition.split("=");
				strFieldToCheck = arrCondition[0];
				strValueToCheck = arrCondition[1];
				strFieldToCheckValue = $(strFieldToCheck).value;
			}
			if ( strFieldToCheckValue != strValueToCheck ) {
				if_typeVal = false;
				break;
			} else {
				arrFieldVal.shift();
			}
		} // Fim do while match:^if
		
		if ( !if_typeVal ) {
			continue;
		}

		var typeVal   = arrFieldVal[0]; 
		var field     = arrFieldVal[1]; 
		var msgToUser = '';
		if ( arrFieldVal.length == 4 ) { 
			var field2 = arrFieldVal[2];
			msgToUser = arrFieldVal[3];
		} else {
			msgToUser = arrFieldVal[2]; 
		}

		if ( typeVal.match("^length=") ) {
			var strLength_typeVal = typeVal;
			typeVal = "length";
		}
		if ( typeVal.match("^range=") ) {
			var strRange_typeVal = typeVal;
			typeVal = "range";
		}

		switch(typeVal) {
			case 'req' :
				if ( field.match(":") ) {
					var arrFieldInfo = field.split(":");
					var strFormID = arrFieldInfo[0];
					var strRadioName = arrFieldInfo[1];
					if ( typeof($(strFormID)[strRadioName].type) == "undefined" ) {
						var boolRadioChecked = false;
						for ( var r = 0; r < $(strFormID)[strRadioName].length; r++) {
							if ( $(strFormID)[strRadioName][r].checked ) {
								boolRadioChecked = true;
							}
						}
						if ( !boolRadioChecked ) {
							arrMsgToUser.push(msgToUser);
							boolResultVal = false;
						}
					}
				} else {
					removeClass($(field),'w3FieldError');
					if ( !$(field).value ) {
						arrMsgToUser.push(msgToUser);
						arrFields.push($(field));
						boolResultVal = false;
					}
				}
			break;
			case 'email' :
				removeClass($(field),'w3FieldError');
				if ( !this.isEmail($(field).value) ) {
					arrMsgToUser.push(msgToUser);
					arrFields.push($(field));
					boolResultVal = false;
				}
			break;
			case 'url' :
				removeClass($(field),'w3FieldError');
				if ( !this.isURL($(field).value) ) {
					arrMsgToUser.push(msgToUser);
					arrFields.push($(field));
					boolResultVal = false;
				}
			break;
			case 'same' :
				removeClass($(field),'w3FieldError');
				if ( $(field).value != $(field2).value ) {
					arrMsgToUser.push(msgToUser);
					arrFields.push($(field));
					boolResultVal = false;
				}
			break;
			case 'digits' :
				removeClass($(field),'w3FieldError');
				if ( !$(field).value || $(field).value.match(/\D/) ) {
					arrMsgToUser.push(msgToUser);
					arrFields.push($(field));
					boolResultVal = false;
				}
			break;
			case 'length' :
				removeClass($(field),'w3FieldError');
				var strLength = strLength_typeVal.replace("length=","");
				var arrLengthOrRange = strLength.match(/[^_]+/);
				var arrLength = arrLengthOrRange[0].split("-");
				if ( arrLength.length == 2 ) {
					if ( ( $(field).value.length < arrLength[0] ) || ( $(field).value.length > arrLength[1] ) ) {
						arrMsgToUser.push(msgToUser);
						arrFields.push($(field));
						boolResultVal = false;
					}
				} else {
					if ( $(field).value.length != arrLength ) {
						arrMsgToUser.push(msgToUser);
						arrFields.push($(field));
						boolResultVal = false;
					}
				}
			break;
			case 'range' :
				removeClass($(field),'w3FieldError');
				var strRange = strRange_typeVal.replace("range=","");
				var arrRange = strRange.split("-");
				if ( ( $(field).value.match(/\D/) ) || ( $(field).value <  Number(arrRange[0]) ) || ( $(field).value > Number(arrRange[1]) ) ) {
					arrMsgToUser.push(msgToUser);
					arrFields.push($(field));
					boolResultVal = false;		
				}
			break;
			default :
				alert('O tipo de validação desejado não é suportado ou desconhecido pelo w3FormValidation.\n\n-------------------------\nTipo de validação: ' + typeVal + '\n-------------------------\n\nConsulte a documentação do programa para maiores detalhes em:\n\nhttp://leandro.w3invent.com.br.');
				return false;
		} // fim do switch(typeVal);

	} // fim do loop for

	if ( boolResultVal ) {
		return true;
	} else {
		
		for ( var x = 0; x < arrFields.length; x++ ) {
			addClass(arrFields[x],'w3FieldError');
		}
		
		this.showMsgToUser(arrMsgToUser);
		
		return false;
	}

}; // Validation

w3FormValidation.prototype.isEmail = function(strEmail) {
	return strEmail.search(/(\w[\w\.\+]+)@(.+)\.(\w+)$/) == 0;	
};

w3FormValidation.prototype.isURL = function(strURL) {
	return strURL.search(/http(s)?:\/\/(www.)?([\w.]+)(\.\w{2,4})+$/) == 0;
};

w3FormValidation.prototype.showMsgToUser = function(arrMsgToUserParam) {

	this.closeMsgToUser('noFade');

	var arrTagSelect = $tags("select");
	for ( var i = 0; i < arrTagSelect.length; i++ ) {
		arrTagSelect[i].style.visibility = "hidden";
	}
	
	if ( this.boolEncobrirBody ) {
		this.encobrirBody();	
	}
	
	var arrTagsLi = [];
	for ( i = 0; i < arrMsgToUserParam.length; i++ ) {
		arrTagsLi.push($new('li',arrMsgToUserParam[i]));
	}
	$append($new('div','id=w3ShowMsgToUser',[$new('h3',this.strTitleMsgToUser),$new('ol',arrTagsLi),$new('form',$new('input',["type=button","value=Ok","id=w3ShowMsgToUserBtnOk"],""))]));
	var fadeBox = new w3FadingOpacity('w3ShowMsgToUser',0,100,100);
	fadeBox.start();
	$('w3ShowMsgToUser').style.top = this.atualScrollingPositionY + this.top + 'px';
	addEvent($('w3ShowMsgToUserBtnOk'),'click',this.closeMsgToUser, false);
	$('w3ShowMsgToUserBtnOk').focus();
};

w3FormValidation.prototype.encobrirBody = function() {
	var sizesPage = getPageSize();
	$append($new("div","id=w3BodyOverlay",''));
	$('w3BodyOverlay').style.height = arrayPageSize[1] + 'px';
	var fadeOverlay = new w3FadingOpacity('w3BodyOverlay',0,80,100);
	fadeOverlay.start();

};

w3FormValidation.prototype.closeMsgToUser = function(strFade) {

	if ( strFade != 'noFade' ) {
		var fadeBox = new w3FadingOpacity('w3ShowMsgToUser',100,0,100,removerBoxes);
		fadeBox.start();
	}
	function removerBoxes() {
		$remove($('w3ShowMsgToUser'));
		$remove($('w3BodyOverlay'));

		var arrTagSelect = $tags("select");
		for ( var i = 0; i < arrTagSelect.length; i++ ) {
			arrTagSelect[i].style.visibility = "visible";
		}

	}
};
w3FormValidation.prototype.getScrollingPosition = function() {
	var position = [0, 0];
	if (typeof window.pageYOffset != 'undefined') {
		position = [window.pageXOffset, window.pageYOffset];
	}
	else if (typeof document.documentElement.scrollTop != 'undefined' && document.documentElement.scrollTop > 0) {
		position = [document.documentElement.scrollLeft, document.documentElement.scrollTop];
	}
	else if (typeof document.body.scrollTop != 'undefined') {
		position = [document.body.scrollLeft, document.body.scrollTop];
	}
	return position;
};

function getPageSize(){
	
	var xScroll, yScroll;
	
	if (window.innerHeight && window.scrollMaxY) {	
		xScroll = document.body.scrollWidth;
		yScroll = window.innerHeight + window.scrollMaxY;
	} else if (document.body.scrollHeight > document.body.offsetHeight){ // all but Explorer Mac
		xScroll = document.body.scrollWidth;
		yScroll = document.body.scrollHeight;
	} else { // Explorer Mac...would also work in Explorer 6 Strict, Mozilla and Safari
		xScroll = document.body.offsetWidth;
		yScroll = document.body.offsetHeight;
	}
	
	var windowWidth, windowHeight;
	if (self.innerHeight) {	// all except Explorer
		windowWidth = self.innerWidth;
		windowHeight = self.innerHeight;
	} else if (document.documentElement && document.documentElement.clientHeight) { // Explorer 6 Strict Mode
		windowWidth = document.documentElement.clientWidth;
		windowHeight = document.documentElement.clientHeight;
	} else if (document.body) { // other Explorers
		windowWidth = document.body.clientWidth;
		windowHeight = document.body.clientHeight;
	}	
	
	if(yScroll < windowHeight){
		pageHeight = windowHeight;
	} else { 
		pageHeight = yScroll;
	}

	if(xScroll < windowWidth){	
		pageWidth = windowWidth;
	} else {
		pageWidth = xScroll;
	}

	arrayPageSize = new Array(pageWidth,pageHeight,windowWidth,windowHeight);

};

function w3FadingOpacity(strID, intOpacityStart, intOpacityEnd, intFadeDuration, fnAfterFaded) {
	
	this.intOffset = 10;
	this.strID = strID; // String contendo o atributo ID do objeto desejado
	this.intOpacityStart = intOpacityStart; // Valor - inteiro - inicial para o Fade
	this.intOpacityEnd = intOpacityEnd; // Valor - inteiro - final para o Fade
	this.intFadeDuration = intFadeDuration; // Valor - inteiro - para a duração do ciclo do Fade
	this.fnAfterFaded = fnAfterFaded; // Nome da função a ser chamado após a conclusão do ciclco do Fade
	this.intInterval = 0;
	
};

w3FadingOpacity.prototype.start = function() {
	var thisClass = this;	
	this.intInterval = setInterval(function() { thisClass.fadeCycle(); }, (this.intFadeDuration / this.intOffset));
	
};

w3FadingOpacity.prototype.fadeCycle = function() {
	if ( this.intOpacityEnd < this.intOpacityStart ) {
		if ( this.intOpacityStart > this.intOpacityEnd ) {
			this.intOpacityStart -= this.intOffset;
		} else {
			this.finalize();
		}
	} else {
		if ( this.intOpacityStart < this.intOpacityEnd ) {
			this.intOpacityStart += this.intOffset;
		} else {
			this.finalize();
		}
	}
	
	this.setOpacity(this.intOpacityStart / 100);
};

w3FadingOpacity.prototype.setOpacity = function(intOpacity) {
	if ( $(this.strID) ) {
		$(this.strID).style.opacity = intOpacity;
		$(this.strID).style.filter = "alpha(opacity=" + (intOpacity*100) + ")";
	}
};

w3FadingOpacity.prototype.finalize = function() {
	this.intOpacityStart = this.intOpacityEnd;
	clearInterval(this.intInterval);
	if ( this.fnAfterFaded ) {
		this.fnAfterFaded();
	}
};