/**

	TÃ­tulo..: VeryTinyAJAX2 0.2, Wrapper JavaScript simple a funciones XMLHTTP para AJAX
	          e integraciÃ³n con PHP en busca de la reducciÃ³n y simplificaciÃ³n de cÃ³digo.
  Licencia: GPLv2 (http://www.gnu.org/licenses/gpl.txt)
	Autores.: Pablo RodrÃ­guez Rey (mr.xkr -en- inertinc -punto- org)
	          http://mr.xkr.inertinc.org/
            Javier Gil Motos (cucaracha -en- inertinc -punto- org)
            http://cucaracha.inertinc.org/

	Agradecimientos a Cucaracha, por darme interÃ©s en el desarrollo de webs usando
	AJAX y proveerme del ejemplo bÃ¡sico con el que estÃ¡ desarrollada esta librerÃ­a.
	TambiÃ©n a Binny V A (binnyva -en- hotmail -punto- com - binnyva.com) por la funciÃ³n adump.

	MÃ³dulo de funciones cliente JavaScript.
	
	Ejemplo de usos comunes (pueden ser probados en ajax.test.php):
	
		PETICIÃ“N COMPLETA (GET ajax=eco POST data=datos):
			ajax({
				"get":{"ajax":"eco"},
				"post":{"data":"datos de ejemplo"},
				"async":function(resultado){
					alert(adump(resultado.data));
				},
				"error":function(error){
					error.show();
				}
			});
		
		PETICIÃ“N ABREVIADA EQUIVALENTE (GET ajax=eco POST data=datos):
			ajax("eco","datos de ejemplo",function(resultado){
				alert(adump(resultado.data));
			});
		
		PETICIÃ“N DE TEXTO ABREVIADA (solo campos tipo POST):
			ajax({
				"datos":"datos de ejemplo"
			},function(resultado){
				alert(adump(resultado.data));
			});

*/

// informaciÃ³n de versiÃ³n
function ajaxVersion() { return("VeryTinyAJAX2/0.2"); }

// get object id (incluida en common.js)
function gid(id) {
	try {
		if (typeof(id)=="object") return id;
		else return document.getElementById(id);
	} catch(e) {
		return(null);
	}
}

// generar un nuevo objeto XMLHttpRequest
function httpObject() {
	var xmlhttp;
	try { xmlhttp=new ActiveXObject("Msxml2.XMLHTTP"); }
	catch (e) { try { xmlhttp=new ActiveXObject("Microsoft.XMLHTTP"); }
	catch (e) { try { xmlhttp=new XMLHttpRequest(); }
	catch (e) { xmlhttp=false; } } }
	return xmlhttp;
}

// cadena de estado de la peticiÃ³n
function httpStateString(readyState) {
	switch (readyState) {
	case 0: return("Uninitialized")
	case 1: return("Loading");
	case 2: return("Loaded");
	case 3: return("Interactive");
	case 4: return("Complete");
	case 5: return("Server Crashed");
	}
}

// comprobar si las peticiones AJAX estÃ¡n soportadas por este navegador
function ajaxEnabled() {
	return (httpObject()?true:false);
}

// parsear cadena para ser enviada por GET/POST
function gescape(torg) {
	var d=""+torg;
	try { var d=d.replace(/\"/gi,"%22"); } catch(e) {}
	try { var d=d.replace(/\\/gi,"%5C"); } catch(e) {}
	try { var d=d.replace(/\?/gi,"%3F"); } catch(e) {}
	try { var d=d.replace(/&/gi,"%26"); } catch(e) {}
	try { var d=d.replace(/=/gi,"%3D"); } catch(e) {}
	try { var d=d.replace(/\+/gi,"%2B"); } catch(e) {}
	try { var d=d.replace(/ /gi,"%20"); } catch(e) {}
	return(d);
}

// hard escape: codifica aparte de los especiales,
// tambiÃ©n aquellos cuyo ASCII sea <32 o >127
function hescape(t) {
	var s=gescape(t);
	var r="";
	var c;
	for (var i=0;i<s.length;i++) {
		c=s.charCodeAt(i);
		r+=(c<32 || c>127?"%"+c.toString(16):s.charAt(i));
	}
	return r;
}

// funciÃ³n auxiliar para crear cadenas PHP sin caracteres de control
function jescape(torg) {
	var d=""+torg;
	try { var d=d.replace(/\\/gi,"\\\\"); } catch(e) {}
	try { var d=d.replace(/\"/gi,"\\\""); } catch(e) {}
	try { var d=d.replace(/\n/gi,"\\n"); } catch(e) {}
	try { var d=d.replace(/\t/gi,"\\t"); } catch(e) {}
	try { var d=d.replace(/\f/gi,"\\f"); } catch(e) {}
	try { var d=d.replace(/\r/gi,"\\r"); } catch(e) {}
	return(d);
}

// array to get
function atoget(a,extra) {
	var g="";
	for (var i in a)
		g+=(g?"&":"?")+gescape(i)+"="+gescape(a[i]);
	if (extra)
		for (var i in extra)
			g+=(g?"&":"?")+gescape(i)+"="+gescape(extra[i]);
	return g;
}

// convertir variable JavaScript a JSON
function json(a,level) {
	if (!level) level=0;
	if (a==null) return 'null';
	switch (typeof(a)) {
	case 'object':
		var s="";
		for (var i in a) s+=(s?",":"")+(a.length?'':'"'+jescape(i)+'":')+json(a[i],level+1);
		return (a.length?"[":"{")+s+(a.length?"]":"}");
	case 'boolean': return (a?'true':'false');
	case 'number': return a;
	case 'string': default: return '"'+jescape(a)+'"';
	}
	return null;
}

// volcar el Ã¡rbol de una variable JavaScript
function adump(arr,level) {
	if (!level) level=0;
	var s="";
	var t=""; for (var j=0;j<level;j++) t+="\t";
	try {
		if (typeof(arr)=='object') {
			if (arr.nextSibling) return t+"{*}\n"; // NO devolver elementos internos del navegador
			for (var item in arr) {
				var value=arr[item];
				if (typeof(value)=='object') {
					var size=0; for (var none in value) size++;
					s+=t+'"' + item + '" = '+typeof(value)+'('+size+'):\n';
					s+=adump(value,level+1);
				} else {
					s+=t+'"' + item + '" = '+typeof(value)+'("' + value + '")\n';
				}
			}
		} else {
			s="("+typeof(arr)+") "+arr;
		}
	} catch(e) {}
	return s;
}

// peticiÃ³n AJAX
function ajax(data,realdata,func,isplain) {
	
	// convertir llamada abreviada en significado real: llamada en plano
	if (typeof(data)=="object" && typeof(realdata)=="function") {
		// configuraciÃ³n por defecto:
		ajax({
			"post":data, // datos que se enviarÃ¡n por post
			"async":realdata, // funciÃ³n de retorno asÃ­ncrona
			"showerrors":false, // se mostrarÃ¡n errores tÃ­picos
			"plain":true // la peticiÃ³n es AJAX o es de texto plano/XML
		});
		return;
	}
	
	// convertir llamada abreviada en significado real: llamada abreviada
	if (typeof(data)=="string" && typeof(func)=="function") {
		// configuraciones por defecto
		if (typeof(isplain)=="function") {
			ajax({
				"ajax":data, // comando ajax
				"data":realdata, // datos que se enviarÃ¡n
				"showerrors":true, // se mostrarÃ¡n errores tÃ­picos
				"always":func, // ejecutar esta funciÃ³n siempre (al terminar o al ocurrir un error)
				"async":isplain // funciÃ³n de retorno asÃ­ncrona
			});
		} else {
			ajax({
				"ajax":data, // comando ajax
				"data":realdata, // datos que se enviarÃ¡n
				"async":func, // funciÃ³n de retorno asÃ­ncrona
				"showerrors":true, // se mostrarÃ¡n errores tÃ­picos
				"plain":(isplain?true:false) // la peticiÃ³n es AJAX o es de texto plano/XML
			});
		}
		return;
	}

	// si no estÃ¡ soportado, cancelar peticiÃ³n
	if (!ajaxEnabled()) return false;

	// si no se especifica donde se realiza la peticiÃ³n, se presupone a si mismo
	if (data.url==undefined) {
		var url=location.href;
		if ((i=url.indexOf("?"))!=-1) url=url.substring(0,i);
		data.url=url;
	}
	
	// control de eventos HTTP
	function events(http) {
		
		// objeto resultado
		function result() {
			
			// estado de la peticiÃ³n y cadena de estado
			try { this.state=http.readyState; } catch(e) { this.state=5; }
			this.stateString=httpStateString(this.state);

			// indicar si se ha completado la operaciÃ³n
			this.complete=(http.readyState==4?true:false);

			// cÃ³digo de protocolo del servidor
			try { this.status=http.status; } catch(e) { this.status=null; }
			
			// si el estado es OK, devolver datos
			if (this.status==200) {
				this.text=http.responseText; // datos recibidos en texto plano
				this.xml=http.responseXML; // datos recibidos en XML
				this.data=null; // ausencia de datos por defecto
				try { eval("this.data="+http.responseText); }
				catch(e) { this.error=true; } // datos recibidos en JSON son preparados
			}
			
		}

		// Comprobar que la respuesta del servidor es la 200 (HTTP OK)
		var error=false;
		if (http.readyState==4) {
			try { error=(http.status!=200); }
			catch(e) { error=true; }
		}

		// crear objeto resultado
		var r=new result();
		
		// devolver evento
		if (error) {
			if (data.error || data.showerrors) {
				function result_error() {
					this.status=r.status;
					this.error=(r.status
						?"Se ha encontrado el error "+r.status+" en el servidor."
						:"El servidor no responde a la peticiÃ³n!\nPruebe dentro de unos instantes."
					);
					this.show=function(){
						if (typeof(newalert)=="function") newalert({"ico":"error","id":"verytinyajax2","msg":this.error});
						else alert(this.error);
					}
				}
				var re=new result_error();
				switch (typeof(data.error)) {
				case "boolean": re.show(); break;
				case "string":
					if (typeof(newalert)=="function") newalert(data.error);
					else alert(data.error);
					break;
				case "function": data.error(re); break;
				}
				if (always) always(re);
				if (data.showerrors && re.status) re.show();
			}
		} else {
			if (r.complete) {
				if (data.showerrors && r.error && !data.plain) {
					var alertmsg="Error en buffer de salida: No se puede procesar la peticiÃ³n AJAX";
					if (typeof(newalert)=="function") newalert({"ico":"error","id":"verytinyajax2","msg":r.text,"title":alertmsg});
					else alert(alertmsg+"\n\n"+r.text);
				}
				if (always) always(r);
				func(r);
			} else {
				if (data.events)
					data.events(r);
			}
		}
	
	}
	
	// preparar datos
	var http=httpObject();
	var async=(data.sync?false:true);
	var func=(async?data.async:data.sync);
	var always=data.always;
	var url=data.url;
	var post="";

	// si se especifica acciÃ³n, incluir parÃ¡metro GET ajax=acciÃ³n
	if (data.ajax) url+=(url.indexOf("?")<0?"?":"&")+"ajax="+data.ajax;
	
	// si se especifican parÃ¡metros GET adicionales, incluirlos
	if (data.get)
		if (typeof(data.get)=="object") {
			for (var i in data.get)
				url+=(url.indexOf("?")<0?"?":"&")+i+"="+gescape(data.get[i]);
		} else {
			url+=(url.indexOf("?")<0?"?":"&")+data.get;
		}
	
	// si se especifican datos por POST, incluirlos
	if (data.post)
		if (typeof(data.post)=="object") {
			for (var i in data.post)
				post+=(post?"&":"")+i+"="+gescape(data.post[i]);
		} else {
			post=data.post;
		}

	// si hay datos prefijados, aÃ±adir al POST en formato JSON
	if (data.data)
		post+=(post?"&":"")+"data="+gescape(json(data.data));

	// peticiÃ³n HTTP
	http.open((post?"POST":"GET"),url,async);
	if (async) http.onreadystatechange=function(){ events(http); };
	http.setRequestHeader('Content-Type','application/x-www-form-urlencoded; charset=UTF-8"');
	http.send(post?post:null);
	if (!async) events(http);
	
	// completado correctamente
	return true;
	
}

// mÃ©todos de xform
function xform() {

	// devuelve un valor de un campo
	this.value=function(object) {
		switch (gid(object).type) {
		case "checkbox": return(object.checked?"1":"0");
		case "select-multiple": var d=[]; for (var i=0; i<object.length; i++) if (object.options[i].selected) d.push(object.options[i].value); return(d);
		case "radio": case "button": case "select-one": case "text": case "textarea": default: return(object.value);
		}
	}
	
	// habilitar o deshabilitar la posibilidad de introducciÃ³n
	// o modificaciÃ³n de datos de un formulario completo.
	this.enabled=function(formObject,isEnabled) {
		var formObject=gid(formObject);
		for (var i=0;i<formObject.length;i++) {
			try { formObject[i].disabled=!isEnabled; } catch(e) {}
		}
	}
	
	// devuelve todos los campos y datos de un formulario en formato JSON
	this.form=function(formObject){
		var formObject=gid(formObject);
		var fields=new Object();
		for (i=0;i<formObject.length;i++) {
			if (!formObject[i].name) continue;
			if (formObject[i].type=="radio" && !formObject[i].checked) continue;
			fields[formObject[i].name]=this.value(formObject[i]);
		}
		return fields;
	}
	
	// devuelve todos los campos y datos de un lista de identificadores
	// tipo id1,id2,id3 y lo devuelve en formato JSON
	this.fields=function(fieldNames) {
		var fn=(typeof(fieldNames)=="object"?fieldNames:fieldNames.split(","));
		var fields=new Object();
		var formValue;
		for (i=0;i<fn.length;i++) {
			formValue=gid(fn[i]);
			if (!formValue) continue;
			if (formValue.type=="radio" && !formValue.checked) continue;
			fields[fn[i]]=this.value(formValue);
		}
		return fields;
	}

}

// instanciar xform
var xf=new xform();
// common.js by mr.xkr v2 rev.4

// pequeÃ±as funciones para reducir cÃ³digo
function gid(id) {
	try {
		if (typeof(id)=="object") return id;
		else return document.getElementById(id);
	} catch(e) {
		return(null);
	}
}
function gidget(id) { return(gid(id).innerHTML); }
function gidset(id,html) { gid(id).innerHTML=html; }
function gidval(id,data) { if (typeof(data)!="undefined") gid(id).value=data; else return(gid(id).type=="checkbox"?(gid(id).checked?gid(id).value:""):gid(id).value); }
function gidvals(idsdata) { for (var i in idsdata) gidval(i,idsdata[i]); }
function giddel(id) { var d=gid(id); d.parentNode.removeChild(d); }
function gidmove(id_org,id_dst) { gid(id_dst).innerHTML=gid(id_org).innerHTML; gid(id_org).innerHTML=""; }
function alter(id) { gid(id).style.display=(gid(id).style.display=="none"?"block":"none"); }
function show(id) { gid(id).style.display="block"; }
function hide(id) { gid(id).style.display="none"; }
function cell(id) { gid(id).style.display="table-cell"; }
function visible(id) { gid(id).style.visibility="visible"; }
function hidden(id) { gid(id).style.visibility="hidden"; }
function isShow(id) { return(gid(id).style.display=="block"?true:false); }
function isVisible(id) { return(gid(id).style.display!="none"?true:false); }
function showSwitch(id) { gid(id).style.display=(gid(id).style.display=="block"?"none":"block"); }

// obtener todos los datos de campos segÃºn su ID prefijados y/o sufijados
function gpreids(prefix,ids,sufix) {
	var ids=ids.split(" ");
	var a={};
	for (var i in ids)
		if (gid((prefix?prefix+"_":"")+ids[i]+(sufix?"_"+sufix:"")))
			a[ids[i]]=gidval((prefix?prefix+"_":"")+ids[i]+(sufix?"_"+sufix:""));
	return a;
}

// establecer todos los datos de campos segÃºn su ID prefijados y/o sufijados
function spreids(prefix,ids,values,sufix) {
	var ids=ids.split(" ");
	for (var i in ids)
		if (gid((prefix?prefix+"_":"")+ids[i]+(sufix?"_"+sufix:""))) {
			var o=gid((prefix?prefix+"_":"")+ids[i]+(sufix?"_"+sufix:""));
			var v=values[ids[i]];
			switch (o.type) {
			case "checkbox":
				if (parseInt(v) || (v.length>0 && v!="0")) o.checked=true;
				break;
			case "select-one":
			case "select-multiple":
				for (var j=0;j<o.options.length;j++)
					if (o.options[j].value==v) {
						gidval(o,v);
						break;
					}
				break;
			default:
				gidval(o,v);
			}
		}
}

// carga el contenido HTML de una capa y realiza reemplazos para usarla como template para ventanas o bÃºsquedas AJAX
// por defecto, los reemplazos que hace son automÃ¡ticamente de id y name con prefijo $
function gtemplate(id,replaces) {
	var s=gidget("template:"+id);
	s=s.replace(/ id=\$/gi," id=");
	s=s.replace(/ id=\'\$/gi," id='");
	s=s.replace(/ id=\"\$/gi,' id="');
	s=s.replace(/ name=\$/gi," name=");
	s=s.replace(/ name=\'\$/gi," name='");
	s=s.replace(/ name=\"\$/gi,' name="');
	if (replaces)
		for (var i in replaces)
			s=s.replace(new RegExp(i.replace(/([.?*+^$[\]\\(){}-])/g, "\\$1"),'g'),replaces[i]);
	return s;
}

// funciones auxiliares
function getTop(id) { var o=gid(id); var p=0; do { p+=o.offsetTop; } while (o=o.offsetParent); return(p); }
function getLeft(id) { var o=gid(id); var p=0; do { p+=o.offsetLeft; } while (o=o.offsetParent); return(p); }
function getWidth(id) { return gid(id).offsetWidth; }
function getHeight(id) { return gid(id).offsetHeight; }
function style(id,styles) { var o=gid(id); for (var i in styles) o.style[i]=styles[i]; }

// propiedades del documento y ventana
function ieTrueBody() { return((!ischrome() && document.compatMode && document.compatMode!="BackCompat")?document.documentElement:document.body); }
function scrollLeft() { return(ieTrueBody().scrollLeft); }
function scrollTop() { return(ieTrueBody().scrollTop); }
function windowWidth() { return(document.documentElement.clientWidth?document.documentElement.clientWidth:(window.innerWidth?window.innerWidth:document.body.clientWidth)); }
function windowHeight() { return(document.documentElement.clientHeight?document.documentElement.clientHeight:(window.innerHeight?window.innerHeight:document.body.clientHeight)); }
function documentWidth() { return(document.body.clientWidth); }
function documentHeight() { return(document.body.clientHeight); }

// establecer cursor
function setCursor(cursor) { document.body.style.cursor=(cursor?cursor:"auto"); }

// obtiene el ancho del borde (horizontal)
function getBorderWidth(id) {
	var wext=(parseInt(getStyle(id,"border-left-width"))+parseInt(getStyle(id,"border-right-width")));
	return (!isNaN(wext)?wext:0);
}

// obtiene el alto del borde (vertical)
function getBorderHeight(id) {
	var wext=(parseInt(getStyle(id,"border-top-width"))+parseInt(getStyle(id,"border-bottom-width")));
	return (!isNaN(wext)?wext:0);
}

// obtiene el alto del borde superior
function getBorderTopHeight(id) {
	var wext=parseInt(parseInt(getStyle(id,"border-top-width")));
	return (!isNaN(wext)?wext:0);
}

// obtiene el alto del borde inferior
function getBorderBottomHeight(id) {
	var wext=parseInt(parseInt(getStyle(id,"border-bottom-width")));
	return (!isNaN(wext)?wext:0);
}

// obtiene el ancho del padding (horizontal)
function getPaddingWidth(id) {
	var wext=(parseInt(getStyle(id,"padding-left"))+parseInt(getStyle(id,"padding-right")));
	return (!isNaN(wext)?wext:0);
}

// obtiene el alto del padding (vertical)
function getPaddingHeight(id) {
	var wext=(parseInt(getStyle(id,"padding-top"))+parseInt(getStyle(id,"padding-bottom")));
	return (!isNaN(wext)?wext:0);
}

// obtiene el estilo final computado de un elemento
function getStyle(id,styleProp) {
	var x=gid(id);
	if (x.currentStyle) { return x.currentStyle[styleProp]; }
	else if (window.getComputedStyle) { return document.defaultView.getComputedStyle(x,null).getPropertyValue(styleProp); }
	return null;
}

// ancho interno (sin mÃ¡rgenes/paddings/bordes)
function crossInnerWidth(id) {
	var element=gid(id);
	try {
		if (window.getComputedStyle(element,""))
			return(element.clientWidth-parseInt(window.getComputedStyle(element,"").getPropertyValue("padding-left"))-parseInt(window.getComputedStyle(element,"").getPropertyValue("padding-right")));
	} catch(e) {
		return(element.clientWidth-parseInt(element.currentStyle.paddingLeft)-parseInt(element.currentStyle.paddingRight));
	}
}

// alto interno (sin mÃ¡rgenes/paddings/bordes)
function crossInnerHeight(id) {
	var element=gid(id);
	try {
		if (window.getComputedStyle(element,""))
			return(element.clientHeight-parseInt(window.getComputedStyle(element,"").getPropertyValue("padding-top"))-parseInt(window.getComputedStyle(element,"").getPropertyValue("padding-bottom")));
	} catch(e) {
		return(element.clientHeight-parseInt(element.currentStyle.paddingTop)-parseInt(element.currentStyle.paddingBottom));
	}
}

// precarga de imÃ¡genes
var imagePreloadList=new Object();
function imagePreload(imageorlist) {
	var image_list=(typeof image=="string"?[imageorlist]:imageorlist);
	for (var i in image_list) {
		var image=image_list[i];
		imagePreloadList[image]={"loaded":false,"img":new Image()};
		imagePreloadList[image].img.src=image;
		imagePreloadList[image].img.onload=function(){imagePreloadList[image].loaded=true;};
	}
}

// ancho del scroll vertical
// thanks to Alexandre Gomes (Portugal)
// http://www.alexandre-gomes.com/?p=115
function scrollWidth() {

	var inner=document.createElement('p');
	inner.style.width='100%';
	inner.style.height='200px';

	var outer=document.createElement('div');
	outer.style.position='absolute';
	outer.style.top='0px';
	outer.style.left='0px';
	outer.style.visibility='hidden';
	outer.style.width='200px';
	outer.style.height='150px';
	outer.style.overflow='hidden';

	outer.appendChild(inner);
	document.body.appendChild(outer);

	var w1=inner.offsetWidth;
	outer.style.overflow='scroll';
	var w2=inner.offsetWidth;
	if (w1==w2) w2=outer.clientWidth;

	document.body.removeChild(outer);
	return(w1-w2);
}

// almacenar cookie
function setCookie(name,value,days) {
	var expires="";
	value=""+value;
	if (days) {
		var date=new Date();
		date.setTime(date.getTime()+(days*86400000));
		expires="; expires="+date.toGMTString();
	}
	document.cookie=name+"="+value.replace(/\\/gi,"\\\\").replace(/\n/gi,"\\n").replace(/;/gi,"\\,")+expires+"; path=/";
}

// obtener cookie
function getCookie(name) {
	var nameEQ=name+"=";
	var ca=document.cookie.split(';');
	for (i=0;i<ca.length;i++) {
		var c=ca[i];
		while (c.charAt(0)==' ')
			c=c.substring(1,c.length);
		if (c.indexOf(nameEQ)==0)
			return(c.substring(nameEQ.length,c.length).replace(/\\\\/gi,"\\").replace(/\\n/gi,"\n").replace(/\\,/gi,";"));
	}
	return("");
}

// borrar cookie
function delCookie(name) {
	setCookie(name,"",-1);
}

// comprobaciÃ³n de navegadores
function isie() { return (navigator.userAgent.indexOf("MSIE")!=-1); }
function ismoz() { return (navigator.userAgent.indexOf("Firefox")!=-1 || navigator.userAgent.indexOf("Iceweasel")!=-1); }
function ischrome() { return (navigator.userAgent.indexOf("Chrome")!=-1); }

// oculta todos los selects de la pÃ¡gina si es IE
function hideSelects(hidden) {
	if (!isie()) return;
	selects=document.getElementsByTagName("select");
	for (i=0;i<selects.length;i++)
		selects[i].style.visibility=(hidden?"hidden":"visible");
}

// buscar y ejecutar tags <script> embebidos
function getrunjs(data) {
	runjs(getjs(data));
}

// buscar tags <script> embebidos
function getjs(data) {
	scode="";
	while (true) {
		ss=data.toLowerCase().indexOf("<script>"); if (ss<0) break;
		es=data.toLowerCase().indexOf("<\/script>",ss+2); if (es<0) break;
		scode=scode+data.substring(ss+8,es);
		data=data.substring(0,ss)+data.substring(es+9);
	}
	return(scode);
}

// ejecutar cadena de javascript (mucho mejor que eval)
function runjs(data) {
	if (!data) return;
	var escode=document.createElement("script");
	escode.setAttribute("type","text/javascript");
	escode.text=data;
	document.getElementsByTagName("body").item(0).appendChild(escode);
}

// convertir retornos de carro en nuevas lineas HTML
function nl2br(t) {
	try { var e=/\n/gi; t=t.replace(e,"<br />"); } catch(e) {}
	return(t);
}

// id/object merge: de una lista de identificadores separadas por comas,
// mezclar sus datos con objetos JavaScript previamente existentes
function ioMerge(ids,root,obj) {
	ids=ids.split(",");
	for (i=0;i<ids.length;i++)
		if (gid(root+ids[i]))
			obj[ids[i]]=gidval(root+ids[i]);
	return(obj);
}

// object/object merge: de una lista de objetos separados por comas,
// copia los los datos del primero objeto en el segundo y devuelve este
function ooMerge(ids,obj1,obj2) {
	ids=ids.split(",");
	for (i=0;i<ids.length;i++)
		obj2[ids[i]]=obj1[ids[i]];
	return(obj2);
}

// aÃ±ade CSS al documento (no funciona bien en IE6)
function cssAdd(css) {
  var style=document.createElement("style");
  style.type="text/css";
  if (style.styleSheet) style.styleSheet.cssText=css;
  else style.appendChild(document.createTextNode(css));
  document.getElementsByTagName("head")[0].appendChild(style);
}

// array_merge: mezcla arrays puros o asociativos
// es equivalente a la funcion de PHP
function array_merge(a1,a2) {
	for (var i in a2) a1[i]=a2[i];
	return a1;
}

// array_remove: elimina claves de un array asociativo
function array_remove(a1,a2) {
	var a=new Object();
	var clone;
	for (var i in a1) {
		clone=true;
		for (var j in a2)
			if (i==a2[j]) {
				clone=false;
				break;
			}
		if (clone)
		a[i]=a1[i];
	}
	return a;
}

// elimina un elemento en la posiciÃ³n del indice de un array
function array_delete(a,index) {
	var n=Array();
	for (var i in a)
		if (i!=index)
			n[n.length]=a[i];
	return n;
}

// array_get: devuelve las claves de un array dada una lista de ellas
function array_get(a,list) {
	var o=new Object();
	for (var i in list)
		o[list[i]]=a[list[i]];
	return o;
}

// array_save: busca las claves de la lista en el segundo array y los mezcla con el primero
function array_save(a1,a2,list) {
	for (var i in list)
		a1[list[i]]=a2[list[i]];
	return a1;
}

// copia en profundidad de un objeto
function array_copy(o) {
	if (typeof o != "object" || o === null) return o;
	var r = o.constructor == Array ? [] : {};
	for (var i in o) r[i] = array_copy(o[i]);
	return r;
}

// aÃ±ade un objeto a un array plano
function array_push(a,o) {
	a.push(o);
}

// verifica si un array estÃ¡ vacÃ­o o no
function array_isclean(a) {
	if (!a) return true;
	for (var i in a)
		return false;
	return true;
}

// control de impresiÃ³n, sobrecargar este mÃ©todo
function doprint() { window.print(); }

// init_fast
var init_fast_func=new Array();
function init_fast(add) {
	if (add) init_fast_func[init_fast_func.length]=add;
	else { for (var i in init_fast_func) { try { init_fast_func[i](); } catch(e) {} } }
}

// onload
var init_func=new Array();
var init_func_last=window.onload;
function init(add) {
	if (add) init_func[init_func.length]=add;
	else { for (var i in init_func) { try { init_func[i](); } catch(e) {} } }
}
window.onload=function(){
	try { init_func_last(); } catch(e) {}
	try { init(); } catch(e) {}
}

// onunload
var unload_func=new Array();
var unload_func_last=window.onunload;
function unload(add) {
	if (add) unload_func[unload_func.length]=add;
	else { for (var i in unload_func) { try { unload_func[i](); } catch(e) {} } }
}
window.onunload=function(){
	try { unload_func_last(); } catch(e) {}
	try { unload(); } catch(e) {}
}

// onresize
var resize_func=new Array();
var resize_func_last=window.onresize;
function resize(add) {
	if (add) resize_func[resize_func.length]=add;
	else { for (var i in resize_func) { try { resize_func[i](); } catch(e) {} } }
}
window.onresize=function(){
	try { resize_func_last(); } catch(e) {}
	try { resize(); } catch(e) {}
}

// onkeydown
var keydown_func=new Array();
var keydown_func_last=document.onkeydown;
function keydown(p) {
	if (typeof(p)=="function") keydown_func[keydown_func.length]=p;
	else { for (var i in keydown_func) { try { keydown_func[i](p); } catch(e) {} } }
}
document.onkeydown=function(we){
	try { keydown_func_last(we); } catch(e) {}
	try { keydown(we); } catch(e) {}
}

// onkeyup
var keyup_func=new Array();
var keyup_func_last=document.onkeyup;
function keyup(p) {
	if (typeof(p)=="function") keyup_func[keyup_func.length]=p;
	else { for (var i in keyup_func) { try { keyup_func[i](p); } catch(e) {} } }
}
document.onkeyup=function(we){
	try { keyup_func_last(we); } catch(e) {}
	try { keyup(we); } catch(e) {}
}

// onscroll
var scroll_func=new Array();
var scroll_func_last=document.onscroll;
function scroll(p) {
	if (typeof(p)=="function") scroll_func[scroll_func.length]=p;
	else { for (var i in scroll_func) { try { scroll_func[i](p); } catch(e) {} } }
}
document.onscroll=function(we){
	try { scroll_func_last(we); } catch(e) {}
	try { scroll(we); } catch(e) {}
}

// onmouseup
var mouseup_func=new Array();
var mouseup_func_last=document.onmouseup;
function mouseup(p) {
	if (typeof(p)=="function") mouseup_func[mouseup_func.length]=p;
	else { for (var i in mouseup_func) { try { mouseup_func[i](p); } catch(e) {} } }
}
document.onmouseup=function(we){
	if (!we) we=window.event;
	try { mouseup_func_last(we); } catch(e) {}
	try { mouseup(we); } catch(e) {}
}

// onmousedown
var mousedown_func=new Array();
var mousedown_func_last=document.onmousedown;
function mousedown(p) {
	var ret=null;
	if (typeof(p)=="function") mousedown_func[mousedown_func.length]=p;
	else {
		for (var i in mousedown_func) { try { ret=mousedown_func[i](p); } catch(e) {} }
		if (typeof(ret)!="undefined" && typeof(ret)!="null") return(ret);
	}
}
document.onmousedown=function(we){
	var ret=null;
	if (!we) we=window.event;
	try { ret=mousedown_func_last(we); } catch(e) {}
	try { ret=mousedown(we); } catch(e) {}
	if (typeof(ret)!="undefined" && typeof(ret)!="null") return(ret);
}

// onmousemove
var mousemove_func=new Array();
var mousemove_func_last=document.onmousemove;
function mousemove(p) {
	if (typeof(p)=="function") mousemove_func[mousemove_func.length]=p;
	else { for (var i in mousemove_func) { try { mousemove_func[i](p); } catch(e) {} } }
}
document.onmousemove=function(we){
	if (!we) we=window.event;
	try { mousemove_func_last(we); } catch(e) {}
	try { mousemove(we); } catch(e) {}
}

// mouse delta
var mousewheel_func=new Array();
function mousewheel(p) {
	if (typeof(p)=="function") mousewheel_func[mousewheel_func.length]=p;
	else { for (var i in mousewheel_func) { try { mousewheel_func[i](p); } catch(e) {} } }
}
function mousewheel_eventhandler(event) {
	var delta=0;
	if (!event) event=window.event; // IE
	if (event.wheelDelta) { // IE/Opera
		delta=event.wheelDelta/120;
		// In Opera 9, delta differs in sign as compared to IE.
		if (window.opera) delta=-delta;
	} else if (event.detail) { // Mozilla
		// In Mozilla, sign of delta is different than in IE. Also, delta is multiple of 3.
		delta=-event.detail/3;
	}
	// If delta is nonzero, handle it. Basically, delta is now positive
	// if wheel was scrolled up, and negative, if wheel was scrolled down.
	if (delta) {
		//handle(delta);
		var cancel=false;
		for (var i in mousewheel_func) { try { if (mousewheel_func[i](delta,event)) cancel=true; } catch(e) {} }
	}
	// Prevent default actions caused by mouse wheel. That might be ugly,
	// but we handle scrolls somehow anyway, so don't bother here..
	if (cancel) {
		if (event.preventDefault)
			event.preventDefault();
		event.returnValue=false;
	}
}
if (window.addEventListener) window.addEventListener('DOMMouseScroll', mousewheel_eventhandler, false); // DOMMouseScroll for Mozilla
window.onmousewheel=document.onmousewheel=mousewheel_eventhandler; // IE/Opera

// habilitar/deshabilitar seleccionar texto en un elemento
function selectionEnabled(o,enable) {
	var o=gid(o);
	if (typeof o.onselectstart!="undefined") { if (enable) o.onselectstart=null; else { o.onselectstart=function(){ return false; } } } // IE
	else if (typeof o.style.MozUserSelect!="undefined") { o.style.MozUserSelect=(enable?"":"none"); } //Firefox
	else { if (enable) o.onmousedown=null; else { o.onmousedown=function(){ return false; } } } // all other navs
	o.style.cursor="default";
}

// entrada sÃ³lo numÃ©rica entera
function gInputInt(id,negatives,floating) {
	var input=gid(id);
	input.style.textAlign="right";
	input.onkeydown=function(e){
		var c=e.keyCode;
		if (c>=35 && c<=39) return true;
		if (c==8) return true;
		if (c==46) return true;
		if (c==116) return true;
		if (c==9) return true;
		if (c==13) return true;
		if (c==15) return true;
		if (floating)
			if (c==110 || c==190)
				return (this.value.indexOf(".")==-1?true:false);
		if (negatives)
			if (c==109)
				return (this.value.indexOf("-")==-1?true:false);
		if (c>=48 && c<=57) return true;
		return false;
	}
	input.onblur=function(e){
		var v=parseFloat(this.value);
		this.value=(isNaN(v)?"":v);
	}
}

// entrada sÃ³lo numÃ©rica floatante
function gInputFloat(id,negatives) {
	gInputInt(id,negatives,true);
}

// eliminar espacios de una cadena
function trim(str) {
	return (""+str).replace(/^\s*|\s*$/g,"");
}

// elimina la ruta de un nombre de fichero completo,
// y tambiÃ©n su sufijo, si se especifica y coincide
function basename(path, suffix) {
	var b=path.replace(/^.*[\/\\]/g, '');
	if (typeof(suffix) == 'string' && b.substr(b.length-suffix.length) == suffix)
		b=b.substr(0, b.length-suffix.length);
	return b;
}

// equivalente a br2nl en php
function br2nl(s) {
	return s.replace(/<br\s*\/?>/mg,"\n");
}

// mostrar un nÃºmero en formato X.XXX,XX
function spf(n) {
	var n=Math.round(n*100)/100;
	var d=Math.round((n-parseInt(n))*100);
	var x=""+parseInt(n);
	var rgx=/(\d+)(\d{3})/;
	while (rgx.test(x))
		x=x.replace(rgx,'$1'+'.'+'$2');
	return x+","+d;
}

// convierte una cadena YYYY-MM-DD HH:II:SS a DD/MM/YYYY HH:II:SS
function sqlDateSP(d) {
	if (!d || (d.length!=10 && d.length!=19)) return "";
	return d.substring(8,10)+"/"+d.substring(5,7)+"/"+d.substring(0,4)+d.substring(10);
}

// convierte una cadena DD/MM/YYYY HH:II:SS a YYYY-MM-DD HH:II:SS
function spDateSQL(d) {
	if (!d || (d.length!=10 && d.length!=19)) return "";
	return d.substring(6,10)+"-"+d.substring(3,5)+"-"+d.substring(0,2)+d.substring(10);
}

// devuelve la fecha actual en formato DD/MM/YYYY
function spDateNow() {
	var dd=new Date().getDate(); if (dd<10) dd='0'+dd;
	var mm=new Date().getMonth()+1; if (mm<10) mm='0'+mm;
	var yyyy=new Date().getFullYear();
	return String(mm+"/"+dd+"/"+yyyy);
}

// getElementsByClassName, implementaciÃ³n para IE (el Ãºnico que no lo soporta)
function getElementsByClassName(oElm, strTagName, strClassName){
	var arrElements = (strTagName == "*" && oElm.all)? oElm.all :	oElm.getElementsByTagName(strTagName);
	var arrReturnElements = new Array();
	strClassName = strClassName.replace(/\-/g, "\\-");
	var oRegExp = new RegExp("(^|\\s)" + strClassName + "(\\s|$)");
	var oElement;
	for (var i=0; i<arrElements.length; i++) {
		oElement = arrElements[i];     
		if(oRegExp.test(oElement.className))
			arrReturnElements.push(oElement);
	}
	return arrReturnElements;
}
function gid(id) {
	try {
		if (typeof(id)=="object") return id;
		else return document.getElementById(id);
	} catch(e) {
		return(null);
	}
}

function comboEnabled(combo,enabled) {
	gid(combo).disabled=!enabled;
}

function comboVisible(combo,visible) {
	gid(combo).style.visibility=(visible?"visible":"hidden");
}

function comboAdd(combo,text,value,selected,sBold) {

	combo=gid(combo);

	var selOpcion=new Option(text,value);
	selOpcion.selected=selected;

	try {
		try { combo.add(selOpcion,null); } catch(e) { combo.add(selOpcion); }
		if (sBold!=undefined) selOpcion.style.fontWeight=(sBold?"bold":"normal");
	} catch(e) {
		//alert(e+"\nError adding option ("+value+") - "+text);
		return(false);
	}

	return(true);

}

function comboDel(combo,index) {
	combo=gid(combo);
	try {
		combo.options[index]=null;
		return(true);
	} catch(e) {
		return(false);
	}
}

function comboDelSelected(combo) {
	while (combo.selectedIndex>=0)
		comboDel(combo,combo.selectedIndex);
}

function comboClear(combo) {
	gid(combo).length=0;
}

function comboValue(combo,value,newvalue) {
	combo=gid(combo);
	if (newvalue==undefined) {
		if (combo.selectedIndex<0) return(false);
		if (value!=undefined) { combo.value=value; return true; }
		return combo.value;
	} else {
		for (var i in combo.options) {
			if (combo.options[i].value==value) {
				combo.options[i].value=newvalue;
				return true;
			}
		}
		return false;
	}
}

function comboText(combo,id,text) {
	var combo=gid(combo);
	if (typeof(id)=="undefined") {
		if (combo.selectedIndex<0) return(false);
		return(combo.options[combo.selectedIndex].text);
	} else {
		for (var i in combo.options) {
			if (combo.options[i].value==id) {
				if (typeof(text)=="undefined") return combo.options[i].text;
				else {
					combo.options[i].text=text;
					return true;
				}
			}
		}
		return false;
	}
}

function comboIndexByValue(combo,value) {
	combo=gid(combo);
	for (var i=0;i<combo.options.length;i++)
		if (combo.options[i].value==value) return(i);
	return -1;
}

function comboIndexByText(combo,text) {
	combo=gid(combo);
	for (var i=0;i<combo.options.length;i++)
		if (combo.options[i].text==text) return(i);
	return -1;
}

function comboValueExists(combo,value) {
	combo=gid(combo);
	return (comboIndexByValue(combo,value)>=0);
}

function comboTextExists(combo,text) {
	combo=gid(combo);
	return (comboIndexByText(combo,text)>=0);
}

function comboClearFill(combo,lista,valorActual,formaMostrar,indiceValor,filtro) {
	combo=gid(combo);
	comboClear(combo);
	comboFill(combo,lista,valorActual,formaMostrar,indiceValor,filtro);
}

function comboFill(combo,lista,valorActual,formaMostrar,indiceValor,filtro) {

	combo=gid(combo);

	if (!indiceValor) indiceValor="i";
	if (!formaMostrar) formaMostrar="lista[i]";
	if (!filtro) filtro="";

	eval // es más eficiente meter el bucle for dentro que fuera, aunque el código quede más sucio
		("for (var i in lista) {"
		+"	"+(filtro?"if("+filtro+")":"")+"comboAdd(combo,"+formaMostrar+","+indiceValor+",(valorActual=="+indiceValor+"?true:false));"
		+"}");

}

function comboSortTextNaturalSP(t) {
	var s=t.toLowerCase();
	s=s.replace("á","a");
	s=s.replace("é","e");
	s=s.replace("í","i");
	s=s.replace("ó","o");
	s=s.replace("ú","u");
	s=s.replace("Á","a");
	s=s.replace("É","e");
	s=s.replace("Í","i");
	s=s.replace("Ó","o");
	s=s.replace("Ú","u");
	s=s.replace("Ñ","nz");
	s=s.replace("ñ","nz");
	return s;
}

function comboSortCompareText(o1, o2) {
	return (comboSortTextNaturalSP(o1.text)<comboSortTextNaturalSP(o2.text)
		?-1
		:(comboSortTextNaturalSP(o1.text)>comboSortTextNaturalSP(o2.text)?1:0)
	);
}

function comboSortCompareTextCaseSensitive(o1, o2) {
	return (o1.text<o2.text?-1:o1.text>o2.text?1:0);
}

function comboSort(combo,compareFunction) {
	combo=gid(combo);
	if (!compareFunction) compareFunction=comboSortCompareText;
	var options=new Array (combo.options.length);
	for (var i=0; i<options.length; i++)
		options[i]=new Option(
			combo.options[i].text,
			combo.options[i].value,
			combo.options[i].defaultSelected,
			combo.options[i].selected
		);
	options.sort(compareFunction);
	combo.options.length=0;
	for (var i=0; i<options.length; i++)
		combo.options[i]=options[i];
}

function comboMove(combo1,combo2,sorted,compareFunction) {
	combo1=gid(combo1);
	combo2=gid(combo2);
	while (combo1.selectedIndex>=0) {
		var option=new Option(
			combo1.options[combo1.selectedIndex].text,
			combo1.options[combo1.selectedIndex].value,
			combo1.options[combo1.selectedIndex].defaultSelected,
			combo1.options[combo1.selectedIndex].selected
		);
		try { combo2.add(option,null); } catch(e) { combo2.add(option); }
		combo1.options[combo1.selectedIndex]=null;
	}
	if (sorted==undefined || sorted) comboSort(combo2,compareFunction);
}

function comboMoveIndex(combo1,index,combo2,sorted,compareFunction) {
	combo1=gid(combo1);
	combo2=gid(combo2);
	var option=new Option(
		combo1.options[index].text,
		combo1.options[index].value,
		combo1.options[index].defaultSelected,
		combo1.options[index].selected
	);
	try { combo2.add(option,null); } catch(e) { combo2.add(option); }
	combo1.options[index]=null;
}

function combosVisible(visible) {
	var elements=document.body.getElementsByTagName("select");
	for (var i in elements)
		if (elements[i].type)
			if (elements[i].type=="select-one" || elements[i].type=="select-multiple")
				elements[i].style.visibility=(visible?"visible":"hidden");
}

function combosVisibleIE(visible) {
	if (isie()) combosVisible(visible);
}

function comboAutoImage(s) {
	gid(s).style.backgroundImage=gid(s).options[gid(s).selectedIndex].style.backgroundImage;
}

function comboAutoImageSetup(s) {
	gid(s).onclick=function(){ comboAutoImage(s); }
	gid(s).onchange=function(){ comboAutoImage(s); }
	gid(s).onkeyup=function(){ comboAutoImage(s); }
	comboAutoImage(s);
}
// requiere common.js

var newalert_images="images/";
var newalert_id="newalert_";
var newalert_iecomboshide=false;

var newalert_active=new Object();
var newalert_return_function=new Object();
var newalert_open_windows=0;
var newalert_action_functions=new Object();

function newalert_support_opacity() { return (navigator.userAgent.indexOf("MSIE 6")==-1 && navigator.userAgent.indexOf("MSIE 7")==-1); }
function newalert_support_fixed() { return ( navigator.userAgent.indexOf("MSIE 6")==-1); }
function newalert_exec_action(id,i) { newalert_action_functions[id][i](); }

function newalert(o) {
	if (newalert_iecomboshide) combosVisibleIE(false);
	if (typeof(o)=="string") {
		var id="";
		var msg=o;
		var buttons=null;
		var ico="notice";
	} else {
		var id=(o.id?o.id:"");
		var msg=(o.msg?o.msg:"");
		var ico=(o.ico?o.ico:null);
		var buttons=o.buttons;
	}
	if (buttons==null) buttons=[{"caption":"Aceptar"}];
	newalert_return_function[id]=o.func;
	newalert_action_functions[id]=new Object();
	var d=document.createElement("div");
	newalert_remove(id);
	newalert_active[id]=true;
	d.setAttribute("id",newalert_id+id);
	style(d,{
		"position":(newalert_support_fixed()?"fixed":"absolute"),
		"left":(newalert_support_fixed()?0:scrollLeft())+"px",
		"top":(newalert_support_fixed()?0:scrollTop())+"px",
		"width":windowWidth()+"px",
		"height":windowHeight()+"px",
		"zIndex":990
	});
	if (!o.noshadow) style(d,{"backgroundImage":"url('"+newalert_images+"trans."+(newalert_support_opacity()?"png":"gif")+"')"});
	var cols=(ico?"colspan='2'":"");
	s="<table cellpadding='0' cellspacing='0' width='100%' height='100%'><tr><td align='center'>";
	if (o.body) s+=o.body;
	else {
		s+="<table class='"+(o.className?o.className:"newalert")+"' cellpadding='0' cellspacing='0'>"
			+(o.title==null?"":"<tr><th "+cols+" class='newalert_title'>"+(o.title?o.title:"")+"</th></tr>")
			+"<tr>"
			+(ico
				?"<td class='newalert_icon' width='48' valign='top'>"
				+"<img src='"+newalert_images+"newalert-"+(o.ico?o.ico+(o.ico.indexOf(".")>=0?"":".png"):"notice.png")+"' alt='' />"
				+"</td>"
				:""
			)
			+"<td class='newalert_body' valign='middle'>"+msg+"</td></tr>";
		if (buttons.length) {
			s+="<tr><td "+cols+" class='newalert_cmd' align='center'>";
			for (var i in buttons) {
				if (buttons[i].caption) {
					if (buttons[i].ico) {
						s+=" <a id='"+newalert_id+id+"_cmd_"+i+"' class='cmd' href='javascript:"
							+(buttons[i].action
								?(typeof(buttons[i].action)=="function"
									?"newalert_exec_action(\""+id+"\","+i+");"
									:buttons[i].action
								)
								:"newalert_close(\""+id+"\")"
							)
							+";'>"
							+"<span class='icon' style='background-image:url(\""+buttons[i].ico+"\")'>"
							+buttons[i].caption
							+"</span>"
							+"</a>";
					} else {
						s+=" <input id='"+newalert_id+id+"_cmd_"+i+"' class=cmd type=button onClick='javascript:"
							+(buttons[i].action
								?(typeof(buttons[i].action)=="function"
									?"newalert_exec_action(\""+id+"\","+i+");"
									:buttons[i].action
								)
								:"newalert_close(\""+id+"\")"
							)
							+";' value='"+buttons[i].caption+"' />";
					}
					newalert_action_functions[id][i]=buttons[i].action;
				}
			}
			s+"</td></tr>";
		}
		s+="</table>";
	}
	s+="</td></tr></table>";
	d.innerHTML=s;
	document.body.appendChild(d);
	newalert_open_windows++;
	try { gid(newalert_id+id+"_cmd_0").focus(); } catch(e) {}
	return {
		"id":id,
		"close":function(){ newalert_close(id); }
	};
}

function newalert_event_timer() {
	for (var id in newalert_active) {
		if (newalert_active[id]) {
			style(newalert_id+id,{
				"left":(newalert_support_fixed()?0:scrollLeft())+"px",
				"top":(newalert_support_fixed()?0:scrollTop())+"px",
				"width":windowWidth()+"px",
				"height":windowHeight()+"px"
			});
		}
	}
	newalert_event_poll=setTimeout("newalert_event_timer()",30);
}

function newwait(o) {
	if (typeof(o)=="string") {
		var msg=o;
		o=new Object();
		o.id="wait";
		o.msg=msg;
		o.ico="busy.gif";
		o.buttons=[];
	} else {
		if (!o) o=new Object();
		o.id=(o.id!=null?o.id:"wait");
		o.msg="Proceso en curso, por favor, espere...";
		o.ico=(o.ico!=null?o.ico:"busy.gif");
		o.buttons=[];
	}
	newalert(o);
}

function newsimplewait() {
	var o=new Object();
	o.id="wait";
	o.noshadow=true;
	o.body="<img src='"+newalert_images+"newalert-busy.gif' />";
	newalert(o);
}

var newok_num=0; function newok(msg,action) { var myid="ok"+(++newok_num); newalert({"id":myid,"ico":"ok","msg":msg,"buttons":[{"caption":"Aceptar","action":function(){ if (action) action(); newalert_close(myid); }}]}); }
var newwarn_num=0; function newwarn(msg,action) { var myid="warn"+(++newok_num); newalert({"id":myid,"ico":"warn","msg":msg,"buttons":[{"caption":"Aceptar","action":function(){ if (action) action(); newalert_close(myid); }}]}); }
var newerror_num=0; function newerror(msg,action) { var myid="error"+(++newok_num); newalert({"id":myid,"ico":"error","msg":msg,"buttons":[{"caption":"Aceptar","action":function(){ if (action) action(); newalert_close(myid); }}]}); }

function newalert_remove(id) {
	if (!id) var id="";
	newalert_active[id]=false;
	if (gid(newalert_id+id)) {
		newalert_open_windows--;
		gid(newalert_id+id).parentNode.removeChild(gid(newalert_id+id));
		if (newalert_iecomboshide && !newalert_open_windows) combosVisibleIE(true);
	}
}

function newalert_close(id) {
	if (!id) var id="";
	newalert_remove(id);
	try { newalert_return_function[id](id); } catch(e) {}
}

function newwait_close(id) {
	newalert_close(id?id:'wait');
}

// lanzar timer de eventos
newalert_event_timer();
/*
 * A JavaScript implementation of the RSA Data Security, Inc. MD5 Message
 * Digest Algorithm, as defined in RFC 1321.
 * Version 2.1 Copyright (C) Paul Johnston 1999 - 2002.
 * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
 * Distributed under the BSD License
 * See http://pajhome.org.uk/crypt/md5 for more info.
 */

/*
 * Configurable variables. You may need to tweak these to be compatible with
 * the server-side, but the defaults work in most cases.
 */
var hexcase = 0;  /* hex output format. 0 - lowercase; 1 - uppercase        */
var b64pad  = ""; /* base-64 pad character. "=" for strict RFC compliance   */
var chrsz   = 8;  /* bits per input character. 8 - ASCII; 16 - Unicode      */

/*
 * These are the functions you'll usually want to call
 * They take string arguments and return either hex or base-64 encoded strings
 */
function hex_md5(s){ return binl2hex(core_md5(str2binl(s), s.length * chrsz));}
function b64_md5(s){ return binl2b64(core_md5(str2binl(s), s.length * chrsz));}
function str_md5(s){ return binl2str(core_md5(str2binl(s), s.length * chrsz));}
function hex_hmac_md5(key, data) { return binl2hex(core_hmac_md5(key, data)); }
function b64_hmac_md5(key, data) { return binl2b64(core_hmac_md5(key, data)); }
function str_hmac_md5(key, data) { return binl2str(core_hmac_md5(key, data)); }

/*
 * Perform a simple self-test to see if the VM is working
 */
function md5_vm_test()
{
  return hex_md5("abc") == "900150983cd24fb0d6963f7d28e17f72";
}

/*
 * Calculate the MD5 of an array of little-endian words, and a bit length
 */
function core_md5(x, len)
{
  /* append padding */
  x[len >> 5] |= 0x80 << ((len) % 32);
  x[(((len + 64) >>> 9) << 4) + 14] = len;

  var a =  1732584193;
  var b = -271733879;
  var c = -1732584194;
  var d =  271733878;

  for(var i = 0; i < x.length; i += 16)
  {
    var olda = a;
    var oldb = b;
    var oldc = c;
    var oldd = d;

    a = md5_ff(a, b, c, d, x[i+ 0], 7 , -680876936);
    d = md5_ff(d, a, b, c, x[i+ 1], 12, -389564586);
    c = md5_ff(c, d, a, b, x[i+ 2], 17,  606105819);
    b = md5_ff(b, c, d, a, x[i+ 3], 22, -1044525330);
    a = md5_ff(a, b, c, d, x[i+ 4], 7 , -176418897);
    d = md5_ff(d, a, b, c, x[i+ 5], 12,  1200080426);
    c = md5_ff(c, d, a, b, x[i+ 6], 17, -1473231341);
    b = md5_ff(b, c, d, a, x[i+ 7], 22, -45705983);
    a = md5_ff(a, b, c, d, x[i+ 8], 7 ,  1770035416);
    d = md5_ff(d, a, b, c, x[i+ 9], 12, -1958414417);
    c = md5_ff(c, d, a, b, x[i+10], 17, -42063);
    b = md5_ff(b, c, d, a, x[i+11], 22, -1990404162);
    a = md5_ff(a, b, c, d, x[i+12], 7 ,  1804603682);
    d = md5_ff(d, a, b, c, x[i+13], 12, -40341101);
    c = md5_ff(c, d, a, b, x[i+14], 17, -1502002290);
    b = md5_ff(b, c, d, a, x[i+15], 22,  1236535329);

    a = md5_gg(a, b, c, d, x[i+ 1], 5 , -165796510);
    d = md5_gg(d, a, b, c, x[i+ 6], 9 , -1069501632);
    c = md5_gg(c, d, a, b, x[i+11], 14,  643717713);
    b = md5_gg(b, c, d, a, x[i+ 0], 20, -373897302);
    a = md5_gg(a, b, c, d, x[i+ 5], 5 , -701558691);
    d = md5_gg(d, a, b, c, x[i+10], 9 ,  38016083);
    c = md5_gg(c, d, a, b, x[i+15], 14, -660478335);
    b = md5_gg(b, c, d, a, x[i+ 4], 20, -405537848);
    a = md5_gg(a, b, c, d, x[i+ 9], 5 ,  568446438);
    d = md5_gg(d, a, b, c, x[i+14], 9 , -1019803690);
    c = md5_gg(c, d, a, b, x[i+ 3], 14, -187363961);
    b = md5_gg(b, c, d, a, x[i+ 8], 20,  1163531501);
    a = md5_gg(a, b, c, d, x[i+13], 5 , -1444681467);
    d = md5_gg(d, a, b, c, x[i+ 2], 9 , -51403784);
    c = md5_gg(c, d, a, b, x[i+ 7], 14,  1735328473);
    b = md5_gg(b, c, d, a, x[i+12], 20, -1926607734);

    a = md5_hh(a, b, c, d, x[i+ 5], 4 , -378558);
    d = md5_hh(d, a, b, c, x[i+ 8], 11, -2022574463);
    c = md5_hh(c, d, a, b, x[i+11], 16,  1839030562);
    b = md5_hh(b, c, d, a, x[i+14], 23, -35309556);
    a = md5_hh(a, b, c, d, x[i+ 1], 4 , -1530992060);
    d = md5_hh(d, a, b, c, x[i+ 4], 11,  1272893353);
    c = md5_hh(c, d, a, b, x[i+ 7], 16, -155497632);
    b = md5_hh(b, c, d, a, x[i+10], 23, -1094730640);
    a = md5_hh(a, b, c, d, x[i+13], 4 ,  681279174);
    d = md5_hh(d, a, b, c, x[i+ 0], 11, -358537222);
    c = md5_hh(c, d, a, b, x[i+ 3], 16, -722521979);
    b = md5_hh(b, c, d, a, x[i+ 6], 23,  76029189);
    a = md5_hh(a, b, c, d, x[i+ 9], 4 , -640364487);
    d = md5_hh(d, a, b, c, x[i+12], 11, -421815835);
    c = md5_hh(c, d, a, b, x[i+15], 16,  530742520);
    b = md5_hh(b, c, d, a, x[i+ 2], 23, -995338651);

    a = md5_ii(a, b, c, d, x[i+ 0], 6 , -198630844);
    d = md5_ii(d, a, b, c, x[i+ 7], 10,  1126891415);
    c = md5_ii(c, d, a, b, x[i+14], 15, -1416354905);
    b = md5_ii(b, c, d, a, x[i+ 5], 21, -57434055);
    a = md5_ii(a, b, c, d, x[i+12], 6 ,  1700485571);
    d = md5_ii(d, a, b, c, x[i+ 3], 10, -1894986606);
    c = md5_ii(c, d, a, b, x[i+10], 15, -1051523);
    b = md5_ii(b, c, d, a, x[i+ 1], 21, -2054922799);
    a = md5_ii(a, b, c, d, x[i+ 8], 6 ,  1873313359);
    d = md5_ii(d, a, b, c, x[i+15], 10, -30611744);
    c = md5_ii(c, d, a, b, x[i+ 6], 15, -1560198380);
    b = md5_ii(b, c, d, a, x[i+13], 21,  1309151649);
    a = md5_ii(a, b, c, d, x[i+ 4], 6 , -145523070);
    d = md5_ii(d, a, b, c, x[i+11], 10, -1120210379);
    c = md5_ii(c, d, a, b, x[i+ 2], 15,  718787259);
    b = md5_ii(b, c, d, a, x[i+ 9], 21, -343485551);

    a = safe_add(a, olda);
    b = safe_add(b, oldb);
    c = safe_add(c, oldc);
    d = safe_add(d, oldd);
  }
  return Array(a, b, c, d);

}

/*
 * These functions implement the four basic operations the algorithm uses.
 */
function md5_cmn(q, a, b, x, s, t)
{
  return safe_add(bit_rol(safe_add(safe_add(a, q), safe_add(x, t)), s),b);
}
function md5_ff(a, b, c, d, x, s, t)
{
  return md5_cmn((b & c) | ((~b) & d), a, b, x, s, t);
}
function md5_gg(a, b, c, d, x, s, t)
{
  return md5_cmn((b & d) | (c & (~d)), a, b, x, s, t);
}
function md5_hh(a, b, c, d, x, s, t)
{
  return md5_cmn(b ^ c ^ d, a, b, x, s, t);
}
function md5_ii(a, b, c, d, x, s, t)
{
  return md5_cmn(c ^ (b | (~d)), a, b, x, s, t);
}

/*
 * Calculate the HMAC-MD5, of a key and some data
 */
function core_hmac_md5(key, data)
{
  var bkey = str2binl(key);
  if(bkey.length > 16) bkey = core_md5(bkey, key.length * chrsz);

  var ipad = Array(16), opad = Array(16);
  for(var i = 0; i < 16; i++)
  {
    ipad[i] = bkey[i] ^ 0x36363636;
    opad[i] = bkey[i] ^ 0x5C5C5C5C;
  }

  var hash = core_md5(ipad.concat(str2binl(data)), 512 + data.length * chrsz);
  return core_md5(opad.concat(hash), 512 + 128);
}

/*
 * Add integers, wrapping at 2^32. This uses 16-bit operations internally
 * to work around bugs in some JS interpreters.
 */
function safe_add(x, y)
{
  var lsw = (x & 0xFFFF) + (y & 0xFFFF);
  var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
  return (msw << 16) | (lsw & 0xFFFF);
}

/*
 * Bitwise rotate a 32-bit number to the left.
 */
function bit_rol(num, cnt)
{
  return (num << cnt) | (num >>> (32 - cnt));
}

/*
 * Convert a string to an array of little-endian words
 * If chrsz is ASCII, characters >255 have their hi-byte silently ignored.
 */
function str2binl(str)
{
  var bin = Array();
  var mask = (1 << chrsz) - 1;
  for(var i = 0; i < str.length * chrsz; i += chrsz)
    bin[i>>5] |= (str.charCodeAt(i / chrsz) & mask) << (i%32);
  return bin;
}

/*
 * Convert an array of little-endian words to a string
 */
function binl2str(bin)
{
  var str = "";
  var mask = (1 << chrsz) - 1;
  for(var i = 0; i < bin.length * 32; i += chrsz)
    str += String.fromCharCode((bin[i>>5] >>> (i % 32)) & mask);
  return str;
}

/*
 * Convert an array of little-endian words to a hex string.
 */
function binl2hex(binarray)
{
  var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef";
  var str = "";
  for(var i = 0; i < binarray.length * 4; i++)
  {
    str += hex_tab.charAt((binarray[i>>2] >> ((i%4)*8+4)) & 0xF) +
           hex_tab.charAt((binarray[i>>2] >> ((i%4)*8  )) & 0xF);
  }
  return str;
}

/*
 * Convert an array of little-endian words to a base-64 string
 */
function binl2b64(binarray)
{
  var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
  var str = "";
  for(var i = 0; i < binarray.length * 4; i += 3)
  {
    var triplet = (((binarray[i   >> 2] >> 8 * ( i   %4)) & 0xFF) << 16)
                | (((binarray[i+1 >> 2] >> 8 * ((i+1)%4)) & 0xFF) << 8 )
                |  ((binarray[i+2 >> 2] >> 8 * ((i+2)%4)) & 0xFF);
    for(var j = 0; j < 4; j++)
    {
      if(i * 8 + j * 6 > binarray.length * 32) str += b64pad;
      else str += tab.charAt((triplet >> 6*(3-j)) & 0x3F);
    }
  }
  return str;
}
/*
	Ejemplos de uso:
	
	var xcal1,xcal2,xcal3,xcal4;
	
	init(function(){
		
		xcal1=new xcalendar({
			"input":"fecha_inicio",
			"trigger":"fecha_inicio",
			"min":new Date(2011,3,12),
			"max":"xcal2",
			"onselect":function(fecha){
				//xcal2.min=fecha;
			}
		});

		xcal2=new xcalendar({
			"input":"fecha_fin",
			"trigger":"fecha_fin",
			"min":"xcal1"
		});
			
		xcal3=new xcalendar({
			"div":"calendario1",
			"input":"fecha_inicio2",
			"min":new Date(2011,3,12),
			"max":"xcal4",
			"onselect":function(fecha){
				//xcal2.min=fecha;
			}
		});

		xcal4=new xcalendar({
			"div":"calendario2",
			"input":"fecha_fin2",
			"min":"xcal3"
		});
			
		gid("fecha_inicio").focus();
		
	});
*/
var xcalendars=[];
var xcalendars_active=null;
var xcalendars_cancelclick=false;
function xcalendar(o) {
	this.fecha=o.fecha;
	if (!this.fecha) this.fecha=new Date();

	var a=xcalendars.length;
	xcalendars_active=a;
	xcalendars[a]=this;
	var xcal=xcalendars[a];
	
	this.seleccionada=null;
	this.seleccionados={};
	
	this.div=gid(o.div);
	this.input=gid(o.input);
	this.trigger=gid(o.trigger);
	this.min=o.min;
	this.max=o.max;
	this.onselect=o.onselect;
	
	this.loaded=false;

	this.y=this.fecha.getFullYear();
	this.m=this.fecha.getMonth();
	this.d=this.fecha.getDate();
	var week_abrev="LMXJVSD";
	var months=[
		"Enero","Febrero","Marzo","Abril","Mayo","Junio","Julio",
		"Agosto","Septiembre","Octubre","Noviembre","Diciembre"
	];

	this.mesAnterior=function(){
		this.m--; if (this.m<0) { this.m=11; this.y--; }
		this.refresh();
	};

	this.mesSiguiente=function(){
		this.m++; if (this.m>11) { this.m=0; this.y++; }
		this.refresh();
	};
	
	this.setAnyo=function(ny){
		if (ny>=1900 && ny<3000)
			this.y=ny;
		this.refresh();
	};

	this.spDate=function(fecha){
		return (fecha.getDate()<10?"0":"")+fecha.getDate()+"/"+(fecha.getMonth()<9?"0":"")+(1+fecha.getMonth())+"/"+fecha.getFullYear();
	};

	this.sqlDate=function(fecha){
		return fecha.getFullYear()+"-"+(fecha.getMonth()<9?"0":"")+(1+fecha.getMonth())+"-"+(fecha.getDate()<10?"0":"")+fecha.getDate();
	};
		
	this._efectiveDate=function(minmax){
		if (typeof(minmax)=="string") {
			eval("var o="+minmax+";");
			if (o && o.seleccionada) {
				return o.seleccionada;
			}
			return null;
		}
		return minmax;
	};
		
	// actualizar
	this.refresh=function(){
		if (!this.div) return;
		
		var month_day=((new Date(this.y-1900,this.m,1)).getDay()+1)%7;
		var month_days=(32-new Date(this.y-1900,this.m,32).getDate());
		
		var i;
		var h="";
		h+="<table class='xcalendar"+(this.trigger?" xcalendar_popup":"")+"'>";
		h+="<thead>";
		h+="<tr class='xcalendar_title'>";
		h+="<td><a href='javascript:void(0)' onClick='javascript:xcalendars["+a+"].mesAnterior();'>&lt;</a></td>";
		h+="<td colspan='5'>"
			+months[this.m]
			+" <input type='text' value='"+this.y+"' style='text-align:center;width:32px;'"
				+" onFocus='javascript:this.select()'"
				+" onChange='javascript:xcalendars["+a+"].setAnyo(this.value)'"
				+" onKeyPress='javascript:if(event.keyCode==13)xcalendars["+a+"].setAnyo(this.value)'"
			+" />"
			+"</td>";
		h+="<td><a href='javascript:void(0)' onClick='javascript:xcalendars["+a+"].mesSiguiente();'>&gt;</a></td>";
		h+="</tr>";
		h+="<tr>";
		for (i=0;i<7;i++) {
			h+="<th>"+week_abrev[i]+"</th>";
		}
		h+="</tr>\n";
		h+="</thead>\n";
		h+="<tbody>\n";
		h+="<tr>";
		for (i=0;i<month_day;i++) {
			h+="<td></td>";
		}
		
		var today=new Date();
		for (i=0;i<month_days;i++) {
			var dia=new Date(this.y,this.m,i+1)
			var isToday=(this.sqlDate(dia)==this.sqlDate(today));
			if (dia)
				h+="<td>"
					+(this._efectiveDate(this.min) && dia<this._efectiveDate(this.min)
						|| this._efectiveDate(this.max) && dia>this._efectiveDate(this.max)
						?"<span>"+(i+1)+"</span>"
						:"<a"
						+" class='"
							+(isToday?"xcalendar_today ":"")
							+(this.seleccionados[this.sqlDate(dia)]?"xcalendar_selected":"")
						+"'"
						+" title='"+(isToday?"Hoy":"")+"'"
						+" href='javascript:void(0)'"
						+" onClick='javascript:xcalendars["+a+"]._seleccionar("+(i+1)+");'>"+(i+1)+"</a>"
					)
					+"</td>"
			if (!((i+month_day+1)%7)) {
				h+="</tr>\n";
				if (i+1!=month_days) {
					h+="<tr>";
				}
			}
		}
		for (i=((i+month_day)%7);i<7;i++) {
			h+="<td></td>";
		}
		h+="</tr>\n";
		h+="</tbody>\n";
		h+="</table>";
		this.div.innerHTML=h;
	};
	
	// actualizar otros divs relaccionados
	this._updateOthers=function(){
		if (typeof(this.min)=="string") {
			eval("var o="+this.min+";");
			if (o && o.refresh) o.refresh();
		}
		if (typeof(this.max)=="string") {
			eval("var o="+this.max+";");
			if (o && o.refresh) o.refresh();
		}
		this.refresh();
	};
	
	// seleccionar
	this._seleccionar=function(dia){
		var fecha=new Date(this.y,this.m,dia);
		this.seleccionar(fecha);
		if (this.loaded)
			if (this.onselect)
				this.onselect(fecha);
		if (this.input)
			this.input.value=this.spDate(this.seleccionada);
	};

	// seleccionar
	this.seleccionar=function(fecha){
		this.seleccionada=fecha;
		this.seleccionados={};
		if (fecha) {
			this.y=fecha.getFullYear();
			this.m=fecha.getMonth();
			this.seleccionados[this.sqlDate(this.seleccionada)]=this.seleccionada;
		}
		this.refresh();
		this._updateOthers();
	};
	
	// cerrar popup
	this.close=function(){
		if (xcal.trigger && xcal.div) {
			xcal.div.parentNode.removeChild(xcal.div);
			delete xcal.div;
		}
	};
	
	// convertir valor en fecha
	this.dateFromInput=function(v){
		if (v) {
			var x=v.split("/");
			if (x
				&& parseInt(x[0],10)>=1 && parseInt(x[0],10)<=31
				&& parseInt(x[1],10)>=1 && parseInt(x[1],10)<=12
				&& parseInt(x[2],10)>=1900 && parseInt(x[2],10)<=2999
			) {
				this.y=parseInt(x[2],10);
				this.m=parseInt(x[1],10)-1;
				var nueva=new Date(this.y,this.m,parseInt(x[0],10));
				return nueva;
			}
		} else {
			return null;
		}
		this.refresh();
	}
	
	// actualizar desde valor de input
	this.fromInput=function(){
		if (this.input) {
			var nueva=this.dateFromInput(this.input.value);
			if (nueva) {
				if (
					(!this._efectiveDate(this.min) || this.min && nueva>=this._efectiveDate(this.min))
					&& (!this._efectiveDate(this.max) || this.max && nueva<=this._efectiveDate(this.max))
				) {
					this.seleccionar(nueva);
				}
			} else {
				this.seleccionar(null);
			}
		}
	};
	
	// activar triggers
	if (this.input) {
		this.input.onfocus=this.input.onclick=function(){
			
			var xcal=xcalendars[xcalendars_active];
			xcal.close();
			
			xcalendars_active=a;
			var xcal=xcalendars[xcalendars_active];
			
			if (xcal.input) {
				xcal.fromInput();
				xcal.input.select();
			}
			
			if (xcal.trigger) {

				if (!xcal.div) {
					xcal.div=document.createElement("div");
					style(xcal.div,{
						"display":"block",
						"position":"absolute",
						"top":(getTop(xcal.input)+getHeight(xcal.input))+"px",
						"left":getLeft(xcal.input)+"px",
						"position":"absolute"
					});
					xcal.div.onmousedown=function(){
						xcalendars_cancelclick=true;
					}
					document.body.appendChild(xcal.div);
				}
				
				xcal.refresh();
				
			}
			
		};
	}
		
	if (xcal.trigger) {
		this.trigger.onkeydown=function(e){
			if (!e) var e=window.event;
			if (e.keyCode==9)
				xcal.close();
		};
		
	}
	
	// inicialización de eventos por primera vez
	if (xcalendars.length==1) {
		if (this.trigger) {
			mouseup(function(){
				var xcal=xcalendars[xcalendars_active];
				if (!xcalendars_cancelclick)
					if (xcal.div && xcal.trigger)
						xcal.close();
				xcalendars_cancelclick=false;
			});
		}
	}
	
	// filtrar inputs
	if (this.input) {
		
		this.input.onkeydown=function(e) {
			if (!e) var e=window.event;
			var c=e.keyCode;
			if (c>=35 && c<=39) return true;
			switch (c) {
			case 32:
			//case 190:
				//if (with_time)
					//return true;
			case 67: // C
			case 86: // V
			case 88: // X
				if (xcal.keyControl)
					return true;
				return false;
				if (xcal.keyControl)
					return true;
				return false;
			case 16: xcal.keyShift=true;
			case 17: xcal.keyControl=true;
			case 46:
			case 116:
			case 8:
			case 13:
			case 9:
				if (xcal.trigger)
					xcal.close();
			case 15:
			case 55:
				return true;
			default:
				//alert(c);
			}
			//if (selectedText()=="" && i.value.length==10) return false;
			if (!xcal.keyShift && c>=48 && c<=57) return true;
			return false;
		}

		this.input.onkeypress=function(e) {
			if (!e) var e=window.event;
			var c=e.keyCode;
		}

		this.input.onkeyup=function(e) {
			if (!e) var e=window.event;
			var c=e.keyCode;
			//var l=(with_time?16:10);
			switch (c) {
			case 16: xcal.keyShift=false; break;
			case 17: xcal.keyControl=false; break;
			}
			//if (xcal.input.value.length>l) xcal.input.value=xcal.input.value.substring(0,l);
			xcal.fromInput();
		}

		this.input.onchange=function(){
			xcal.fromInput();
		};
		
	}
	
	// actualizar fecha desde input
	this.fromInput();
	
	// si hay DIV indicado, escribir el calendario en dicho DIV
	this.refresh();
	
	// actualizar otros divs asociados
	setTimeout(function(){
		xcal._updateOthers();
		xcal.loaded=true;
	},1);

}
/*
	TÃ­tulo..: xpopup - mr.xkr's JavaScript Carrusel
	Licencia: GPL (http://www.gnu.org/licenses/gpl.txt)
	Autor...: Pablo RodrÃ­guez Rey (mr -en- xkr -punto- es)
	          http://mr.xkr.es/
	Requiere: common.js
	Usa libremente esta librerÃ­a bajo los tÃ©rminos de la licencia GPL, pero por favor,
	deja la autorÃ­a intacta, es lo Ãºnico que te pido, sÃ³lo son unos pocos bytes de carga ;-)
*/

var xcarruseles={};

function xcarrusel(id,imagenes) {
	
	xcarruseles[id]=this;
	
	// siguiente imÃ¡gen
	this.next_image=function(a) {
		return (this.actual_image+1==this.imagenes.length?0:this.actual_image+1);
	}
	
	// temporizador
	this.transition_timer=function() {
		var base=this;
		base.actual_transition=0;
		setTimeout(function(){ base.next(base); },base.time);
	}
	
	// siguiente
	this.next=function(base) {
		base.transition(base);
	}

	// transiciÃ³n
	this.transition=function(base){
		
		var isie=function() { return (navigator.userAgent.indexOf("MSIE")!=-1); }
		
		var finished=false;
		var io=gid(base.imgid+base.actual_image);
		var id=gid(base.imgid+base.next_image(base.actual_image));
		
		base.actual_transition+=2;
		if (base.actual_transition>=100) {
			base.actual_transition=100;
			finished=true;
		}
		
		io.style.opacity=(1-base.actual_transition/100);
		id.style.opacity=(base.actual_transition/100);
		if (isie()) {
			io.style.filter="alpha(opacity="+(100-base.actual_transition)+");";
			id.style.filter="alpha(opacity="+(base.actual_transition)+");";
		}
		
		if (io.style.display!="block") io.style.display="block";
		if (id.style.display!="block") id.style.display="block";
		if (!finished) setTimeout(function() { base.transition(base); },30);
		else {
			io.style.display="none";
			base.actual_image=base.next_image(base.actual_image);
			base.transition_timer();
		}
		
	};

	// parÃ¡metros
	this.imagenes=imagenes;
	this.id=id;
	this.imgid="carrusel_"+id+"_";
	this.image_cache=[];
	this.time=3000;
	this.actual_image=0;
	this.actual_transition=0;
	this.ids={};

	// inicializaciÃ³n
	var h="";
	for (var i in imagenes) {
		h+="<div id='"+this.imgid+i+"'"
			+" style=\""
				+"position:absolute;width:100%;height:100%;background:url('"+imagenes[i].img+"') center center no-repeat;"
				+"display:"+(parseInt(i)?"none":"block")+";"
				+(imagenes[i].onclick || imagenes[i].href?"cursor:pointer;":"")
				+"\""
			+" title='"+(imagenes[i].title?imagenes[i].title:"")+"'"
			+"></div>";
		this.image_cache[i]=new Image(); 
		this.image_cache[i].src=imagenes[i].img; 
	}
	gidset(id,h);
	
	// enlaces
	for (var i in imagenes) {
		if (imagenes[i].onclick)
			gid(this.imgid+i).onclick=imagenes[i].onclick;
		if (imagenes[i].href) {
			var href=imagenes[i].href;
			this.ids[this.imgid+i]=i;
			gid(this.imgid+i).onclick=function(){
				location.href=xcarruseles[id].imagenes[xcarruseles[id].ids[this.id]].href;
			};
		}
	}
	
	// iniciar temporizador
	this.transition_timer();
	
}
var xformdata={};

function xformDateDown(e,i,with_time) {
	if (!e) var e=window.event;
	var c=e.keyCode;
	if (c>=35 && c<=39) return true;
	switch (c) {
	case 32:
	case 190:
		if (with_time)
			return true;
	case 16: keyShift=true;
	case 46:
	case 116:
	case 8:
	case 13:
	case 9:
	case 15:
		return true;
	}
	//if (selectedText()=="" && i.value.length==10) return false;
	if (!keyShift && c>=48 && c<=57) return true;
	return false;
}

function xformDatePress(e,i) {
	if (!e) var e=window.event;
	var c=e.keyCode;
	if (c==16) keyShift=false;
	if (i.value.length==2 && e.keyCode!=8)
		i.value+="/";
	if (i.value.length==5 && e.keyCode!=8)
		i.value+="/";
}

function xformDateUp(e,i,with_time) {
	if (!e) var e=window.event;
	var c=e.keyCode;
	var l=(with_time?16:10);
	if (c==16) keyShift=false;
	if (i.value.length>l) i.value=i.value.substring(0,l);
}

function xformPhoneDown(e,i) {
	if (!e) var e=window.event;
	var c=e.keyCode;
	if (c>=35 && c<=39) return true;
	switch (c) {
	case 16: keyShift=true;
	case 46:
	case 116:
	case 107:
	case 8:
	case 13:
	case 9:
	case 15:
		return true;
	}
	if (!keyShift && c>=48 && c<=57) return true;
	return false;
}

