i_core_nVersion=0.914;

/**
 * @overview Esta librería contiene los objetos y métodos generales para JS.
 * <BR>©2008 Intelygenz - www.intelygenz.com
 * <BR>[JSDOC]	http://intranet.intelygenz.com/ig11_desarrollo_librerias/ig11_01_js/docs/i_core.html
 * <BR>[VER] 	P:\IG_IntelyGenZ\IG11_Desarrollo_Librerias\IG11_01_Js\docs\i_core.txt
 * <BR>[DOC]	http://intranet.intelygenz.com/ig05_intranet/desarrollo/areas/dev/docs/i_core.html
 * <BR>[DEV]	P:\IG_IntelyGenZ\IG11_Desarrollo_Librerias\IG11_01_Js\src\i_core.js
 * <BR>[PRO]	P:\IG_IntelyGenZ\IG11_Desarrollo_Librerias\IG11_01_Js\pro
 *
 * @name i_core.js
 * @author <a href="mailto:manuel.martin-vivaldi@intelygenz.com">Manuel</a>
 * @version    0.914
 */


/*
	open -> i_igz.js,  i_marray.js, i_xbd.js, i_lang_XX.js
*/


//
// ************************* INICIO DE PROTOTYPEs y Funciones Globales
//


// [nFuns]	: numero de funciones
// [bUltima]: pinta tambien la ultima funcion
// [bInverso]: orden de las funciones
function FunCaller(nFuns,bUltima,bInverso) {
	var sFun, sText = "";
	if (!ICore.m_bIsServer && !oIGZ.m_bIE) return (sText)
	var a = arguments;
	if (!bUltima) a = a.caller;
	if (!nFuns) nFuns=-1;
	for (a = a.caller; a !=null; a = a.caller) {
		sFun = a.callee.toString().match(/function (.*\))/);
		if ((sFun != null) && (sFun.length!=0)) {
			if (bInverso) sText += "\n < "+sFun[1];
			else sText = "\n > "+sFun[1]+sText;
		}
		if (a.caller == a || !nFuns) break;
		else --nFuns
	}
	return (sText + "\n");
}
function funcname(f) {
 var s = f.toString().match(/function (\w*)/)[1];
 if ((s == null) || (s.length==0)) return "anonymous";
 return s;
}
function stacktrace() {
 var s = "";
 for (var a = arguments.caller; a !=null; a = a.caller) {
	s += "->"+funcname(a.callee) + "\n";
	if (a.caller == a) {s+="*"; break;}
 }
 return s;
}


OBJECT = new function (){
	this.f_indexOf = function (oObj, sItemName){
		var nIndex = -1;
		var f=-1;
		for ( obj_param in oObj ) {
			f++;
			if ( obj_param == sItemName ){
				nIndex = f;
				break;
			}
		}
		return nIndex;
	}
}

// [3] Number
// sFormatOut = cIcDDdd	('I','.I,DD','I,dd','I,Ddd')
Number.prototype.f_formatNumber = function (sFormatOut){
	var sNumDec = "", nNumInt;
	var cCharInt = "", cCharDec = ""
	if (IsNull(sFormatOut)) sFormatOut = ICore.m_sNumberFormat
	var nPos = sFormatOut.toLowerCase().lastIndexOf("i")
	if (nPos!=-1 && (nPos+2)<sFormatOut.length)  cCharDec = sFormatOut.charAt(nPos+1)
	if (cCharDec=="") {
		nNumInt = Math.floor(Math.round(this))
	}
	else {
		nNumInt = Math.floor(Math.abs(this))
		var sDec = this.toString()
		var nDecsMin =  sFormatOut.f_countMatches ("D")
		var nDecs = 0
		var nPosD = sDec.indexOf (".")
		if (nPosD!=-1) {
			nDecs = sDec.length - (nPosD+1)
		}
		if (nDecsMin || nDecs) {
			var nDecsMax =	sFormatOut.f_countMatches ("d",1)
			if (nDecs>nDecsMax)	{	//Redondeo
				var n = this*Math.pow(10, nDecsMax)
				n = (Math.round (n)*Math.pow(0.1, nDecsMax)).toString()
				var nDec2 = n.indexOf (".")
				nNumInt = n.substr(0,Math.max(1,nDec2))
				sDec = n.substr(1+nDec2,nDecsMax)
				sDec = sDec.replace(new RegExp("0*$","g"),"")
				nDecs = sDec.length
			}
			else {
				sDec = sDec.substring (sDec.length-nDecs)
			}
			if (nDecs<nDecsMin) {	//Añado 0
				sDec = sDec + "0000000000".substring(0,nDecsMin-nDecs)
			}
			if (sDec) sNumDec = cCharDec + sDec
		}
	}
//if (this==-15.9999) alert (this+"\n"+nPosD+"\n"+nDecs+"\n["+nNumInt+sNumDec+"]")

	var sNumInt = nNumInt.toString()
	if (sFormatOut.f_indexOf ("i",0,1)==1)  cCharInt = sFormatOut.charAt(0)
	if (cCharInt!="") {
		var sNumFmt = ""
		while (sNumInt.length>3){
			sNumFmt = cCharInt + sNumInt.substring(sNumInt.length-3,sNumInt.length) + sNumFmt ;
			sNumInt = sNumInt.substring(0,sNumInt.length-3) ;
		}
//if (this=='-9.375') alert (this+"\n"+nNumInt.toString()+"\n"+cCharInt+"\n["+sNumInt+"."+sNumFmt+"]")
		sNumInt = sNumInt + sNumFmt;
	}
	if (this<0 && nNumInt>0) sNumInt = "-"+sNumInt			//0.828
	return (sNumInt+ sNumDec)
}

Number.prototype.f_toNumber = function (){
	return (this)
}


/*
Pasa números a formatos de texto standar
Formatos: "IMPORTE" (1.300,25), "EUR" (100.485,124), "USA" (100,485.124)
*/
Number.prototype.m_a_vNumberFormats=["IMPORTE", ".I,DD"
 								    ,"EUR" 	  , ".I,ddd"
 								    ,"USA"    , ",I.ddd"
 								    ];
Number.prototype.f_parse2Format = function (sOut){
	var vVal 	 = Number(this);
	var nTypeOut = this.m_a_vNumberFormats.f_indexOf(sOut);
	var sFormat  = nTypeOut!=-1 ? this.m_a_vNumberFormats[nTypeOut+1] : "";
	vVal = this.f_formatNumber( sFormat );
	return ( vVal );
}

// [vNumber] oNumber/sNumber
Number.prototype.f_range= function (vMin,vMax) {
	var bOk =1
	if (vMin) {
		if (typeof(vMin)=="string") vMin=vMin.f_toNumber()
		if (this<vMin) bOk=0
	}
	if (bOk && vMax) {
		if (typeof(vMax)=="string") vMax=vMax.f_toNumber()
		if (this>vMax) bOk=0
	}
	return (bOk)
}

//
// [4] String
//
// sFormatOut, [sFormatIn], [sIsNaN]
String.prototype.f_formatNumber = function (sFormatOut,sFormatIn,sIsNaN){
	var nNum = this.f_toNumber (sFormatIn, "-")
	if (isNaN(nNum) && !IsUndefined(sIsNaN)) {
		sNum = sIsNaN
	}
	else {
		if (isNaN(nNum)) nNum = 0
		sNum = nNum.f_formatNumber(sFormatOut)
	}
	return (sNum)
}

// [sFormatIn] por defecto intenta detectarlo
String.prototype.f_toNumber = function (sFormatIn, sIsNaN){
	var nNum = this;
	if (this.length==0) nNum = sIsNaN ? sIsNaN : "0";
	var cCharInt = "", cCharDec = ""
	if (IsNull(sFormatIn) || !sFormatIn) {
		sFormatIn = this.f_findFormat()
	}
	if (sFormatIn.f_indexOf ("i",0,1)==1)  cCharInt = sFormatIn.charAt(0)
	var nPos = sFormatIn.toLowerCase().lastIndexOf("i")
	if (nPos!=-1 && (nPos+1)!=sFormatIn.length)  cCharDec = sFormatIn.charAt(nPos+1)

	if (cCharInt!="") nNum = nNum.f_replace (cCharInt,"")
	if (cCharDec==",") nNum = nNum.f_replace (cCharDec,".")

	return (parseFloat(nNum))		//Es mejor un Number que un ParseFloat???
}

String.prototype.f_findFormat = function () {
	var re = new RegExp(".*\\..*,.*","gi");
	if (re.exec(this)) return (".I,")
	re = new RegExp(".*,.*\\..*","gi");
	if (re.exec(this)) return (",I.")

	re = new RegExp(",","gi");				//BUG: si 1,000 ¿1000 o 1?
	var a_sMatches = this.match(re);
	if (a_sMatches) {
		if (a_sMatches.length>1) return (",I.");
		else return ("I,")
	}

	re = new RegExp("\\.","gi");			//BUG: si 1.000 ¿1000 o 1?
	a_sMatches = this.match(re);
	if (a_sMatches && a_sMatches.length>1) return (".I,");

	return ("I.")
}


// Devuelve el numero máximo de caracteres nMaxLength y le suma sFin si ha tenido que recortarlo
//nMaxLength, [sFin], [bPalabra], [bRemoveHtml]
String.prototype.f_getMaxString = function (nMaxLength, sFin, bPalabra, bRemoveHtml){
	return ( this.f_maxLength(nMaxLength, sFin, bPalabra, bRemoveHtml) );
}
String.prototype.f_maxLength = function (nMaxLength, sFin, bPalabra, bRemoveHtml){
	var sStr = this;
	if (bRemoveHtml) {
		sStr = sStr.replace (/<(?:.*?\s*)?>/g,"")
	}
	if ( sStr.length >= nMaxLength ) {
		sStr = sStr.substring(0, nMaxLength);
		if (bPalabra) {
			var re = new RegExp(".*[^a-z0-9_áéíóúñ]","gi");	//(".*\\W","gi") falla con acentos
			var oMatch = re.exec(sStr)
			if (oMatch) sStr = sStr.substr(0,oMatch.lastIndex-1)
		}
		if (!IsNull(sFin)) sStr += sFin;	// && sFin
	}
	return (sStr);
}




//Usa RegExp y algunos caracteres especiales dan problemas !!!
//Cuenta numero de coincidencias de una cadena en otra
String.prototype.f_countMatches = function (sBuscado, bCaseInd, nStartPos){
	var sTexto = this;
	var nCount = 0;
	var sModo = "g"
	if (bCaseInd) sModo += "i"
	if (nStartPos) sTexto = sTexto.substr(nStartPos)
	if (sBuscado.indexOf(".")!=-1) sBuscado = sBuscado.replace(".","\\.")
	var re = new RegExp(sBuscado,sModo);
	var a_sMatches = sTexto.match(re);
	if (a_sMatches) nCount = a_sMatches.length;
	return (nCount)
}

// [nVeces] = el numero de ocurrencia que nos interesa del texto buscado (la segunda, la tercera...)
String.prototype.f_indexOf = function (sBuscado,nStartPos,bCaseInd,nVeces,bAcentoInd){
	var oMatch;
	var nPos=-1;
	var sTexto = this;
	var sModo = "g"
	if (bCaseInd) sModo += "i"
	if (nStartPos) sTexto = sTexto.substr(nStartPos)
	else nStartPos = 0
	if (!nVeces) nVeces=1
	if (bAcentoInd) sTexto = sTexto.f_removeAcentos()
	var re = new RegExp(sBuscado,sModo);
	while ((oMatch = re.exec(sTexto))!=null && --nVeces){	}
	if (oMatch) nPos = oMatch.index + nStartPos
	return (nPos)
}

// El orden de los cambios es fundamental (no cambiar caracteres que acabamos de añadir)
// String.fromCharCode(92,34) = //'
// Para JS: /',/",/r,/n,//.... son un solo caracter
/*
String.prototype.m_a_vTextFormats=["TEXT"	,[String.fromCharCode(92)		,"\r" 	,"\n"    	,"'"	,'"']
 								  ,"HTML"	,["&#92;"				 		,""   	,"<BR />"	,"'"	,'"']
 								  ,"JS"  	,[String.fromCharCode(92,92)	,"\\r"	,"\\n"   	,"\'" 	,String.fromCharCode(92,34)]
 								  ,"JSHTML" ,[String.fromCharCode(92,92)	,""		,"<BR />"	,"\\'"	,String.fromCharCode(92,34)]
 								  ,"SQL" 	,[String.fromCharCode(92)	 	,""   	,""			,"''"	,""]
 								  ];
*/
String.prototype.m_a_vTextFormats=["TEXT"	,[String.fromCharCode(92)	 	,"\r" 	,"\n"		,"'"	,'"'	,'/'	]
 								  ,"HTML"	,["&#92;"				  	 	,""   	,"<BR />"	,"'"	,'"'	,'/'	]
 								  ,"JS"  	,[String.fromCharCode(92,92)	,"\\r"	,"\\n"		,"\\'"	,'\\"'	,'\\/'	]
 								  ,"JSHTML" ,[String.fromCharCode(92,92)	,""		,"<BR />"	,"\\'"	,'\\"'	,'\\/'	]
 								  ,"SQL" 	,[String.fromCharCode(92)		,"\r"   ,"\n"		,"''"	,'"'	,'/'	]
 								  ]

String.prototype.f_parse2Format= function (sFrom,sTo){
	var sStr=String( this );
	var nFrom=this.m_a_vTextFormats.f_indexOf(sFrom);
	var nTo=this.m_a_vTextFormats.f_indexOf(sTo);
	var a_sFrom=this.m_a_vTextFormats[nFrom+1];
	var a_sTo=this.m_a_vTextFormats[nTo+1];

	for(var n=0;n<a_sFrom.length;n++){
		sStr=sStr.f_replace(a_sFrom[n],a_sTo[n]);
	}
	return ( sStr );
}

String.prototype.f_removeAcentos = function () {
	var sTexto = this;
	var a_sOldChar = ["/[á]/g","/[é]/g","/[í]/g","/[ó]/g","/[úü]/g","/[Á]/g","/[É]/g","/[Í]/g","/[Ó]/g","/[ÚÜ]/g"]
	var a_sNewChar = ["a","e","i","o","u","A","E","I","O","U"]

	for (var f=0;f<a_sOldChar.length;f++){
		sTexto = sTexto.replace (eval(a_sOldChar[f]), a_sNewChar[f]);
	}
	return (sTexto)
}

//"abcx".f_replace("x","d");
//nAccion : (0 por defecto)  0=replace+delete / 1=insert delante / 2=insert detras
//	[DEPRECATED] 3=replace+delete+NoCaseSensitive	(Usar nAccion=0 y bCaseInd=1)
//bOnlyOne : (0 por defecto)  0=realiza n cambios 1=realiza solo 1 cambio
String.prototype.f_replace=function(sBuscado,sNuevo,nAccion,bOnlyOne,nStartPos,bCaseInd){	// 9.2 Search & insert/replace/delete un texto
	if (nAccion==3) {
		nAccion = 0
		bCaseInd = 1
	}

	if (!sBuscado) bOnlyOne=1;
	if (!bOnlyOne) bOnlyOne=0;
	if (!nAccion)  nAccion =0;
	var nPos1, nPos2, sTexto=this;
	if (sNuevo==null) sNuevo="";
	var sNuevoTmp = "";
	var nBuscado= sBuscado.length;
	var nNuevo	= sNuevo.length;

	if (bCaseInd) {
		sBuscado = sBuscado.toUpperCase()
		nPos1 = sTexto.toUpperCase().indexOf(sBuscado, nStartPos);
	}
	else nPos1 = this.indexOf(sBuscado,nStartPos);

	var nC = 0;
	while (nPos1!=-1 && ++nC<1000){
		nPos2=nPos1;
		if (nAccion==0) nPos2 += nBuscado;
		if (nAccion==2) {
			nPos1 += nBuscado;
			nPos2 += nBuscado;
		}
		if (bCaseInd) {
			sNuevoTmp = sNuevo.f_replace("<SEARCH />", sTexto.substring(nPos1, nPos1+nBuscado) );
			nNuevo	  = sNuevoTmp.length;
			sTexto = sTexto.substr(0,nPos1) + sNuevoTmp + sTexto.substr(nPos2);
		}
		else {
			sTexto = sTexto.substr(0,nPos1) + sNuevo + sTexto.substr(nPos2);
		}
		//sTexto = sTexto.substr(0,nPos1) + sNuevo.f_replace("<"+"SEARCH /"+">", sTexto.substring(nPos1, nPos2) ) + sTexto.substr(nPos2);
		if (!bOnlyOne) {
			nPos1 += nNuevo;
			if (nAccion==1) nPos1 += nBuscado;
			if (bCaseInd){
				nPos1 = sTexto.toUpperCase().indexOf(sBuscado, nPos1);
			}
			else nPos1 = sTexto.indexOf(sBuscado,nPos1);
		}
		else nPos1=-1;
	}
	return (sTexto);
}

// [bNoLeft],[bNoRight]
String.prototype.f_trim = function(bNoTrimL,bNoTrimR) {
	var sTrimL, sTrimR;
	if (!bNoTrimL) sTrimL = "\\s"
	if (!bNoTrimR) sTrimR = "\\s"
	return (this.f_trimString (sTrimL, sTrimR, null, "g"))
}

// [sTrimL],[sTrimL],[sTrim],[sFlags]
String.prototype.f_trimString = function(sTrimL,sTrimR,sTrimAll,sFlags) {
	var sStr = this
	if (IsNull(sFlags)) sFlags = "g";	//Espacios
	if (sTrimL) {
		var re = new RegExp("^"+sTrimL+"*",sFlags);
		sStr = sStr.replace(re,"")
	}
	if (sTrimR) {
		var re = new RegExp(sTrimR+"*$",sFlags);
		sStr = sStr.replace(re,"")
	}
	if (sTrimAll) {
		var re = new RegExp(sTrimAll+"*",sFlags);
		sStr = sStr.replace(re,"")
	}
	return (sStr)
}


//
// Devuelve un número hexadecimal único para cada cadena (Se usa en los menus)
String.prototype.f_getHexCode = function () {
	var sStr = this;
	var vReturn = "", vCharCode;
	for (var f=0, F=sStr.length; f<F; f++) {
		vCharCode = sStr.charCodeAt(f);			// Caracter en ASCII
		vCharCode = vCharCode.toString(16);		// Entero a Hexadecimal
		vReturn  += vCharCode;
	}
	return (vReturn);
}


//
// [5] Array
//

Array.prototype.m_a_sCOLs = [];
Array.prototype.m_a_aROWs = [];

// v0.823 [new] Array.prototype.f_replace - Jonas
Array.prototype.f_replace=function(sBuscado,sNuevo,nAccion,bOnlyOne,nStartPos,bCaseInd){
	var a_new = [];
	for ( var f=0, F=this.length; f<F; f++ ){
		a_new.push( String(this[f]).f_replace(sBuscado,sNuevo,nAccion,bOnlyOne,nStartPos,bCaseInd) );
	}
	return a_new;
}

// Igual que f_insert, pero modifica directamente el array que le pasamos
Array.prototype.f_add=function (a_vValores,nPos){
	var f
	var nLen = this.length;
	if (!IsArray(a_vValores)) a_vValores = [a_vValores]
	var nLenSub = a_vValores.length;
	if (nPos>=0) {
		for (f=nLen;f>nPos;f--) {
			this [f+nLenSub] = this [f]
		}
	}
	else {
		nPos = nLen
	}
	for (f=0; f<nLenSub; f++){
		this [nPos+f] = a_vValores[f]
	}
}

Array.prototype.f_move=function (nPosI, nPosF){
	var vVal  = this[nPosI];
	var a_new = this.f_delete(nPosI, 1);
//	if ( nPosI < nPosF ) nPosF++;
	a_new = a_new.f_insert(vVal, nPosF);
	return (a_new);
}

Array.prototype.f_addArguments=function (){
	for(var n=0;n<arguments.length;n++){
		this[this.length]=arguments[n];
	}
}

Array.prototype.f_avg = function (){
	var nSuma = 0, nTotal = 0
	for (var f=0;f<this.length;f++){
		nSuma += Number (this[f])
		if(this[f]!=''){nTotal++}
	}
	if(nTotal!=0) nTotal = nSuma / nTotal
	return (nTotal)
}

Array.prototype.f_copy = function (){
	return (this.concat())
}

// Cuenta el numero de coincidencias de un valor en el Array
Array.prototype.f_countMatches=function (vValue,sProp,bCaseInd,bParte,nStartPos){
	var vValueC,f;
	var nLen = this.length;
	if (bCaseInd) vValue = vValue.toLowerCase();
	var nCount=0;
	if (!nStartPos) nStartPos=0
	for (f=nStartPos;f<nLen;f++){
		if(sProp) eval("vValueC=this[f]."+sProp) ;
		else vValueC = this[f];
		if (bCaseInd) vValueC = vValueC.toLowerCase();
		if (bParte) {
			if (vValueC.indexOf(vValue)!=-1) nCount++;
		}
		else{
			if (vValueC==vValue) nCount++;
		}
	}
	return (nCount);
}

//Borra el numero de elementos (nElements) desde la posicion (nPos)
Array.prototype.f_delete=function (nPos,nElements){
	if(!nElements) nElements=this.length-nPos;
	var a_vItem1=this.slice(0, nPos);
	var a_vItem2=this.slice(nPos+nElements);
	return ( a_vItem1.concat(a_vItem2) );
}

Array.prototype.f_getMax = function (){
	var aTemp = [].concat(this)
	return (aTemp.sort(OrdenNumerico).reverse())[0]
}

Array.prototype.f_getMin = function (){
	var aTemp = [].concat(this)
	return (aTemp.sort(OrdenNumerico))[0]
}

Array.prototype.f_getVal = function (nIndex){
	var sVal = ''
	if (!isNaN(nIndex) && nIndex<this.length){
		 sVal = this [nIndex]
	}
	return (sVal)
}

Array.prototype.f_getVals = function (vIndex){
	if(!IsArray(vIndex)) vIndex=[vIndex];
	var nIndex
	var a_vDatos = []
	for (var f=0;f<vIndex.length;f++)	{
		nIndex = vIndex [f]
		if (!isNaN(nIndex) && nIndex<this.length){
			 a_vDatos.push (this[nIndex])
		}
	}
	return (a_vDatos)
}

//Devuelve la posicion de vValue en el array, si no existe -1
//[sProp] para objetos
Array.prototype.f_indexOf=function (sBuscado,sProp,bCaseInd,bParte,nStartIndex,nStartPos,bAcentoInd){
	var vValueC;
	var nPos=-1;
	// String(sBuscado)=="undefined"
	if (IsNull(sBuscado)) return (nPos)
	sBuscado = sBuscado.toString()
	if (!nStartIndex) nStartIndex=0
	var f=nStartIndex;
	var nLen=this.length;
	if (bCaseInd) sBuscado = sBuscado.toLowerCase();
	if (bAcentoInd)	sBuscado = sBuscado.f_removeAcentos()
	while(f<nLen && nPos<0){
		if(sProp){
			eval("vValueC=this[f]."+sProp)
		}
		else {
			if (String(this[f]) == "undefined") break
			vValueC = this[f];
		}
		vValueC = vValueC.toString()
		if (bParte) {
			if (vValueC.f_indexOf(sBuscado,nStartPos,bCaseInd,0,bAcentoInd)!=-1) nPos=f;
		}
		else{

			if (bCaseInd) vValueC = vValueC.toLowerCase();
			if (nStartPos) vValueC = vValueC.substr(nStartPos)
			if (bAcentoInd)	 vValueC = vValueC.f_removeAcentos()

			if (vValueC==sBuscado) nPos=f;
		}
		f++
	}
	return (nPos);
}

// Devuelve el value que esta en la posicion relativa al valor buscado
Array.prototype.f_indexOfVal=function (sBuscado,nPosVal,vReturn){
	var sVal=(vReturn==0 || vReturn)? vReturn : "";
	var nPos = this.f_indexOf (sBuscado)
	if (nPos!=-1) sVal = this[nPos+nPosVal]
	return (sVal)
}

Array.prototype.f_insert = function(a_vArrayMed,nPos){
var a_vArrayIni, a_vArrayFin = []
	if (nPos==null){

		a_vArrayIni = this
	}
	else{
		a_vArrayIni = this.slice(0, nPos)
		a_vArrayFin = this.slice(nPos)
	}
	return (a_vArrayIni.concat(a_vArrayMed,a_vArrayFin))
}

//nAccion: 0=replace / 1=insert delante / 2=insert detras
Array.prototype.f_setVals=function (sValor,nAccion){
	var sValorT = sValor
	for (var f=0;f<this.length;f++){
		if (nAccion==1) sValorT = sValor + this[f];
		if (nAccion==2) sValorT = this[f]+ sValor;
		this[f] = sValorT
	}
}

// [bIndices]			Devuelve array con valores/indices				0/1
// [bOrdenacion]		Ordenado creciente/decreciente					0/1
// [nOrden]				""=auto 0=numerica 1=alfabetica 2=fecha
// [bCaseDependiente]	0=AaBb		1=ABab
Array.prototype.f_sort=function (bIndices,bOrdenacion,nOrden,bCaseDependiente){
var f=0,vValor,vValorT,sCifrasF,nCifrasF
	var bValoresNulos=0
	var nLength = this.length				//elementos
	if (nLength==0) return (this)

	var a_vArrayWork = []
	a_vArrayWork = a_vArrayWork.concat(this)

	var nCifras = nLength.toString().length		// cifras
	var sBase = "000000"

	if (nOrden==null || nOrden==""){			// determinamos el tipo de datos
		nOrden=0						//Numeros
		while (nOrden==0 && f<nLength){				//buscamos algun texto
			vValor = a_vArrayWork[f++]
/*
			if (IsUndefined(vValor)) vValor=""
			vValor = vValor.toString().replace(/[,]/g,".")				// cambio comas por puntos
			if (vValor!=parseFloat(vValor)) nOrden=1		//Texto
*/
			if (!IsNull(vValor) && isNaN(vValor) && vValor!=""){
				vValor = vValor.toString().replace(/[,]/g,".")				// cambio comas por puntos
				if (vValor!=parseFloat(vValor)) nOrden=1		//Texto
			}
			else {
				bValoresNulos=1
			}
		}

		if (!IsNull(vValor) && isNaN(vValor)) {
			var sDateFormat = "D/M/Y h:m"
			var sDateFormatOut = "nYYYYnMMnDDnHH24nMMN"
			if (vValor.length<=10) {
				sDateFormat = "D/M/Y"
				sDateFormatOut = "nYYYYnMMnDD"
				if (vValor.indexOf("/")==4) sDateFormat = "Y/M/D"
			}
			else {
				if (vValor.f_countMatches(":")==2) sDateFormat = "D/M/Y h:m:s"
			}
			vValorT = vValor.f_toDate(sDateFormat)

			if (GetType(vValorT)==Date) {
				for (f=0;f<nLength;f++){
					a_vArrayWork[f] =  a_vArrayWork[f].toString().f_toDateDraw (sDateFormat,sDateFormatOut)
				}
				nOrden=2
			}
		}
	}

	if (isNaN(nOrden) || (nOrden==0 && bValoresNulos)) {		//v0.743
		f=0
		while (f<nLength){
			vValor = a_vArrayWork[f++]
			if (vValor=="" || IsNull(vValor)) a_vArrayWork[f-1] = -999999999
		}
	}

	for (f=0;f<nLength;f++){
		sCifrasF = f.toString()
		nCifrasF = sCifrasF.length
		a_vArrayWork[f] = a_vArrayWork[f] + "" + sBase.substring(0,nCifras-nCifrasF) + sCifrasF
	}

	switch (nOrden){
	case 1:					//Str
		for (f=0;f<nLength;f++){
			if (!bCaseDependiente) a_vArrayWork[f] = a_vArrayWork[f].toLowerCase()
			a_vArrayWork[f] = a_vArrayWork[f].f_removeAcentos()
		}
		a_vArrayWork.sort()
		break
	case 2:					//Date
		a_vArrayWork.sort()
		break
	default:				//Num
		a_vArrayWork.sort(OrdenNumerico)
	}

	var a_vArrayDest = []
	if (bIndices){								//Indices
		for (f=0;f<nLength;f++){
			vValor = a_vArrayWork[f]
			a_vArrayDest[f] = parseInt (vValor.substr(vValor.length-(nCifras)),10)
		}
	}
	else{										//Vals
		for (f=0;f<nLength;f++){
			vValor = a_vArrayWork[f]
			a_vArrayDest[f] = this [parseInt (vValor.substr(vValor.length-(nCifras)),10)]
		}
	}
	if (bOrdenacion) a_vArrayDest.reverse()		//Desc

	return (a_vArrayDest)
}

function OrdenNumerico(nValor1,nValor2){	//pasa del caso de igualdad
	if (parseFloat(nValor1)==parseFloat(nValor2)) return (0);
	if (parseFloat(nValor1)<parseFloat(nValor2)) return (-1);
	return (1);
}

// Devuelve array ordenado con los elementos diferentes del primer array o repetidos en los 2 arrays
// [bRepetidos] devuelve array de elementos repetidos
// [bPos] : 0=array de Datos 1=array de Indices
Array.prototype.f_subCompare=function (a_vArray,bRepetidos,bPos,bCaseInd,bDistintosAll){
	var g = 0;
	var a_vUnicos = []
	var a_vUnicosPos = []
	for (var f=0;f<this.length;f++){
		if (a_vArray.f_indexOf(this[f],0,bCaseInd)==-1) {
			if (!bRepetidos) {
				a_vUnicos[g] = this[f]
				a_vUnicosPos[g++] = f;
			}
		}
		else {
			if (bRepetidos) {
				a_vUnicos[g] = this[f]
				a_vUnicosPos[g++] = f;
			}
		}
	}
	if (!bRepetidos && bDistintosAll) {
		for (var f=0;f<a_vArray.length;f++){
			if (this.f_indexOf(a_vArray[f],0,bCaseInd)==-1) {
				a_vUnicos[g] = a_vArray[f]
				a_vUnicosPos[g++] = f;
			}
		}
	}

	if (a_vUnicos.length>1) a_vUnicos = a_vUnicos.f_sort();
	if (bPos) a_vUnicos = a_vUnicosPos;
	return (a_vUnicos)
}

// Devuelve el array sin los elementos con el mismo valor que le pasamos
Array.prototype.f_subDelete= function (sTexto) {
	return (this.f_subIndexOf (sTexto,0,0,0,0,0,0,1))
}

// Devuelve array ordenado con los elementos unicos de 1 array (distinct)
// [bPos] : 0=array de Datos 1=array de Pos
// [bRepetidos] : devuelve los repetidos
Array.prototype.f_subDistinct=function (bPos,bCaseInd,bRepetidos,bNoOrdenado){
	var g = 0, h=0;
	var a_vUnicos = []
	var a_vUnicosPos = []
	var a_vRepetidos = []
	var a_vRepetidosPos = []
	for (var f=0;f<this.length;f++){
		if (a_vUnicos.f_indexOf(this[f],0,bCaseInd)==-1) {
			a_vUnicos[g] = this[f]
			a_vUnicosPos[g++] = f;
		}
		else {
			a_vRepetidos[h] = this[f]
			a_vRepetidosPos[h++] = f;
		}
	}
	if (!bRepetidos) {
		if (bPos) a_vUnicos = a_vUnicosPos;
	}
	else {
		a_vUnicos = a_vRepetidos	//.f_sort();
		if (bPos) a_vUnicos = a_vRepetidosPos;
	}
	if (!bNoOrdenado && !bPos) a_vUnicos = a_vUnicos.f_sort()
	return (a_vUnicos)
}

Array.prototype.f_subIndexOf = function(sTexto,bIndices,bCaseDependiente,bParte,bAcentoDependiente,nStartIndex,nStartPos,bDistinto){
	var f,vValue,vValueC,nIndex
	var a_vFinal= []
	var nFinal=0

	sTexto = String(sTexto);
	if (!nStartIndex) nStartIndex = 0
	for (f=nStartIndex;f<this.length;f++){
		vValue = String(this[f]);
		if (bParte) {
			nIndex = vValue.f_indexOf(sTexto,nStartPos,!bCaseDependiente)
		}
		else {
			vValueC = vValue
			if (!bCaseDependiente){
				sTexto = sTexto.toUpperCase()
				vValueC = vValueC.toUpperCase()
			}
			if (!bAcentoDependiente){
				 sTexto = sTexto.f_removeAcentos()
				 vValueC = vValueC.f_removeAcentos()
			}
			nIndex= -1
			if (vValueC==sTexto) nIndex=1
		}
		if (nIndex!=-1 ^ bDistinto ){
			if (bIndices) vValue = f
			a_vFinal[nFinal++]= vValue
		}
	}
	return (a_vFinal);
}

Array.prototype.f_suma = function (){
	var nNum, nSuma = 0
	for (var f=0;f<this.length;f++){
		nNum   = Number (this[f])
//alert(nNum+"\n"+this[f])
		if(!isNaN(nNum)) nSuma += nNum;
	}
	return (nSuma)
}

// *** DEP **
Array.prototype.f_addElements=function (){
	var oArgs=( IsArray(arguments[0]) )? arguments[0] : arguments;
	for(var n=0;n<oArgs.length;n++){
		this[this.length]=oArgs[n];
	}
}
Array.prototype.f_cmpElements=function (a_vArray,bRepetidos,bPos,bCaseInd){
	return (this.f_subCompare (a_vArray,bRepetidos,bPos,bCaseInd))
}
Array.prototype.f_delOfArray=function (nPos,nElements){
	return (this.f_delete (nPos,nElements))
}
Array.prototype.f_getColIf = function (vValue,bCaseInd,bParte,nStartIndex,nStartPos){
	return (this.f_subIndexOf(vValue,1,!bCaseInd,bParte,0,nStartIndex,nStartPos) )
}
Array.prototype.f_getDistinct=function (bPos,bCaseInd){
	return (this.f_subDistinct (bPos,bCaseInd))
}
Array.prototype.f_getValFromIndex = function (a_nIndex) {
	return (this.f_getVals (a_nIndex))
}
Array.prototype.f_subVal = function (a_nIndex) {
	return (this.f_getVals (a_nIndex))
/*
	var a_vValues = []
	for (var f=0; f<a_nIndex.length; f++){
		a_vValues [f] = this [a_nIndex[f]]
	}
	return (a_vValues)
*/
}
// ***

// [6] MArray
// Reg = numero Registro
// Row = Datos de 1 Fila (Registro)
// Col = Datos de 1 Columna (Campo)
// Val = Valor del Campo de un Registro


Array.prototype.f_addColEXML=function (sCampo,sEXML){
	oIEXML.f_addColEXML (this,sCampo,sEXML)
}

Array.prototype.f_modColEXML=function (sCampo,sEXML){
	oIEXML.f_modColEXML (this,sCampo,sEXML)
}


//Añade un columna nueva a un MArray
//sNewCol  : Nombre de la nueva columna
//nValor : Valor para la nueva columna
Array.prototype.f_maAddCol=function (sNewCol,vValor){
	var a_vNextValues = []
	var nCols = this[0].length
	var nPosOld = this[1].length - 1
	var nRegs= this.f_maGetRegs();
	this[0].f_addElements(sNewCol);
	var nPosNew = nPosOld + nRegs
	for(var n=nRegs;n>0;n--){
		this[1][nPosNew--]=vValor;
		if (n>1) {
			for (var f=0; f<nCols; f++){
				this[1][nPosNew--] = this[1][nPosOld--]
			}
		}
	}
}

//Copia columnas de un array a otro cuando tienen un campo que los relaciona
// vCampoRelacionado = s/a = sCampo/['sCampoS','sCampoD']
// vCampoS = s/a = sCampo/[sCampo1,sCampo2...]
// [vCampoD] = s/a = sCampo/[sCampo1,sCampo2...]
Array.prototype.f_maCopyCols=function (a_ArrayS,vCampoRel,vCampoS,vCampoD){
	var sCampoD,nID,nReg,vValue
	var sCampoRelS = vCampoRel
	var sCampoRelD = vCampoRel
	if (IsArray(vCampoRel)){
		sCampoRelS = vCampoRel[0]
		sCampoRelD = vCampoRel[1]
	}
	if (!IsArray(vCampoS)) vCampoS = [vCampoS]
	if (!IsArray(vCampoD)) vCampoD = [vCampoD]
	for (var f=0;f<vCampoS.length;f++){
		sCampoD = vCampoD[f]
		if (!sCampoD) {
			sCampoD = vCampoS[f]
			vCampoD[f] = vCampoS[f]
		}
		if (this[0].f_indexOf(sCampoD)==-1) {
			this.f_maAddCol(sCampoD,"");
		}
	}
	for(var n=0;n<this.f_maGetRegs();n++){
		nID =this.f_maGetVal(sCampoRelD,n);
		nReg  =a_ArrayS.f_maGetReg(sCampoRelS,nID);
		for (var f=0;f<vCampoS.length;f++){
			vValue=a_ArrayS.f_maGetVal(vCampoS[f],nReg);
			this.f_maSetVal(vCampoD[f],vValue,n);
		}
	}
}
String.prototype.f_maCopyCols=function (a_ArrayS,vCampoRel,vCampoS,vCampoD){
	(this.f_maBArray2MArray()).f_maCopyCols (a_ArrayS,vCampoRel,vCampoS,vCampoD)
}

// numero de coincidencias de los valores de un columna
Array.prototype.f_maCountMatches=function (sFieldName,vValue,sProp,bCaseInd,bParte,nStartPos){
	var a_vCountMatches=[];
	for(var n=0;n<this.f_maGetRegs();n++){
		a_vCountMatches.f_addElements(this.f_maGetVal(sFieldName,n));
	}
	return ( a_vCountMatches.f_countMatches(vValue,sProp,bCaseInd,bParte,nStartPos) );
}
String.prototype.f_maCountMatches = function(sFieldName,vValue,sProp,bCaseInd,bParte,nStartPos){
	return ((this.f_maBArray2MArray()).f_maCountMatches(sFieldName,vValue,sProp,bCaseInd,bParte,nStartPos))
}

Array.prototype.f_maDeleteCol=function (a_sCampos){
	if(!IsArray(a_sCampos)) a_sCampos=[a_sCampos];
	var a_nPosiciones = this[0].f_subCompare ( a_sCampos,1,1,0)
	a_nPosiciones.reverse()		//para borrar 1º los ultimos

	var a_vArray=this[1];
	var nCampos = this[0].length
	var nRegs = this.f_maGetRegs()
	var nLastRegPos = nCampos * (nRegs-1)

	for(var f=0; f<nRegs;f++){
		for (var g=0; g<a_nPosiciones.length; g++){
			if (f==0) this[0].splice(a_nPosiciones[g], 1)
			this[1].splice(nLastRegPos+a_nPosiciones[g], 1)
		}
		nLastRegPos -= nCampos
	}
}

//Borra Filas
//[nRegPos] : 0-(n-1) Registro donde borramos. Por defecto es el ultimo.
//[nRegs] : Filas que borra. Por defecto 1
Array.prototype.f_maDeleteRow=function (nRegPos,nRegs){
	var a_vArray=this[1];
	if (nRegPos!=0 && !nRegPos) nRegPos =this.f_maGetRegs()-1;
	if (!nRegs) nRegs=1
	var nCampos = this[0].length
	var nDelPosIni = (nRegPos) * nCampos
	var nDelPosFin = (nRegPos+nRegs) * nCampos
	this[1]=a_vArray.slice(0, nDelPosIni);
	this[1]=this[1].concat(a_vArray.slice(nDelPosFin));
}

Array.prototype.f_maDeleteRows=function (a_nRegs){
	a_nRegs = a_nRegs.f_sort (0,1,0)
	for (var f=0;f<a_nRegs.length;f++) {
		this.f_maDeleteRow (a_nRegs[f],1)
	}
}

// Devuelve un Array con la columna pedida
Array.prototype.f_maGetCol=function (sCampo){
	var a_vCampo = [];
	if(this.f_maGetRegs() && sCampo && this[0].length!=0){
		var nCampoPos=this[0].f_indexOf(sCampo,"",1);
		if (nCampoPos != -1){
			var nCampos = this[0].length;
			for (var f=0;f<this.f_maGetRegs();f++){
				a_vCampo[f] = this[1] [(f*nCampos)+nCampoPos]
			}
		}
		else {
			ErrorJS ("f_maGetCol: no esta definido el campo ["+sCampo+"]\n"+this[0]+FunCaller(),"",1)		// de ["+sArrayBase+"]
		}
	}
	return (a_vCampo)
}
String.prototype.f_maGetCol=function (sCampo){
	return ((this.f_maBArray2MArray()).f_maGetCol(sCampo))
}

Array.prototype.f_maGetColName=function (nPos){
	return (this[0][nPos])
}

Array.prototype.f_maGetColPos=function (sCampo){
	return (this[0].f_indexOf(sCampo));
}
String.prototype.f_maGetColPos = function(sCampo){
	return ((this.f_maBArray2MArray()).f_maGetColPos(sCampo))
}

Array.prototype.f_maGetCols = function(){
	return (this[0].length)
}


// Devuelve el numero de registro en el que se encuentra un valor de un campo
// sValue :Valor buscado
// sFieldName:Nombre del campo
Array.prototype.f_maGetReg=function (sFieldName,sValue){
	var a_sTags=this[0], a_vValues=this[1], nPosValue=-1, nRegNum=-1, nPosInc=0;

	if(a_sTags.length!=0 && this.f_maGetRegs()){
		if(sFieldName) nPosInc=a_sTags.f_indexOf(sFieldName);
		var nPosC=nPosInc;
		sValue = String (sValue)
		while(nPosC<a_vValues.length && nPosValue==-1){
			if(a_vValues[nPosC]==sValue) nPosValue=nPosC;
			nPosC+=a_sTags.length;
		}
		if(nPosValue!=-1) nRegNum=Math.floor(nPosValue/a_sTags.length);
	}
	return (nRegNum)
}
String.prototype.f_maGetReg=function (sFieldName,sValue){
	return ((this.f_maBArray2MArray()).f_maGetReg(sFieldName,sValue))
}

Array.prototype.f_maGetRegIf = function(sCampoIn, sValueIn){
	var a_vCol=this.f_maGetCol(sCampoIn);
	var nReg  =a_vCol.f_indexOf(sValueIn);
	return ( nReg );
}

Array.prototype.f_maGetRegs=function (){
	var nRegs=0;
/*
	if(!IsArray(this[0]) || this[0].length==0 || !IsArray(this[1]) || this[1].length==0) {
		nRegs=0
	}
*/
//ErrorJS (this.length +"\n"+IsArray(this[0]) +"\n"+ IsArray(this[1]))
	if (this.length==2 && IsArray(this[0]) && IsArray(this[1])) {
		nRegs = this[1].length/this[0].length
	}

	if (nRegs>0 && (nRegs != Math.ceil(nRegs))){
		ErrorJS("[i_core.js "+ICore.m_nVersion +"] El numero de campos del MArray ["+ this[0].length+"] no es proporcional al numero de elementos ["+ this[1].length+ "]\n\n"+this.f_maDebug(),"",1) ;
	}
	return (nRegs);
}
String.prototype.f_maGetRegs = function(){
	return ((this.f_maBArray2MArray()).f_maGetRegs())
}

// Devuelva un array con los registros que cumplen TODAS las condiciones
Array.prototype.f_maGetRegsIf=function (a_sCampo,a_vValor){
	var nReg=-1, f=0, a_nRegs, a_nIndices
	a_nRegs=this.f_maSubIndexOf (a_sCampo[f],a_vValor[f],1);
	while (a_nRegs.length && ++f<a_sCampo.length) {
		a_nIndices = this.f_maSubIndexOf (a_sCampo[f],a_vValor[f],1)
		if (a_nIndices.length) {
			a_nRegs = a_nRegs.f_subCompare (a_nIndices,1,0)
		}
		else {
			a_nRegs = []
			break
		}
	}
	return (a_nRegs)
}

/*
[a_nReg/nReg]	Numero de Registro que queremos recoger (0 por defecto)
[sReturn]	Cadena que devuelve si no existe el campo/registro
*/
Array.prototype.f_maGetVal=function (sCampo,a_nReg,sReturn){
	var	vValor=""
	var bError=1
	if (!IsUndefined(sReturn)) {
		vValor = sReturn
		bError=0
	}
	var nCol = this[0].f_indexOf (sCampo,"",1)
	if (nCol != -1){
		if(!IsArray(a_nReg)) {
			if (IsUndefined(a_nReg)) a_nReg=0
			if (a_nReg>=this.f_maGetRegs()){
				if (bError) ErrorJS ("f_maGetVal: campo '"+sCampo+"' del registro "+a_nReg+" y este MArray solo tiene "+this.f_maGetRegs() +" registros."+FunCaller(),this,1)		// de ["+sArrayBase+"]
			}
			else {
				vValor=this[1][nCol+(this[0].length*a_nReg)];
			}
		}
		else{
			vValor = []
//No avisa si el registro se sale del rango
			for (var f=0;f<a_nReg.length;f++){
				vValor[f]=this[1][nCol+(this[0].length*a_nReg[f])];
			}
		}
	}
	else {
		if (bError) ErrorJS ("f_maGetVal: no esta definido el campo ["+sCampo+"]\n"+this[0]+FunCaller(),"",1)		// de ["+sArrayBase+"]
	}
	return (vValor);
}
String.prototype.f_maGetVal = function(sCampo,nReg,sReturn){
	return ((this.f_maBArray2MArray()).f_maGetVal(sCampo,nReg,sReturn))
}

//[sVal] Valor por defecto en el caso de que no haya ninguno
Array.prototype.f_maGetValIf=function (sField, sColName, vColVal, sVal){
	if (IsUndefined(sVal)) sVal = ""
	var nReg=this.f_maGetReg(sColName, vColVal);
//if (sColName=="sTAGName") alert (nReg+"\n"+vColVal)
	if (nReg!=-1) sVal = this.f_maGetVal(sField ,nReg)
	return (sVal);
}

//Une 2 marrays
Array.prototype.f_maJoin=function (a_maData){
//Debug(a_maData[0] + "_"+a_maData[0].length)
	for (var g=0;g<a_maData[0].length;g++) {	//Campos
//Debug(g+". "+a_maData[0][g])
//Debug(a_maData.f_maGetCol (a_maData[0][g]))
		this.f_maAddCol(a_maData[0][g],  a_maData.f_maGetCol (a_maData[0][g]))
	}
}



/*
a_vValues	: Valores del nuevo registro. Admite "" para insertar registro vacio
[nRegPos]	: Registro donde añadimos los nuevos valores. Por defecto es el ultimo.
[bDelRegs]	: Borra los registros cuya posicion haya sido sustituida
*/
Array.prototype.f_maNewRow=function (a_vValues,nRegPos,bDelRegs){
	var a_sArray=this[0], a_vArray=this[1];
	if (typeof(a_vValues)=="string") {
		a_vValues = []
		for (var f=0; f<a_sArray.length; f++){
			a_vValues[f] = ""
		}
	}

	if((a_vValues.length%a_sArray.length)!=0) {
		ErrorJS("f_maNewRow(): a_vValues tiene tamaño "+a_vValues.length+" y deberia ser "+a_sArray.length+"\nValores: "+a_vValues+"\n"+this.f_maDebug(),"",1) ;
	}
	else{
		nRegPos=(!nRegPos && nRegPos!=0)? a_vArray.length : nRegPos*a_sArray.length;
		this[1]=a_vArray.slice(0, nRegPos);
		if (!IsArray(a_vValues)) {
			if (a_vValues.length){
				var a_vValuesNew = []
				for (var f=0; f<a_vValues.length; f++){
					a_vValuesNew[f] = a_vValues[f]
				}
				a_vValues = a_vValuesNew
			}
//			else {
//				a_vValues = a_vValues.toString().split(",")
//			}
		}
		else {
			a_vValues = ArrayObject2Array (a_vValues);
		}

		this[1]=this[1].concat(a_vValues);
		if(bDelRegs) this[1]=this[1].concat(a_vArray.slice(nRegPos+a_vValues.length));
		else this[1]=this[1].concat(a_vArray.slice(nRegPos));
	}
}



Array.prototype.f_maGetRows = function (a_nRegs){
	if(!IsArray(a_nRegs)) a_nRegs=[a_nRegs];
	var nPos, a_vRows=[];
	for(var f=0; f<a_nRegs.length; f++){
		nPos=Number(a_nRegs[f]*this[0].length);
		a_vRows=a_vRows.concat(this[1].slice(nPos, nPos+this[0].length));
	}
	return (a_vRows);
}

Array.prototype.f_maSetVal=function (sCampo,vValue,nReg){
	this[1][(nReg*this[0].length)+this[0].f_indexOf(sCampo,"",1)]=vValue;
}
String.prototype.f_maSetVal = function(sCampo,Value,nRegistro){
	return ((this.f_maBArray2MArray()).f_maSetVal(sCampo,Value,nRegistro))
}

Array.prototype.f_maSetValIf=function (sCampoIf,sValueIf,sCampo,vValue, bAddIfNot){
	var nReg = this.f_maGetReg (sCampoIf,sValueIf)
	if (nReg!=-1) {
		this.f_maSetVal (sCampo, vValue, nReg);
	}
	else {
		if(bAddIfNot){
			this.f_maNewRow (new Array(this[0].length));
			nReg = this.f_maGetRegs()-1;
			this.f_maSetVal (sCampoIf, sValueIf, nReg);
		}
	}
}

Array.prototype.f_maSort = function(sCampo,bIndices,bOrdenacion,nOrden,bCaseDependiente){
	var a_vOrdenado = []
	var a_vCol = this.f_maGetCol (sCampo)
	if (a_vCol.length) a_vOrdenado = a_vCol.f_sort (bIndices,bOrdenacion,nOrden,bCaseDependiente)
	return (a_vOrdenado)
}
String.prototype.f_maSort = function(sCampo,bIndices,bOrdenacion,nOrden,bCaseDependiente){
	return ((this.f_maBArray2MArray()).f_maSort(sCampo,bIndices,bOrdenacion,nOrden,bCaseDependiente))
}

Array.prototype.f_maSubDistinct = function(sCampo,bIndices,bCaseDependiente,bRepetidos,bOrdenados){
	var a_vDistinct = []
	var a_vCol = this.f_maGetCol (sCampo)
	if (a_vCol.length) a_vDistinct = a_vCol.f_subDistinct (bIndices,!bCaseDependiente,bRepetidos,!bOrdenados)
	return (a_vDistinct)
}
String.prototype.f_maSubDistinct = function(sCampo,bIndices,bCaseDependiente,bRepetidos,bOrdenados){
	return ((this.f_maBArray2MArray()).f_maSubDistinct(sCampo,bIndices,bCaseDependiente,bRepetidos,bOrdenados))
}

// vLogic: OR / AND / NOT / XOR
// 	OR : 		 	sCampo	/a_sValor
// 	OR/AND/NOT/XOR: a_sCampo/a_sValor
// [bIndices],[bCaseDep],[bParte],[bAcentoDep],[bRepetidos],[bDistinto],[vLogic]
Array.prototype.f_maSubIndexOf = function(vCampo,vValor,bIndices,bCaseDep,bParte,bAcentoDep,bRepetidos,bDistinto,vLogic){
	var f,g,a_vCol, a_vSubVal, sLogic
	var a_vSub = []
	if (!bDistinto) bDistinto=0

	if (!IsArray(vCampo)) {
		vCampo = [vCampo];
		vValor = [vValor];
		if (!vLogic) vLogic = ["OR"]
	}
	else {
		if (!vLogic) vLogic = ["AND"]
	}
	if (!IsArray (vLogic)) vLogic = [vLogic]

	if (vCampo.length!=vValor.length) {
		ErrorJS("[f_maSubIndexOf] Los parámetros vCampo y vValor tienen distinta dimensión:\n["+vCampo.length+"] "+ vCampo +"\n["+vValor.length+"] "+ vValor+"\n","",1) ;
	}

/*
		a_vCol = this.f_maGetCol (vCampo)
		if (a_vCol.length) {
			if(!IsArray(vValor)) vValor = [vValor];
			for (f=0;f<vValor.length;f++){
				a_vSub = a_vSub.concat(a_vCol.f_subIndexOf (vValor[f],bIndices,bCaseDep,bParte,bAcentoDep,0,0,bDistinto))
			}
			if (vValor.length>1 && !bRepetidos) a_vSub = a_vSub.f_subDistinct (0,!bCaseDep,bRepetidos,1)
		}
	}
*/

	sLogic = "OR"	//La primera es siempre OR
	for (f=0;f<vCampo.length;f++){
		a_vCol = this.f_maGetCol (vCampo[f])
		a_vVal = vValor[f]

//Array.prototype.f_maGetVal=function (sCampo,a_nReg,sReturn)
//Optimizar: solo coja los valores que no tenemos ya
		if(!IsArray(a_vVal)) a_vVal = [a_vVal];
		a_vSubVal = []
		for (g=0;g<a_vVal.length;g++) {
			a_vSubVal = a_vSubVal.concat(a_vCol.f_subIndexOf (a_vVal[g],bIndices,bCaseDep,bParte,bAcentoDep,0,0,bDistinto))
//alert(f+"_"+g+" "+vCampo[f]+"="+vValor[g]+"\n"+a_vSubVal)
		}

		switch (sLogic) {
			case "OR":
				a_vSub = a_vSub.concat (a_vSubVal)
				break
			case "AND":
				a_vSub = a_vSub.f_subCompare (a_vSubVal,1)
				break
			case "NOT":
//alert(a_vSub+"\n_"+a_vSubVal+"\n_"+(a_vSub.f_subCompare (a_vSubVal,1)).f_subCompare (a_vSubVal,0,0,0,1))
				a_vSub = (a_vSub.f_subCompare (a_vSubVal,1)).f_subCompare (a_vSub,0,0,0,1)
				break
			case "XOR":
				a_vSub = a_vSub.f_subCompare (a_vSubVal,0,0,0,1)
				break
		}
		if (f<vLogic.length) {
			sLogic = vLogic[f]
		}
	}
	if (!bRepetidos) a_vSub = a_vSub.f_subDistinct (0,!bCaseDep,bRepetidos,1)
//Devolver ordenados los indices?
	return (a_vSub)
}

String.prototype.f_maSubIndexOf = function(sCampo,sTexto,bIndices,bCaseDep,bParte,bAcentoDep){
	return ((this.f_maBArray2MArray()).f_maSubIndexOf(sCampo,sTexto,bIndices,bCaseDep,bParte,bAcentoDep))
}

Array.prototype.f_maSubSort = function(a_nIndices,sCampo,bIndices,bOrdenacion,nOrden,bCaseDependiente){
	var a_vOrdenado = []
	var a_vCol = this.f_maGetVal (sCampo,a_nIndices)
	if (a_vCol.length) a_vOrdenado = a_vCol.f_sort (bIndices,bOrdenacion,nOrden,bCaseDependiente)
	if (bIndices) a_vOrdenado = a_nIndices.f_getVals (a_vOrdenado)
	return (a_vOrdenado)
}

String.prototype.f_maSubSort = function(a_nIndices,sCampo,bIndices,bOrdenacion,nOrden,bCaseDependiente){
	return ((this.f_maBArray2MArray()).f_maSubSort(a_nIndices,sCampo,bIndices,bOrdenacion,nOrden,bCaseDependiente))
}



//Da un subarray con los camposOut cuando el campoIn es igual al valor pasado
//Para los indices usar f_maSubIndexOf
// vValue = sText/a_sTextos
// [a_sCampoOut] : Por defecto devuelve todos los campos
// [bDistinto] : cuando el campoIn NO es igual
Array.prototype.f_maSubValIf = function (sCampoIn,vValue,a_sCampoOut,bCaseDep,bParte,bDistinto,bAcentoDep,bRepetidos){
	var a_vCampoOut = new Array();
	if (!this.f_maGetRegs()) return (a_vCampoOut)
	if(a_sCampoOut && !IsArray(a_sCampoOut)) a_sCampoOut = [a_sCampoOut];			//Compatibilidad: si viene una cadena lo convertimos en un array con un solo valor
	if(!a_sCampoOut || a_sCampoOut.length==0) a_sCampoOut = this[0];

	var a_nSubIndex = this.f_maSubIndexOf (sCampoIn,vValue,1,bCaseDep,bParte,bAcentoDep,bRepetidos,bDistinto)
	for (var f=0;f<a_nSubIndex.length;f++){
	 	for(var g=0; g<a_sCampoOut.length; g++){
	 		a_vCampoOut[a_vCampoOut.length] = this.f_maGetVal(a_sCampoOut[g],a_nSubIndex[f]);
	 	}
	}
	return (a_vCampoOut)
}

//Da un subarray con los camposOut de los registros a_nRegs
// [a_sCampoOut] : Por defecto devuelve todos los campos
Array.prototype.f_maSubValByRegs =function (a_sCampoOut, a_nRegs){
	var a_vVals=new Array();
	if(a_sCampoOut && !IsArray(a_sCampoOut)) a_sCampoOut = [a_sCampoOut];
	if(!a_sCampoOut || a_sCampoOut.length==0) a_sCampoOut = this[0];
	for(var f=0; f<a_nRegs.length; f++){
		for(var g=0; g<a_sCampoOut.length; g++){
			a_vVals[a_vVals.length]=this.f_maGetVal(a_sCampoOut[g], a_nRegs[f]);
		}
	}
	return (a_vVals);
}

Array.prototype.f_maSuma = function (sCampo,a_nRegs){
	var a_sValores = []
	if (a_nRegs) {
		a_sValores = this.f_maGetVal (sCampo,a_nRegs)
	}
	else {
		a_sValores = this.f_maGetCol (sCampo)
	}
	return (a_sValores.f_suma())
}

Array.prototype.f_maSumaCampos = function (a_sCampos,a_nRegs){
	if(!IsArray(a_nRegs)) a_nRegs = [a_nRegs];
	var maValores = this.f_maSubValByRegs (a_sCampos, a_nRegs)
	var a_sValores = new Array()
	for (var f=0;f<a_nRegs.length;f++) {
		a_sValores = a_sValores.concat(maValores[f])
	}
	return (a_sValores.f_suma())
}


// sCampo,[sCampoIf],[sValueIf]
Array.prototype.f_maSumaColIf = function (sCampo,sCampoIf,sValueIf,bDistinto){
	var a_sValores = []
	if (sCampoIf) {
		a_sValores = this.f_maSubValIf (sCampoIf,sValueIf,sCampo,0,0,bDistinto)
	}
	else {
		a_sValores = this.f_maGetCol (sCampo)
	}
	return (a_sValores.f_suma())
}
String.prototype.f_maSumaColIf = function(sCampo,sCampoIf,sValueIf,bDistinto){
	return ((this.f_maBArray2MArray()).f_maSumaColIf(sCampo,sCampoIf,sValueIf,bDistinto))
}

// Pasa dos arrays a MArray
String.prototype.f_maBArray2MArray = function(){
	return ([eval ("a_s"+this),eval ("a_v"+this)])
}

// *** DEP **
Array.prototype.f_addCol=function (sNewCol,vValor){
	this.f_maAddCol (sNewCol,vValor)
}
Array.prototype.f_addRegVal=function (a_vValues,nRegPos,bDelRegs){
	this.f_maNewRow (a_vValues,nRegPos,bDelRegs)
}
Array.prototype.f_copyCol=function (a_Array,sRel,sNew){
	this.f_maCopyCols (a_Array,sRel,sNew)
}
Array.prototype.f_maDelRow=function (nRegPos,nRegs){	// DEP usar f_maDeleteRow que va de 0-(n-1)
	if (nRegPos) nRegPos --
	this.f_maDeleteRow (nRegPos,nRegs)
}
Array.prototype.f_getRegNumOfVal=function (sFieldName,sValue){
	return (this.f_maGetReg (sFieldName,sValue))
}
Array.prototype.f_getRegsNum=function (){
	return (this.f_maGetRegs())
}
	String.prototype.f_getRegsNum = function(){
		return ((this.f_maBArray2MArray()).f_maGetRegs())
	}
Array.prototype.f_getRegVal=function (sCampo,nReg){
	return (this.f_maGetVal(sCampo,nReg))
}
	String.prototype.f_getRegVal = function(sCampo,nReg){
		return ((this.f_maBArray2MArray()).f_maGetVal(sCampo,nReg))
	}
Array.prototype.f_maBuscaValor=function (sFieldName,sValue){
	return (this.f_maGetReg(sFieldName,sValue))
}
	String.prototype.f_maBuscaValor=function (sFieldName,sValue){
		return ((this.f_maBArray2MArray()).f_maGetReg(sFieldName,sValue))
	}
Array.prototype.f_maDelReg=function (nRegPos,nRegs){
	this.f_maDelRow (nRegPos,nRegs)
}
Array.prototype.f_maGetColIf = function (sCampoIn,vValue,sCampoOut,bCaseInd,bParte){
	return (this.f_maSubValIf (sCampoIn,vValue,sCampoOut,bCaseInd,bParte))
}
Array.prototype.f_maGetDistinct = function(sCampo,bIndices,bCaseDependiente){
	return (this.f_maSubDistinct(sCampo,bIndices,bCaseDependiente))
}
	String.prototype.f_maGetDistinct = function(sCampo,bIndices,bCaseDependiente){
		return ((this.f_maBArray2MArray()).f_maSubDistinct(sCampo,bIndices,bCaseDependiente))
	}
Array.prototype.f_maGetValFromCol=function (sField, sColName, vColVal){
	return ( this.f_maGetValIf(sField, sColName, vColVal) );
}
Array.prototype.f_setRegVal=function (sCampo,vValue,nReg){
	return (this.f_maSetVal(sCampo,vValue,nReg))
}
	String.prototype.f_setRegVal = function(sCampo,vValue,nReg){
		return ((this.f_maBArray2MArray()).f_maSetVal(sCampo,vValue,nReg))
	}
// ***

// [7] Objetos
//Borra los elementos que le pasemos
//[ vValue, [sProp ]solo si es un objeto ]
Array.prototype.f_delElements=function (){
	var nPos, vValue, sProp;
	var a_vArray=this;
	for(var n=0;n<arguments.length;n+=2){
		vValue=arguments[n];
		sProp =arguments[n+1];
		nPos  =this.f_indexOf(vValue,sProp);
		if(nPos!=-1) a_vArray=this.f_delOfArray(nPos,1);		//esta funcion esta deprecated !!!
	}
	return (a_vArray);
}

//Cualquier 'Object' hereda todos los miembros de oObj
/*	Deprecated v0.826
Object.prototype.f_extend = function (oObj) {
	for (var sProp in oObj) {
		this[sProp] = oObj[sProp];
	}
}
*/


//Ordena un array de objetos según la propiedad sProperty
//[bDesc] 0-ASC o 1-DESC
protected_sArrayProperty="";
Array.prototype.f_sortBy=function (sProperty,bDesc){
	this.sort( function (p_vValue1,p_vValue2){ return (eval("p_vValue1."+protected_sArrayProperty) - eval("p_vValue2."+protected_sArrayProperty)); } );
}

//Objetos genéricos
oITraceFlags=new function(){
	this.m_sObj="oITraceFlags";
	this.m_a_Flags=[["sName","nTime"],[]];
	this.f_newFlag=function (sName){
		var nReg=this.m_a_Flags.f_getRegNumOfVal("sName",sName);
		if(nReg==-1) nReg=this.m_a_Flags.f_getRegsNum();
		this.m_a_Flags.f_addRegVal([sName,new Date().getTime()/1000],nReg);
	}

	this.f_getFlag=function (sName){
		var nTime1 = this.m_a_Flags.f_getRegVal("nTime",this.m_a_Flags.f_getRegNumOfVal("sName",sName));
		var nTime2 = new Date().getTime()/1000;
		return (nTime2-nTime1);
	}
}

// [8] Fecha

function ICrono(){
	this.m_sObj="ICrono";

	this.f_reset=function (){
		this.m_Start=new Date();
		this.m_Last =this.m_Start;
	}
	this.f_reset();

	this.f_get=function (bTexto){
		var oTime = new Date() - this.m_Last;
		this.m_Last = new Date();
		if (bTexto) oTime = " ["+oTime+"/"+(this.m_Last-this.m_Start)+"]"
		return oTime
	}
}

IDate = new function () {
	this.m_a_sDateNames =[["Lunes","Martes","Miércoles","Jueves","Viernes","Sábado","Domingo"]
							,["Enero","Febrero","Marzo","Abril","Mayo","Junio","Julio","Agosto","Septiembre","Octubre","Noviembre","Diciembre"]
							,["L","M","X","J","V","S","D"]
						];
}
Date.prototype.m_a_sDateNames=IDate.m_a_sDateNames;
Date.prototype.m_a_sDateChars=["nHH24","nH24","nHH12","nH12","sH12","nMMN","nMN","nSS","nS","nMIL","sDD","sD","nDD","nD","sMM","sM","nMM","nM","nYYYY","nYY"];
Date.prototype.f_drawFormat=function (sFormat,a_sSemana,a_sMeses){
	if (this=="undefined" || this=="NaN" || typeof(this)!="object") return ("")
	var cChar, nWeekDay=(this.getDay()>0)? this.getDay()-1 : 6;
//	var a_sSemana=(!a_sSemana)? this.m_a_sDateNames[0] : a_sSemana;
//	var a_sMeses =(!a_sMeses)? this.m_a_sDateNames[1] : a_sMeses;
	if (IsNull(a_sSemana)) a_sSemana=this.m_a_sDateNames[0]
	if (IsNull(a_sMeses)) a_sMeses=this.m_a_sDateNames[1]

	var sDD	 =a_sSemana[nWeekDay];
	var sD	 =sDD.substring(0, 3)+".";
	var nD	 =this.getDate();
	var nDD  =(nD<10)? "0"+nD : nD;
	var nM =this.getMonth()+1;
	var sMM  =a_sMeses[nM-1];
	var sM =sMM.substring(0, 3)+".";
	var nMM  =(nM<10)? "0"+nM : nM;
	var nYYYY=this.getYear();
	if (nYYYY < ICore.m_nY2K)  nYYYY += 2000
	if (nYYYY < 500) nYYYY += 1900
	var nYY  =String(nYYYY).substring(2,String(nYYYY).length);
	var nH24 =this.getHours();
	var nHH24=(nH24<10)? "0"+nH24 : nH24;
	var nH12 =((this.getHours()%12)==0)? 12 : this.getHours()%12;
	var nHH12=(nH12<10)? "0"+nH12 : nH12;
	var sH12 =(nH24>12)? "pm" : "am";
	var nMN  =this.getMinutes();
	var nMMN =(nMN<10)? "0"+nMN : nMN;
	var nS =this.getSeconds();
	var nSS  =(nS<10)? "0"+nS : nS;
	var nMIL =this.getMilliseconds();

	if (IsNull(sFormat)) sFormat = "nDD/nMM/nYYYY"
	var sDate=sFormat;
	for(var i=0; i<this.m_a_sDateChars.length; i++){
		cChar=this.m_a_sDateChars[i];
		vChar=eval(cChar);
		if(sFormat.indexOf(cChar)!=-1) sDate=sDate.f_replace(cChar,eval(cChar));
	}
	return ( sDate );
}

Date.prototype.f_printFormat=function (sFormat){ document.write( this.f_drawFormat(sFormat) ) }

/**
 * @deprecated usar el metodo <A href='#String.f_swapDateFormat'>f_toDateDraw()</A>
 */
String.prototype.f_swapDateFormat=function (sInputFormat, sOutputFormat){
	ErrorJS ("f_swapDateFormat deprecated: usa f_toDate","",5)
}

// [vDate]: oDate, sDate
Date.prototype.f_range= function (vDateMin,vDateMax) {
	var bOk =1
	if (vDateMin) {
		if (typeof(vDateMin)=="string") vDateMin=vDateMin.f_toDate()
		if (this<vDateMin) bOk=0
	}
	if (bOk && vDateMax) {
		if (typeof(vDateMax)=="string") vDateMax=vDateMax.f_toDate()
		if (this>vDateMax) bOk=0
	}
//alert (this+"\n"+vDateMin+"\n"+vDateMax+"\n"+bOk)
	return (bOk)
}

//[nMode] [0=Tiempo total]/1=Reset/2=Tiempo desde el anterior
Date.prototype.f_timer=function (nMode){
	var dTime;
	if (nMode==1) {
		var dHoy = new Date();
		this.setTime (dHoy.getTime());
	}
	if (nMode==2) {
		dTime = new Date() - ICore.m_nTimerLap
	}
	else {
		dTime = new Date() - this
	}
	ICore.m_nTimerLap = new Date();
	return (dTime)
}


// Solo importa el caracter que va despues del de formato
// "D/M/Y h:m_s.i"	"YMD"
// [nForceFormat] el dato tiene que tener el formato exacto que le pasamos 	[0/1/2] [No/Todos/solo el Y (YYYY/YY)]		//v0.783
String.prototype.f_toDate=function (sInputFormat,nForceFormat){
	if (!sInputFormat && IsDate(this)) {	//v0.906
		oDate=new Date(this);
	}
	else {
		var nLen,nLenInput,nChar,nDateType,nChar2,nDateType2,f
		var a_sDateTypes = ["Y","M","D","h","m","s","i"];
		var a_sDate = [0,1,1,0,0,0,0];
		var a_sLen =  [0,0,0,0,0,0,0];
		var oDate = null;		//v0.783
		var reF
		if (IsNull(sInputFormat)) sInputFormat = "D/M/Y"
		var sIF = sInputFormat
		var nDateDiffs = 0		//errores de formato con nForceFormat

		reF = RegExp("nYYYY|nYY|YYYY|YY|Y","gi");
		sIF = sIF.replace(reF,"Y");

		reF = RegExp("nMIL","g");		// Importante que se parseen antes que el mes (...nMM|nM|MM...)
		sIF = sIF.replace(reF,"i");
		reF = RegExp("nMMN|nMN","g");
		sIF = sIF.replace(reF,"m");

		reF = RegExp("sMM|sM|nMM|nM|MM","g");
		sIF = sIF.replace(reF,"M");
		reF = RegExp("sDD|sD|nDD|nD|DD","g");
		sIF = sIF.replace(reF,"D");
		reF = RegExp("nHH24|nH24|nHH12|nH12|sH12","g");
		sIF = sIF.replace(reF,"h");
		reF = RegExp("nSS|nS","g");
		sIF = sIF.replace(reF,"s");

		if (nForceFormat) { 			//v0.783
			for (f=0; f<sIF.length; f++) {
				if (a_sDateTypes.f_indexOf (sIF.charAt(f),"",0,0)!=-1) nDateDiffs++
			}
		}

		var sDate = this.f_trim()
		while (sIF.length) {
			nLen = 1
			nLenInput = 1

			nChar = sIF.charAt(0)
			nDateType = a_sDateTypes.f_indexOf (nChar,"",0,0)
			if (nDateType!=-1){		//Es un tipo de dato
				nDateDiffs--
				nChar2 = sIF.charAt(1)
				nDateType2 = a_sDateTypes.f_indexOf (nChar2,"",0,0)
				if (nDateType2!=-1) {		//Hemos encontrado donde termina
					nLen=2
					if (nChar=="Y") {
						nLen=4
					}
				}
				else{
					nLen =  sDate.indexOf(nChar2)
					if (nChar2!="" && nLen!=-1) {							//0.775 hay caracter de fin
						nLenInput = sIF.indexOf(nChar2)
					}
					else{
						nLen = sDate.length
						nLenInput = sIF.length
					}
				}
	//if (nDateType==0) alert(nLen+"_"+parseInt(sDate)+"\nsIF:"+sIF+"\nnDateType2:"+nDateType2+"\nnChar2:"+nChar2)
	//alert (sDate.substr (0,nLen) +"_"+Number (sDate.substr (0,nLen))+"_"+parseInt (sDate.substr (0,nLen)))
				a_sDate [nDateType] = Number (sDate.substr (0,nLen))	//0.778
				a_sLen  [nDateType] = nLen
			}
			sIF = sIF.substr (nLenInput)
			sDate = sDate.substr (nLen)
		}

		if (nForceFormat==2 || (nForceFormat==1 && !nDateDiffs)) {		//Y	0.786
			var nY = sInputFormat.f_countMatches("Y")
			if (nY>1 && nY!=a_sLen[0]) {
				nDateDiffs = 1
			}
			else {
				nDateDiffs = 0
			}
		}

		if (!nForceFormat || !nDateDiffs) {		//0.783
			if (a_sDate[0]<ICore.m_nY2K) a_sDate[0] = 2000 + Number (a_sDate[0])
			if (a_sDate[0] && a_sDate[1] && a_sDate[2]) oDate = new Date(a_sDate[0], a_sDate[1]-1, a_sDate[2], a_sDate[3], a_sDate[4], a_sDate[5],a_sDate[6])

			if (!IsNull(oDate)){				//0.803
				if ( (a_sDate[1]!=1+oDate.getMonth()) || (a_sDate[2]!=oDate.getDate()) ) oDate = null
			}
		}
	}
	return (oDate);
}

/**
 * @description Devuelve una fecha con otro formato
 * @param {string} sInputFormat Formato de entrada.
 * @param {string} sFormat Formato de salida.
 * @param {string} a_sSemana Se le puede pasar el array de semana (ej: en caso de otro idioma).
 * @param {string} a_sMeses Se le puede pasar el array de meses (ej: en caso de otro idioma).
 * @param {integer} nForceFormat [1|0] si el valor es 1, entonces se forza el uso estricto del sInputFormat. Por defecto, si el sInputFormat no corresponde exactamente con el valor, el metodo aplica otra regla de formato para llegar a un resultado.
 * @example
 * var sMes = "2";	//febrero
 * var sResult = sMes.f_toDateDraw("nMM", "sMM");
 * -> sResult = "febrero"
 *
 * Los diferentes formatos son los siguientes: ["nHH24","nH24","nHH12","nH12","sH12","nMMN","nMN","nSS","nS","nMIL","sDD","sD","nDD","nD","sMM","sM","nMM","nM","nYYYY","nYY"];
 */
String.prototype.f_toDateDraw = function (sInputFormat,sFormat,a_sSemana,a_sMeses,nForceFormat){
	var sDate = ""
	if (this!=''){
		var dDate = this.f_toDate (sInputFormat,nForceFormat)
//		if (typeof(dDate)!='undefined' ) sDate = dDate.f_drawFormat (sFormat,a_sSemana,a_sMeses)
		if (!IsNull(dDate)) sDate = dDate.f_drawFormat (sFormat,a_sSemana,a_sMeses)
	}
	return (sDate)
}


/*	DEP
	USAR:
		Date.prototype.f_drawFormat
		String.prototype.f_toDate
*/
String.prototype.m_a_sDateNames=[new Date().m_a_sDateNames[1]
								,new Date().m_a_sDateNames[0]
					];
String.prototype.f_parse2Date=function (nShowType){
	ErrorJS ("f_parse2Date deprecated: usa f_drawFormat","",5)
	var sDate="";
	var oDate=this.f_toDate("D/M/Y");
	switch(nShowType){
		case 1:
			sDate=oDate.f_drawFormat("nDD/nMM/nYY");
			break;
		case 2:
			sDate=oDate.f_drawFormat("nD de sMM de nYYYY");
			break;
		case 3:
			sDate=oDate.f_drawFormat("sDD, nD de sMM de nYYYY");
			break;
		case 4:
			sDate=oDate.f_drawFormat("sD, nDD/nMM/nYY");
			break;
		case 5:
			sDate=oDate.f_drawFormat("nYYYY/nMM/nDD");
			break;
		default:
			sDate=oDate.f_drawFormat("nDD/nMM/nYYYY");
	}
	return ( sDate );
}

// [9] Auxiliares
function ArrayObject2Array (a_vArray){
	if (typeof(a_vArray.join) != "function") { 		// 0.809 falso Array de IE (es un object y no un function)
//		a_vArray = a_vArray.toString().split(",")	// Falla si el contenido tiene ,
		var a_vNew = new Array();
//alert (typeof(a_vArray.join)+"\n"+a_vArray.length+"\n"+a_vArray[0])
		for(var f=0;f<a_vArray.length;f++) {
			a_vNew[f] = a_vArray[f]
		}
//alert (f+"\n"+a_vNew+"\n"+a_vArray.join)
		a_vArray = a_vNew
	}
	return a_vArray;
}

function CompareValues (v1,v2,bAnyType) {
	var b=0;
	if (bAnyType || (typeof(v1)==typeof(v2))) {
		if (IsArray (v1) && v1.length == v2.length) {
			b=1;
		    for (var i = 0; i < v1.length; i++) {
				b=1;
		        if (IsArray (v1[i])) { // nested array
		            if (!CompareValues(v1[i],v2[i]) ) {
		            	b=0
		            	break;
		            }
		        }
		    	else {
		        	if (v1[i]!=v2[i]) {
		        		b=0;
		        		break;
		        	}
				}
		    }
		}
		else {
			if (v1==v2) b=1
		}
	}
	else {
		ErrorJS ("[i_core.CompareValues] Estas comparando tipos distintos: " +v1+ "("+typeof(v1)+")/" +v2+ "("+typeof(v2)+")")
	}
    return b;
}

function GetType(vObj, bExists){
	var vType=0;
	if(bExists){
		if(typeof(vObj)=="string"){
			vType =eval("typeof("+vObj+")")

			if (vType=="undefined" || vType=="unknown") {
				vType=0
			}
			else if(vType=="object"){
				vType=eval(vObj+".constructor");
				if(typeof(vType)=="undefined") vType=eval(vObj);
			}
		}
		else ErrorJS("GetType: Debes pasar 'vObj' entre comillas si quieres saber si la variable ha sido definida.");
	}
	else {
		if(vObj!=null){			//a veces da un error raro por multisesion en aspirina
			vType= vObj.constructor
			if(typeof(vType)=="undefined") vType=vObj;
		}
	}
	if(typeof(vType)=="undefined" || vType=="undefined") vType=0;

	return (vType);
}

function IsArray(vVar){
	var bReturn = 0;
	if (vVar) {
		var a = vVar.push;
//ErrorJS (vVar+"\n"+typeof(a)+"\n"+!IsUndefined(a)+"\n"+String(GetType(vVar)).substring(0,20).toUpperCase())
		var sType = String(GetType(vVar)).substring(0,20).toUpperCase()		//para SAFARI y Arrays falsos
//		if ( !IsUndefined(a) && (sType.indexOf("INTERNAL FUNCTION")!=-1 || sType.indexOf("FUNCTION ARRAY()")!=-1) ) {
		if ( !IsUndefined(a) && sType.indexOf("FUNCTION")!=-1 ) {
			bReturn = 1;
		}
	}
	//if (vVar && typeof(vVar)=="object" && vVar.constructor==Array)
	return( bReturn );
}


function IsDate(vVar){
	var bDate=0;
//	if ( isNaN(sStr) ) {
	 if (GetType(vVar)==String && vVar.indexOf("UTC+")!=-1){
		vVar=new Date(vVar);
	}
	if (GetType(vVar)==Date) {
		bDate=1;
	}
	return (bDate);
}

// [bOnlyNull] no admite undefined como null
function IsNull(vVar,bOnlyNull){
	return ((vVar==null && !(bOnlyNull && IsUndefined(vVar)) )? 1 : 0 );
}

function IsUndefined(vVar){
	return( ( typeof(vVar)=="undefined")? 1 : 0 );
}

function IsMArrays(vVar){
	return (IsMArray(vVar) || IsMArrayOld(vVar));
}

function IsMArray(vVar){
	return ( (vVar && vVar.m_sObj && vVar.m_sObj.indexOf("[NotAnObject] MArray_instance_")!=-1) ? 1 : 0 );
}

function IsMArrayOld(vVar){
	var bReturn = false;
	if (IsArray(vVar) && vVar.length == 2 && IsArray(vVar[0]) && IsArray(vVar[1])) {
		bReturn = true;
	}
	return (bReturn);
}

//Devuelve numero entre 1 y nMax
function Random(nMax) { return (Math.ceil (Math.random()*nMax) ) }

// [10] Debug & Error
function DebugObj(oObj, nGroups, sFilter, bNotValue, bReturn){
	var i,v,s,nPos,sObj

	if (IsNull(oObj)) return ("null")
	if(!sFilter) sFilter="";
	if(!nGroups) nGroups=50;
	if(ICore.m_bIsServer) Response.write("<B>- - - - - - DebugObj - "+ICore.f_getVersion()+"</B><BR />");
	var a = [];

	if (IsArray(oObj)){
		for (i=0;i<oObj.length;i++){
			a.push (i +".["+oObj[i]+"] ("+typeof(oObj[i])+")")
		}
	}
	else {
		for(i in oObj){
			if(!bNotValue && i) {
				v = oObj[i]
				s=v + " ("+typeof(v)+")"
				if (typeof(v)=="function") {
					sObj = v.toString()
					nPos= sObj.indexOf("{")
					if (nPos!=-1) s= sObj.substring(0,nPos)
				}
			}
			if(i.indexOf(sFilter)!=-1) a.push (i +" = "+s)
			s=""
		}
		a.sort();
	}

	s="";
	if(oObj.m_sKeyName) s+=oObj.m_sKeyName;
	else if (oObj.m_sObj) s+=oObj.m_sObj;
	if(oObj.m_nVersion) s+=" [v"+oObj.m_nVersion + "]";
	s+= " ("+a.length+" propiedades)\n"
	var nGroupsC=0;
	for(i=0; i<a.length; i++){
		nGroupsC++;
		if(nGroupsC>=nGroups){
			nGroupsC=0;
			if(ICore.m_bIsServer) Response.write(s+"<BR />")
			else if (!bReturn) {
				alert(s);
				s="";
			}
			else {
				s +="\n"
			}
		}
		s+=a[i]+""
		if(ICore.m_bIsServer) s+="<BR />";
		else s+="\t";
	}
	if(ICore.m_bIsServer) Response.write("<HR><BR /><BR />");
	return (s)
}

//	[nReg],[nModo],[a_sCampos],[bOrdenado]
//	nModo	: 0(por campos)=Campo,Valor... / 1(por registros)=Campos,Valores
Array.prototype.f_maShowDebug=function (nReg,nModo,a_sCampos,bOrdenado) {
	var sTexto,nDir
	if (nReg!=null) {
		sTexto = DebugMArrayReg (this,a_sCampos,nReg,nModo,bOrdenado)
		sTexto += "\n\n Pulsa [Cancelar] para ver el siguiente registro"
		if (nReg++>=this.f_maGetRegs()-1 ) nReg=0
		nDir = confirm (sTexto)
		if (!nDir) {
			this.f_maShowDebug (nReg,nModo,a_sCampos,bOrdenado)
		}
	}
	else {
		sTexto = this.f_maDebug (a_sCampos,nModo)
		alert (sTexto)
	}
}

// [a_sCampos]	: campos a mostrar
Array.prototype.f_maDebug=function (a_sCampos,nModo) {
	var f,g, nPos,nRegLen, nRegistrosIni=3, nRegistrosFin=2
	var nRegistrosMax=nRegistrosIni + nRegistrosFin
	var sHTML= ""

	var nRegistros = Math.ceil(this[1].length/this[0].length)
	if (nRegistros<=nRegistrosMax) {
		nRegistrosMax = nRegistros
		nRegistrosIni = nRegistros
	}
	sHTML += "\tETIQUETAS ("+this[0].length+" etiquetas)\n[" + this[0] + "]\n"
	sHTML += "\tVALORES ("+this[1].length + " valores / " + this[1].length/this[0].length + " registros)\n"
	if (nModo) {
		for (f=0;f<nRegistrosIni;f++){
			sHTML += DebugMArrayReg (this,a_sCampos,f,nModo)
		}
		if (nRegistrosMax<nRegistros){
			sHTML += "\t...\n\t...\n\t...\n"
			for (f=nRegistros-nRegistrosFin;f<nRegistros;f++){
				sHTML += DebugMArrayReg (this,a_sCampos,f,nModo)
			}
		}
	}
	else {
		if (!a_sCampos) a_sCampos = this[0]
		for (f=0;f<a_sCampos.length;f++){
			sHTML += a_sCampos[f] +":\t"

			nPos = this[0].f_indexOf(a_sCampos[f],0,1)
			if (nPos==-1) {
				sHTML += "este campo no existe"
			}
			else {
				nRegLen = this[0].length
				for (g=0;g<nRegistrosIni;g++){
					sHTML += this[1][(g*nRegLen)+nPos] + "\t,"
				}
				if (nRegistrosMax<nRegistros){
					sHTML += "\t.....\t,"
					for (g=nRegistros-nRegistrosFin;g<nRegistros;g++){
						sHTML += this[1][(g*nRegLen)+nPos] + "\t,"
					}
				}
				sHTML = sHTML.substring (0,sHTML.length-2)
			}
			sHTML += "\n"
		}
	}
	return sHTML
}
String.prototype.f_maDebug=function (a_sCampos){
	return ((this.f_maBArray2MArray()).f_maDebug(a_sCampos))
}

function DebugMArrayReg (vMArrayBase,a_sCampos,nReg,bSimple,bOrdenado) {
	var sValor,nPos
	var sHTML = ""
	if (!a_sCampos) a_sCampos = vMArrayBase[0]
	var nDatos = a_sCampos.length
	if (bOrdenado) a_sCampos.sort()
	for (var g=0;g<nDatos;g++){
		sValor = "No existe!!!"
		nPos = vMArrayBase[0].f_indexOf(a_sCampos[g],0,1)
		if (nPos!=-1) sValor = vMArrayBase[1][(vMArrayBase[0].length*nReg)+nPos]
		if (!bSimple) sHTML += "\n" + a_sCampos[g] + ":\t "
		else if (g) sHTML += ","
		sHTML += sValor
	}
	if (bSimple) {
		sHTML = "["+ sHTML+"]\t(Reg." + (nReg) + ")\n"
	}
	else {
		sHTML = "[Registro " + (nReg) + " / "+ vMArrayBase.f_maGetRegs() +" ]\n"+sHTML
	}
	return (sHTML)
}

function Porcentaje (vNum,vTotal,sFmt) {
	var nRes = 0
	var nNum = vNum.f_toNumber ()
	var nTotal = vTotal.f_toNumber ()
//	if (!isNaN(nNum) && !isNaN())
	nRes = nNum*100/nTotal
	if (!isNaN(nRes)) nRes = nRes.f_formatNumber(sFmt)
//	if (nDecs)
	return (nRes)
}

function ErrorEx (e) {
	var sError = e+" "+e.name + ": "+e.description + " [" + (e.number>>16&0x1FFF) + " " + (e.number&0xFFFF) + "/"+ e.number +"]";
	return sError
}

function ErrorJSLibs(){
	ErrorJS(null,null,null,null, 1);
}

function ErrorJS(vVar,oObj,nModo,bManual, bShowLibs){
	if (IsUndefined(vVar)) {
		vVar="";
		if ( bShowLibs ) vVar += this.m_sErroresLibs
		vVar += ICore.m_sErrores
		if (IsUndefined(nModo)) nModo = 4
		if (!ICore.m_nShowErrores) ICore.m_nShowErrores=1
	}
	else {
		if (nModo!=2 && !ICore.m_bIsServer && !bManual) {
			var sSign = "*"
			if (nModo==5) sSign="-"
			try{
				window.top.document.title += sSign
			}catch(e){
			}
		}
		ICore.m_sErrores += "[Error: "+ ++ICore.m_nErrores + "["+new Date().f_drawFormat("nH24:nMMN")+"]" + vVar + "\n\n"
	}
	var sError = vVar,sErrorObj=""
	if (nModo==5) nModo=2;

	if (!bManual) {
		if (!ICore.m_nShowErrores) return;
		if (!nModo || ICore.m_nHTMLErrores--<ICore.m_nShowErrores) --ICore.m_nShowErrores
	}

	var sPagePath = (ICore.m_bIsServer)? "http://"+Request.ServerVariables("HTTP_HOST")+Request.ServerVariables("URL") : document.location.href;
/*
	if (oObj) {
		if (!IsNull(oObj) && typeof(oObj)=="object"){
			sErrorObj += DebugObj(oObj,8,null,null,1)
		}
	}

	if (IsMArray(vVar)) sError = vVar.f_debug()
	else if (GetType(vVar)==Array && IsMArrayOld(vVar)) sError = vVar.f_maDebug()
*/
//	if (IsMArray(vVar) || (GetType(vVar)==Array && IsMArrayOld(vVar))) sError = vVar.f_maDebug()
	if (oObj && !IsNull(oObj) && typeof(oObj)=="object") vVar = oObj
	if (IsMArrays(vVar)) sErrorObj = vVar.f_maDebug()
	else if (typeof(vVar)=="object") {
		sErrorObj = DebugObj(vVar,10,null,null,1)
//Response.write(typeof(vVar))
	}

	var sHTML=""
	sHTML+="<TABLE cellpadding='1' cellspacing='0' border='1' width='100%'>";
	sHTML+="<TR bgcolor='#666666'>";
	sHTML+="<TD><FONT face='Arial' size='1' color='#FF0000'><NOBR><B>ErrorJS "+ (ICore.m_bIsServer ? "Servidor" : "Cliente")+":</B></NOBR></FONT></TD>";
	sHTML+="<TD><FONT face='Arial' size='1' color='#c0c0ff'>"+sPagePath+"</FONT></TD>";
	sHTML+="<TD align='right'><A href='javascript:document.location.reload()'><FONT face='Arial' size='1' color='#00FF00'><B>[ RELOAD PAGE ]</B></FONT></A></TD>";
	sHTML+="</TR>";
	sHTML+="<TR bgcolor='#000000'>";
	sHTML+="<TD colspan='3'>"
	sHTML+=		"<FONT face='Arial' size='2' color='#e0e0e0'>"+sError.toString().f_replace("\n","<BR>")+"</FONT>"
	if (sErrorObj) {
//		sHTML+=		"<BR />"
//	sHTML+=		"<FONT face='Arial' size='2' color='#b0b0b0'>"+sErrorObj.toString().f_replace("\n","<BR>")+"</FONT>"
		sHTML+=		"<FONT color='#b0b0b0' size=3><PRE>"+sErrorObj+"</PRE></FONT>"
	}
	sHTML+=		"</TD>";
	sHTML+="</TR>";
	sHTML+="</TABLE>";

	var sErrorAlert = sPagePath + "\n\n***Error JS ["+new Date().f_drawFormat("nH24:nMMN")+"] ***\n" + sError + "\n" + sErrorObj

//alert(nModo+": "+sErrorAlert +"\n"+ICore.m_sServer)
	switch (nModo) {
		case 1 :
			if (ICore.m_bIsServer) {
				Response.write (sHTML);
			}
			else {
				if (ICore.m_sServer=="DEV") {
					if (oIGZ.m_bInitialized) {
						var sBody =document["body"].innerHTML;
						document["body"].innerHTML=sHTML+sBody;
					}
					else {
						if (!ICore.m_sErrorJS) oIGZ.m_a_sPostStartUps[oIGZ.m_a_sPostStartUps.length] = 'document["body"].innerHTML=ICore.m_sErrorJS+document["body"].innerHTML';
						ICore.m_sErrorJS += sHTML
					}
				}
				else {
					window.status = sError
				}
			}
			break;
		case 2 :
			if (ICore.m_bIsServer) {
				Response.write ("/*"+sHTML+"*/\n");
			}
			else if (ICore.m_sServer=="DEV") {
				window.status = sError
			}
			break;
		case 3 :
			sHTML = sError
			break;
		case 4 :
			sHTML = ""
			ICore.f_showError (sErrorAlert)
			break;
		default:
			if (ICore.m_sServer=="DEV") {
				if(ICore.m_bIsServer) {
					Response.write (sHTML);
					Response.end ()
				}
				else {
					ICore.f_showError (sErrorAlert)
				}
			}
			else {
				if(!ICore.m_bIsServer) window.status = sError
				else {
					Debug( sError );
					if (protected_bDebugMode) Response.end ()
				}
			}
	}
	if (sHTML) return (sHTML)
}


//
// ************************* FIN DE PROTOTYPEs y Funciones Globales
//


//
// El objeto ICore tiene que ir siempre al final
//


ICore = new function () {
	this.m_sObj = "ICore";
	this.m_bIsServer = ( typeof(Server)!="undefined" )? 1 : 0;
	this.DEV = 0;
	this.m_sIGZsign  = "© " +new Date().getYear()+ " Intelygenz - www.intelygenz.com";
	this.m_sAuthor 	 = "";
	this.m_nVersion	 = i_core_nVersion;
	this.m_sKeyName	 = "iCore";
	this.f_getVersion = function () {
		return (this.m_sKeyName+ " v" +this.m_nVersion+ "\n"+this.m_sIGZsign);
	}

	this.m_nShowErrores = 3;	// alert N errores / 0=todos
	this.m_nHTMLErrores = 5;    // pinta N errores / 0=todos
	this.m_nY2K		 	= 20;   // años menores de XX se ponen a 20XX

	this.m_oOnErrorEvent=(!this.m_bIsServer)? window.onerror : null;

	if(this.m_bIsServer) this.m_sUrl=("http://"+Request.ServerVariables("SERVER_NAME")+Request.ServerVariables("URL")).toLowerCase()
	else this.m_sUrl=String(document.location.href)

	this.m_a_sDevIgz = ["aspnet1","aspnet2","dev","formacion","intranet"]
	this.m_a_sDevHosts = [
						 // dev servers
						  "://almax", "://192.168.0.9"
						 ,"://debi", "://192.168.0.15"
						 // old dev servers
						 ,"://cafetera", "://192.168.0.7"
						 // local
						 ,"://localhost", "://127.0.0.1"
						 ]
	this.f_checkDevHosts = function () {
		var sEntorno = "PRO"
		var a_sHosts = 	this.m_a_sDevHosts;
		if (this.m_sUrl.indexOf("intelygenz.com")!=-1) {
			a_sHosts = 	this.m_a_sDevIgz;
		}
		var f=-1, F=a_sHosts.length;
		while ( ++f<F && this.m_sUrl.indexOf(a_sHosts[f])==-1 ) { }
		if (  f<F ) {
			sEntorno = "DEV";
			this.DEV=1;
		}
		this.m_sServer = sEntorno
	}
	this.f_checkDevHosts();

	this.m_oErrorJS = ""
	this.m_sErrorJS = ""
	this.m_nErrores = 0
	this.m_sErrores = ""
	this.m_sLibsPath = "/libs/js";

	this.m_sNumberFormat = ".I,DD"

	this.m_nTimerLap;


	// Controla todas las cargas de librerias
	this.m_sDebugLoad = ""
	this.m_sErroresLibs = "";
	this.f_debugLoad = function (sText,nMode) {		//ponerlo al principio o antes de la funcion
		this.m_sErroresLibs += g_oICrono.f_get(1) +"\n"+ sText;
		this.m_sErroresLibs += "\t\t\t\t".substring (0,4-((sText.length)/9))
		if (!this.m_bIsServer && !IsNull(document.location.search) && document.location.search.indexOf("igzdebug")!=-1) {
			if (!this.m_sDebugLoad) this.m_sDebugLoad = "["+document.location.pathname+"]\n"

			this.m_sDebugLoad += sText + "\n";
			if (nMode==1) {
				oIGZ.m_a_sStartUps.push("ICore.f_debugLoad (oIGZ.f_checkLoadedLibs ())");
			}
			alert(this.m_sDebugLoad)
		}
	}

	// Mensaje de error controlado
	this.f_showError = function (sError) {
		var bNotCopy = confirm(sError + "\n\nPulsa 'Cancelar' o ESC para copiar el error al portapapeles");

		if (oIGZ.m_bIE) {	//no funciona en FF	?que pasa con IE7¿
			if (!bNotCopy && document["body"]) {
				var oForm = document.createElement("<FORM name='FCopy' style='display:none'>")
	//			var oForm = document.createElement("FORM")
	//			oForm.name = "FCopy"
	//			oForm.style = "display:none"

				var oInput = document.createElement("<TEXTAREA NAME='zzCopy'>")
	//			var oInput = document.createElement("TEXTAREA")
	//			oInput.name = "zzCopy"
				oInput.value=sError
				document["body"].appendChild(oForm)
				oForm.appendChild(oInput)
				var oRange=oInput.createTextRange()
				oRange.execCommand("Copy")
				document["body"].removeChild(oForm)
			}
		}
	}

	// Devuelve el texto sDefault que le pasemos si el valor de vVal es null
	this.f_getValue = function (vVal, sDefault, bOnlyNull) {
		return IsNull( vVal, bOnlyNull ) ? sDefault : vVal;
	}
//alert(document.location.href)
	// JS CLIENTE
	//
	this.m_sLang   = "es";
	this.m_sParams = "";		//"?" 0.814
	this.f_loadPath = function () {
		var sPath="", sParam = "";

		var oUserAgent = navigator.userAgent.toLowerCase();
		var bDOM  = document.getElementById ? 1 : 0;
		var sLang = this.m_sLang;
//alert(bDOM)
		if (bDOM) {
			var sLangT;
			var a_scripts = document.getElementsByTagName("SCRIPT");
			var f=0, F=a_scripts.length;

			while( f<F && a_scripts[f]
			 		&& (
			 			!a_scripts[f].getAttribute("src")
			 			|| (a_scripts[f].getAttribute("src") && a_scripts[f].getAttribute("src").indexOf("i_core.js")==-1)
			 		)
			 	){
//alert( a_scripts[f].getAttribute("src") )
					f++
				}

			if ( f<F ) {
				sPath  = a_scripts[f].getAttribute("src");
				sLangT = a_scripts[f].getAttribute("lang");
			}

			if ( sLangT ) sLang=sLangT;
		}
		else {
			sPath = document.all["Ncore"].src;
		}

		this.m_sLang = sLang

		if (sPath) {
			if (sPath.indexOf("?")!=-1) this.m_sParams = sPath.substring(sPath.indexOf("?")-1);				//0.814
			sPath  = sPath.substring(0,sPath.lastIndexOf("/")+1)
		}
//alert(sPath+"\n"+this.m_sLibsPath)
		this.m_sLibsPath = sPath;		//0.914

		if ( !this.m_sLibsPath
		  || IsNull(this.m_sLibsPath)
		  || this.m_sLibsPath==""
		) {
		  	this.m_sLibsPath = "/libs/js/";
		}

		return this.m_sLibsPath			//0.914
	}

	// Retrocompatibilidad y comprobación de carga de i_xbd.js
	oXBD = new function () {
		this.f_load = function () { ErrorJS("Falta el objeto oXBD.\nComprueba que la librería '"+sPath+"i_xbd.js' existe."); }
	}
	oXJS = oXBD;
}

var LIBS_PATH = ICore.f_loadPath();

g_oICrono = new ICrono ();
ICore.f_debugLoad ("i_core")


//Retro-Compatibilidad
//
oCore = ICore;
var g_nShowErrores = ICore.m_nShowErrores;
var g_nHTMLErrores = ICore.m_nHTMLErrores;
var g_nY2K 		   = ICore.m_nY2K;
var g_sLang		   = ICore.m_sLang;

ICore.f_debugLoad ("i_core END");

document.write ("<SCRIPT type='text/javascript' charset='iso-8859-1' src='" +LIBS_PATH+ "i_igz.js"+ICore.m_sParams+"'></SCRIPT>\n");
ICore.f_debugLoad ("i_core igz");
document.write ("<SCRIPT type='text/javascript' charset='iso-8859-1' src='" +LIBS_PATH+ "i_marray.js"+ICore.m_sParams+"'></SCRIPT>\n");
document.write ("<SCRIPT type='text/javascript' charset='iso-8859-1' src='" +LIBS_PATH+ "i_lang_"+ICore.m_sLang+".js"+ICore.m_sParams+"'></SCRIPT>\n");
document.write ("<SCRIPT type='text/javascript' charset='iso-8859-1' src='" +LIBS_PATH+ "i_xbd.js"+ICore.m_sParams+"'></SCRIPT>\n");

