// (C) 2002 WebMedia - www.webmedia.es - manuel@webmedia.es   
// Funciones WebMedia v1.39	[libs 1.39]
// v1.00 [3] InsertArray()
// v1.01 [9] CambiaTexto()
// v1.02 [5] SignoAleatorio()
// v1.03 Fixed 		[2.1] Numero2Texto / Numero2Idioma
// v1.04 Deprecated [2.2] Numero2Idioma
// v1.05 Updated 	[2.1] Numero2Texto
// v1.06 [9.6] Texto2HTML(sTexto)	
// v1.07 Updated 	[9.2] CambiaTexto()
// v1.08 Fixed		[9.6] Texto2HTML(sTexto)	
// v1.09 Updated	[9.1] BuscaTexto (sCadena,sTexto,bHaciaAtras)
// v1.10 Updated	[1.1] FechaHoraTexto ("fechamini") : fechas estilo dd.mm.aaaa
// v1.11 [3.7] BuscaMultiarray (sCampo,sArrayBase,nRegistro)
// v1.12 [3.2] CopyJoinArray(a_sArrayS,a_sArrayD)
// v1.13 [3.8] GetBiarray		[3.9] SetBiarray
// v1.14 Fixed		[1.7] ValidaFecha(nDD,nMM,nAAAA)
// v1.15 Updated	[3.3] RemoveDeArray
// v1.16 [2.7] Porcentaje
// v1.17 [3.10] OrdenarArray	[3.11] OrdenarMultiarray	[3.12] AddCampo2Multiarray
// v1.18 [3.13] ParseCodigo
// v1.19 [1.9] Fecha2Date(sFecha,cSeparador)
// v1.20 Updated 	[3.10] OrdenarArray
// v1.21 [5.3] ParseEXMLs ()	[5.4] ParseEXML(sTag,sCodigo,oObj,nRegistro)
// v1.22 Fixed		[3.10] OrdenarMultiarray	[3.11] OrdenarMultiarray
// v1.23 [3.14] BuscarSubArray(a_vArray,sTexto,bIndices)
// v1.24 Fixed		[1.1] FechaHoraTexto
// v1.25 [10.1] ExisteFuncion	[10.2] ExisteFrame
// v1.26 [3.15] RegsMultiarray (sArrayBase)
// v1.27 Updated 	[3.11]		[3.12]
// v1.28 [1.10] EsHora(sHora)	[1.11] ValidaHora
// v1.29 [7.2] ComboEXML()
// v1.30 Updated	[5.3] ParseEXMLs 	[5.4] ParseEXML
// v1.31 Fixed		[2.1] Numero2Texto	[2.3] Texto2Numero
// v1.32 [7.1] CreaCombo
// v1.33 [3.16] BuscaMArrayValor		[3.17] ModMultiarray
// v1.34 [3.18] SubMArray				[7.1]  CreaCombo
// v1.35 [3.19] DelRegMArray			[3.20] SetMArray
// v1.36 Fixed 		[2.3] Texto2Numero
// v1.37 Fixed		[1.9] Fecha2Date
// v1.38 Fixed		[1.2] FechaDifHoras	[1.3] FechaDifDias	[1.4] FechaDifMeses	[1.5] FechaDifAnyos
// v1.39 Fixed		[2.2] Entero2Texto	[2.7] Porcentaje


// Texto2Numero: convierte cualquier cosa a un numero 
// MArrays: borrar registros repetidos o con un campo con un valor determinado
//			parecido a: BorraRepetidos("Proyecto") de http://inet.evoluciona/trabajo/predictor/info/listado.asp
// ComboEXML : 	sTitulo: añadirle Titulo 
//				bDiff: Cree COMBO solo con valores diferentes EXML (para evitar opciones repetidas)
//				Valor=nPosArray(+X) [con [FUN] quiza se pueda hacer ya]
//				No coja el primer valor del array
// CreaCombo : variable que decida si pasa de valores o textos nulos para creas opciones del combo
// Mejorar/unificar todas las funciones de numero a texto (añadir euro/pesetas)
// Cuando cambio un Array no lo devuelva, sino que lo cree (usar CopyJoinArray())
// Ver que fecha es mayor de dos/ si es mayor que hoy (podriamos usar FechaDifDias)
// Aleatorio: x numeros distintos
// Cronometro (Jonas tiene uno)


// 0. URL
//		0.1 ParamURL(sParam)					// 0.1 Devuelve el valor del parametro pedido
//		0.2 WebPath()
//		0.3 HostName ()  
//		0.4 PathName (sPath) 
// 1. Fecha
//		1.1 FechaHoraTexto(sParametro,dFecha){		// fecha/fechamini/fechacorta/hora/dia/dia_texto/mes/mes_texto/año/horas/minutos/ 
//		1.2 FechaDifHoras("1/12/1967","2/3/1975")		// "mes/dia/año" !!!
//		1.3 FechaDifDias ("1/12/1967","2/3/1975")		// "mes/dia/año" !!!
//		1.4 FechaDifMeses("1/12/1969","2/3/1968")		// "mes/dia/año" !!!
//		1.5 FechaDifAnyos("3/12/1967","2/3/1968")		// "mes/dia/año" !!!
//		1.6 CambiaFecha("1/1/19")						// BUG !!! dd/mm/aa o mm/dd/aa
//		1.7 ValidaFecha(nDD,nMM,nAAAA)					// 0/1  Invalida/Valida
//		1.8 DiasMes (nAnyo, nMes)
//		1.9 Fecha2Date(sFecha,cSeparador)				// Convierte una cadena en un objeto Date
//		1.10 EsHora(sHora)								//
//		1.11 ValidaHora (nHoras,nMinutos,nSegundos)		// Valida una hora
// 2. Dar formato a numeros (Pone puntos de millar, comas, menos...)
//		2.1 Numero2Texto(nNumero,nDecimales,nFormato,bForzarDecs)
//		2.2 Entero2Texto(nNumero)
//		2.3 Texto2Numero(sNumero)
//		2.5 Dec2Hex(nNum)
//		2.6 Numero2Grafico(sNumero)
//		2.7 Porcentaje(nValor,nTotal,nDecimales)
// 3. Arrays
//		3.1 BuscaEnArray (sArray,vValor){		//Busca la posicion en el array del valor que se le pasa
//		3.2 CopyJoinArray(a_sArrayS,a_sArrayD){				// Une/Copia un Array a continuacion de otro
//		3.3 RemoveDeArray (a_vArray,nPosicion,nElementos)	// a_t = RemoveDeArray (a_t,2,0)
//		3.4 RemoveElemento (a_vArray,vValor)				// Borra un elemento de un array
//		3.5 SubArray(a_sArray,a_sArrayD,nInicial,nSalto)	// Crea un subarray de otro array
//		3.6 InsertArray (a_vArrayDest,a_vArray,nPosicion)	// Inserta/une un array/elemento en otro array
//		3.8 GetBiarray(sCampo,a_sArray1,a_vArray2)			// Busca sCampo en array1 y devuelve el valor que esta en la misma posicion en Array2
//		3.9 SetBiarray(sCampo,a_sArray1,a_vArray2,vValor)	// Busca sCampo en array1 y guarda vValor en la misma posicion en Array2
//		3.10 OrdenarArray(aMatriz,bCual,nDireccion)			// Ordena un array
//		3.14 BuscarSubArray(a_vArray,sTexto,bIndices)		// Crea un array con los datos que contienen el texto
// 3. Multiarray
//		3.7 BuscaMultiarray (sCampo,sArrayBase,nRegistro)	// Busca sCampo en CampoArray1 y devuelve el valor que esta en la misma posicion en el nRegistro(0-N) del MultiArray2
//		3.11 OrdenarMultiarray(sArrayBase,sCampo,bCual,nDireccion)	//Ordena un multiarray por el campo que queramos
//		3.12 AddCampo2Multiarray (sArrayBase,sCampo,vValor)	// Añade un nuevo campo al final de un MA
//		3.13 _ParseCodigo (sJSarrayBase,sCodigo,nRegistro)	// [ParseEXML] Deprecated: Parsea codigo de tipo %Campo%
//		3.15 RegsMultiarray (sArrayBase)					// Numero de registros de MultiArray
//		3.16 BuscaMArrayValor(sArrayBase,sCampo,vValor)		// Busca un valor en un MA y devuelve el nReg
//		3.17 ModMultiarray(sArrayBase,sCampo,sEXML)			// Modifica un campo completo del MBArray (hay que programar lo que necesitemos y renombrar la funcion)
//		3.18 SubMArray(sJSarrayBase,a_sArrayD,a_nPos)		// Crea un subMArray de otro MArray
//		3.19 DelRegMArray (sArrayBase,nReg)					// Borra un registro de un MArray
//		3.20 SetMArray(sArrayBase,sCampo,nRegistro,vValor){	// Busca sCampo de nRegistro y lo modifica
// 4. Ventanas
//		4.1 AbreWindow(html,ancho,alto)
//		4.2 CierraWindow()
//		4.3 AbreAyuda()
// 5. Varias
//		5.1 Aleatorio (nMaximo)
//		5.2 SignoAleatorio()
//		5.3 ParseEXMLs (sCodigo,oObj,sJSarrayBase,nRegistro) 	//("ifBD","BD","OBJ","FUN")
//		5.4 ParseEXML(sTag,sCodigo,oObj,sJSarrayBase,nRegistro)
// 6. DIVS
//		6.1 CambiarDIV(divID,sText,sFrame) 
//		6.2 ShowDIV(sId,nVisible)		// v0.1 	0/1/2 Hide/ver/Swap (aun falta)
// 7. Combos
//		7.1 CreaCombo(sSelectName,sFuncion,sTitulo,a_sNombre,a_sValor,vValorSelected)
//		7.1 _CrearCombo(sFormName,sFuncion,a_sNombre,a_sValor,a_sValorSelected)
//		7.2 ComboEXML(sFormName,sFuncion,sJSarrayBase,sEXMLtexto,sEXMLvalor,vValorSelected)
// 8. Debug
//		8.1 Debug  ("sVariable1", "sV2",...)  
// 9. Cadenas
//		9.1 BuscaTexto (sCadena,sTexto,bHaciaAtras)		//Busca texto en una cadena (devuelve posicion o -1 si no existe)
//		9.2 CambiaTexto(nAccion,sTexto,sBuscado,sNuevo)		// v1.07	Search & insert/replace/delete un texto
// 		9.3 LimiteCadena(sCadena,nMaximo)	//Comprueba tamaño de una cadena
//		9.4 HTML2Texto(sTexto)				//Convierte HTML en texto <=&lt; y >=&gt;
//		9.5 ValidarCadena(sTexto,a_cValidos_E)		//Comprueba que solo haya letras, numeros y los caracteres del array que le pasamos
//		9.6 Texto2HTML(sTexto)				//Convierte texto en HTML para evitar problemas de : "" y '
//10. Internas JavaScript
//		10.1 ExisteFuncion(sFuncion)
//		10.2 ExisteFrame (sFrame)


//-----------------------------------------------




// 1. Fecha ----------------------------------------------------------------------

function ParamURL(sName){					// 0.1 Devuelve el valor del parametro o ""
var sParam=""	
	if (location.search != null && location.search !=''){
		var sTodo = unescape((location.search.substring(1,location.search.length)));
		var nIni = sTodo.indexOf(sName+"=")
		if (nIni!=-1) {
			nIni += sName.length+1
			sParam = sTodo.substring(nIni,sTodo.length)
			var nFin = sParam.indexOf("&")
			if (nFin!=-1) sParam = sParam.substring(0,nFin)
		}
	}
	return sParam
}

function WebPath() {						//0.2
	sHost = HostName()
	if (sHost=="webmedia"){					// Datos para WebMedia
		sPath = "/columbia/"
	}
	else{	
		//sPath = "http://"& sHost &"/"		//Full Path
		sPath =  "/"					//Relative path
	}
	return sPath
}

function HostName() {						// 0.3 Devuelve "webmedia" o el nombre del host
var sHost = document.location.hostname;
//	if (sHost.indexOf(".webmedia")) sHost="webmedia"
//	if (sHost.indexOf(".evoluciona")) sHost="webmedia"
	if (sHost=="pub.webmedia.es" || sHost=="dev.webmedia" || sHost=="t2k.webmedia.es") sHost = "webmedia"		//Datos para WebMedia
	return sHost
}


function PathName(sCadena) {				// 0.4 Devuelve lugar si encuentra la cadena o -1 si no existe
var sPath = document.location.href			// document.location.pathname
	return sPath.indexOf(sCadena)
}



// 1. Fecha ----------------------------------------------------------------------

//alert (FechaHoraTexto("fecha",document.lastModified))
dFecha = new Date(document.lastModified); 	//Fecha modificacion fichero
dFecha = new Date(); 						//Hoy

function FechaHoraTexto(sParametro,dFecha){ 			// 1.10 fecha/fechacorta/fechamini/hora/dia/dia_texto/mes/mes_texto/anyo/horas/minutos/ 
	var a_mes=new Array (0,"Enero", "Febrero", "Marzo", "Abril", "Mayo", "Junio", "Julio","Agosto", "Septiembre", "Octubre", "Noviembre", "Diciembre")
	var a_dia=new Array ("Domingo","Lunes","Martes","Miércoles","Jueves","Viernes","Sábado")

	if (dFecha) {
		dFecha = CambiaFecha(dFecha)		//Paso fecha a formato USA
		dFecha = new Date(dFecha); 	//Fecha que le pasamos
	}
	else {
		dFecha = new Date(); 					//Fecha de hoy
	}

	dia= dFecha.getDate()
	dia_texto = a_dia[dFecha.getDay()]
	mes = dFecha.getMonth() + 1
	mes_texto = a_mes[mes]
//	anyo = dFecha.getFullYear()		//En NS3 getYear() !!!
	anyo = dFecha.getYear()			//En NS3 getYear() !!!
	if (anyo<=30) anyo+=100
	if (anyo<=150) anyo+=1900

	horas = dFecha.getHours()
	minutos = dFecha.getMinutes()

	minuto = minutos
	if (minuto<10) minuto="0" + minuto
	hora = horas + ":" + minuto
	fecha = dia_texto + ", " + dia + " de " + mes_texto + " de " + anyo
	fechacorta = dia + " de " + mes_texto + " de " + anyo
	fechahora = fecha + " - " + hora
	fechamini = dia + "/" + mes + "/" + anyo

	vFecha=fechahora
	if (sParametro) vFecha = eval (sParametro.toLowerCase())

	return (vFecha)
}


//Pueden ser negativos
//alert (FechaDifDias ("1/20/1967","2/20/1975"))		// mes/dia/año !!!
//alert (FechaDifMeses("1/19/1969","2/19/1968"))		// mes/dia/año !!!
//alert (FechaDifAnyos("3/17/1967","2/17/1968"))		// mes/dia/año !!!

function FechaDifHoras(dFecha1,dFecha2){			//1.2 mm/dd/aa
	if (dFecha1) dFecha1 = new Date(dFecha1);
	else dFecha1 = new Date()
	if (dFecha2) dFecha2 = new Date(dFecha2);
	else dFecha2 = new Date()

    interval = dFecha2.getTime() - dFecha1.getTime(); 	// Difference in ms
    msecondsPorHora = 1000 * 60 * 60;

    days = Math.ceil( interval / msecondsPorHora );
    return (days)
}

function FechaDifDias(dFecha1,dFecha2){				//1.3 mm/dd/aa
	if (dFecha1) dFecha1 = new Date(dFecha1);
	else dFecha1 = new Date()
	if (dFecha2) dFecha2 = new Date(dFecha2);
	else dFecha2 = new Date()

    interval = dFecha2.getTime() - dFecha1.getTime(); 	// Difference in ms
    msecondsPerDay = 1000 * 60 * 60 * 24;

    days = Math.ceil( interval / msecondsPerDay );
    return (days)
}

function FechaDifMeses(dFecha1,dFecha2){			//1.4 mm/dd/aa
	if (dFecha1) dFecha1 = new Date(dFecha1);
	else dFecha1 = new Date()
	if (dFecha2) dFecha2 = new Date(dFecha2);
	else dFecha2 = new Date()

    months = (dFecha2.getFullYear() - dFecha1.getFullYear()) * 12;
    addmonths = dFecha2.getMonth() - dFecha1.getMonth();
    months = months + addmonths;				// the previous calculation could result in a negative number
    
    if(dFecha1.getDate() < dFecha2.getDate()){	// Adjust month total if the birthday hasn't occurred yet this month
       months--;
    }
    return (months)
}

function FechaDifAnyos(dFecha1,dFecha2){			//1.5 mm/dd/aa
	if (dFecha1) dFecha1 = new Date(dFecha1);
	else dFecha1 = new Date()
	if (dFecha2) dFecha2 = new Date(dFecha2);
	else dFecha2 = new Date()

    years = dFecha2.getFullYear() - dFecha1.getFullYear();
    dFecha1.setYear( dFecha2.getFullYear() ); 
    if(dFecha2 < dFecha1){	 // If your birthday hasn't occurred yet this year, subtract 1
       years-- ;
    }
    return (years)
}

function CambiaFecha(sFecha) {				//1.6 Cambia entre dd/mm/aa y mm/dd/aa
	nBarra1 = sFecha.indexOf("/")
	nBarra2 = sFecha.lastIndexOf("/")

	if (nBarra1!=-1 || nBarra2!=-1){	
		sDia= sFecha.substring(0,nBarra1)
		sMes= sFecha.substring(nBarra1+1,nBarra2)
		sAno= sFecha.substring(nBarra2+1)

		sFecha = sMes + "/" + sDia + "/" + sAno
	}
	return sFecha
}

// Usada en: ev_form_validar.js
function ValidaFecha (nDD,nMM,nAAAA){		//1.7 0/1  Invalida/Valida
	if (!nDD || !nMM || !nAAAA) return false
	if (isNaN(nDD)|| isNaN(nMM)|| isNaN(nAAAA)) return false
	if (nAAAA < 100) nAAAA+=1900			//Chapucilla
	var dFecha=new Date(nAAAA,nMM-1,nDD)
	if (nDD!=dFecha.getDate()) return false
	if (nMM!=(dFecha.getMonth()+1)) return false
	if (nAAAA!=dFecha.getFullYear()) return false
	return true;
}


function DiasMes (nAnyo, nMes) {			//1.8
	return (32 - new Date(nAnyo, --nMes, 32).getDate());
}

function Fecha2Date(sFecha,cSeparador){		//1.9
var nBarra1,nBarra2,sDia,sMes,sAno,dFecha
	
	if (!cSeparador) cSeparador="/"

	nBarra1 = sFecha.indexOf(cSeparador)
	nBarra2 = sFecha.lastIndexOf(cSeparador)

	if (nBarra1!=-1 && nBarra2!=-1){	
		sDia= sFecha.substring(0,nBarra1)
		sMes= sFecha.substring(nBarra1+1,nBarra2)
		sAno= sFecha.substring(nBarra2+1)
//alert(sDia+"_"+sMes+"_"+sAno+"_"+dFecha)
		if (ValidaFecha(sDia,sMes,sAno)) dFecha = new Date(sAno,sMes,sDia)
	}
	return dFecha
}

function EsHora(sHora){							//1.10
var nPuntos1,nPuntos2,nHoras,nMinutos,nSegundos

	nPuntos1= sHora.indexOf(":")
	nPuntos2= sHora.indexOf(":",nPuntos1+1)
	if (nPuntos1==-1 || nPuntos1==sHora.length-1) return false

	nHoras = sHora.substring(0,nPuntos1)
	if (nPuntos2==-1){
		nMinutos = sHora.substring(nPuntos1+1)
		nSegundos=0
	}
	else{
		nMinutos = sHora.substring(nPuntos1+1,nPuntos2)
		nSegundos = sHora.substring(nPuntos2+1)
	}
	return (ValidaHora (nHoras,nMinutos,nSegundos))
}

function ValidaHora (nHoras,nMinutos,nSegundos){		//1.11	0/1  Invalida/Valida
	if (isNaN(nSegundos)) nSegundos=0
	if (isNaN(nHoras)|| isNaN(nMinutos)) return false

	if (nHoras>24 || nHoras<0) return false
	if (nMinutos>59 || nMinutos<0) return false
	if (nSegundos>59 || nSegundos<0) return false

	if (nHoras==24 && nMinutos>0) return false
	return true;
}


// 2. Otras ------------------------------------------------------

// Devuelve el numero con la puntuación y el numero de decimales que se le diga.
function Numero2Texto(nNum,nNumDec,nFormato,bForzarDecs){			//1.05	nFormato: 1/2 (Español/Ingles)
var a_sPuntEnt = new Array (0,".",",");
var a_sPuntDec = new Array (0,",",".");
var sSigno="";

	nNum = Texto2Numero(nNum)			//Verifica el numero
	if (nFormato==null) nFormato=1
	if (nNum<0){
		sSigno="-";
		nNum= Math.abs(nNum);
	}

	if (nNumDec) {				// Con decimales los redondea
		nNum = Math.round(nNum * Math.pow(10,nNumDec))
		nNum = nNum/Math.pow(10,nNumDec)
		sNumeroEntero = Math.floor(nNum).toString()
	}
	else{ 						// Sin decimales
		sNumeroEntero = Math.round(nNum).toString()
	}
	sNumero=nNum.toString()

	nInicioDec = sNumeroEntero.length+1
	sDecimales = sNumero.substring(nInicioDec,nInicioDec+nNumDec)
	if (bForzarDecs) for (i=sDecimales.length;i<nNumDec;i++) sDecimales += "0";

	sEntero=""
	while (sNumeroEntero>=1000){
		sEntero = a_sPuntEnt[nFormato] + sNumeroEntero.substring(sNumeroEntero.length-3,sNumeroEntero.length) + sEntero ;
		sNumeroEntero = sNumeroEntero.substring(0,sNumeroEntero.length-3) ;
	}
	sEntero = sNumeroEntero + sEntero;
	if (sDecimales.length) sNumeroEntero= sSigno + sEntero + a_sPuntDec[nFormato] + sDecimales;
	else sNumeroEntero= sSigno + sEntero;
	return sNumeroEntero;
}



function _Numero2Texto(nNumero,nDecimales,bForzarDecs) {		//v0.92
	sNumero = ""+ (Math.abs (nNumero))							//Pasa a cadena
	if (nDecimales==0) nNumeroEntero = Math.round (Math.abs(nNumero))
	else nNumeroEntero = Math.floor (Math.abs(nNumero))
	sNumeroEntero = nNumeroEntero.toString()

	nPrimerDecimal = sNumero.indexOf(".")+1							//Decimales
	if (nDecimales==0){
		nPrimerDecimal=0
	}
	else if (!nDecimales) {	
		nDecimales=sNumero.length - nPrimerDecimal
	}
	sDecimales=""
	if (nPrimerDecimal) sDecimales = sNumero.substring(nPrimerDecimal,nPrimerDecimal+nDecimales)
	if (bForzarDecs) {
		nPrimerDecimal = 1
		sDecimales += "00000000"
	}
	else if ((nPrimerDecimal-1)==sNumero.length) nDecimales=0
	sDecimales= sDecimales.substring(0,nDecimales)
	
	sNumeroEntero = Entero2Texto (sNumeroEntero)						//Crea numero
	if (nNumero<0) 	sNumeroEntero = "-" + sNumeroEntero
	if (nPrimerDecimal) sNumeroEntero += ","+ sDecimales
	return (sNumeroEntero)
}

//Devuelve el numero con la puntuación y el numero de decimales que se le diga.
// nFormato 1.Español / 2.Ingles
function _Numero2Idioma(nNum,nFormato,nNumDec){
	var sSigno="";
	if (nNum<0){
		sSigno="-";
		nNum= (-1) * nNum;
	}
	var a_sPuntEnt = new Array (0,".",",");
	var a_sPuntDec = new Array (0,",",".");

	sNumero=nNum.toString()
	if (nNumDec==0) sNumeroEntero = Math.round(nNum).toString()
	else sNumeroEntero = Math.floor(nNum).toString()

	nInicioDec = sNumeroEntero.length+1
	sDecimales = sNumero.substring(nInicioDec,nInicioDec+nNumDec)
	for (i=sDecimales.length;i<nNumDec;i++) sDecimales += "0";

	sEntero=""
	while (sNumeroEntero>=1000){
		sEntero = a_sPuntEnt[nFormato] + sNumeroEntero.substring(sNumeroEntero.length-3,sNumeroEntero.length) + sEntero ;
		sNumeroEntero = sNumeroEntero.substring(0,sNumeroEntero.length-3) ;
	}
	sEntero = sNumeroEntero + sEntero;
	if (nNumDec) sNumeroEntero= sSigno + sEntero + a_sPuntDec[nFormato] + sDecimales;
	else sNumeroEntero= sSigno + sEntero;
	return sNumeroEntero;
}

function Entero2Texto (nNumero){
 	var sNueva = "";
 	sNumero = ""+ Math.round(nNumero)
	while (sNumero.length>3) {
		sNueva  = "." + sNumero.substring(sNumero.length-3,sNumero.length)+sNueva 
		sNumero = sNumero.substring(0,sNumero.length-3)
	}	
	sNueva = sNumero + sNueva 
	return (sNueva);
}

function Texto2Numero(sNumero){		// 	Genera un Numero a partir de un String - Transforma de 1.000,5 a 1000.5 
var nPuntoPos1,nComaPos1,nPuntoPos2,nComaPos2,regExp,nNumero
var regCantidades=/[^0-9 .,-]/gi

	sNumero = "" + sNumero
	sNumero = sNumero.replace(regCantidades,"")		//quito puntos	
	if (sNumero=="") sNumero="0"

	nPuntoPos2 = sNumero.lastIndexOf(".")
	nComaPos2 = sNumero.lastIndexOf(",")

	if (nComaPos2>nPuntoPos2){		//'Decimales con ,
		nComaPos1 = sNumero.indexOf(",")
		regExp = /[\x2e]/g			// \x25\s
		sNumero = sNumero.replace(regExp,"")		//quito puntos	
		if (nComaPos1==nComaPos2){
			regExp = /[\x2c]/g
			sNumero = sNumero.replace(regExp,"\x2e")  		//cambio comas por puntos  
		}
		else{
			regExp = /[\x2c]/g
			sNumero = sNumero.replace(regExp,"")		//quito comas		
		}
	}
	else{							// Decimales con .
		nPuntoPos1 = sNumero.indexOf(".")
		regExp = /[\x2c]/g
		sNumero = sNumero.replace(regExp,"")		//quito comas		
		if (nPuntoPos1!=nPuntoPos2){
			regExp = /[\x2e]/g
			sNumero = sNumero.replace(regExp,"")		//quito puntos
		}
	}

	nPuntoPos2 = sNumero.lastIndexOf(".")	//Excepcion para numeros del tipo 1.000
	if (nPuntoPos2==sNumero.length-4 && sNumero.length<=7){
		regExp = /[\x2e]/g
		sNumero = sNumero.replace(regExp,"")		//quito puntos	
	}
	nNumero= parseFloat(sNumero)
	return nNumero
}

	
function _Texto2Numero(sNumero){		// 	Genera un Numero a partir de un String - Transforma de 1.000,5 a 1000.5 
	sNumero = "" + sNumero; // Casting a cadena
										
	reg = /[\x2e\x25\s]/g
	importe_sin_puntos  = sNumero.replace(reg,"");			
	importe_coma2punto = importe_sin_puntos.replace(",","\x2e")    
	importe_retorno = 1 * importe_coma2punto; // Casting a numero
	if (isNaN(importe_retorno)) importe_retorno=0
	return(importe_retorno);				
}

function Dec2Hex (nDec){
	return nDec.toString(16)				// Dec2Hex
}

var hexChars = "0123456789ABCDEF";
function _Dec2Hex (Dec){
	var a = Dec % 16;
	var b = (Dec - a)/16;
	hex = "" + hexChars.charAt(b) + hexChars.charAt(a);
	return hex;
}

function Numero2Grafico(sPuntos){
	sHTML=""
	if (sPuntos<0) {
	    sHTML="<IMG SRC='pix/menosdigital.gif'> "
	    sPuntos=sPuntos.substring(1,sPuntos.length)
	}
	for (f=0; f<sPuntos.length;f++){
		cCifra = sPuntos.charAt(f);	
		sHTML += "<IMG SRC='pix/"+ cCifra +"digital.gif'>" 
	}
	sHTML += "&nbsp;<IMG SRC='pix/kmdigital.gif'>"
	return sHTML
}


function Porcentaje (nValor,nTotal,nDecimales) {		//2.7
	if (!nDecimales) nDecimales=0
	var sPorcentaje ="- %"
	nValor = parseFloat(nValor)
	if (!isNaN(nValor)){
		sPorcentaje = Math.round(nValor * 100 * Math.pow(10,nDecimales))/nTotal
		sPorcentaje = Math.round(sPorcentaje)
		sPorcentaje = sPorcentaje/Math.pow(10,nDecimales) + " %"
	}
	return sPorcentaje
}



// 3. Arrays y cadenas ------------------------------------------------------

function BuscaEnArray (a_vArray,vValor){			//3.1 Busca la posicion en el array del ultimo valor que se le pasa (Devuelve -1 si no encuentra ninguna)
	var nLen = a_vArray.length
	var nPos=-1
	while (nPos<--nLen){ 
		if (a_vArray[nLen]==vValor) nPos=nLen
	}
	return nPos
}

function CopyJoinArray(a_sArrayS,a_sArrayD){		//3.2  Une/Copia un Array a continuacion de otro
	a_sArrayD = a_sArrayD.concat(a_sArrayS)
}


function RemoveDeArray (a_vArray,nPosicion,nElementos){		//3.3 a_vNewArray = RemoveDeArray (a_vArray,2,1)
	if(!nElementos) nElementos=a_vArray.length-nPosicion;
	var t1 = a_vArray.slice(0, nPosicion)
	var t2 = a_vArray.slice(nPosicion+nElementos)
	return (t1.concat(t2)) 					//Devuelve el array original sin los nElementos 
}

//Necesita: BuscaEnArray() y RemoveDeArray()
//Uso obligatorio: (igualar array a la funcion)
// a_vNewArray = RemoveElemento (a_sArray,"mi casa")
function RemoveElemento (a_vArray,vValor){					//3.4 Borra un elemento de un array
	nPos=BuscaEnArray (a_vArray,vValor)
	if (nPos!=-1) a_vArray=RemoveDeArray(a_vArray,nPos,1)
	return a_vArray
}


function SubArray(a_sArray,a_sArrayD,nInicial,nSalto){		//3.5 Crea un subarray de otro array
	var g=0
	for (var f = nInicial; f < a_sArray.length ; f+=nSalto){
		a_sArrayD[g++]=a_sArray[f]
	}
}

//a_vArray: puede ser un array o un valor	(a_1,a_2,0) o (a_1,"x",0)
//nPosicion ""/0/x = Final/Principio/Pos.x
function InsertArray (a_vArrayDest,a_vArray,nPosicion){		//3.6 a_vNewArray = InsertArray (a_vArray,"B",2)
	if (nPosicion==null){
		var t1=a_vArrayDest
		var t2=a_vArray
	}
	else{ 
		var t1 = a_vArrayDest.slice(0, nPosicion)
		var t2 = a_vArrayDest.slice(nPosicion)
		t1[nPosicion]=a_vArray
	}
	return (t1.concat(t2))
}

function BuscaMultiarray (sCampo,sArrayBase,nRegistro){		//3.7 Busca sCampo en CampoArray1 y devuelve el valor que esta en la misma posicion en el nRegistro(0-N) del MultiArray2
var a_sArray1 = eval ("a_s"+sArrayBase)
var a_vArray1 = eval ("a_v"+sArrayBase)

	var vValor="",f=0
	var nCampos = a_sArray1.length
	sCampo = sCampo.toLowerCase()			//No distingue entre MAY y min
	while (f<nCampos){
		if (typeof(a_sArray1[f])!="object"){
			if (sCampo==a_sArray1[f].toLowerCase()){
	
				nRegistro = (nRegistro*nCampos) +f
				vValor=a_vArray1[nRegistro]
				break
			}
		}
		f++
	}
	return vValor
}

// Se usa en: ev_cookies.js
function GetBiarray(sCampo,a_sArray1,a_vArray2){	//3.8 Busca valor en array1 y devuelve el valor que esta en la misma posicion en Array2
	var vValor="",f=0
	sCampo = sCampo.toLowerCase()			//No distingue entre MAY y min
	while (f<a_sArray1.length){
		if (sCampo==a_sArray1[f].toLowerCase()){
			vValor=a_vArray2[f]
			break
		}
		f++
	}
	return vValor
}

// Se usa en: ev_cookies.js
function SetBiarray(sCampo,a_sArray1,a_vArray2,vValor){	//3.9 Busca valor en array1 y guarda valor en la misma posicion en Array2
	var f=0
	sCampo = sCampo.toLowerCase()			//No distingue entre MAY y min
	while (f<a_sArray1.length){
		if (sCampo==a_sArray1[f].toLowerCase()){
			a_vArray2[f]=vValor
			break
		}
		f++
	}
//	return vValor
}

// aMatriz: nombre del array con los valores a ordenar
// bCual: Devuelve array con valores/indices				0/1
// direccion:Ordenado creciente/decreciente					0/1
function OrdenarArray(aMatriz,bCual,nDireccion){
	var final= new Array()
	var final_orden= new Array()
	final[0]=aMatriz[0]
	final_orden[0]=0
	for (j=1;j<aMatriz.length;j++){
		ordenando=1
		for (k=0;k<j;k++){

			vValor1 = final[k].toUpperCase()
			vValor2 = aMatriz[j].toUpperCase()
			vValor1T= Fecha2Date(vValor1)	//Para ordenar fechas en formato texto
			vValor2T= Fecha2Date(vValor2)
			if (typeof(vValor1T)=="object" && typeof(vValor1T)=="object"){
				if (vValor1T.constructor==Date && vValor2T.constructor==Date){
					vValor1= vValor1T
					vValor2= vValor2T
				}
			}

			if (!isNaN(vValor1) && !isNaN(vValor2)){
				 vValor1=parseFloat(vValor1)
				 vValor2=parseFloat(vValor2)
			}

			if (nDireccion!=0) cual=(vValor1<vValor2)
			else cual=(vValor1>vValor2)

			if ((cual) && (ordenando)){
				for (n=j;n>k;n--){
					final[n]=final[n-1]
					final_orden[n]=final_orden[n-1]
					ordenando=0
				}
				final[k]=aMatriz[j]
				final_orden[k]=j
			}
		}
		if (ordenando) {
			final[j]=aMatriz[j]
			final_orden[j]=j
		}
	}
	if (bCual) final = final_orden;
	return final;
}


// aMatriz: nombre del array con los valores a ordenar
// bCual: Devuelve array con valores/indices				0/1
// direccion:Ordenado creciente/decreciente					0/1
function OrdenarMultiarray(sArrayBase,sCampo,bCual,nDireccion){		//3.11
var a_sArray1,a_sArray2,a_sArrayDatos,nCampos, nPos,f
a_sArray1 = eval ("a_s"+sArrayBase)
a_sArray2 = eval ("a_v"+sArrayBase)
a_sArrayDatos = new Array()

	nRegs = RegsMultiarray (sArrayBase)
	nCampos = a_sArray1.length
	nPos = BuscaEnArray (a_sArray1,sCampo)
	for (f=0;f<nRegs;f++){
		a_sArrayDatos[f]= a_sArray2[(f*nCampos)+nPos]
	}
	return OrdenarArray(a_sArrayDatos,bCual,nDireccion)
}

function AddCampo2Multiarray (sArrayBase,sCampo,sEXML){			//3.12
var a_sArray1,a_sArray2,nRegistros,nDatos,f,vValor
a_sArray1 = eval ("a_s"+sArrayBase)
a_sArray2 = eval ("a_v"+sArrayBase)
nRegistros = RegsMultiarray (sArrayBase)

nDatos = a_sArray1.length

	a_sArray1=InsertArray (a_sArray1,sCampo)
	for (f=0;f<nRegistros;f++){
		vValor = ParseEXMLs(sEXML,"",sArrayBase,f)
		a_sArray2 = InsertArray (a_sArray2,vValor,((f+1)*nDatos)+f)
	}
	eval ("a_s"+sArrayBase+"=a_sArray1")	
	eval ("a_v"+sArrayBase+"=a_sArray2")
}



// DEPRECATED !!! usar ParseEXMLs()
// 	Parse: "texto%nombre del campo%texto"
//			Si ponemos "Texto false%%campo%Texto True" justo al inicio como un switch
function _ParseCodigo (sJSarrayBase,sCodigo,nRegistro){		// 3.13
var nPos1,nPos2,nPos3,sTag,vDato
var sTagIni = "%", sTagFin = "%", sTabValidar = "%%", sFinal=""

	nPos1	= sCodigo.indexOf(sTagIni)
	nPos2	= sCodigo.indexOf(sTagFin,nPos1+1)
	WhileLabel:
	while (nPos1!=-1 && nPos2!=-1){
		sFinal	= sFinal + sCodigo.substr(0,nPos1) 
		nPos3 = sCodigo.indexOf(sTabValidar)
		if (nPos3!=-1 && nPos1==nPos3){ 		//Caso %%
			nPos1 = nPos3
			nPos2 = sCodigo.indexOf(sTagFin,nPos1+2)
			sTag  = sCodigo.substr(nPos1+2,nPos2-nPos1-2) 

			bValidar= BuscaMultiarray (sTag,sJSarrayBase,nRegistro)
			if (!bValidar){
				sCodigo=""
				break WhileLabel
			}
			else{ 
				sFinal=""
			}
		}	
		else{									//Caso %
			sTag	= sCodigo.substr(nPos1+1,nPos2-nPos1-1) 
			vDato = BuscaMultiarray (sTag,sJSarrayBase,nRegistro)
//			if (IsDate(vDato)) then vDato=FechaFormatoBD (vDato, "ES")	'Fechas BD
//			if (IsNumeric(vDatoBD)) then vDato=Round(vDato,2)
			sFinal	= sFinal + vDato
		}
		sCodigo	= sCodigo.substr(nPos2+1)
		nPos1	= sCodigo.indexOf(sTagIni)
		nPos2	= sCodigo.indexOf(sTagFin,nPos1+1)
	}
	sFinal	= sFinal + sCodigo
	if (sFinal=="") sFinal="&nbsp;"

	return sFinal
}


// bIndices: Devuelve array con valores/indices				0/1
function BuscarSubArray(a_vArray,sTexto,bIndices){			//3.14 Crea un array con los datos que contienen el texto
var a_vFinal,nFinal,f,sDato
	a_vFinal= new Array()

	nFinal=0
	for (f=0;f<a_vArray.length;f++){
		sDato = "" + a_vArray[f]
		if  (sDato.indexOf(sTexto)!=-1){
			if (bIndices){
				a_vFinal[nFinal++]= f
			}
			else{
				a_vFinal[nFinal++]= sDato			
			}			
		}
	}
	return a_vFinal;
}


function RegsMultiarray (sArrayBase){			//3.15  Numero de registros de MultiArray
var a_sArray1,a_sArray2,nRegs
a_sArray1 = eval ("a_s"+sArrayBase)
a_sArray2 = eval ("a_v"+sArrayBase)
	nRegs= (a_sArray2.length / a_sArray1.length)
	return nRegs
}

function BuscaMArrayValor(sArrayBase,sCampo,vValor){		//3.16	Busca un valor en un MA y devuelve el nReg
var a_sArray1,a_sArray2,a_sArrayDatos,nRegs,nCampos,nPos,nReg,f
a_sArray1 = eval ("a_s"+sArrayBase)
a_sArray2 = eval ("a_v"+sArrayBase)

	nRegs = RegsMultiarray (sArrayBase)
	nCampos = a_sArray1.length
	nPos = BuscaEnArray (a_sArray1,sCampo)
	nReg=-1
	for (f=0;f<nRegs;f++){
		vValorC = a_sArray2[(f*nCampos)+nPos]
		if (vValor==vValorC){
			nReg=f
			break
		}
	}
	return nReg
}

function ModMultiarray(sArrayBase,sCampo,sEXML){		// Modifica un campo completo del MBArray (hay que programar lo que necesitemos y renombrar la funcion) 
var	nPos,nRegs,vValor
var a_sArray1 = eval ("a_s"+sArrayBase)
var a_sArray2 = eval ("a_v"+sArrayBase)

	nPos = BuscaEnArray (a_sArray1,sCampo)
	if (nPos!=-1) {
		nCampos = a_sArray1.length	//+1
		nRegs = (a_sArray2.length) / nCampos
		for (f=0;f<nRegs;f++){ 
			vValor = ParseEXMLs(sEXML,"",sArrayBase,f)
			a_sArray2[nPos] = vValor
			nPos = nPos + nCampos
		}
	}
}

function SubMArray(sJSarrayBase,a_sArrayD,a_nPos){		//3.18 Crea un subMArray de otro MArray
var a_sArray1 = eval ("a_s"+sJSarrayBase)
var a_sArray2 = eval ("a_v"+sJSarrayBase)
var nRegs,nCampos,nPos,g=0

	nCampos = a_sArray1.length
	for (var f = 0; f < a_nPos.length ; f++){
		nPos = a_nPos[f]*nCampos
		for (h=0;h<nCampos;h++){			//Copia todo el registro
			a_sArrayD[g++]=a_sArray2[nPos++]
		}
	}
}

function DelRegMArray (sArrayBase,nReg){		//3.19 Borra un registro de un MArray
var a_sArray1 = eval ("a_s"+sArrayBase)
var a_sArray2 = eval ("a_v"+sArrayBase)
var nRegLen = a_sArray1.length
	a_sArray2 = RemoveDeArray (a_sArray2,nReg*nRegLen,nRegLen)
	eval ("a_v"+sArrayBase+"=a_sArray2")
}

function SetMArray(sArrayBase,sCampo,nRegistro,vValor){	//3.20 Busca sCampo de nRegistro y lo modifica
var a_sArray1 = eval ("a_s"+sArrayBase)
var a_vArray1 = eval ("a_v"+sArrayBase)
var f=0
	var nCampos = a_sArray1.length
	sCampo = sCampo.toLowerCase()			//No distingue entre MAY y min
	while (f<nCampos){
		if (typeof(a_sArray1[f])!="object"){
			if (sCampo==a_sArray1[f].toLowerCase()){
				nRegistro = (nRegistro*nCampos) +f
				a_vArray1[nRegistro]=vValor
				break
			}
		}
		f++
	}
}




// 4. Ventanas ------------------------------------------------------

function AbreWindow(html,ancho,alto){		
// Añadir parametros: scrollbar, toolbar, top left
	propiedades='"width='+ancho+',height='+alto+',scrollbars=auto,toolbar=no,location=no,menu=no,resizable=no,left=0,top=0"'
	WebMediaWindow = window.open(html, "WebMedia", eval(propiedades))
}	

function CierraWindow(){
	window.close()	
}

function AbreAyuda(){
	WebmediaWindow = window.open("ayuda.html", "Ayuda", "width=260,height=300,scrollbars=yes,toolbar=no,location=no,menu=no,left=0,top=0")
}	


// 5. Otras ------------------------------------------------------



function Aleatorio(nMaximo) {						// 5.1 Devuelve numero entre 1 y numero
	return (Math.ceil (Math.random()*nMaximo) )			//funciona en NS3,NS4,IE5 ¿IE3,IE4?
}

function SignoAleatorio() {							// 5.2 Devuelve 1 o -1
	return (-1+2*(Math.round(Math.random())))
}

g_dFecha  =new Date();
g_nRndSeed=g_dFecha.getTime();
function Aleatorio_old(nMaximo){						//de 1 a nMaximo 
	g_rnd_seed=(g_nRndSeed*9301+49297)%233280;
	return (Math.ceil((g_nRndSeed/233280)*(nMaximo)));
}

function ParseEXMLs (sEXML,oObj,sJSarrayBase,nRegistro) {		//5.3
var a_sTags,f,s
a_sTags = new Array("ifBD","BD","OBJ","FUN")	//Es muy importante el orden !!!

	if (!sJSarrayBase) sJSarrayBase=eval (oObj.m_sObj+".m_sJSarrayBase")
	for (f=0;f<a_sTags.length;f++){
//alert (a_sTags[f]+"_______"+sEXML)
		sEXML = ParseEXML(a_sTags[f],sEXML,oObj,sJSarrayBase,nRegistro)
	}
	return sEXML
}

//La version de ev_tablas.js es mas completa
function ParseEXML(sTag,sEXML,oObj,sJSarrayBase,nRegistro) {		//5.4
var nPos1,nPos2,sDato
var sTagIni = "<"+sTag+">", sTagFin = "</"+sTag+">", sFinal=""
var nTag1=sTagIni.length, nTag2=sTagFin.length

	if (!sJSarrayBase) sJSarrayBase=eval (oObj.m_sObj+".m_sJSarrayBase")
	nPos1	= sEXML.indexOf(sTagIni)
	nPos2	= sEXML.indexOf(sTagFin,nPos1+nTag1)

	WhileLabel:
	while (nPos1!=-1 && nPos2!=-1){
		sFinal	= sFinal + sEXML.substr(0,nPos1) 

		sDato	= sEXML.substr(nPos1+nTag1,nPos2-nPos1-nTag1)

		switch (sTag){
		case "ifBD":
			bValidar= BuscaMultiarray (sDato,sJSarrayBase,nRegistro)
			if (!bValidar){
				sEXML=""
			}
			else{ 
				sFinal=""
			}
			sDato=""
			break
		case "BD":
			sDato = BuscaMultiarray (sDato,sJSarrayBase,nRegistro)
			break
		case "OBJ":
			sDato = eval (oObj.m_sObj+".m_"+sDato)
			break	
		case "FUN":
			sDato = eval (sDato)
			break	
		default:
		}

//		if (IsDate(vDato)) then vDato=FechaFormatoBD (vDato, "ES")	'Fechas BD
//		if (IsNumeric(vDatoBD)) then vDato=Round(vDato,2)
		sFinal	= sFinal + sDato

		sEXML	= sEXML.substr(nPos2+nTag2)
		nPos1	= sEXML.indexOf(sTagIni)
		nPos2	= sEXML.indexOf(sTagFin,nPos1+nTag1)
	}
	sFinal	= sFinal + sEXML
	if (sFinal=="") sFinal="&nbsp;"

	return sFinal
}



// 6. DIV ------------------------------------------------------

bIE4 = (document.all);
bNS4 = (document.layers);

function CambiarDIV(divID,sText,sFrame) {					//v1.01 Cambia DIVS de otros frames
	if (!sFrame) sFrame=""

	if (bNS4) {
		var lyr = eval (sFrame + "document.layers[divID].document")
		lyr.open()
		lyr.write(sText)
		lyr.close()
	}
	else if (bIE4) eval (sFrame + "document.all[divID].innerHTML = sText")
}

function ShowDIV(sId,nVisible){		// v0.1 	0/1/2 Hide/ver/Swap (aun falta)
	if(bNS4) {
		sVisible = 'hide'
		if (nVisible) sVisible = 'show'
		eval("document."+sId+".visibility ='"+sVisible+"'");
	}
	else {
		sVisible = 'hidden'
		if (nVisible) sVisible = 'visible'
		eval(sId+".style.visibility 	= '"+sVisible+"'");
	}
}


// 7. Combos ------------------------------------------------------

// a_sNombre (pasa de los valores nulos del array de textos)
// a_sValor: array de valores
//			-1 = usa el valor siguiente de a_sNombre
//			 X = usa pos del array+X
// vValorSelected --> "Valor1" ó "Valor2" ...  (es el que aparece por defecto)
function CreaCombo(sSelectName,sFuncion,sTitulo,a_sNombre,a_sValor,vValorSelected) { 	//7.1
var i,nValue
	var nValor=0
	if (a_sValor==-1) {
		a_sValor=a_sNombre					// -1
		nValor=1
	}
	if (typeof(a_sValor)=="number") {
		nValue=a_sValor
		a_sValor=new Array()
		for (i=0;i<a_sNombre.length;i++){	// X
			a_sValor[i]=i+nValue
		}
	}

	var sCombo ='<SELECT NAME="'+sSelectName+'"'
	if (sFuncion) sCombo+= " " +sFuncion
	sCombo+='>'

	if (sTitulo!=""){
		sCombo += "<OPTION value=''"
		sCombo += ">" + sTitulo + "</OPTION>"
	}

	for (i=0;i<a_sNombre.length-nValor;i+=1+nValor){
		if (a_sNombre[i]){
			sCombo += "<OPTION "
			sCombo += 'value="' + a_sValor[i+nValor] + '"'
			if (vValorSelected && a_sValor[i+nValor]==vValorSelected) sCombo +=" selected"
			sCombo +=  ">" + a_sNombre[i] + "</OPTION>"
		}
	}
	sCombo+='</SELECT>'
	return sCombo
}


// Deprecated: usar CreaCombo() (No es compatible)
// vValorSelected --> "Valor1" ó "Valor2" ...  (es el que aparece por defecto)
// a_sValor: array de valores/0=usa los mismos valores de a_sNombre/1=usa el valor siguiente de a_sNombre
function _CrearCombo(sFormName,sFuncion,a_sNombre,a_sValor,vValorSelected) { 
var nValor=0
	if (a_sValor==0) a_sValor=a_sNombre		// 0 = usa los mismos valores
	if (a_sValor==1) {
		a_sValor=a_sNombre					// 1 = usa el siguiente valor de a_sNombre
		nValor=1
	}
	var sCombo ='<SELECT NAME="'+sFormName+'"'
	if (sFuncion) sCombo+= " " +sFuncion
	sCombo+='>'
	for (i=0;i<a_sNombre.length-nValor;i+=1+nValor){
		sCombo += "<option "
		sCombo += 'value="' + a_sValor[i+nValor] + '"'
		if (a_sValor[i+nValor]==vValorSelected)  sCombo +=" SELECTED"
		sCombo +=  ">" + a_sNombre[i] + "</option>"
	}
	sCombo+='</SELECT>'
	return sCombo
} 


// Funciones externas: 	[3.15] RegsMultiarray ()		[5.3] ParseEXMLs ()
function ComboEXML(sFormName,sFuncion,sJSarrayBase,sEXMLtexto,sEXMLvalor,vValorSelected) { 		//7.2
var nFilas,sCombo,i,sValor
	nFilas = RegsMultiarray (sJSarrayBase)
	if (sEXMLvalor=="") sEXMLvalor=sEXMLtexto

	sCombo ='<SELECT NAME="'+sFormName+'"'
	if (sFuncion) sCombo+= " " +sFuncion
	sCombo+='>'

	for (i=0;i<nFilas;i+=1){
		sCombo += "<option "
		sValor = ParseEXMLs (sEXMLvalor,"",sJSarrayBase,i)
		sCombo += 'value="' + sValor + '"'
		if (sValor==vValorSelected)  sCombo +=" SELECTED"
		if (sEXMLvalor==sEXMLtexto) sTexto=sValor			
		else sTexto = ParseEXMLs (sEXMLtexto,"",sJSarrayBase,i)
		sCombo +=  ">" + sTexto + "</option>"
	}
	sCombo+='</SELECT>'
	return sCombo
}

// 8. Debug ------------------------------------------------------

g_nDebugMode = 1		//0=disabled / 1=alert / 2=alert mo salen si tienes el boton derecho apretado / 3=todo al status / 4=return

function DebugMode () {
	var sHTML=""
	for (i=0;i<arguments.length;i++){
		sHTML += arguments[i]+":`"+eval(arguments[i])+"´\n"
	}	
	if (g_nDebugMode==1) alert (sHTML)
	if (g_nDebugMode==2) alert (sHTML)
	if (g_nDebugMode==3) window.status=sHTML
	if (g_nDebugMode==4) return sHTML
}

// 9. Cadenas ------------------------------------------------------

function BuscaTexto(sCadena,sTexto,bHaciaAtras) {	// 9.1 Busca texto en una cadena (devuelve posicion o -1 si no existe)
	if (bHaciaAtras) return sCadena.lastIndexOf(sTexto)
	else return sCadena.indexOf(sTexto)
}


//sNuevoTexto=CambiaTexto(0,"un texto antiguo, muy antiguo","antiguo","nuevo",1)
//nAccion: 0=replace+delete / 1=insert delante / 2=insert detras
//bMultiple:  0=realiza 1 cambio / 1=realiza n cambios
function CambiaTexto(nAccion,sTexto,sBuscado,sNuevo,bMultiple){			// 9.2 Search & insert/replace/delete un texto
	var nPos1,nPos2;
	if (sNuevo==null) sNuevo=""
	nBuscado= sBuscado.length
	nNuevo	= sNuevo.length
	nPos1 = sTexto.indexOf(sBuscado)
	while (nPos1!=-1){
		nPos2=nPos1
		if (nAccion==0) nPos2 += nBuscado
		if (nAccion==2) {
			nPos1 += nBuscado
			nPos2 += nBuscado
		}
		sTexto = sTexto.substr(0,nPos1) + sNuevo + sTexto.substr(nPos2)
		if (bMultiple) {
			nPos1 += nNuevo
			if (nAccion==1) nPos1 += nBuscado
			nPos1 = sTexto.indexOf(sBuscado,nPos1)
		}
		else nPos1=-1
	}
	return (sTexto)
}


function LimiteCadena(sCadena,nMaximo){		//9.3 Comprueba tamaño de una cadena
	var nLongitud = sCadena.length
	if (nLongitud>nMaximo) alert ("El texto es demasiado largo. Sobran "+(nLongitud-nMaximo)+" letras.")
}


function HTML2texto(sTexto){				//9.4 Convierte HTML en texto <=&lt; y >=&gt;
var f,sRegExp,a_sOldChar,a_sNewChar;
a_sOldChar = new Array ("/[<]/gi","/[>]/gi")
a_sNewChar = new Array ("&lt;","&gt;")
	for (f=0;f<a_sOldChar.length;f++){
		sRegExp = a_sOldChar[f];
  		sTexto = sTexto.replace (eval(sRegExp), a_sNewChar[f]);
	}
	return (sTexto)
}

//a_cValidos_E = new Array (" ",".","_","@")
//ValidarCadena("texto de prueba",a_cValidos_E)
function ValidarCadena(sCadena,a_cValidos){		// 9.5 Comprueba que solo haya letras, numeros y los caracteres del array que le pasamos
	var bCaracter
	miCadena = sCadena.toUpperCase();
	for (f = 0; f < miCadena.length ; f++){
		bCaracter = miCadena.charAt(f);		
		if (!(BuscaEnArray (a_cValidos_B,bCaracter)!=-1 || (bCaracter >= "A" && bCaracter <= "Z") || (bCaracter >= "0" && bCaracter <= "9"))) return sCadena.charAt(f);
	}
	return 0;
}

function Texto2HTML(sTexto){				//9.6
var f,sRegExp,a_sOldChar,a_sNewChar;
a_sOldChar = new Array ('/["]/gi',"/[']/gi")
a_sNewChar = new Array ("&quot;","&39;")
	for (f=0;f<a_sOldChar.length;f++){
		sRegExp = a_sOldChar[f];
  		sTexto = sTexto.replace (eval(sRegExp), a_sNewChar[f]);
	}
	return (sTexto)
}


// 10. Internas ------------------------------------------------------

function ExisteFuncion(sFuncion){			//10.1 [0/1 No/si] funcion entre comillas "Init"
var sType,bExiste
	bExiste=0
	sType = eval("typeof("+sFuncion+")")
	if (sType=="function") bExiste=1
	return bExiste
}

function ExisteFrame(sFrame){			//0/1 No/si , frame sin comillas (parent.FR_Main)
var sType,bExiste
	bExiste=0
	sType=(typeof(sFrame))
	if (sType!="undefined") bExiste=1
	return bExiste
}