var msgAlertaAlteracao = "Deseja sair sem salvar os dados?";
var formularioAlteradoName = null;
var alertaAlteracao = false;
var indicaAlteracaoFunctionName = "indicaAlteracao";
var disparaAlertaAlteracaoFunctionName = "disparaAlertaAlteracao";
var inibePadrao = new Array("btn_salvar");

function configuraAlertaAlteracao(faName) {
	//define nome do campo que guardará se o form foi alterado
	formularioAlteradoName = faName;
	alertaAlteracao = true;

	defineMonitorNasTags("INPUT", 			"change", 	indicaAlteracaoFunctionName);
	defineMonitorNasTags("TEXTAREA", 		"change", 	indicaAlteracaoFunctionName);
	defineMonitorNasTags("SELECT", 			"change", 	indicaAlteracaoFunctionName);
	
	defineMonitorNasTags("A", 				"click", 	disparaAlertaAlteracaoFunctionName);
	defineMonitorNasTags("INPUT#button",	"click", 	disparaAlertaAlteracaoFunctionName);
	defineMonitorNasTags("BUTTON", 			"click", 	disparaAlertaAlteracaoFunctionName);
	
	//aplica alteração, caso já esteja alterado
	if ( verificaAlteracao() ) {
		indicaAlteracaoVisualmente();
	}
}

function defineMonitorNasTags(tag, evento, funcao) {
	var elementos = obtemElementos(tag, null, null);
	aplicaEventoEmElementos(elementos, evento.toLowerCase(), funcao);
}

function indicaAlteracao(o){
	if (alertaAlteracao) {
		//alert(o.name);
		var formAlterado = document.getElementsByName(formularioAlteradoName)[0];
		formAlterado.value = "true";
		indicaAlteracaoVisualmente();
	}
	return true;
}

function indicaAlteracaoVisualmente(){
	//Sobrescreva essa função para indicar alteração na tela
}

function verificaAlteracao(){
	var formAlterado = document.getElementsByName(formularioAlteradoName)[0];
	return formAlterado.value == "true";
}

function disparaAlertaAlteracao(o) {
	if ( verificaAlteracao() ) {
		return confirm(msgAlertaAlteracao);
	}
	return true;
}

function inibeAlertaAlteracao(objeto){
	//Verifica se tem o atributo que inibe
	var atributoInibe = objeto.getAttribute("inibeAlertaAlteracao");
	if (atributoInibe != null && atributoInibe == "true") {
		return true;
	}
	//Caso nao tenha, verifica se é um botão reservado para não ter
	if (objeto.id != null) {
		for (var t = 0; t < inibePadrao.length; t++) {
			if (inibePadrao[t] == objeto.id) {
				return true;
			}
		}
	}
	return false;
}

function obtemElementos(tag, nome, idElemento) {
	var elementos = new Array();
	if (tag != null && tag != "") {
		//TAGS
		var tags = null;
		var tipo = null;
		var posTipo = tag.indexOf("#");
		if (posTipo >= 0) {
			tags = document.getElementsByTagName(tag.substring(0, posTipo));
			tipo = tag.substring(posTipo + 1);
		} else {
			tags = document.getElementsByTagName(tag);
		}
		//filtra por tipo
		for (var t = 0; t < tags.length; t++) {
			var umaTag = tags[t];
			if (umaTag && (tipo == null || umaTag.type == tipo) ) {
				if (!inibeAlertaAlteracao(umaTag)) {
					elementos.push(umaTag);
				}
			}
		}
	}else if (nome != null && nome != "") {
		//NOME
		var es = document.getElementsByName(nome);
		for (var t = 0; t < es.length; t++) {
			if (!inibeAlertaAlteracao(es[t])) {
				elementos.push(es[t]);
			}
		}
	} else if (idElemento != null && idElemento != "") {
		//ID
		var es = document.getElementById(idElemento);
		if (!inibeAlertaAlteracao(es)) {
			elementos.push(es);
		}
	}
	return elementos;
}

function aplicaEventoEmElementos(elementos, evento, funcao) {
	if (elementos != null && elementos.length > 0) {
		for (var e = 0; e < elementos.length; e++) {
			var elemento = elementos[e];
			//guarda ultimo e novo evento
			eval("elemento.old_on" + evento + " = elemento.on" + evento);
			eval("elemento.new_on" + evento + " = " + funcao);
			//cria evento novo
			var conjuntoEvento = function(evt) {
				var obj = null;
				if (window.event) {
					obj = window.event.srcElement;
				} else if (evt) {
					obj = evt.target;
				}
				//captura eventos
				var oldEvento = eval("obj.old_on" + evento);
				var newEvento = eval("obj.new_on" + evento);
				//alert(newEvento);
				//alert(obj.name + " - " + oldEvento + " - " + newEvento );
				var r = newEvento.call(obj, obj);
				if (r != null && r && oldEvento != null) {
					oldEvento.call(obj);
				}
			}
			eval("elemento.on" + evento + " = " + conjuntoEvento );
		}
	}
}

