/** ***************************************************************************** */
/*------Funções executar funções especificas ou para melhorar a biblioteca------*/
/** ***************************************************************************** */

/**
 * debugger off
 */
var KM_DEBUG = false;

/**
 * @todo O remapeamento não é necessário quando não utiliza os scripts do
 *       AtJsMenu
 */
try {
	alert = window.alert;
	setInterval = window.setInterval;
	clearInterval = window.clearInterval;
	setTimeout = window.setTimeout;
} catch (e) {
}

try {
	/**
	 * Funções para ser executadas no carregamento da pagina
	 */
	$(document).ready( function() {

		/**
		 * O a variavel console esta presente quando se esta usando a extensão
		 * firebug do firefox, caso contrario tem que criar um objeto com o
		 * mesmo nome para não dar erro no javascript ou desabilita caso não
		 * esteja fazendo debug
		 */
		if (typeof console != 'object' || !KM_DEBUG) {
			if (typeof console == 'undefined') {
				console = {};
			}
			console.dir = function() {
			};
			console.log = function() {
			};
			console.debug = function() {
			};
			console.group = function() {
			};
			console.groupEnd = function() {
			};
		}
	});
} catch (e) {
}


/**
 * Oculta os Selects para o internet explorer, esta funçõa auxiliará os
 * utilizadores de div para não parecerem quebrados
 */
function km_toggleSelect(hidden) {
	$('object,select').css('visibility', (hidden ? "hidden" : 'visible'));
}

/**
 * Função para facilitar o debug de variaveis
 * 
 * @param {Object}
 *            aVar
 */
function print_r(aVar) {
	var aux = '';
	for ( var i in aVar) {
		aux += (aux != '' ? '\n' : '') + i + ' := ' + aVar[i];
	}
	km_Debug('\nArray(\n' + aux + '\n)');
}

/**
 * Escreve uma mensagem de debug
 * 
 * @param {string}
 *            sMsg
 */
function alertx(sMsg) {
	km_Debug(sMsg);
}

/**
 * Escreve uma mensagem de debug
 * 
 * @param {string}
 *            sMsg
 */
function km_Debug(sMsg) {
	if (!document.getElementById('debug')) {
		var el = document.createElement('textarea');
		el.id = 'debug';

		$(el).css( {
			display :'block',
			clear :'left',
			height :'200px',
			margin :'0 1% 0 1%',
			padding :'2px',
			width :'98%'
		});
		document.body.insertBefore(el, document.body.firstChild);
	}
	$E('debug').value += sMsg + '\n';
	$E('debug').scrollTop = $E('debug').scrollHeight;
}

/**
 * Pega as coordenadas do click do mouse ref:
 * http://www.codelifter.com/main/javascript/capturemouseposition1.html
 */
function km_getEventXY(e) {
	if ($.browser.msie) {
		tempX = event.clientX + document.body.scrollLeft;
		tempY = event.clientY + document.body.scrollTop;
	} else {
		tempX = e.pageX;
		tempY = e.pageY;
	}
	tempX = (tempX < 0 ? 0 : tempX);
	tempY = (tempY < 0 ? 0 : tempY);
	return {
		0 :tempX,
		1 :tempY,
		x :tempX,
		y :tempY
	};
}

/**
 * Redimenciona a janela (parecido com o maximizar) e centraliza a janela
 * 
 * @param {Object}
 *            refW
 * @param {Object}
 *            refH
 */
function km_resizeWin(refW, refH) {
	var w = 0;
	var h = 0;
	if (typeof refW == 'undefined') {
		/* se não veio informação nenhuma, redimenciona para o maximo */
		w = screen.availWidth;
		h = screen.availHeight;
	} else {
		if (typeof refW == 'string' && refW.indexOf('%') != -1) {
			/* valores em % do tamanho da tela */
			w = (screen.availWidth * parseInt(refW)) / 100;
			h = (screen.availHeight * parseInt(refH)) / 100;
		} else {
			/* valores em px ou veio direto o numero do tamanho da tela */
			w = parseInt(refW);
			h = parseInt(refH);
		}
	}
	window.moveTo(parseInt((screen.availWidth - w) / 2), parseInt((screen.availHeight - h) / 2));
	window.resizeTo(w, h);
}

/**
 * Função atalho para document.getElementById e a pesquisa de elementos por
 * seletor css
 */
function $E(ELEMENTO) {
	var el = document.getElementById(ELEMENTO);
	if (el) {
		return el;
	} else {
		throw 'O elemento "' + ELEMENTO + '" não esta definido.';
	}
	return false;
}

/**
 * Atalho para a função document.getElementById('field').value creation date:
 * 20.04.2006 Kai Tobias Burwieck <burwieck@disbit.de> nome original:
 * getFieldValue endereço original:
 * http://www.breakingpar.com/bkp/home.nsf/0/87256B14007C5C6A87256B060048A4A5
 */
function $V(field) {
	/* passou o nome */
	if (typeof field == "string")
		field = document.getElementById(field);
	
	/**
	 * Se (não passou o proprio objeto HTML) || (o ID do objeto(ou o elemento
	 * referenciado pelo id não foi encontrado))
	 */
	if (!field)
		return '';

	switch (field.type) {
	case "text":
	case "textarea":
	case "password":
	case "hidden":
		return field.value;
	case "select-one":
		var i = field.selectedIndex;
		if (i == -1) {
			return "";
		} else {
			return (field.options[i].value == "") ? field.options[i].text : field.options[i].value;
		}
		break;
	case "select-multiple":
		var allChecked = [];
		for (i = 0; i < field.options.length; i++) {
			if (field.options[i].selected) {
				allChecked[allChecked.length] = (field.options[i].value == "") ? field.options[i].text
						: field.options[i].value;
			}
		}
		return allChecked;

	case "button":
	case "reset":
	case "submit":
		return "";

	case "checkbox":
		return field.checked;
		break;
	case "radio":
		if (field.checked) {
			return field.value;
		} else {
			return "";
		}
		break;
	default:
		if (field[0].type == "radio") {
			for (i = 0; i < field.length; i++) {
				if (field[i].checked) {
					return field[i].value;
				}
			}
			return "";
		} else if (field[0].type == "checkbox") {
			allChecked = new Array();
			for (i = 0; i < field.length; i++) {
				if (field[i].checked) {
					allChecked[allChecked.length] = field[i].value;
				}
			}
			return allChecked;
		} else {
			var str = "";
		}
		for (x in field) {
			str += x + "\n";
		}
		alert("I couldn't figure out what type this field is...\n\n" + field.name + ": ???\n\n\n" + str
					+ "\n\nlength = " + field.length);

		break;
	}
	return "";
}

/**
 * Liga e desliga a tela que pede ao usuario esperar alguns momentos pelo
 * processamento da requisiçao
 */
function km_toggleSplat(display) {
	var w = km_winW();
	var h = km_winH();
	var y = km_winY();

	if (display) {
		km_toggleSelect(true);

		/* tela acinzendata */
		$E('sk_splat_dcontainer').style.display = 'block';
		$E('sk_splat_dcontainer').style.width = w + 'px';
		$E('sk_splat_dcontainer').style.height = h + 'px';
		$E('sk_splat_dcontainer').style.top = y + 'px';
		$E('sk_splat_dcontainer').style.left = '0px';

		/* div com a imagem */
		$E('sk_splat_despera').style.display = 'block';
		$E('sk_splat_despera').style.top = y + 200 + 'px';
	} else {
		km_toggleSelect(false);
		$E('sk_splat_dcontainer').style.display = 'none';
		$E('sk_splat_despera').style.display = 'none';
	}
}

/**
 * Handller de erro do javascript que chama uma outra pagina para gravar um log
 * do acontecido
 * 
 * @param {Object}
 *            msg
 * @param {Object}
 *            url
 * @param {Object}
 *            line
 */
function km_onError(msg, url, line) {
	var aux = onErrorUrl ;
	aux += '&MSG: ' + msg;
	aux += '||LINE: ' + line;
	aux += '||URL: ' + escape(window.location.search);
	aux += '||AGENT: ' + escape(navigator.userAgent);
	aux += '||OS: ' + escape(navigator.platform);

	if(!$('#iError').length){
		$('body').append('<iframe id="iError" style="display: none;"></iframe>');		
	}
	$('#iError').attr('src', aux );
}

/** ****************************************************** */
/*------Funções para manipulação de janelas--------------*/
/** ****************************************************** */
/**
 * getPageScroll() Returns with y of the page scroll values. Core code from -
 * quirksmode.org
 */
function getPageScroll() {
	var yScroll;
	if (window.pageYOffset) {
		yScroll = window.pageYOffset;
	} else if (document.documentElement && document.documentElement.scrollTop) {
		/* Explorer 6 Strict */
		yScroll = document.documentElement.scrollTop;
	} else if (document.body) {
		/* all other Explorers */
		yScroll = document.body.scrollTop;
	}
	return yScroll;
}

/**
 * getPageSize() Returns array with page width, height and window width, height
 * Core code from - quirksmode.org Edit for Firefox by pHaez
 */
function getPageSize() {
	var xScroll, yScroll, pageHeight, pageWidth;
	if (typeof window.innerHeight != 'undefined' && typeof window.scrollMaxY != 'undefined') {

		if (typeof document.body != 'undefined' && typeof document.body.scrollWidth != 'undefined') {
			xScroll = document.body.scrollWidth;
		} else {
			xScroll = window.innerWidth
		}
		yScroll = window.innerHeight;
		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 (typeof window.innerHeight != 'undefined') {
		/* all except Explorer */
		windowWidth = window.innerWidth;
		windowHeight = window.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;
	}
	/* for small pages with total height less then height of the viewport */
	if (yScroll < windowHeight) {
		pageHeight = windowHeight;
	} else {
		pageHeight = yScroll;
	}
	/* for small pages with total width less then width of the viewport */
	if (xScroll < windowWidth) {
		pageWidth = windowWidth;
	} else {
		pageWidth = xScroll;
	}
	return [ pageWidth, pageHeight, windowWidth, windowHeight ];
}

/**
 * Pega a altura da pagina
 */
function km_winH() {
	var h = getPageSize();
	return h[3];
}

/**
 * Pega a largura da pagina
 */
function km_winW() {
	var h = getPageSize();
	return h[2];
}

/**
 * Pega a altura do scroll
 */
function km_winY() {
	return getPageScroll();
}

/**
 * Abre um div semelhante a uma janela de browser
 * 
 * @param {String}
 *            sName: Nome unico da janela (como no popup)
 * @param {String}
 *            sTitle: Titulo da janela
 * @param {String}
 *            sContent: Conteudo da janela
 * @param {Integer}
 *            w: largura
 * @param {Integer}
 *            h: altura
 * @param {boolean}
 *            resize: se poderá ser redimencionado
 * @param {boolean}
 *            scroll: se pode dar scrool
 * @param {Event}
 *            e=event
 */
function km_winDhtml(sName, sTitle, sContent, w, h) {
	/*
	 * e=event bResize=1 bScroll=1
	 */
	if (typeof w == null) {
		w = 80;
	}
	if (typeof h == null) {
		h = 80;
	}
	var x = 0;
	var y = 0;
	if (arguments.length > 5 && typeof arguments[5] == 'object') {
		var aux = km_getEventXY(arguments[5]);
		x = aux.x + 25;
		y = aux.y - km_winY() - (h / 2);
	} else {
		x = (km_winW() - w) / 2;
		y = (km_winH() - h) / 2 + km_winY();
	}
	var bResize = 1;
	if (arguments.length > 6) {
		bResize = arguments[6];
	}
	var bScroll = 1;
	if (arguments.length > 7) {
		bScroll = arguments[7];
	}
	var def = '';
	def += 'width=' + w;
	def += 'px,height=' + h;
	def += 'px,left=' + x;
	def += 'px,top=' + y;
	def += 'px,resize=' + bResize;
	def += ',scrolling=' + bScroll;
	return dhtmlwindow.open(sName, 'inline', sContent, sTitle, def, 'recal');
}

/**
 * Fecha a janela aberta pela função km_winDhtml sName: Nome unico da janela
 * (como no popup)
 */
function km_winDhtmlClose(sName) {
	return dhtmlwindow.close(sName);
}

/**
 * A variavel guardará referencia para todas as janelas abertas
 */
var kmOpenedWindows = {};

/**
 * Abre uma janela
 * 
 * @param {String}
 *            url : Endereço
 * @param {String}
 *            winName : Nome da janela, para ser sobreposta com a abertura de
 *            outra
 * @param {Integer}
 *            refW : Largura da janela referencial à pai(somente numeros) ou
 *            tamanho fixo(final com px)
 * @param {Integer}
 *            refH : Autura da janela referencial à pai(somente numeros) ou
 *            tamanho fixo(final com px)
 * @param {String}
 *            menu : se será mostrado o menu ou não
 */
function km_winOpen(url, winName, refW, refH) {
	if (!refW) {
		refW = '80%';
		refH = '80%';
	}
	var winW = km_winW();
	var winH = km_winH();
	var menu = (arguments.length < 5 ? 0 : arguments[4]);
	var w = 0;
	var h = 0;

	/* por padrão a janela será tratada como px */
	if (typeof refW == 'string' && refW.indexOf('px') != -1) {
		/* valores em px do tamanho da tela */
		w = refW.replace(/px/, '');
		h = refH.replace(/px/, '');
	} else if (typeof refW == 'string' && refW.indexOf('%') != -1) {
		/* valores em % do tamanho da tela */
		w = winW * refW.replace(/%/, '') / 100;
		h = winH * refH.replace(/%/, '') / 100;
	} else {
		w = refW;
		h = refH;
	}
	var x = (winW - w) / 2;
	var y = (winH - h) / 2;

	if (winName == null) {
		winName = 'kmpopup';
	}
	if (typeof kmOpenedWindows !='undefined' && kmOpenedWindows[winName] && kmOpenedWindows[winName].closed == false) {
		kmOpenedWindows[winName].close();
	}
	try {
		var aux = '';
		aux += 'width=' + w;
		aux += ',height=' + h;
		aux += ',top=' + y;
		aux += ',left=' + x;
		aux += ',scrollbars=1,directories=0,location=0,menubar=' + menu;
		aux += ',status=0,titlebar=0,toolbar=0,resizable=1';
		var win = window.open(url, winName, aux);
	} catch (e) {
	}
	if (!win) {
		var msg = '';
		msg += 'Não foi possivel abrir a janela,\n';
		msg += ' um bloqueador de PopUp deve estar bloqueando a abertura\n';
		msg += ' desabilite o bloqueador e tente novamente.';
		window.alert(msg);
		return false;
	}
	win.focus();
	kmOpenedWindows[winName] = win;
	return win;
}

/** ****************************************************** */
/*------Funções para manipulação de atalhos--------------*/
/** ****************************************************** */
/**
 * variavel que vai guardar as teclas de atalho para serem monitoradas
 */
var kmHK_array = [];
var kmHK_shift = 91;
var kmHK_ctrl = 181;
var kmHK_alt = 361;

/**
 * Adiciona uma entrada no monitoramento de atalhos para funções e paginas da
 * biblioteca
 */
function km_setHotKey(nKey, sAction, sModKey) {
	/* se nKey não for numerico converte */
	if (isNaN(nKey)) {
		nKey = String(nKey);
		nKey = nKey.toUpperCase();
		nKey = Number(nKey.charCodeAt());
	}
	sModKey = String(sModKey);
	sModKey.charCodeAt('A');
	if (sModKey.indexOf('shift') != -1) {
		nKey += kmHK_shift;
	}
	if (sModKey.indexOf('ctrl') != -1) {
		nKey += kmHK_ctrl;
	}
	if (sModKey.indexOf('alt') != -1) {
		nKey += kmHK_alt;
	}
	kmHK_array[nKey] = sAction;
}

/**
 * Monitora as teclas precionadas no sistema para identificar teclas de atalho
 * precionadas
 */
function km_onKeyDown(evt) {
	if (!evt) {
		evt = event;
	}

	var key = evt.keyCode ? evt.keyCode : evt.which;

	if (evt.shiftKey) {
		key += kmHK_shift;
	}
	if (evt.ctrlKey) {
		key += kmHK_ctrl;
	}
	if (evt.altKey) {
		key += kmHK_alt;
	}

	if (typeof kmHK_array[key] != 'undefined') {
		var a = kmHK_array[key];
		a = eval(a);
		if (typeof a == 'function') {
			a();
		}
		evt.cancelBubble = true;
		if (evt.stopPropagation) {
			evt.stopPropagation();
		}
	}
}

document.onkeydown = function(evt) {
	km_onKeyDown(evt);
};

/** ****************************************************** */
/*------Funções para manipulação de numeros--------------*/
/** ****************************************************** */
Math.floor = km_floor;
function km_floor(nValor) {
	if (arguments.length > 1 && arguments[1] > 0) {
		var nInt = 0;
		var nDec = arguments[1];
	} else {
		return Math.round(nValor);
	}
	nValor = String(nValor * Math.pow(10, nDec)).toString();
	if (nValor.search(/[.]/) != -1) {
		nValor = nValor.substring(0, nValor.search(/[.]/));
	}
	nInt = nValor.length - nDec;
	return nValor.substring(0, nInt) + '.' + nValor.substring(nInt);
}

/** ******************************************** */
/*------Funções para manipulação de strings------*/
/** ******************************************** */

/**
 * Adiciona método trim() à classe String. Elimina brancos no início e fim da
 * String. http://www.sosdesigners.com/colunas-87.html
 */
String.prototype.trim = function() {
	return this.replace(/^\s*/, "").replace(/\s*$/, "");
}

/**
 * http://forum.imasters.com.br/index.php?showtopic=144107&pid=416406&st=0&#entry416406
 * Javascript prototypes - Number.format() Carlos Reche (carlosreche@yahoo.com)
 */
Number.prototype.format = function(d_len, d_pt, t_pt) {
	d_len = d_len || 0;
	d_pt = d_pt || ".";
	t_pt = t_pt || ",";
	if ((typeof d_len != "number") || (typeof d_pt != "string") || (typeof t_pt != "string")) {
		throw new Error("wrong parameters for method 'String.pad()'.");
	}
	var integer = "", decimal = "";
	var n = new String(this).split(/\./), i_len = n[0].length, i = 0;
	if (d_len > 0) {
		n[1] = (typeof n[1] != "undefined") ? n[1].substr(0, d_len) : "";
		decimal = d_pt.concat(n[1].pad(d_len, "0", String.PAD_RIGHT));
	}
	while (i_len > 0) {
		if ((++i % 3 == 1) && (i_len != n[0].length)) {
			integer = t_pt.concat(integer);
		}
		integer = n[0].substr(--i_len, 1).concat(integer);
	}
	return (integer + decimal);
}

/**
 * 1º Recebe uma string no formato "1.234.567,89" 2º Elimina qualquer caracter
 * que não seja numerico ou a virgula "1234567,89" 3º Substitui a virgula por
 * ponto "1234567.89" 4º Remove zeros a esquerda 5º trata campos zerados como
 * "00.0000" como simples "0"
 * 
 * @return String de número no formato numerico
 */
String.prototype.unformat = function() {
	return this.replace(/[^0-9,]/g, "").replace(/[,]/, ".").replace(/^0+/, "").replace(/^[.][0]+$/, "0")
			.replace(/^[.]/, "0.").replace(/^[0][.]$/, "0").replace(/[.]$/, "");
};

/**
 * http://forum.imasters.com.br/index.php?showtopic=144107&pid=416406&st=0&#entry416406
 * Javascript prototypes - String.pad() Carlos Reche (carlosreche@yahoo.com)
 */
String.PAD_LEFT = 0;
String.PAD_RIGHT = 1;
String.PAD_BOTH = 2;

String.prototype.pad = function(size, pad, side) {
	var str = this, append = "", size = (size - str.length);
	var pad = ((pad != null) ? pad : " ");
	if ((typeof size != "number") || ((typeof pad != "string") || (pad == ""))) {
		throw new Error("Wrong parameters for String.pad() method.");
	}
	if (side == String.PAD_BOTH) {
		str = str.pad((Math.floor(size / 2) + str.length), pad, String.PAD_LEFT);
		return str.pad((Math.ceil(size / 2) + str.length), pad, String.PAD_RIGHT);
	}
	while ((size -= pad.length) > 0) {
		append += pad;
	}
	append += pad.substr(0, (size + pad.length));
	return ((side == String.PAD_LEFT) ? append.concat(str) : str.concat(append));
}

/**
 * Adiciona método lpad() à classe String. Preenche a String à esquerda com o
 * caractere fornecido, até que ela atinja o tamanho especificado.
 */
String.prototype.lpad = function(pSize, pCharPad) {
	return this.pad(pSize, pCharPad, String.PAD_LEFT);
}

/** ******************************************** */
/*------Funções para manipulação de datas------*/
/** ******************************************** */
/**
 * Checa se uma data é valida
 * 
 * @param {String|Date}
 *            sDate String datas nos formatos: 9/9/9999, 9/99/9999, 99/9/9999 e
 *            99/99/9999
 * 
 * @return bool
 */
function km_isDate(sDate) {
	if (typeof sDate == 'string') {
		/**
		 * O parametro é tratado como uma string
		 */

		/* Pre validação da string */
		if (!/^\d{1,2}\/\d{1,2}\/\d{4}$/.test(sDate)) {
			return false;
		}

		/* criando as variaveis */
		var bissexto = false;
		var dia = sDate.split("/")[0];
		var mes = sDate.split("/")[1];
		var ano = sDate.split("/")[2];

		/* Se mes não tiver 2 algarismos, preenche com um '0'(zero) a esquerda */
		if (mes.length != 2) {
			mes = '0' + mes;
		}

		/* Confere a quantidade de dias, com base no mes e ano */
		switch (mes) {
		case '01':
		case '03':
		case '05':
		case '07':
		case '08':
		case '10':
		case '12':
			if (dia <= 31) {
				return true;
			}
			break
		case '04':
		case '06':
		case '09':
		case '11':
			if (dia <= 30) {
				return true;
			}
			break
		case '02':
			/* Validando ano Bissexto / fevereiro / dia */
			if ((ano % 4 == 0) || (ano % 100 == 0) || (ano % 400 == 0)) {
				bissexto = true;
			}

			/* se bissexto fevereito tem ate 29, se não no maximo 28 */
			if (bissexto == true && dia <= 29) {
				return true;
			} else if (!bissexto && dia <= 28) {
				return true;
			}
			break
		}
	} else if (typeof sDate == 'object' && typeof sDate.getMonth == 'function') {
		/**
		 * É um objeto da classe Date
		 */
		return true;
	}
	return false;
}

// REQUIRES: km_isDate()
function dateAdd(p_Interval, p_Number, p_Date) {
	if (!km_isDate(p_Date)) {
		return "invalid date: '" + p_Date + "'";
	}
	if (isNaN(p_Number)) {
		return "invalid number: '" + p_Number + "'";
	}

	p_Number = Number(p_Number);
	var dt = new Date(p_Date);
	switch (p_Interval.toLowerCase()) {
	case "yyyy": // year
		dt.setFullYear(dt.getFullYear() + p_Number);
		break;
	case "q": // quarter
		dt.setMonth(dt.getMonth() + (p_Number * 3));
		break;
	case "m": // month
		dt.setMonth(dt.getMonth() + p_Number);
		break;
	case "y": // day of year
	case "d": // day
	case "w": // weekday
		dt.setDate(dt.getDate() + p_Number);
		break;
	case "ww": // week of year
		dt.setDate(dt.getDate() + (p_Number * 7));
		break;
	case "h": // hour
		dt.setHours(dt.getHours() + p_Number);
		break;
	case "n": // minute
		dt.setMinutes(dt.getMinutes() + p_Number);
		break;
	case "s": // second
		dt.setSeconds(dt.getSeconds() + p_Number);
		break;
	case "ms": // second
		dt.setMilliseconds(dt.getMilliseconds() + p_Number);
		break;
	default:
		return "invalid interval: '" + p_Interval + "'";
	}
	return dt;
}
/**
 * Converte uma string de data ou data/hora no formato ISO8859 (o formato 'd/m/Y
 * H:i' veja {@link http://www.php.net/date}) para o Date do javascript
 * 
 * @param {ISO8859}
 *            sDateTime: string no formato
 * @return Date
 */
function strToDateTime(sDateTime) {
	/* separa as partes da data */
	var aDateTime = sDateTime.replace(/\D/g, ':').split(':');

	/* dia,mes,ano,hora,minuto */
	var d = 0;
	var m = 0;
	var Y = 0;
	var H = 0;
	var i = 0;
	var s = 0;

	for ( var j in aDateTime) {
		switch (j) {
		case '0':
			d = aDateTime[j];
			break;
		case '1':
			m = aDateTime[j];
			break;
		case '2':
			Y = aDateTime[j];
			break;
		case '3':
			H = aDateTime[j];
			break;
		case '4':
			i = aDateTime[j];
			break;
		case '5':
			s = aDateTime[j];
			break;
		}
	}

	return new Date(Y, m - 1, d, H, i, s);
}

/**
 * Calcula a diferença de tempo entre duas datas passadas, semelhante à função
 * KM_dataDiff da lib php <code>
 * "ww": semanas
 * "y": anos 
 * "m": meses
 * "d": dias
 * "h": horas
 * "i" ou "n": minutos
 * "s": segundos 
 * "ms": Milli segundos
 * </code>
 * 
 * @param {Date|ISO8859}
 *            dDateIni: Date ou string no formato d/m/Y H:i
 * @param {Date|ISO8859}
 *            dDateFin: Date ou string no formato d/m/Y H:i
 * @param {String}
 *            sInterval: Tipo do intervalo que será calculado
 * @return {Integer}
 */
function KM_dataDiff(dDateIni, dDateFin, sInterval) {
	if (typeof dDateIni == "string") {
		dDateIni = strToDateTime(dDateIni);
	}
	if (typeof dDateFin == "string") {
		dDateFin = strToDateTime(dDateFin);
	}

	// calc various diffs
	var nYears = dDateFin.getUTCFullYear() - dDateIni.getUTCFullYear();
	var nMonths = dDateFin.getUTCMonth() - dDateIni.getUTCMonth() + (nYears !== 0 ? nYears * 12 : 0);

	// get ms between dates (UTC) and make into "difference" date
	var nMilliseconds = dDateFin.valueOf() - dDateIni.valueOf();
	var nSeconds = parseInt(nMilliseconds / 1000, 0);
	var nMinutes = parseInt(nSeconds / 60, 0);
	var nHours = parseInt(nMinutes / 60, 0);
	var nDays = parseInt(nHours / 24, 0);
	var nWeeks = parseInt(nDays / 7, 0);

	// return requested difference
	switch (sInterval.toLowerCase()) {
	case "y":
		return nYears;
	case "m":
		return nMonths;
	case "d":
	case "w":
		return nDays;
	case "ww":
		return nWeeks; // week of year // <-- inaccurate, WW should count
		// calendar weeks (# of sundays) between
	case "h":
		return nHours;
	case "i":
	case "n":
		return nMinutes;
	case "s":
		return nSeconds;
	case "ms":
		return nMilliseconds; // millisecond // <-- extension for JS, NOT
		// available in VBScript
	default:
		return "invalid interval: '" + p_Interval + "'";
	}
}
/** ******************************************** */
/*------Funções para validações em geral-------*/
/** ******************************************** */
var NUM_DIGITOS_CPF = 11;
var NUM_DIGITOS_CNPJ = 14;
var NUM_DGT_CNPJ_BASE = 8;

/**
 * Formata a string fornecida como CNPJ ou CPF, adicionando zeros à esquerda se
 * necessário e caracteres separadores, conforme solicitado.
 * 
 * @param {String}
 *            pCpfCnpj : String fornecida para ser formatada.
 * @param {Boolean}
 *            pUseSepar : Indica se devem ser usados caracteres separadores (. -
 *            /).
 * @param {Boolean}
 *            pIsCnpj : Indica se a string fornecida é um CNPJ. Caso contrário,
 *            é CPF. Default = false (CPF).
 * @return {String} CPF ou CNPJ devidamente formatada.
 */
function formatCpfCnpj(pCpfCnpj, pUseSepar, pIsCnpj) {
	if (pCpfCnpj == '')
		return '';
	if (pIsCnpj == null)
		pIsCnpj = false;
	if (pUseSepar == null)
		pUseSepar = true;
	var maxDigitos = pIsCnpj ? NUM_DIGITOS_CNPJ : NUM_DIGITOS_CPF;
	var numero = pCpfCnpj.unformat();

	numero = numero.lpad(maxDigitos, '0');
	if (!pUseSepar)
		return numero;

	if (pIsCnpj) {
		reCnpj = /(\d{2})(\d{3})(\d{3})(\d{4})(\d{2})$/;
		numero = numero.replace(reCnpj, "$1.$2.$3/$4-$5");
	} else {
		reCpf = /(\d{3})(\d{3})(\d{3})(\d{2})$/;
		numero = numero.replace(reCpf, "$1.$2.$3-$4");
	}
	return numero;
}

/**
 * Rodrigo Caldeira - Bebado
 * http://www.pcforum.com.br/cgi/yabb/YaBB.cgi?board=cgi;action=display;num=1090001360
 * Testa se a strig passada é um cpf valido
 * 
 * @param {String}
 *            cpf sem formatação
 * @return bool
 */
function isCpf(cpf) {
	var numeros, digitos, soma, i, resultado, digitos_iguais;
	digitos_iguais = 1;
	if (cpf.length != 11) {
		return false;
	}
	for (i = 0; i < cpf.length - 1; i++) {
		if (cpf.charAt(i) != cpf.charAt(i + 1)) {
			digitos_iguais = 0;
			break;
		}
	}
	if (!digitos_iguais) {
		numeros = cpf.substring(0, 9);
		digitos = cpf.substring(9);
		soma = 0;
		for (i = 10; i > 1; i--) {
			soma += numeros.charAt(10 - i) * i;
		}
		resultado = soma % 11 < 2 ? 0 : 11 - soma % 11;
		if (resultado != digitos.charAt(0)) {
			return false;
		}
		numeros = cpf.substring(0, 10);
		soma = 0;
		for (i = 11; i > 1; i--) {
			soma += numeros.charAt(11 - i) * i;
		}
		resultado = soma % 11 < 2 ? 0 : 11 - soma % 11;
		if (resultado != digitos.charAt(1)) {
			return false;
		}
		return true;
	} else {
		return false;
	}
}

/**
 * Rodrigo Caldeira - Bebado
 * http://www.pcforum.com.br/cgi/yabb/YaBB.cgi?board=cgi;action=display;num=1090001360
 * Testa se a strig passada é um cnpj valido
 * 
 * @param {String}
 *            cnpj sem formatação
 * @return bool
 */
function isCnpj(cnpj) {
	var numeros, digitos, soma, i, resultado, pos, tamanho, digitos_iguais;
	digitos_iguais = 1;
	if (cnpj.length != 14) {
		return false;
	}
	for (i = 0; i < cnpj.length - 1; i++) {
		if (cnpj.charAt(i) != cnpj.charAt(i + 1)) {
			digitos_iguais = 0;
			break;
		}
	}
	if (!digitos_iguais) {
		tamanho = cnpj.length - 2
		numeros = cnpj.substring(0, tamanho);
		digitos = cnpj.substring(tamanho);
		soma = 0;
		pos = tamanho - 7;
		for (i = tamanho; i >= 1; i--) {
			soma += numeros.charAt(tamanho - i) * pos--;
			if (pos < 2) {
				pos = 9;
			}
		}
		resultado = soma % 11 < 2 ? 0 : 11 - soma % 11;
		if (resultado != digitos.charAt(0)) {
			return false;
		}
		tamanho = tamanho + 1;
		numeros = cnpj.substring(0, tamanho);
		soma = 0;
		pos = tamanho - 7;
		for (i = tamanho; i >= 1; i--) {
			soma += numeros.charAt(tamanho - i) * pos--;
			if (pos < 2) {
				pos = 9;
			}
		}
		resultado = soma % 11 < 2 ? 0 : 11 - soma % 11;
		if (resultado != digitos.charAt(1)) {
			return false;
		}
		return true;
	} else {
		return false;
	}
}
/**
 * Checa se um campo é um cpf ou cpnj valido
 * 
 * @param {Object}
 *            pCpfCnpj
 */
function isCpfCnpj(pCpfCnpj) {
	var numero = pCpfCnpj.replace(/\D/g, "");
	if (numero.length == 14)
		return isCnpj(pCpfCnpj)
	else
		return isCpf(pCpfCnpj);
}

/**
 * Equivalnte a função php http://br2.php.net/html_entity_decode This script and
 * many more are available free online at The JavaScript Source!!
 * http://javascript.internet.com Created by: Ultimater |
 * http://webdeveloper.com/forum/member.php?u=30185
 */
function html_entity_decode(str) {
	if (!str)
		return '';
	var ta = document.createElement("textarea");
	console.log(str+' '+typeof str);
	ta.innerHTML = str.replace(/</g, "&lt;").replace(/>/g, "&gt;");
	return ta.value;
}

function KM_XulGO(url, updateMain) {
	url = unescape(url);
	if (typeof updateMain == "undefined") {
		updateMain = false;
	}

	if (updateMain) {
		document.location.href = url;
	} else {
		document.getElementById("frame").setAttribute("src", url);
	}
}

function KM_XulCall(js) {
	eval(unescape(js));
}

/**
 * Atualiza o valor de um campo qualquer, tratando cada tipo de campo em
 * especial(Ex: Select, checkbox, div e span) e ao final executa a função de
 * onchange do campo
 * 
 * @param field
 *            string(ID do campo) ou objeto(getElementById) do campo a ser
 *            atualizado
 * @param value
 *            valor que o campo deve receber
 * @return
 */
function setVal(field, value) {
	/* passou o nome */
	if (typeof field == 'string')
		field = document.getElementById(field);

	/**
	 * Se - não passou o proprio objeto HTML - nem o ID do objeto(ou o elemento
	 * referenciado pelo id não foi encontrado)
	 */
	if (!field)
		return false;

	/*pega o tipo do campo para fazer o tratamento*/
	var type = field.type ? field.type : field.nodeName;

	/*atualizando cada campo respeitando as particularidades*/
	switch (type.toLowerCase()) {
		case 'select-one' :
			$(field).find('option[value=' + value + ']').attr('selected', true);
			break;
		case 'text' :
		case 'textarea' :
		case 'password' :
		case 'hidden' :
			$(field).val(value);
			break;
		case 'checkbox' :
			$(field).attr('checked', value);
			break;
		case 'span' :
		case 'div' :
			$(field).text(value);
			break;
		default :
			console.log('Tipo de elemento não reconhecido: id=' + field.id + ' type=' + type);
			break;
	}

	/* executa os eventos de change e keyup do campo*/
	$(field).trigger('change').trigger('keyup');
}