



// Funções e variáveis comuns

var Common = new Object();
Common._debug = false;

/* Adiciona uma função que será executada quando determinado evento de um elemento for disparado.
 *
 * element:		Elemento que contém o evento.
 * event:		Nome do evento.
 * func:		Função que será executada.
 * [ieEvent]:	Nome do evento exclusivo para IE (opcional).
 */
Common.addEvent = function (element, event, func, ieEvent)
{
	if(element)
	{
		// Adiciona o evento
		if(element.addEventListener)
		{	// FF
			element.addEventListener(event, func, false);
			return true;
		}
		else if(element.attachEvent)
		{	// IE
			if(!ieEvent) ieEvent = "on"+event;
			element.attachEvent(ieEvent, func);
			return true;
		}
	}

	return false;		
}

// Indica se a página terminou de carregar
Common.isLoaded = false;
Common.addEvent(window,'load',function(){Common.isLoaded = true;},'onload');


/* Seleciona um elemento filho seguindo um determinado critério.
 *
 * criteria:	Critério para a busca.
 * [baseEl]:	Elemento que será a base para a procura, se não informado, será usado o DOCUMENT.
 */
Common.selectElement = function(criteria, baseEl)
{
	/*
		'>' = filhos
		' ' = qualquer descendente
		'<' = pai ou ancestral
		'*' = qualquer elemento
		'+' = próximo irmão
		'-' = irmão anterior
		'#' = id do elemento
		'.' = nome da classe
		'DIV' = qualquer filho ou desendente 'div'
		'<A' = qualquer pai 'a'
		'P' = qualquer filho ou desendente 'p'
		'>DIV#des' = filho 'div' com id 'des'
		'A.link' = qualquer desendente 'a' com classe 'link'
	*/
	
	// Verifica se informou o critério
	if(criteria)
	{
		if(Common._debug) alert("Criteria: "+criteria);
		
		var ret;
		
		// Obtém o elemento pai se não existir
		if(!baseEl) ret = document;
		else ret = baseEl;

		var lastDirCh;
		var navChars="<>*+- #."; // Caracteres de navegação
		var dirChars="<+-"; // Caracteres de direção

		// Verifica cada caractere
		for(var i=0;i<criteria.length;)
		{
			if(dirChars.indexOf(ch)>=0) // Verifica se é um char de direção
				lastDirCh = ch;
			else
				lastDirCh = null;
			var ch = criteria.charAt(i);
			i++;
			
			if(ch=='#') // Id
			{
				// Lê o id do elemento
				var elId = "";
				for(;i< criteria.length;i++)
				{
					var chi = criteria.charAt(i);
					elId+=chi;
					if(navChars.indexOf(chi)>=0) break;
				}

				if(lastDirCh) // Se tiver a direção pega com o document
				{
					ret = document.getElementById(elId);
				}
				else if(ret.getElementById) // Usa a função do próprio elemento
					ret = ret.getElementById(elId);
				else if(ret.tagName && ret.id!=elId) // Procura nos filhos
				{
					var els = ret.getElementsByTagName("*");
					for(var j=0;j<els.length;j++)
					{
						var el = els[j];
						if(el.id==elId)
						{
							ret = el;
							break;
						}
					}
				}
				else // Procura na lista
					for(var j=0;j<ret.lenght;j++)
						if(ret[j].id==elId)
						{
							ret = ret[j];
							break;
						}
			}
			else if(ch=='.') // Nome da classe
			{
				// Lê o nome da classe do elemento
				var elClass = "";
				for(;i< criteria.length;i++)
				{
					var chi = criteria.charAt(i);
					elClass+=chi;
					if(navChars.indexOf(chi)>=0) break;
				}

				if(lastDirCh && ret.tagName) // Segue a direção se for elemento
				{
					if(lastDirCh=="<") // Se for pai, retorna somente o primeiro
					{
						while(true)
						{
							ret = ret.parentNode;

							if(!ret) break;
							if(ret.className && ret.className.indexOf(elClass)>=0) break;
						}
					}
					else // Retorna a lista
					{
						var newRet = new Array();
						while(true)
						{
							if(lastDirCh=="+")
								ret = ret.nextSibling;
							else if(lastDirCh=="-")
								ret = ret.previousSibling;
							else
								break;

							if(!ret) break;
							if(ret.className && ret.className.indexOf(elClass)>=0) newRet.push(ret);
						}
						ret = newRet;
					}
				}
				else // Procura um elemento com a classe nos filhos
				{
					if(ret.getElementsByClassName) // Usa a função do elemento
						ret = ret.getElementsByClassName(elClass);
					else if(ret.tagName) // Procura nos filhos do elemento
					{
						var newRet = new Array();
						var els = ret.getElementsByTagName("*");
						for(var j=0;j<els.length;j++)
						{
							var el = els[j];
							if(el.className && el.className.indexOf(elClass)>=0)
								newRet.push(el);
						}
						ret = newRet;
					}
					else // Procura na lista
					{
						var newRet = new Array();
						for(var j=0;j<ret.lenght;j++)
						{
							var el = ret[j];
							if(el.className && el.className.indexOf(elClass)>=0)
								newRet.push(el);
						}
						ret = newRet;
					}
				}
			}
			else if(ch=='<') // Pai
			{
				if(ret.tagName)
					ret = ret.parentNode;
				else
					for(var j=0;j<ret.lenght;j++)
						ret[j] = ret[j].parentNode;
			}
			else if(ch=='>') // Filho
			{
				if(ret.tagName)
					ret = ret.childNodes;
				else
				{
					var newRet = new Array();
					for(var j=0;j<ret.lenght;j++)
						newRet.concat(ret[j].childNodes);
					ret = newRet;
				}
			}
			else if(ch=='*') // Qualquer elemento
			{
				if(ret.getElementsByTagName)
					ret = ret.getElementsByTagName('*');
				else
				{
					var newRet = new Array();
					for(var j=0;j<ret.length;j++)
						newRet.concat(ret[j].getElementsByTagName('*'));
					ret = newRet;
				}
			}
			else if(ch=='+') // Próximo irmão
			{
				if(ret.tagName)
					ret = ret.nextSibling;
				else
					for(var j=0;j<ret.lenght;j++)
						ret[j] = ret[j].nextSibling;
			}
			else if(ch=='-') // Irmão anterior
			{
				if(ret.tagName)
					ret = ret.previousSibling;
				else
					for(var j=0;j<ret.lenght;j++)
						ret[j] = ret[j].previousSibling;
			}
			else if(ch==' ') // Espaço
				continue;
			else // Nome da tag
			{
				// Lê o nome da tag
				var tagName = ch;
				for(;i< criteria.length;i++)
				{
					var chi = criteria.charAt(i);
					tagName+=chi;
					if(navChars.indexOf(chi)>=0) break;
				}

				if(lastDirCh && ret.tagName) // Segue a direção se for elemento
				{
					if(lastDirCh=="<") // Pai somente retorna o primeiro
					{
						while(true)
						{
							ret = ret.parentNode;

							if(!ret) break;
							if(ret.tagName==tagName) break;
						}
					}
					else // Retorna a lista dos demais
					{
						var newRet = new Array();
						while(true)
						{
							if(lastDirCh=="+")
								ret = ret.nextSibling;
							else if(lastDirCh=="-")
								ret = ret.previousSibling;
							else
								break;

							if(!ret) break;
							if(ret.tagName==tagName) newRet.push(ret);
						}
						ret = newRet;
					}
				}
				else
				{
					if(ret.getElementsByTagName) // Procura pela tag nos filhos
						ret = ret.getElementsByTagName(tagName);
					else  // Procura na lista
					{
						var newRet = new Array();
						for(var j=0;j<ret.lenght;j++)
							newRet.concat(ret[j].getElementsByTagName(tagName));
						ret = newRet;
					}
				}
			}

			// Se nada foi encontrado, retorna
			if(!ret) return null;
		}
		
		return ret;
	}
	
	return null;
}

/* Obtém elementos filhos que possuam uma determinada classe.
 *
 * className:	Nome da classe para a busca.
 * [parentEl]:	Elemento que será a base para a procura, se não informado, será usado o BODY.
 */
Common.getElementsByClassName = function(className,parentEl)
{
	// Obtém o elemento pai se não existir
	if(!parentEl)
	{
		parentEl = document.body;
		if(!parentEl) parentEl = document;
	}
	
	// Verifica se possue a função (FF)
	if(parentEl.getElementsByClassName)
		return parentEl.getElementsByClassName(className);
	else
	{
		// Obtém a lista de filhos e procura (IE)
		var list = new Array();
		var els = parentEl.getElementsByTagName("*");
		for(var i=0;i<els.length;i++)
		{
			var el = els[i];
			var cl = el.className;
			if(cl && cl.indexOf(className)>=0)
				list.push(el);
		}
		return list;
	}
}

/* Obtém a posição atual de um elemento.
 *
 * el:	Elemento.
 */
Common.getPosition = function(el)
{
	var x = 0;
	var y = 0;
	
	// Verifica cada elemento posicionado
	while(el && !isNaN(el.offsetLeft) && !isNaN(el.offsetTop) )
	{
		// Obtém a posição do elemento
		x += el.offsetLeft - el.scrollLeft;
		y += el.offsetTop - el.scrollTop;
		
		// Obtém o elemento pai
		if(el.offsetParent)
			el = el.offsetParent;
		else if(el.tagName!='HTML')
			el = document.getElementsByTagName('HTML')[0];
		else
			break;
		
	}
	return { top: y, left: x };
}

/* Atalho para Common.selectElement
 */
SelectElement = Common.selectElement;

/* Seleciona um elemento por id
 * elId: Id do elemento
 * [parent]: Elemento pai
 */
SelectElement.id = function(elId,parentEl)
{
	// Se não informar o pai, usa o document
	if(!parentEl) return document.getElementById(elId);
	
	// Verifica se possue a função
	if(parentEl.getElementById)
		return parentEl.getElementById(elId);

	// Obtém a lista de filhos e procura
	var els = parentEl.getElementsByTagName("*");
	for(var i=0;i<els.length;i++)
	{
		var el = els[i];
		if(el.id==elId)
			return el;
	}
}

/* Verifica se um textarea passou do limite */

function _DI_TextareaMaxLength(obj,len)
{
	if(obj.value.length>len)
		obj.value = obj.value.substring(0,len)
}



/* Asynchronous JavaScript and XML - Ajax
 */
var Ajax = new Object();

// Indica se é para depurar o ajax
Ajax._debug = false;

// Indica se é para setar a posição da rolagem
Ajax.setScrollNewPos = true;

// Contador
Ajax._rCount = 0;

// Objeto de estado do pedido
//		onStart:
//		onLoad:
//		onError:
//		waitingEl:
//		cropControl:
Ajax.stateObject = undefined;

// Obtém o XMLHttpRequest
Ajax._getXmlHttp = function ()
{
	// Verifica se já obteve
	if(!Ajax._xRequest)
	{
		if (window.XMLHttpRequest) // FF | IE7+
			Ajax._xRequest = new XMLHttpRequest();
		else if (window.ActiveXObject)// IE<7.0
		{
			try
			{
				Ajax._xRequest = new ActiveXObject("Msxml2.XMLHTTP")
			}
			catch(e)
			{
				try
				{
					Ajax._xRequest = new ActiveXObject("Microsoft.XMLHTTP")
				}
				catch(e){}
			}
		}
		
		if(Ajax._debug) alert("Create XMLHTTP: "+(Ajax._xRequest!=null));

		if (Ajax._xRequest==null)
			alert("Seu navegador não suporta XMLHTTP.");
	}
	return Ajax._xRequest;
}

// Exibe um elemento durante o carregamento
Ajax._showWait = function (el)
{
	// Obtém o elemento
	var waitEl;
	if(!el)
		waitEl = document.getElementById("__ajaxWait");
	else if(typeof(el)=="string")
		waitEl = document.getElementById(el);
	else
		waitEl = el;

	if (!waitEl) 
	{ 
		// Se não existir, cria um
		waitEl = document.createElement("div"); 
		waitEl.id = "__ajaxWait"; 
		waitEl.innerHTML = "<b>Carregando...</b>";
		
		// Seta o estilo
		var style = waitEl.style;
		style.width = "85px";
		style.padding = "6px";
		style.right = "15px";
		style.top = "15px";
		style.position = "fixed";
		style.border = "1px solid #DD7700";
		style.backgroundColor = "#FF9900";
		style.color = "white";
		style.fontWeight = "bold";
	    
	    // Adiciona no corpo da página se existir
	    if(document.body)
			document.body.appendChild(waitEl);
		else
			alert("Carregando...");	
	}
	else
		// Exibe o elemento existente
		waitEl.style.display = "block";
		
	// Guarda o elemento
	Ajax._waitEl = waitEl;
}

// Esconde o elemento de espera
Ajax._hideWait = function()
{
	if(Ajax._waitEl)
	{
		Ajax._waitEl.style.display = "none";
		Ajax._waitEl = undefined;
	}
}

// Evento onError
Ajax.onError = function(statusHttp, text)
{
	// Mostra a mensagem de erro
	alert("Ocorreu um erro durante o processamento.\n\nError: "+text+" ("+statusHttp+")");
		
	if(Ajax._debug) alert("Error: "+statusHttp+" | "+text);
};

// Monitora mudanças no estado do processo 
Ajax._stateChange = function ()
{
	var xmlhttp = Ajax._getXmlHttp();

	if(xmlhttp)
	{
		// Verifica se terminou
		if(xmlhttp.readyState==4)
		{
			Ajax._rCount++;
			if(Ajax._debug) alert("rCount: "+Ajax._rCount);

			var error;
			if (xmlhttp.status==200)
			{
				// Verifica se a responsta é 'xml'
				var ctType = xmlhttp.getResponseHeader("Content-Type");
				if(ctType && ctType.indexOf("application/xml")==-1)
				{
					// Se não recarrega
					if(Ajax._debug) alert(ctType+" reload");
					if(confirm('Sua sessão expirou ou ocorreu algum problema durante o processamento.\n\nDeseja recarregar a página?\n\nAtenção! Todos os dados não salvos serão perdidos.\n'))
					{
						window.top.location.reload();
						return;
					}
				}

				// Obtém a resposta
				var xmlResp = xmlhttp.responseXML;
				
				if(Ajax._debug)
				{
					alert(xmlhttp.statusText);
					alert(xmlhttp.getAllResponseHeaders());
					alert(xmlhttp.responseText);
				}

				if(xmlResp)
					Ajax._lastResponse = xmlResp;
					
				// Dispara o evento do objeto de estado se existir
				if(Ajax.stateObject && Ajax.stateObject.onLoad)
					Ajax.stateObject.onLoad(Ajax.stateObject,xmlResp);
					
				Ajax._hideWait();
				
				return;
			}
			else
				error = xmlhttp.statusText;

			// Dispara o evento de erro se existir
			if(error)
			{
				if(Ajax._debug) alert("Error: "+error);

				var onError;
				if(Ajax.stateObject && Ajax.stateObject.onError)
					onError = Ajax.stateObject.onError;
				else if(Ajax.onError)
					onError = Ajax.onError;
				else
					return;

				onError(xmlhttp.status,error);
			}
		}
	}
}

// Cancela o processo de solicitação atual
Ajax.Abort = function ()
{
	// Obtém o request
	var xmlhttp = Ajax._getXmlHttp();

	// Cancela se for algum estado processando
	if(xmlhttp.readyState!=0 && xmlhttp.readyState!=4)
		xmlhttp.Abort();
}

/* Carrega uma url e executa uma função ao terminar.
 * 
 * url:				Url que será carregada.
 * [stateObject]:	Objeto de estado do pedido.
 * [stateObject.onStart]:	Função que será executada no inicio do processo.
 * [stateObject.onLoad]:	Função que será executada ao término do recebimento. (stateObj,xmlResp).
 * [stateObject.onError]:	Função que será executada se ocorrer algum erro.
 * [stateObject.waitingEl]:	Elemento que será exibido até a operação estar concluída.
 * [postData]:		Dados que serão enviados para a url(POST). Se não informado indica GET.
 * [headers]:		Cabeçalhos do pedido.
 */
Ajax.OpenUrl = function (url,stateObject,postData,headers)
{
	// Obtém o request
	var xmlhttp = Ajax._getXmlHttp();

	if(xmlhttp.readyState == 0 || xmlhttp.readyState == 4)
	{
		if(!stateObject) stateObject = new Object();
		if(stateObject.onStart) stateObject.onStart();
		
		// Exibe o elemento de espera
		var waitingEl;
		if(stateObject.waitingEl)
		{
			waitingEl = stateObject.waitingEl;
			if(typeof(waitingEl)=="string")
				waitingEl = document.getElementById(waitingEl)
		}
		Ajax._showWait(waitingEl);

		// Abre o request
		if(!postData)
			xmlhttp.open("GET",url,true);
		else
		{
			xmlhttp.open("POST",url,true);
			xmlhttp.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
			xmlhttp.setRequestHeader('Content-Length',postData.length);
		}

		// Indica que é Ajax
		xmlhttp.setRequestHeader('Accept','application/xml');
		xmlhttp.setRequestHeader('Ajax','true');

		if(headers)
		{
			// Adiciona os headers
		}

		// Objeto de estado
		Ajax.stateObject = stateObject;

		// Evento de monitoramento
		xmlhttp.onreadystatechange = Ajax._stateChange

		// Envia o pedido
		xmlhttp.send(postData);
	}
}

// Obtém um formulário
Ajax._getForm = function(form)
{
	if(form)
	{
		if(typeof(form)=="string")
		{
			var _form = document.forms[form];
			if(!_form) _form = document.getElementById(form);
			if(_form)
				return _form;
		}
		else
			return form;
	}	
	return null;
}

/* Obtém os dados codificados de um formulário para envio.
 * 
 * form: Formulario do qual os dados serão extraídos.
 */
Ajax.GetFormData = function(form)
{
	form = Ajax._getForm(form);

	var data = null;
	var dataItem = null;

	// Obtém todos os elementos do form
	var fElements = form.elements;
	for(i=0;i< fElements.length;i++)
	{
		var el = fElements[i];
		
		if(Ajax._debug)
		{
			alert("Form element: "+el.nodeName);
			alert("Form element type: "+el.type);
			alert("Form element value: "+el.value);
			alert("Form element checked: "+el.checked);
		}

		// Verifica se tem um nome e se não está desabilitado
		if(el.name && el.name!="" && el.disabled!="true")
		{
			// Se for o campo do CKEditor, atualiza o conteúdo
			if(el.attributes["isCKEditor"])
			{
				if(el.updateElement)
					el.updateElement();
				else if(el.cke)
					el.cke.updateElement();
				else 
					alert('CKEditor: Não é possível obter o conteúdo / Cannot get content');
			}
			
			// Campos
			if(el.nodeName=="INPUT")
			{
				// Obtém o tipo do campo
				var elType = el.type;
				
				if(elType=="button" || elType=="submit" || elType=="reset")
				{
					// Não manda o valor se não foi quem enviou
					if(!el._isSubmit) continue;
				}
				else if(elType=="checkbox" || elType=="radio")
				{
					// Não manda o valor se não estiver checado
					if(el.checked!=true) continue;
				}
				
				// Adiciona o valor do campo
				dataItem = escape(el.name)+"="+escape(el.value);
			}
			else if(el.nodeName=="SELECT")
			{
				var values = "";
				var options = el.options;

				for (var o=0;o< options.length; o++)
				{
					var option = options[o];
					if(option.selected)
					{
						if(values!="") values+=",";
						values+= option.value;
						if(!el.multiple) break;
					}
				}
				dataItem = escape(el.name)+"="+escape(values);
			}
			else
				dataItem = escape(el.name)+"="+escape(el.value);
				
			// Adiciona os dados
			if(!data)
				data = dataItem;
			else
				data+= "&"+dataItem;
			
			if(Ajax._debug) alert("Form element data: "+dataItem);
		}
	}

	if(Ajax._debug) alert("Form data: "+data);

	return data;
}
/* * End Ajax * */

// Ocorre quando terminou de carregar uma resposta
function _ajaxOnLoadUrl(stateObj,xmlResp)
{
	if(Ajax._debug)
	{
		alert("ajaxOnLoadUrl: "+(xmlResp!=undefined));
		alert("destEl: "+stateObj.destEl);
		alert("destEl id: "+stateObj.destEl.id);
		alert("destEl Html: "+stateObj.destEl.innerHTML);
	}
	
	// Obtém a resposta
	if(xmlResp)
	{
		// Obtém a tag, deve retornar somente uma
		var nodes = xmlResp.getElementsByTagName('dpsAjax');
		if(nodes && nodes[0])
		{
			if(Ajax._debug)
			{
				alert("dpsAjax: "+nodes[0]);
				alert("dpsAjax childNodes length: "+nodes[0].childNodes.length);
			}

			// Procura o cdata nos filhos
			var nodes = nodes[0].childNodes;
			for(i=0;i< nodes.length;i++)
			{
				var node = nodes[i];
				
				if(Ajax._debug)
				{
					alert("dpsAjax child: "+node);
					alert("dpsAjax child nodeType: "+node.nodeType);
					alert("dpsAjax child data: "+node.data);
				}
				
				if(node.nodeType==4)
				{
					var destEl = stateObj.destEl;
					
					// Verifica se é para setar a nova posição
					if(Ajax.setScrollNewPos)
					{
						var elPos = Common.getPosition(destEl);
						if(elPos.top<0)
						{
							var sTop = destEl.offsetParent.scrollTop;
							if(sTop!=0)
								destEl.offsetParent.scrollTop += elPos.top-25;
							else
								window.scrollBy(0,elPos.top-25);
						}
					}
					
					// Insere o html no objeto
					destEl.innerHTML = node.data;
					break;
				}
			}
		}
		
		stateObj.onLoad = undefined;
		
		// Dispara o evento do usuário do objeto de estado
		if(stateObj && stateObj.userOnLoad)
			stateObj.userOnLoad();
	}
}

/* Carrega uma url via Ajax e insere seu conteúdo em um elemento.
 * 
 * url:						Url que será carregada.
 * destEl:					Elemento que receberá o conteúdo de resposta.
 * [stateObject]:			Objeto de estado do pedido.
 * [stateObject.onStart]:	Função que será executada no inicio do processo.
 * [stateObject.onLoad]:	Função que será executada ao término do recebimento.
 * [stateObject.waitingEl]:	Elemento que será exibido até a operação estar concluída.
 */
function LoadUrl(url,destEl,stateObject)
{
	// Obtém o request
	var xmlhttp = Ajax._getXmlHttp();

	// Verifica se pode enviar (aberto=0 ou pronto=4)
	if(xmlhttp.readyState == 0 || xmlhttp.readyState == 4)
	{
		if(Ajax._debug) alert("LoadUrl Url: "+url);
		
		// Se não tem o objeto de estado, cria
		if(!stateObject) stateObject = new Object();
		
		// Dispara o evento de inicio
		if(stateObject.onStart) stateObject.onStart();
		
		// Obtém o elemento de destino
		if(destEl)
		{
			if(typeof(destEl)=="string") destEl = document.getElementById(destEl);
			if(!destEl) alert('Elemento de destino não encontrado!');
		}
		else alert('Elemento de destino não informado!');

		// Exibe o elemento de espera
		var waitingEl;
		if(stateObject.waitingEl)
		{
			waitingEl = stateObject.waitingEl;
			if(typeof(waitingEl)=="string")
				waitingEl = document.getElementById(waitingEl)
		}
		Ajax._showWait(waitingEl);

		// Abre o request 
		xmlhttp.open("GET",url,true);
		
		// Seta os headers para indicar que é ajax
		xmlhttp.setRequestHeader('Accept','application/xml');
		xmlhttp.setRequestHeader('Ajax','true');
		if(stateObject && stateObject.cropControl)
			xmlhttp.setRequestHeader('Ajax_El',stateObject.cropControl);
		else if(destEl.id)
			xmlhttp.setRequestHeader('Ajax_El',destEl.id);
		
		// Objeto de estado
		Ajax.stateObject = stateObject;
		stateObject.destEl = destEl;
		
		// Adiciona o evento mantendo o evento do usuário
		if(stateObject.onLoad)
			stateObject.userOnLoad = stateObject.onLoad;
		stateObject.onLoad = _ajaxOnLoadUrl;
		
		// Evento de monitoramento
		xmlhttp.onreadystatechange = Ajax._stateChange;

		// Envia o pedido
		xmlhttp.send(null);
	}
}

/* Carrega um link via Ajax e insere seu conteúdo em um elemento.
 * 
 * anchor:					Link que será carregado.
 * [destEl]:				Elemento que receberá o conteúdo de resposta, se não informado será usado o valor de target.
 * [stateObject]:			Objeto de estado do pedido.
 * [stateObject.onLoad]:	Função que será executada ao término do recebimento.
 * [stateObject.waitingEl]:	Elemento que será exibido até a operação estar concluída.
 */
function LoadLink(anchor,destEl,stateObject)
{
	// Se for string, obtém o objeto pelo id
	if(typeof(anchor)=="string") anchor = document.getElementById(anchor);
	if(!destEl) destEl = anchor.target;
	
	LoadUrl(anchor.href,destEl,stateObject)
	
	// Retorna falso para parar a ação
	return false;
}

/* Envia os dados de um formulário via Ajax e insere a resposta em um elemento.
 * 
 * form:					Formulário de onde os dados serão obtidos.
 * destEl:					Elemento que receberá o conteúdo de resposta.
 * [stateObject]:			Objeto de estado do pedido.
 * [stateObject.onLoad]:	Função que será executada ao término do recebimento.
 * [stateObject.waitingEl]:	Elemento que será exibido até a operação estar concluída.
 */
function SendForm(form,destEl,stateObject)
{	
	// Obtém o request
	var xmlhttp = Ajax._getXmlHttp();

	// Verifica se pode enviar (aberto=0 ou pronto=4)
	if(xmlhttp.readyState == 0 || xmlhttp.readyState == 4)
	{
		if(Ajax._debug) alert("SendForm: "+form);
		
		// Cria o objeto de estado se não existir
		if(!stateObject) stateObject = new Object();
		
		// Dispara o evento de inicio
		if(stateObject.onStart) stateObject.onStart();
	
		// Obtém o elemento de destino
		if(destEl)
		{
			if(typeof(destEl)=="string") destEl = document.getElementById(destEl);
			if(!destEl) alert('Elemento de destino não encontrado!');
		}
		else alert('Elemento de destino não informado!');

		// Exibe o elemento de espera
		var waitingEl;
		if(stateObject.waitingEl)
		{
			waitingEl = stateObject.waitingEl;
			if(typeof(waitingEl)=="string")
				waitingEl = document.getElementById(waitingEl)
		}
		Ajax._showWait(waitingEl);

		form = Ajax._getForm(form);
		var url = form.action;
		var method = form.method;

		// Seta os valores que não foram informados
		if(!url) url = window.location.href;
		if(!method) method = "POST"; else method = method.toUpperCase();

		// Obtém os dados do formulario
		var data = Ajax.GetFormData(form);

		if(Ajax._debug)
		{
			alert("SendForm");
			alert("Form id: "+form.id);
			alert("Form name: "+form.name);
			alert("Form action: "+url+" - "+typeof(url));
			alert("Form method: "+method+" - "+typeof(method));
			alert("Form Data: "+data);
		}

		var isPost = (method=="POST");

		// Se não for post, adiciona os dados na url
		if(!isPost)
		{
			// Verifica se já tem query
			if(url.indexOf("?")>=0)
				data="&"+data;
			else
				data="?"+data;

			// Verifica se tem hash
			if(url.indexOf("#")>=0)
				url.replace("#",data+"#");
			else
				// Adiciona na url
				url+=data;
		}

		// Objeto de estado
		Ajax.stateObject = stateObject;
		stateObject.destEl = destEl;

		// Adiciona o evento mantendo o evento do usuário
		if(stateObject.onLoad)
			stateObject.userOnLoad = stateObject.onLoad;
		stateObject.onLoad = _ajaxOnLoadUrl;

		// Abre o request
		xmlhttp.open(method,url,true);
		if(Ajax._debug) alert("Open url: "+url);

		// Seta os headers para indicar que é ajax
		xmlhttp.setRequestHeader('Accept','application/xml');
		xmlhttp.setRequestHeader('Ajax','true');
		if(stateObject && stateObject.cropControl)
			xmlhttp.setRequestHeader('Ajax_El',stateObject.cropControl);
		else if(destEl.id)
			xmlhttp.setRequestHeader('Ajax_El',destEl.id)

		// Evento de monitoramento
		xmlhttp.onreadystatechange = Ajax._stateChange;

		if(isPost)
		{
			// Se for post, adiciona os headers
			xmlhttp.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
			xmlhttp.setRequestHeader('Content-Length', data.length);
			
			// Envia o pedido com os dados
			xmlhttp.send(data);
		}
		else
			// Se for get, envia o pedido sem os dados
			xmlhttp.send(null);
	}

	// Retorna falso para parar a ação
	return false;
}

/* Envia os dados de um formulário via Ajax indicando qual o botão e insere a resposta em um elemento.
 * 
 * submit:			Botão que enviou os dados do formulário.
 * destEl:			Elemento que receberá o conteúdo de resposta
 * [stateObject]:			Objeto de estado do pedido.
 * [stateObject.onLoad]:	Função que será executada ao término do recebimento.
 * [stateObject.waitingEl]:	Elemento que será exibido até a operação estar concluída.
 */
function SubmitForm(submit,destEl,stateObject)
{
	// Se for string, obtém o objeto pelo nome ou pelo id
	if(typeof(submit)=="string")
	{
		var oSubmit = document.getElementsByName(submit);
		if(oSubmit && oSubmit[0]) submit = oSubmit[0];
		else submit = document.getElementById(submit);
	}
	
	// Indica que foi esse botão que enviou
	submit._isSubmit = true;
	
	SendForm(submit.form,destEl,stateObject);
	
	// Retorna falso para parar a ação
	return false;
}



/* * MsgBox * *
 *
 * Cria uma caixa de mensagens.
 *
 * title:	Título do alerta.
 * message:	Mensagem do alerta.
 * [width]:	Tamanho da caixa de alerta.
 */
function MsgBox(title,message,width)
{
	var oBody = document.body;
	if(oBody)
	{
		// Cria os divs
		var divMain = document.createElement("div");
		var divContent = document.createElement("div");
		var divTitle = document.createElement("div");
		var divMsg = document.createElement("div");
		var divButtons = document.createElement("div");
		var divBack = document.createElement("div");

		// Adiciona os styles
		// divMain
		var style = divMain.style;
		style.position = "fixed";
		style.top = "50%";
		style.left = "50%";
		style.height = "100px";
		if(!width)
		{
			style.minWidth = "250px";
			style.maxWidth = "500px";
		}
		else
			style.width = width;

		// divContent
		style = divContent.style;
		style.position = "relative";
		style.top = "-50%";
		style.left = "-50%";
		style.border = "1px solid #DD7700";
		style.backgroundColor = "white";
		style.width = "100%";

		// divTitle
		style = divTitle.style;
		style.padding = "3px";
		style.backgroundColor = "#FF9900";
		style.color = "white";
		style.fontWeight = "bold";

		// divMsg
		style = divMsg.style;
		style.padding = "5px";

		// divButtons
		style = divButtons.style;
		style.textAlign = "center";
		style.width = "100%";

		// divBack
		style = divBack.style;
		style.position = "fixed";
		style.top = "0px";
		style.left = "0px";
		style.width = "100%";
		style.height = "100%";
		style.backgroundColor = "black";
		style.filter = "alpha(opacity=75)";// IE
		style.opacity = "0.75"; // FF
		style.MozOpacity = "0.75"; // NS
		
		// Adiciona os textos
		divTitle.innerHTML = title;
		divMsg.innerHTML = message;

		// Guarda os divs
		this.divButtons = divButtons;
		this.divMain = divMain;

		// Adiciona na hierarquia
		divContent.appendChild(divTitle);
		divContent.appendChild(divMsg);
		divContent.appendChild(divButtons);

		divMain.appendChild(divBack);
		divMain.appendChild(divContent);
		
		// Adiciona o elemento no corpo se a página carregou
		if(Common.isLoaded)
			oBody.appendChild(divMain);
		else
		{
			// Adiciona o evento para inserir o elemento
			MsgBox.divMain = divMain;
			Common.addEvent(window,'load',function(){document.body.appendChild(MsgBox.divMain);},'onload');			
		}

		return;
	}
	
	alert("Não é possível criar MsgBox, veja a sintaxe correta de HTML./Cannot create MsgBox, see the correct HTML syntax.");
	alert(message);
}

/* Fecha o alerta.
 */
MsgBox.prototype.Close = function(ev)
{
	var main;
	if(this.divMain)
		main = this.divMain;
	else if(ev && ev.srcElement) // IE
		main = ev.srcElement.divMain;
	else if(ev && ev.target) // FF
		main = ev.target.divMain;

	main.style.display = "none";
	var oBody = document.body;
	if(oBody)
		oBody.removeChild(main);
}

/* Adiciona um botão com uma determinada ação.
 *
 * name: Nome do botão.
 * func: Função que será executada ao clicar.
 */
MsgBox.prototype.AddButton = function(name,func)
{
	// Cria o botão
	var input = document.createElement("input");
	input.type = "button";
	input.value = name;
	input.style.margin = "5px"

	input.divMain = this.divMain;

	// Adiciona o evento separadamente pois a ordem de execução muda para cada navegador.
	// Deve executar primeiro a função do usuário

	// Adiciona o evento para fechar
	if(input.attachEvent) // IE
		input.attachEvent('onclick', this.Close);

	if(func)
		// Adiciona o evento do usuário
		Common.addEvent(input,'click',func);

	// Adiciona o evento para fechar
	if(input.addEventListener) // FF
		input.addEventListener('click', this.Close, false); 

	// Adiciona
	this.divButtons.appendChild(input);
}
/* * Fim MsgBox * */


/* Exibe um alerta com o botão Ok.
 *
 * title:	Título do alerta.
 * msg:		Mensagem do alerta.
 */
function AlertOk(title,msg)
{
	msg = new MsgBox(title,msg);
	msg.AddButton("Ok");
}

/* Exibe o alerta com os botões sim e não.
 *
 * title:	Título do alerta.
 * msg:		Mensagem do alerta.
 * yesFunc:	Função que será executada ao clicar em sim.
 * noFunc:	Função que será executada ao clicar em não.
 */
function AlertYesNo(title,msg,yesFunc,noFunc)
{
	msg = new MsgBox(title,msg);
	msg.AddButton("Sim",yesFunc);
	msg.AddButton("Não",noFunc);
}



/* * AnimationSet * *
 *
 * Cria animações para um ou mais elementos.
 *
 * stateObj: Objeto de estado compartilhado entre várias animações ou o próprio elemento que será animado.
 */
function AnimationSet(stateObj)
{
	if(stateObj)
		this.stateObj = stateObj;
	else
		this.stateObj = new Object();
		
	this._run = false;
	this._animList = new Array();
}

AnimationSet._mspf = Math.floor(1000/30); // Milisegundos por frame

/* Adiciona uma animação.
 *
 * startValue:		Valor de inicio.
 * endValue:		Valor de fim.
 * duration:		Tempo(segundos) total de duração.
 * startDelay:		Tempo(segundos) de espera para inicio.
 * acceleration:	Taxa de aceleração.
 * updFunc:			Função para atualizar o valor de um atributo do elemento updFunc(stateObj, currValue).
 */
AnimationSet.prototype.AddAnimation = function(startValue,endValue,duration,startDelay,acceleration,updFunc)
{
	var durationMs = duration*1000;
	var dist = endValue-startValue;
	var distMs = dist/durationMs; // Distância por milisegundo
	
	// Verifica se é para calcular a aceleração
	if(acceleration!=0)
	{
		// Aumenta a velocidade pela taxa de aceleração
		distMs = distMs*(1+(Math.abs(acceleration)/100));

		var accEndValue = endValue-((distMs*durationMs)-dist); // Novo fim
		var accDurationMs = Math.floor((accEndValue-startValue)/distMs); // Nova duração
		var accelerationMs =  distMs/(durationMs-accDurationMs) // Aceleração
	}
	
	// Cria o objeto de animação com os valores e adiciona na lista
	this._animList.push({
				startValue: startValue
				,endValue: endValue
				,durationMs: durationMs
				,startDelayMs: startDelay*1000 // Converte para milisegundos
				,acceleration: acceleration
				,distMs: distMs
				,accEndValue: accEndValue
				,accEndValueDelta: endValue-accEndValue
				,accDurationMs: accDurationMs
				,accDurationMsDelta: durationMs-accDurationMs
				,accelerationMs: accelerationMs
				,updFunc: updFunc
				,done: false
				,hasDelay: startDelay>0
			});
}

// Obtém os milisegundos atuais
AnimationSet._getCurrMs = function()
{
	return new Date().getTime();
}

// Processa as animações
AnimationSet._doAnimation = function(animSet)
{
	var animList = animSet._animList;
	var doStop = true;

	for(var i=0;i<animList.length;i++)
	{
		// Obtém a animação e verifica se terminou
		var anim = animList[i];
		if(!anim.done)
		{
			doStop = false;

			// Seta o milisegundo de inicio
			if(!anim.startMs)
				anim.startMs = AnimationSet._getCurrMs();

			// Verifica o tempo de espera
			if(anim.hasDelay)
			{
				if((AnimationSet._getCurrMs() - anim.startMs)<=anim.startDelay)
					continue;
				else
					anim.startMs+= anim.startDelay;
				anim.hasDelay = false;
			}

			// Calcula o tempo decorrido
			var interval = AnimationSet._getCurrMs() - anim.startMs;
			var currVal;

			// Verifica se acabou
			if(interval>anim.durationMs)
			{
				currVal = anim.endValue;
				anim.done = true;
			}
			else
			{
				// Verifica se possue aceleração
				var acceleration = anim.acceleration;
				if(acceleration<0 && interval>anim.accDurationMs) // Aceleração negativa (desaceleração)
				{
					// Calcula o valor atual com desaceleração
					var accMs = anim.accelerationMs;
					var accDistMs = anim.distMs-(accMs*(interval-anim.accDurationMs));
					var accVal = (Math.pow(anim.distMs,2)-Math.pow(accDistMs,2))/(2*accMs);
					currVal = anim.accEndValue + accVal;
				}
				else if(acceleration>0) // Aceleração
				{
					if(interval<anim.accDurationMsDelta)
					{
						// Calcula o valor atual com aceleração
						var accMs = anim.accelerationMs;
						var accDistMs = accMs*interval;
						var accVal = (Math.pow(accDistMs,2))/(2*accMs);
						currVal = anim.startValue + accVal;
					}
					else
						currVal = anim.startValue + (interval * anim.distMs) - anim.accEndValueDelta;
				}
				else // Sem aceleração
				{
					// Calcula o valor atual sem aceleração
					currVal = anim.startValue + (interval * anim.distMs);
				}
			}

			// Chama a função de atualização
			anim.updFunc(animSet.stateObj,currVal);
		}
	}

	if(doStop) animSet.Stop();
}

/* Inicia a animação.
 */
AnimationSet.prototype.Start = function()
{
	// Verifica se já está rodando
	if(this._run) return;

	// Cria a função para chamar as animações
	var funcAnim = function(){ ;
		AnimationSet._doAnimation(funcAnim.animSet) ;
	};
	funcAnim.animSet = this;

	// Inicia as animações
	if(!this._timer)
		this._timer = window.setInterval(funcAnim,AnimationSet._mspf);

	this._run = true;
}

/* Para a animação.
 */
AnimationSet.prototype.Stop = function()
{
	if(this._run)
	{
		// Para o timer
		if(this._timer)
		{
			window.clearInterval(this._timer);
			this._timer = undefined;
		}
		this._run = false;

		// Dispara a função de término se existir
		if(this.onStop)
			this.onStop(this);
	}
}

/* Para a animação e volta para o estado original.
 */
AnimationSet.prototype.StopAndReset = function()
{
	this.Stop();

	// Passa por cada animação e reseta
	var animList = this._animList;
	for(var i=0;i<animList.length;i++)
	{
		var anim = animList[i];
		anim.done = false;
		anim.startMs = undefined;
		anim.hasDelay = anim.startDelayMs>0;
	}
}



/* * PostData * *
 *
 * Cria um objeto para postar valores nomeados.
 *
 * [formEl]:	Elemento, id ou nome do formulário que será usado para enviar os dados
 */
function PostData(formEl)
{
	// Obtém o form
	var form;
	if(formEl)
	{
		if(typeof(formEl)=="string")
		{
			var form = document.getElementById(formEl);
			if(!form)
				form = document.forms[formEl];

			if(form && form.submit)
			{
				this._form = form;
				return;
			}
		}
		else if(formEl.submit)
		{
			this._form = formEl;
			return;
		}
	}
	else
	{
		var form = document.createElement("FORM");
		form.method = "POST";
		var oBody = document.body;
		if(oBody)
			oBody.appendChild(form);

		this._form = form;
		return;
	}
	
	alert("Form '"+formEl+"' not found, invalid or not unique!");
}

/* Seta a ação para enviar os dados
 *
 * action:	Caminho(Url) para onde enviar os dados
 */
PostData.prototype.SetAction = function(action)
{
	this._form.action = action;
}

/* Adiciona um valor nomeado que será enviado
 *
 * name:	Nome
 * value:	Valor
 */
PostData.prototype.AddValue = function (name,value)
{
	var input;
	
	// Verifica se o elemento já existe
	var inputs = this._form.getElementsByTagName("input");
	for(i=0;i<inputs.length;i++)
	{
		if(inputs[i].name == name)
		{
			input = inputs[i];
			break; 
		}
	}
	
	if(!input)
	{
		// Cria o elemento
		input = document.createElement("INPUT");
		input.type = "hidden";
		input.name = name;
		input.value = value;
		
		// Adiciona no form
		this._form.appendChild(input);
	}
	else
		input.value = value;
		
	return this;
}

/* Envia os dados
 */
PostData.prototype.Submit = function ()
{
	this._form.submit();
}

/* Envia os dados via Ajax
 *
 * destEl: Elemento que receberá o conteúdo de resposta
 * [waitingEl]: Elemento que será exibido até a operação estar concluída.
 */
PostData.prototype.SubmitAjax = function (destEl,waitingEl)
{
	SendForm(this._form,destEl,waitingEl);
}

/* * Fim PostData * */


/* Posta um valor nomeado
 *
 * name:		Nome do valor
 * value:		Valor
 * [formEl]:	Formulário que será usado para enviar o valor
 * [action]:	Caminho(Url) para onde enviar os dados
 */
function PostValue(name,value,formEl,action)
{
	dPost = new PostData(formEl);
	if(action) dPost.SetAction(action);
	dPost.AddValue(name,value);
	dPost.Submit();
}

/* Posta um valor nomeado via Ajax
 *
 * name:		Nome do valor
 * value:		Valor
 * destEl:		Elemento que receberá o conteúdo de resposta
 * [formEl]:	Formulário que será usado para enviar o valor
 * [action]:	Caminho(Url) para onde enviar os dados
 * [waitingEl]: Elemento que será exibido até a operação estar concluída
 */
function SendFormValue(name,value,destEl,formEl,action,waitingEl)
{
	dPost = new PostData(formEl);
	if(action) dPost.SetAction(action);
	dPost.AddValue(name,value);
	dPost.SubmitAjax(destEl,waitingEl);
}



// Funções auxiliares para input
var inputHelperFunctions = new Object();

// Inicializa
inputHelperFunctions.init = function()
{
	// Obtém todos os inputs da página
	var inputs = document.getElementsByTagName("input");
	for (var i=0;i<inputs.length;i++)
	{
		var input = inputs[i];

		// Verifica se os inputs são do tipo text
		if (input.type=="text")
		{
			// Inicializa cada input
			inputHelperFunctions.initValueTip(input);
			inputHelperFunctions.initFillMask(input);
		}
	}
}
Common.addEvent(window,'load',inputHelperFunctions.init,'onload');

/* * ValueTip * *
 *
 *		Atributos
 *			valueTip: Valor que será exibido como dica
 *
 */
inputHelperFunctions.initValueTip = function(input)
{
	// Verifica se tem o atributo valueTip
	if (input.attributes["valueTip"] && !input._valueTip)
	{
		input._valueTip = input.attributes["valueTip"].value;
		input.value = input._valueTip;

		//Função focus para apagar o value do input
		var funcfocus = function()
		{
			var input = arguments.callee.input;
			if (input.value==input._valueTip)
				input.value="";
		};
		funcfocus.input = input;

		//Função blur para devolver o value do input
		var funcblur = function()
		{
			var input = arguments.callee.input;
			if (input.value=="")
				input.value=input._valueTip;
		};
		funcblur.input = input;

		Common.addEvent(input,'focus',funcfocus,'onfocus');
		Common.addEvent(input,'blur',funcblur,'onblur');
	}
}

/* * FillMask * *
 *
 *		Atributos 
 *			fillMask: Máscara (0=dígito,#=dígito opcional,A=Letra)
 *			fillMaskRemoveOnBlur: Indica para remover a máscara após o preenchimento
 *			fillMaskDir: Direção de preenchimento
 *			fillMaskPlaceHolderChar: Caractere que indica lugar para ser preenchido
 *
 */
inputHelperFunctions.initFillMask = function(input)
{
	// Verifica se tem o atributo valueTip
	if (input.attributes["fillMask"] && !input.__fillMask)
	{
		// Prepara as propriedades
		input.__fillMask = input.attributes["fillMask"].value;
		if(input.attributes["fillMaskRemoveOnBlur"])
			input.__fillMaskRemoveOnBlur = input.attributes["fillMaskRemoveOnBlur"].value=="true";
		else
			input.__fillMaskRemoveOnBlur = false;
		if(input.attributes["fillMaskDir"])
			input.__fillMaskDir = input.attributes["fillMaskDir"].value;
		else
			input.__fillMaskDir = "ltr";
		if(input.attributes["fillMaskPlaceHolderChar"])
			input.__fillMaskPlaceHolderChar = input.attributes["fillMaskPlaceHolderChar"].value;
		else
			input.__fillMaskPlaceHolderChar = "_";
		
		input.maxLength = input.__fillMask.length;
		input.dir = input.__fillMaskDir;

		// Adiciona os eventos
		Common.addEvent(input,'focus',inputHelperFunctions.fillMaskFocus_KeyUp,'onfocus');
		Common.addEvent(input,'keyup',inputHelperFunctions.fillMaskFocus_KeyUp,'onkeyup');
		Common.addEvent(input,'blur',inputHelperFunctions.fillMaskBlur,'onblur');

		// Aplica a máscara
		if(!input.__fillMaskRemoveOnBlur)
			inputHelperFunctions.fillMaskApply(input);
	}
}

// Aplica a máscara
inputHelperFunctions.fillMaskApply = function(input)
{
	var maskedValue = "";
	
	// Obtém o valor atual
	var currValue = input.value;
	if(!currValue) currValue = "";

	// Obtém a máscara interpretada
	var mask = input.__fillMask;
	var maskSlides = input.__fillMaskSlides;
	if(!maskSlides)
	{
		var sIdx = 0;
		maskSlides = new Array();

		input.__fillMaskSlides = maskSlides;

		// Interpreta a máscara Ex: 00/00/0000 -> 00,/,00,/,0000
		var lastCh = mask.charAt(0);/// adiciona o primeiro char
		maskSlides[sIdx] = lastCh;

		for(var i=1;i<mask.length;i++)
		{
			var ch = mask.charAt(i);
			
			// Verifica se precisa adicionar outro nível
			if(!((ch=='#' && lastCh=='#') 
					|| (ch=='0' && (lastCh=='0' || lastCh=='#'))
					|| (ch=='A' && lastCh=='A')))
				sIdx++;

			// Adiciona
			if(!maskSlides[sIdx])
				maskSlides[sIdx] = ch;
			else
				maskSlides[sIdx]+= ch;

			lastCh = ch;
		}
	}
	
	var sVal;
	var vPos = 0;
	var cM = 0;
	for(;cM<maskSlides.length;cM++)
	{
		// Obtém os caracteres do valor referentes a posição da máscara
		var sMask = maskSlides[cM];
		var sValue = currValue.substr(vPos,sMask.length);
		if(!sValue) break;

		sVal = "";
		var isValid = true;
		
		// Verifica se é o último valor da máscara
		var lastMaskVal;
		if(lastMaskVal)
		{
			if(lastMaskVal==sValue)
			{
				isValid = false;
				break;
			}
			lastMaskVal = null;
		}

		if(sMask.charAt(0)=='#' || sMask.charAt(0)=='0')// Digito
		{
			for(var i=0;i<sValue.length;i++)
			{
				var vCh = sValue.charAt(i);
				var cCode = sValue.charCodeAt(i);

				// Verifica se é um dígito, se for adiciona
				if(cCode>=48 && cCode<=57)
					sVal+= vCh;
				else
				{
					// Verifica se o caracter está na máscara
					var nextSMask = maskSlides[cM+1];
					if(nextSMask==vCh)
					{
						// Se sim, completa com os dígitos requeridos
						var qtDig=0;
						for(var j=0;j<sMask.length;j++)
							if(sMask.charAt(j)=='0') qtDig++;

						while(sVal.length<qtDig)
							sVal = "0"+sVal;
					}
					else
						isValid = false;

					break;
				}
			}
		}
		else if(sMask.charAt(0)=='A') // Letra
		{
			for(var i=0;i<sValue.length;i++)
			{
				var vCh = sValue.charAt(i);
				var cCode = sValue.charCodeAt(i);

				// Verifica se é um dígito, se for adiciona
				if((cCode>=65 && cCode<=90) || (cCode>=97 && cCode<=122))
					sVal+= vCh;
				else
				{
					isValid = false;
					break;
				}
			}
		}
		else if(sMask==sValue) // Verifica se é o mesmo charactere da máscara
		{
			sVal = sValue;
			lastMaskVal = sValue;
		}
		else
		{
			// Adiciona a máscara e tenta continuar a validação
			maskedValue+=sMask;
			continue;
		}

		// Adiciona o valor e avança
		maskedValue+= sVal;
		vPos+= sVal.length;

		// Se não for válido, pára
		if(!isValid) break;

		// Verifica se ainda pode ler caracteres do valor
		if(vPos>=currValue.length) break;
	}

	// Adiciona o próximo caractere da máscara se não for dígito ou letra
	if(maskSlides[cM] && sVal)
	{
		// Conta o total de dígitos opcionais
		sMask = maskSlides[cM];
		var qtDig=0;
		for(var i=0;i<sMask.length;i++)
			if(sMask[i]=='#') qtDig++;

		if(sVal.length==sMask.length-qtDig)
		{
			var mCh = maskSlides[cM+1];
			if(mCh && (mCh[0]!='0' && mCh[0]!='#' && mCh[0]!='A'))
			{
				maskedValue+= mCh;
			}
		}
	}

	// Se passar do tamanho, recorta
	if(maskedValue.length>mask.length)
		maskedValue = maskedValue.substr(0,mask.length);

	// Adiciona o valor com a máscara
	input.value = maskedValue;
}

inputHelperFunctions.fillMaskFocus_KeyUp = function(ev)
{
	// Se for o backspace, não faz nada
	if(ev.keyCode && ev.keyCode==8) return;
	// Obtém o input que disparou o evento
	var input = ev.currentTarget;
	if(!input) input = ev.srcElement;

	inputHelperFunctions.fillMaskApply(input);
}

inputHelperFunctions.fillMaskBlur = function(ev)
{
	// Obtém o input que disparou o evento
	var input = ev.currentTarget;
	if(!input) input = ev.srcElement;

	// Remove os placeholders do valor
	if(input.__fillMaskRemoveOnBlur)
	{
		// Obtém o valor atual e a máscara
		var currValue = input.value;
		if(!currValue) currValue = "";
		var mask = input.__fillMask;

		var maskedValue = "";
		for(var i=0;i<currValue.length;i++)
		{
			var mCh = mask.charAt(i);
			var vCh = currValue.charAt(i);

			if(mCh=="0" || mCh=="#" || mCh=="A")
				maskedValue+= vCh;
		}
		
		// Adiciona o valor sem máscara
		input.value = maskedValue;
	}
}


