/**
 * @author Márcio d'Ávila
 * @version 1.8, 2004-2005
 *
 */

c_HINT_TEXT = "Digite aqui";

/**
 * Construtor da classe CrossEvent.
 */
function CrossEvent(evt)
{
	evt = evt? evt: (window.event? window.event: null);
	if (evt)
	{
		this.originalEvent = evt;
		this.type = evt.type;
		this.screenX = evt.screenX;
		this.screenY = evt.screenY;

		// IE: srcElement
		this.target = evt.target? evt.target: evt.srcElement;

		// N4: modifiers
		if (evt.modifiers)
		{
			this.altKey   = evt.modifiers & Event.ALT_MASK;
			this.ctrlKey  = evt.modifiers & Event.CONTROL_MASK;
			this.shiftKey = evt.modifiers & Event.SHIFT_MASK;
			this.metaKey  = evt.modifiers & Event.META_MASK;
		}
		else
		{
			this.altKey   = evt.altKey;
			this.ctrlKey  = evt.ctrlKey;
			this.shiftKey = evt.shiftKey;
			this.metaKey  = evt.metaKey;
		}

		// N4: which // N6+: charCode
		this.charCode = !isNaN(evt.charCode)? evt.charCode: !isNaN(evt.keyCode)? evt.keyCode: evt.which;
		this.keyCode = !isNaN(evt.keyCode)? evt.keyCode: evt.which;
		this.button = !isNaN(evt.button)? evt.button: !isNaN(evt.which)? evt.which-1: null;
		this.debug = "c:" + evt.charCode + " k:" + evt.keyCode
			+ " b:" + evt.button + " w:" + evt.which;
	}
} // CrossEvent


/**
 * Adiciona metodo lpad() aa classe String.
 * Preenche a String aa esquerda com o caractere fornecido,
 * ate que ela atinja o tamanho especificado.
 */
String.prototype.lpad = function(pSize, pCharPad)
{
	var str = this;
	var dif = pSize - str.length;
	var ch = String(pCharPad).charAt(0);
	for (; dif>0; dif--) str = ch + str;
	return (str);
} //String.lpad


/**
 * Adiciona metodo trim() aa classe String.
 * Elimina brancos no inicio e fim da String.
 */
String.prototype.trim = function()
{
	return this.replace(/^\s*/, "").replace(/\s*$/, "");
} //String.trim


/**
 * Elimina caracteres de formatacao e zeros aa esquerda da string
 * de numero fornecida.
 * @param String pNum
 * 	String de numero fornecida para ser desformatada.
 * @return String de numero desformatada.
 */
function unformatNumber(pNum)
{
	return String(pNum).replace(/\D/g, "").replace(/^0+/, "");
} //unformatNumber


/**
 * Formatos: #*.####,#* ou
 * @param pHasGroup
 *	Indica o uso ou não de separador de grupo (milhar). Default false.
 */
function formatNumber(pNum, pHasGroup, pDecimals)
{
	var sepDec = ",";
	var sepGrp = ".";
	var strNum = unformatNumber(pNum);
	var nDec = pDecimals? pDecimals: 0;
	nDec = Math.min(nDec, strNum.length);
	var nInt = strNum.length - nDec;
	var i = 0;
	var result = "";
	if (nInt > 0)
		if (pHasGroup == true)
		{
			i = nInt % 3;
			if (i == 0) i = 3;
			result = strNum.substring(0, i);
			while (i < nInt)
			{
				result += sepGrp + strNum.substring(i, i+3);
				i += 3;
			}
		}
		else
		{
			result = strNum.substring(0, nInt);
		}

	if (nDec > 0)
	{
		if (result == "") result = "0";
		result += sepDec + strNum.substring(i, strNum.length);
	}
	return result;
} // formatNumber


/**
 *
 */
function formatDate(pDat)
{
	var strNum = unformatNumber(pDat);;
	if (pDat.charAt(0) == '0') strNum = "0" + strNum;

	var result = strNum.substring(0, 2); // dia
	if (strNum.length > 1)
	{
		result += "/" + strNum.substring(2, 4); // mes
		if (strNum.length > 3)
			result += "/" + strNum.substring(4); // ano
	}
	return result;
} // formatDate


/**
 *
 */
function checkDate(pStr, pCharCode)
{
	// 48 a 57: '0' a '9'
	// 0: Mozilla, teclas funcionais/especiais/não-textuais
	if (pCharCode < 48 && pCharCode != 0 || pCharCode > 57)
		return false;

	var dgts = unformatNumber(pStr + String.fromCharCode(pCharCode));
	if (dgts.length == 0) return true;
	if (dgts.length == 1 && dgts > 3) return false;

	if (dgts.length > 1)
	{
		var dia = dgts.substring(0, 2);
		if (isNaN(dia) || dia == 0 || dia > 31) return false;
		if (dgts.length == 3 && dgts.substring(2, 3) > 1) return false;

		if (dgts.length > 3)
		{
			var reDiaMes = /^((0[1-9]|[12]\d)(0[1-9]|1[0-2])|30(0[13-9]|1[0-2])|31(0[13578]|1[02]))$/;
			return (reDiaMes.test(dgts.substring(0, 4)));
		}
	}
	return true;
} // checkDate


function autoSkip(pObj, pKey, pLoop)
{
	// Processa apenas se o objeto fornecido é um INPUT TEXT
	if (! pObj.form || ! pObj.type || pObj.type != "text")
	{
		return false;
	}

	if (pObj.value.length >= pObj.maxLength && (pKey > 47 || pKey == 32))
	{
		var form = pObj.form;
		for(var i = 0; i < form.elements.length; ++i)
		{
			if (form.elements[i] == pObj)
				break;
		}
		var next = (i + 1) % form.elements.length;
		if (! pLoop && next == 0)
			return false;
		while (form.elements[next].disabled || form.elements[next].type == "hidden")
		{
			next = (next + 1) % form.elements.length;
			if (! pLoop && next == 0)
				return false;
		}

		form.elements[next].focus();
		return true;
	}
	return false;
} // autoSkip


//----------------------------------------------------------------------//


/**
 * Trata o evento keyUp e processa o autoSkip() de um campo texto de formulário.
 *
 * @return boolean
 *	Retorna sempre TRUE, confirmando o evento.
 * @param Event pEvent
 *	Object "event", com o evento que disparou a chamada deste método no campo.
 * @param Object pThis
 *	[Opcional] Objeto "this", correspondente ao campo que originou o evento.
 *  Se não for fornecido, é assumido event.target.
 * @param boolean pLoop
 *	[Opcional] Indica se a navegação para o próximo campo deve ser cíclica:
 *  navegar para o primeiro campo do formulário ao sair do último (TRUE).
 *	Se não for fornecido, é assumido FALSE.
 */
function mudaCampo(pEvent, pThis, pLoop)
{
	return doKeyUpSkip(pEvent, pThis, pLoop);
} // mudaCampo

function doKeyUpSkip(pEvent, pThis, pLoop)
{
	var evt = (pEvent? pEvent: window.event);
	if (!evt) return false;
	var evt = new CrossEvent(pEvent);
	var input = (pThis? pThis: evt.target);

	autoSkip(input, evt.keyCode, pLoop);
	return true;
} // doKeyUpSkip


/*
 *
 */
function doKeyPressDigits(pEvent, pThis)
{
	var evt = (pEvent? pEvent: window.event);
	if (!evt) return false;
	var evt = new CrossEvent(pEvent);
	var input = (pThis? pThis: evt.target);

	// 48 a 57: '0' a '9'
	// 13: Enter, necessário para submit no IE
	// 0: teclas funcionais/especiais não-texto, no Mozilla
	return (evt.charCode >= 48 && evt.charCode <= 57 || evt.charCode == 13 || evt.charCode == 0);
} // doKeyPressDigits


/**
 *
 */
function doKeyUpNumber(pEvent, pThis, pHasGroup)
{
	var evt = (pEvent? pEvent: window.event);
	if (!evt) return false;
	evt = new CrossEvent(pEvent);
	var input = (pThis? pThis: evt.target);

	var fmt = formatNumber(input.value, pHasGroup);
	if (input.value != fmt) input.value = fmt;
	return true;
} // doKeyUpNumber


/**
 *
 */
function doKeyPressDate(pEvent, pThis)
{
	var evt = (pEvent? pEvent: window.event);
	if (!evt) return false;
	evt = new CrossEvent(pEvent);
	var input = (pThis? pThis: evt.target);

	return checkDate(input.value, evt.charCode);
} // doKeyPressDate


/**
 *
 */
function doKeyUpDate(pEvent, pThis)
{
	var evt = (pEvent? pEvent: window.event);
	if (!evt) return false;
	evt = new CrossEvent(pEvent);
	var input = (pThis? pThis: evt.target);

	var fmt = formatDate(input.value);

	// Quando o usuário apaga a "/" com backspace, apagar o dígito anterior também
	if (evt.keyCode == 8 && input.value + "/" == fmt)
		fmt = fmt.substring(0, fmt.length - 2);

	if (input.value != fmt) input.value = fmt;
	return true;
} // doKeyUpDate


/**
 *
 */
function doChangeDate(pEvent, pThis)
{
	var evt = (pEvent? pEvent: window.event);
	if (!evt) return false;
	evt = new CrossEvent(pEvent);
	var input = (pThis? pThis: evt.target);

	return validateDate(input.value);
} // doChangeDate


function doFocusHint(pEvent, pThis, pTexto)
{
	var evt = (pEvent? pEvent: window.event);
	if (!evt) return false;
	evt = new CrossEvent(pEvent);
	var input = (pThis? pThis: evt.target);
	var texto = (pTexto? pTexto: c_HINT_TEXT);

	if (input.value == texto) input.value = "";
	return true;
} // doFocusHint


function doBlurHint(pEvent, pThis, pTexto)
{
	var evt = (pEvent? pEvent: window.event);
	if (!evt) return false;
	evt = new CrossEvent(pEvent);
	var input = (pThis? pThis: evt.target);
	var texto = (pTexto? pTexto: c_HINT_TEXT);

	if (input.value == "") input.value = texto;
	return true;
} // doBlurHint

//----------------------------------------------------------------------//


function inspectObject(obj) {
	var result = "";
	var objName = obj.name? obj.name: "object";
	for (var i in obj) {
		result += objName + "." + i + " = " + obj[i] + "\n";
	}
	return result;
} // inspectObject

//----------------------------------------------------------------------//


/**
 * Monta um link de mail-to dinamicamente, para evitar spam.
 * Escreve o codigo HTML do link no documento.
 *
 * @return String
 *	Codigo HTML do link, que foi escrito no documento.
 * @param String pNome
 *	Nome da caixa postal de destino (username) do e-mail.
 * @param String pDomino
 *	Dominio da caixa postal de destino do e-mail.
 * @param String pText
 *	[Opcional] Texto de rotulo do link.
 *	Se nao for fornecido, é assumido o e-mail de destino.
 * @param String pAttr
 *	[Opcional] Atributos a serem adicionados a tag <A>.
 * @param String pQuery
 *	[Opcional] Query de pares parametro/valor a ser adicionada ao link,
 *	permitindo fornecer parametros como subject, cc, body.
 */
function linkMail(pNome, pDominio, pText, pAttr, pQuery)
{
	var destino = pNome + '@' + pDominio;
	var rotulo = (pText!=null && pText!="")? pText: destino;
	var link = '<a';
	if (pAttr!=null) link += ' ' + pAttr;
	link += ' href="m' + 'ailto:' +  destino
	if (pQuery!=null) link += '?' + pQuery;
	link += '">' + rotulo + '</a>';
	document.write(link);
	return link;
} // linkMail

/**
 * Utilizada para a comparação pelo método sort() do array.
 **/
function compareString(a,b) {
	return a[0] < b[0] ? -1 : (a[0] == b[0] ? 0 : 1);
}

/**
 * Utilizada para a comparação pelo método sort() do array.
 **/
function compareNumber(a,b){
	return parseInt(a) - parseInt(b);
}

/**
 * Utilizada para a comparação pelo método sort() do array.
 **/
function compareData(a,b){
	data1 = a[0].split("/");
	data2 = b[0].split("/");
	return parseInt(data1[2] + data1[1] + data1 [0]) - parseInt(data2[2] + data2[1] + data2[0]);
}

/**
 * Função utilizada para ordenar uma tabela sem utilizar submit.
 * Para utilizar esta função, todas as células (tags <td>) devem
 * possuir um id que segue o parametro: id="tXlYcZ", onde X é o nome
 * da tabela passado como primeiro parâmetro da função, Y é o número da
 * linha atual (que deverá inciar pelo número 1, pois o 0 é o cabeçalho
 * da tabela e Z é o nome da coluna atual.
 * <p>
 * @param tableName
 *		nome da tabela que deverá ser atribuído no id de cada célula após
 *		a letra "t"
 * @param column
 *		número da coluna que está sendo ordenada. A primeira coluna da tabela
 *		deve ser a de número 0
 * @param lineNumber
 *		número total de linhas da tabela (excluindo o cabeçalho)
 * @columnNumber
 *		número total de colunas da tabela
 * @return
 *		o tipo de ordenação realizado. Retorna TRUE se a ordenação para esta coluna
 * 		foi ascendente, ou FALSE se foi descentente
 *
 * @autor criado para uso com o framework Struts-Layout
 *	(http://struts.application-servers.com/)
**/
var tables = new Array();
function arraySort(tableName, column, lineNumber, columnNumber) {
	var asc = true;
	var aTable = tables[tableName];
	var arrayToSort;
	var array;
	var reverse = 0;
	if (aTable) {
		array = aTable[0];
		arrayToSort = new Array(lineNumber);
		for (i=0;i<lineNumber;i++) {
			arrayToSort[i] = new Array(2);
			arrayToSort[i][0] = array[i][column];
			arrayToSort[i][1] = i;				
		}
		reverse = 1 - aTable[1];
		aTable[1] = reverse;
	} else {
		array = new Array(lineNumber);
		arrayToSort = new Array(lineNumber);
		for (i=0;i<lineNumber;i++) {	
			array[i] = new Array(columnNumber);
			for (j=0;j<columnNumber;j++) {
				obj = document.getElementById("t" + tableName + "l" + (i+1) +"c" + j);		
				array[i][j] = obj.innerHTML;
			}
			array[i][columnNumber] = obj.parentNode.parentNode.onmouseover;
			array[i][columnNumber+1] = obj.parentNode.parentNode.onmouseout;			
			
			arrayToSort[i] = new Array(2);
			arrayToSort[i][0] = array[i][column];
			arrayToSort[i][1] = i;		
	
			aTable = new Array(2);
			aTable[0] = array;
			aTable[1] = 0;
			tables[tableName] = aTable;
		}
	}

	valor = arrayToSort[0];

	numero = parseInt(valor);
	data = valor[0].split("/");

	if (data.length > 1){
		arrayToSort.sort(compareData);
	}else if (!isNaN(numero)){
		arrayToSort.sort(compareNumber);
	} else {
		arrayToSort.sort(compareString);
	}

	if (reverse) {
		arrayToSort.reverse();
		asc = false;
	}

	for (i=0;i<lineNumber;i++) {
		goodLine = arrayToSort[i][1];
		for (j=0;j<columnNumber;j++) {
			document.getElementById("t" + tableName + "l" + (i+1) +"c" + j).innerHTML = array[goodLine][j];
		}
		document.getElementById("t" + tableName + "l" + (i+1) +"c" + 0).parentNode.parentNode.onmouseover = array[goodLine][columnNumber];
		document.getElementById("t" + tableName + "l" + (i+1) +"c" + 0).parentNode.parentNode.onmouseout = array[goodLine][columnNumber+1];
	}
	
	return asc;
}
