function goToFirstError(first_field_id)
{
        var classElements = new Array();
        var clase = 'form_error';
        var nodo = document;
        var tag = '*';
        var els = nodo.getElementsByTagName(tag);
        var elsLen = els.length;
        var pattern = new RegExp("(^|\\s)"+clase+"(\\s|$)");
        var j = 0;
        for (i = 0; i < elsLen; i++) {
                if (pattern.test(els[i].className) ) {
                        els[i].focus();
                        return;
                }
        }
        nodo.getElementById(first_field_id).focus();
}
function pulsar(e) 
{
   tecla=(document.all) ? e.keyCode : e.which;
    if (tecla==13) 
	{
	return false;
	}
}


//muestra la web a partir de el div con id=elemID; como si fuera un ancla de html.
//ejemplo <script>irA('centro')</script>
// mostraría la web a partir del div con id='centro'
function irA(elemID) {
var offsetTrail = document.getElementById(elemID);
var offsetLeft = 0;
var offsetTop = 0;
while (offsetTrail) {
offsetLeft += offsetTrail.offsetLeft;
offsetTop += offsetTrail.offsetTop;
offsetTrail = offsetTrail.offsetParent;
}
if (navigator.userAgent.indexOf("Mac") != -1 && typeof document.body.leftMargin != "undefined" && navigator.appName=="Microsoft Internet Explorer" ) {
offsetLeft += parseInt(document.body.leftMargin);
offsetTop += parseInt(document.body.topMargin);
}
window.scrollTo(offsetLeft,offsetTop)
}

//CREADOR VINCULO MAILTO ANTI SPAMBOTS  
// Iván Nieto Pérez  
//Este script y otros muchos pueden descarse on-line de forma gratuita en El Código: www.elcodigo.com  
function MailLink (usuario, dominio, tld, texto)
{  
	//codifica los caracteres mas significativos  
	var arroba = '@';
	var punto = '.';
	
	//utiliza variables para ocultar las palabras clave
	var etiqueta = 'ma' + '' + 'il';
	var dospuntos = 'to:';
	var localizador = usuario;
	localizador = localizador + arroba + dominio;
	localizador = localizador + punto + tld;
  
	//escribe en enlace  
	document.write('<a href="' + etiqueta + dospuntos + localizador + '">' + texto + '</a>');
}

function getStyle(elemento, propiedadCss) {
	var valor = "";
	if(document.defaultView && document.defaultView.getComputedStyle){
		valor = document.defaultView.getComputedStyle(elemento, '').getPropertyValue(propiedadCss);
	}
	else if(elemento.currentStyle) {
		propiedadCss = propiedadCss.replace(/\-(\w)/g, function (strMatch, p1) {
			return p1.toUpperCase();
		});
		valor = elemento.currentStyle[propiedadCss];
	}
	return valor;
}

function cambia(id,url)
{
	/* cambia + por - y viceversa*/
	if ( $('img_'+id).src.indexOf('selected') != -1 )
		$('img_'+id).src = url+'/img/desplegado.png';
	else
	  $('img_'+id).src = url+'/img/selected.png';

	/* Oculta o muestra los elementos hijos */
	elementos = $$('.subtipo_'+id);

	if (elementos.length)
	{
		for(i = 0; i < elementos.length; i++)
		{
 			if ( getStyle(elementos[i], 'display') == 'none' )
 			{
				if (navigator.appName == "Microsoft Internet Explorer")	elementos[i].style.display = "block";
				else	elementos[i].style.display = "table-row";
			}
			else
	  		elementos[i].style.display = "none";
		}
	}
}

function tellerror(){
return true;
}
window.onerror=tellerror



var hay_clic = false;
var tiempo_espera = 1500;
function escuchar_clic()
{
	Event.observe($('cuerpo'), 'click',
		function(elEvento)
		{
			var evento = elEvento || window.event
			
			// Internet Explorer
			//var objetivo = evento.srcElement;
			// Navegadores que siguen los estandares
			var objetivo = evento.target;
			if (objetivo.parentNode && (objetivo.parentNode.toString().indexOf('http') != -1 || objetivo.toString().indexOf('http') != -1  || (objetivo.type == 'submit' && objetivo.name != 'buscar') ) )
			{
				if ( !hay_clic )
				{
					if(objetivo.type == 'submit' && objetivo.name != 'buscar' && objetivo.className != 'editor_ok_button')
					{
						tiempo_espera = 60000;
						try
						{
							if(tiempo)
								tiempo.stop();
						}
						catch(e){}
					}
					/*else if ((objetivo.parentNode.toString().indexOf('http') != -1 || objetivo.toString().indexOf('http') != -1) &&  (objetivo.parentNode.toString().indexOf('#') == -1 && objetivo.toString().indexOf('#') == -1) &&  (objetivo.parentNode.toString().indexOf('/tareas/activar/') == -1 && objetivo.toString().indexOf('/tareas/activar/') == -1) &&  (objetivo.parentNode.toString().indexOf('/tareas/pausar/') == -1 && objetivo.toString().indexOf('/tareas/pausar/') == -1) )
						tiempo_espera = 600000;*/
					else
						tiempo_espera = 2000;
					inicia_cuenta();
					hay_clic = true;
				}
				else
				{
					// Internet Explorer
					evento.cancelBubble = true;
					evento.returnValue = false;
					// Navegadores que siguen los estandares
					evento.stopPropagation();
					evento.preventDefault();
				}	
			}
		}
	);
	
}

function inicia_cuenta()
{
		var tiempo_click = setTimeout("hay_clic = false;", tiempo_espera);
}


function mostrar_pantalla()
{
	var dOffsets = document.viewport.getScrollOffsets()
	$("imagen_loading").style.top = dOffsets.top+(document.viewport.getHeight()/2)-150+"px"
	$("imagen_loading").style.left = dOffsets.left+(document.viewport.getWidth()/2)-50+"px"
	$("imagen_loading").style.display='block'
	$("pantalla_loading").style.opacity = 0.55
	$("pantalla_loading").style.filter = "alpha(opacity:55)"
	$("pantalla_loading").style.zIndex = 40000
}
function ocultar_pantalla()
{
	$("imagen_loading").style.display='none'
	
	
	$("pantalla_loading").style.opacity=0
	$("pantalla_loading").style.filter="alpha(opacity:0)"
	$("pantalla_loading").style.zIndex=-1000
}
function deshabilitar_pantalla()
{
	$("pantalla_activ").style.opacity = 0.55
	$("pantalla_activ").style.filter = "alpha(opacity:55)"
	$("pantalla_activ").style.zIndex = 40001
}
function habilitar_pantalla()
{
	$("imagen_loading").style.display='none'
	
	
	$("pantalla_activ").style.opacity=0
	$("pantalla_activ").style.filter="alpha(opacity:0)"
	$("pantalla_activ").style.zIndex=-1001
}
function mostrar_fade()
{
	var dOffsets = document.viewport.getScrollOffsets()
	$("imagen_loading").style.display='none'
	$("pantalla_loading").style.opacity = 0.55
	$("pantalla_loading").style.filter = "alpha(opacity:55)"
	$("pantalla_loading").style.zIndex = 40000
}
function ocultar_fade()
{
	$("imagen_loading").style.display='none'
	$("pantalla_loading").style.opacity=0
	$("pantalla_loading").style.filter="alpha(opacity:0)"
	$("pantalla_loading").style.zIndex=-1000
}

function isLeap(y)
{
	if (((y%4==0)&&(y%100!=0))||(y%400==0)) return true
  return false
}
function char2(v) 
{ 
  if ((v>=0)&&(v<=9)) return "0"+v
  return v
}

function convertir_fecha(el, oblig)
{
	var fecha=el.value
	fecha=fecha.replace(/[^0-9]/g, '')
	
	if(oblig != undefined || fecha != '')
	{
		var fecha_actual=new Date()
		var dia_a=fecha_actual.getDay()
		var mes_a=fecha_actual.getMonth()+1
		var anio_a=fecha_actual.getFullYear()
		
		var error="form_error"
		
		el.className=""
		
		if (fecha.length>5)
		{
			var dia=parseInt(fecha.substring(0,2),10)
			var mes=parseInt(fecha.substring(2,4),10)
			if (fecha.length == 8) var anio=parseInt('20'+fecha.substring(6,8),10)
				else var anio=parseInt('20'+fecha.substring(4,6),10)
			
			var f=(isLeap(anio))?29:28
			var dias_m=new Array(31,f,31,30,31,30,31,31,30,31,30,31)
			
			fecha=char2(dia)+'/'+char2(mes)+'/'+char2(anio)
			
			if (anio<anio_a)
			{
				el.className=error
			}
			else if (anio==anio_a)
			{
				if (mes<mes_a||mes>12)
				{
					el.className=error
				}
				else if (mes==mes_a)
				{
					if (dia<dia_a||dia>dias_m[mes-1]) el.className=error
				}
				else if (dia>dias_m[mes-1]) el.className=error
			}
			else
			{
				if (mes>12)	el.className=error
				else if (dia>dias_m[mes-1]) el.className=error
			}
		}
		else
			el.className=error
		
		el.value=fecha
	}
}
function sleep(milliseconds) {
  var start = new Date().getTime();
  for (var i = 0; i < 1e7; i++) {
    if ((new Date().getTime() - start) > milliseconds){
      break;
    }
  }
}
//SELECCIONA TODOS LOS CHECKBOX DE class = CLASE
function mensajes_todos(clase)
{
	var objetos = $$('.'+clase);
	var i;
for (i = 0; i < objetos.length; i++)
	objetos[i].checked = 'checked' ;
}
//QUITA LA SELECCION DE TODOS LOS CHECKBOX DE class = CLASE
function mensajes_ninguno(clase)
{
	var objetos = $$('.'+clase);
	var i;
for (i = 0; i < objetos.length; i++)
	objetos[i].checked = '' ;
}

function tiempo_limite(obj)
{
	tiempo = obj.value;
	if( strpos(tiempo,':') == -1)
	{
		//formato hhmm
		minutos = substr(tiempo,-2);
		horas = substr(tiempo,0,-2)
		if(horas == '')
			horas = '0';
		if(minutos == '')
			minutos = '0';		
	}
	else
	{
		temp = explode( ':', tiempo )
		if(temp[0] == '')
			temp[0]='0';
		if(temp[1] == '')
			temp[1]='0';
		horas = temp[0];
		minutos = temp[1];
	}
	horas = parseInt(horas); 
	minutos = parseInt(minutos);
	if(minutos>59)
	{
		horas = horas+(parseInt(minutos/60));
		minutos = minutos%60;
	}
	if(horas < 10)
		horas = '0'+horas;
	if(minutos < 10)
		minutos = '0'+minutos;
	if(horas == '0')
		horas = '00';
	if(minutos == '0')
		minutos = '00';		
	//tiempo = horas+':'+minutos;
	//alert (tiempo);
	return (horas+':'+minutos);
		
	
}

function strpos( cadena, busc, inicio)
{
 	if(typeof(inicio) == 'undefined')
 		inicio = 0;
    var c = (cadena+'').indexOf( busc, inicio ); 
    return c===-1 ? -1 : c;
}

// CALCULA LA POSICION DEL SELECT MULTIPLE
function posicion(contenedor,select) 
{
	contenedor = $(contenedor);
	select =  $(select);
	contentenedor = $('content');
	
	//Dimensiones del select_multiple
	var dimensions = contenedor.getDimensions(); 
	var SelmWidth = dimensions.width;
	var SelmHeight = dimensions.height;
	
	//Dimensiones del select
	dimensions = select.getDimensions(); 
	var SelWidth = dimensions.width;
	var SelHeight = dimensions.height;
	
	//Dimensiones del div content
	dimensions = contentenedor.getDimensions(); 
	var ConWidth = dimensions.width;
	var ConHeight = dimensions.height;
	
	//Posicion del select visible de la pantalla
	var posicionselect = Element.viewportOffset(select);
	var Selleft = posicionselect.left;
	var Seltop = posicionselect.top;
	var Selright = Selleft+SelWidth;
	var Selbottom = Seltop+SelHeight;
		
	//Dimensiones totales de la pantalla
	var dOffsets = document.viewport.getScrollOffsets();
	var wWidthT = document.viewport.getWidth() + dOffsets.left;
	var wHeightT = document.viewport.getHeight() + dOffsets.top;

  if((Seltop + SelmHeight ) > ConHeight) //PARA QUE AUMENTE LA ALTURA DEL 'content'
		$('content').style.height = Seltop + SelmHeight + 'px';
	
	if((Selleft + SelmWidth ) > wWidthT) //PARA QUE PASE HACIA LA IZQUIERDA SI NO ENTRA EN LA DERECHA
		contenedor.style.left = -(SelmWidth - (wWidthT - ( Selleft + 50))) + "px";
}

/*Devuelve true si algún checkbox de la clase ClaseName está checked, en otro caso false*/
function checked_checkbox(ClaseName) {
	var nombre = 'input.'+ClaseName;
	var theList = $$(nombre);
	var marcado = false;
	theList.each(function(item)
		{
			if (item.checked)
			{
				marcado = true;
			}
		}
	);
	return marcado;
}

function substr( f_string, f_start, f_length ) {
    // http://kevin.vanzonneveld.net
    // +     original by: Martijn Wieringa
    // +     bugfixed by: T.Wild
    // +      tweaked by: Onno Marsman
    // *       example 1: substr('abcdef', 0, -1);
    // *       returns 1: 'abcde'
    // *       example 2: substr(2, 0, -6);
    // *       returns 2: ''
 
    f_string += '';
 
    if(f_start < 0) {
        f_start += f_string.length;
    }
 
    if(f_length == undefined) {
        f_length = f_string.length;
    } else if(f_length < 0){
        f_length += f_string.length;
    } else {
        f_length += f_start;
    }
 
    if(f_length < f_start) {
        f_length = f_start;
    }
 
    return f_string.substring(f_start, f_length);
}

function explode( delimiter, string, limit ) {
    // http://kevin.vanzonneveld.net
    // +     original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +     improved by: kenneth
    // +     improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +     improved by: d3x
    // +     bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // *     example 1: explode(' ', 'Kevin van Zonneveld');
    // *     returns 1: {0: 'Kevin', 1: 'van', 2: 'Zonneveld'}
    // *     example 2: explode('=', 'a=bc=d', 2);
    // *     returns 2: ['a', 'bc=d']
 
    var emptyArray = { 0: '' };
    
    // third argument is not required
    if ( arguments.length < 2
        || typeof arguments[0] == 'undefined'
        || typeof arguments[1] == 'undefined' )
    {
        return null;
    }
 
    if ( delimiter === ''
        || delimiter === false
        || delimiter === null )
    {
        return false;
    }
 
    if ( typeof delimiter == 'function'
        || typeof delimiter == 'object'
        || typeof string == 'function'
        || typeof string == 'object' )
    {
        return emptyArray;
    }
 
    if ( delimiter === true ) {
        delimiter = '1';
    }
    
    if (!limit) {
        return string.toString().split(delimiter.toString());
    } else {
        // support for limit argument
        var splitted = string.toString().split(delimiter.toString());
        var partA = splitted.splice(0, limit - 1);
        var partB = splitted.join(delimiter.toString());
        partA.push(partB);
        return partA;
    }
}
function implode( glue, pieces ) {
    // http://kevin.vanzonneveld.net
    // +   original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +   improved by: Waldo Malqui Silva
    // *     example 1: implode(' ', ['Kevin', 'van', 'Zonneveld']);
    // *     returns 1: 'Kevin van Zonneveld'
 
    return ( ( pieces instanceof Array ) ? pieces.join( glue ) : pieces );
}
function base64_encode( data ) {
    // http://kevin.vanzonneveld.net
    // +   original by: Tyler Akins (http://rumkin.com)
    // +   improved by: Bayron Guevara
    // +   improved by: Thunder.m
    // +   improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +   bugfixed by: Pellentesque Malesuada
    // +   improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // -    depends on: utf8_encode
    // *     example 1: base64_encode('Kevin van Zonneveld');
    // *     returns 1: 'S2V2aW4gdmFuIFpvbm5ldmVsZA=='
 
    // mozilla has this native
    // - but breaks in 2.0.0.12!
    //if (typeof this.window['atob'] == 'function') {
    //    return atob(data);
    //}
        
    var b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
    var o1, o2, o3, h1, h2, h3, h4, bits, i = 0, ac = 0, enc="", tmp_arr = [];
 
    if (!data) {
        return data;
    }
 
    data = utf8_encode(data+'');
    
    do { // pack three octets into four hexets
        o1 = data.charCodeAt(i++);
        o2 = data.charCodeAt(i++);
        o3 = data.charCodeAt(i++);
 
        bits = o1<<16 | o2<<8 | o3;
 
        h1 = bits>>18 & 0x3f;
        h2 = bits>>12 & 0x3f;
        h3 = bits>>6 & 0x3f;
        h4 = bits & 0x3f;
 
        // use hexets to index into b64, and append result to encoded string
        tmp_arr[ac++] = b64.charAt(h1) + b64.charAt(h2) + b64.charAt(h3) + b64.charAt(h4);
    } while (i < data.length);
    
    enc = tmp_arr.join('');
    
    switch( data.length % 3 ){
        case 1:
            enc = enc.slice(0, -2) + '==';
        break;
        case 2:
            enc = enc.slice(0, -1) + '=';
        break;
    }
 
    return enc;
}
function utf8_encode ( argString ) {
    // http://kevin.vanzonneveld.net
    // +   original by: Webtoolkit.info (http://www.webtoolkit.info/)
    // +   improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +   improved by: sowberry
    // +    tweaked by: Jack
    // +   bugfixed by: Onno Marsman
    // +   improved by: Yves Sucaet
    // +   bugfixed by: Onno Marsman
    // *     example 1: utf8_encode('Kevin van Zonneveld');
    // *     returns 1: 'Kevin van Zonneveld'
 
    var string = (argString+'').replace(/\r\n/g, "\n").replace(/\r/g, "\n");
 
    var utftext = "";
    var start, end;
    var stringl = 0;
 
    start = end = 0;
    stringl = string.length;
    for (var n = 0; n < stringl; n++) {
        var c1 = string.charCodeAt(n);
        var enc = null;
 
        if (c1 < 128) {
            end++;
        } else if((c1 > 127) && (c1 < 2048)) {
            enc = String.fromCharCode((c1 >> 6) | 192) + String.fromCharCode((c1 & 63) | 128);
        } else {
            enc = String.fromCharCode((c1 >> 12) | 224) + String.fromCharCode(((c1 >> 6) & 63) | 128) + String.fromCharCode((c1 & 63) | 128);
        }
        if (enc !== null) {
            if (end > start) {
                utftext += string.substring(start, end);
            }
            utftext += enc;
            start = end = n+1;
        }
    }
 
    if (end > start) {
        utftext += string.substring(start, string.length);
    }
 
    return utftext;
}

function str_replace(search, replace, subject, count) {
    // http://kevin.vanzonneveld.net
    // +   original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +   improved by: Gabriel Paderni
    // +   improved by: Philip Peterson
    // +   improved by: Simon Willison (http://simonwillison.net)
    // +    revised by: Jonas Raoni Soares Silva (http://www.jsfromhell.com)
    // +   bugfixed by: Anton Ongson
    // +      input by: Onno Marsman
    // +   improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +    tweaked by: Onno Marsman
    // +      input by: Brett Zamir (http://brett-zamir.me)
    // +   bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +   input by: Oleg Eremeev
    // +   improved by: Brett Zamir (http://brett-zamir.me)
    // +   bugfixed by: Oleg Eremeev
    // %          note 1: The count parameter must be passed as a string in order
    // %          note 1:  to find a global variable in which the result will be given
    // *     example 1: str_replace(' ', '.', 'Kevin van Zonneveld');
    // *     returns 1: 'Kevin.van.Zonneveld'
    // *     example 2: str_replace(['{name}', 'l'], ['hello', 'm'], '{name}, lars');
    // *     returns 2: 'hemmo, mars'
 
    var i = 0, j = 0, temp = '', repl = '', sl = 0, fl = 0,
            f = [].concat(search),
            r = [].concat(replace),
            s = subject,
            ra = r instanceof Array, sa = s instanceof Array;
    s = [].concat(s);
    if (count) {
        this.window[count] = 0;
    }
 
    for (i=0, sl=s.length; i < sl; i++) {
        if (s[i] === '') {
            continue;
        }
        for (j=0, fl=f.length; j < fl; j++) {
            temp = s[i]+'';
            repl = ra ? (r[j] !== undefined ? r[j] : '') : r[0];
            s[i] = (temp).split(f[j]).join(repl);
            if (count && s[i] !== temp) {
                this.window[count] += (temp.length-s[i].length)/f[j].length;}
        }
    }
    return sa ? s : s[0];
}
//+ Jonas Raoni Soares Silva
//@ http://jsfromhell.com/forms/enter-as-tab [rev. #2]

enterAsTab = function(f, a){
	if(document.all)
	{
	    f.attachEvent("onkeypress", function(e){
	        var l, i, f, j, o = e.target;
	        if(e.keyCode == 13 && (a || !/textarea|submit|reset/i.test(o.type))){ //select
	            for(i = l = (f = o.form.elements).length; f[--i] != o;);
	            for(j = i; (j = (j + 1) % l) != i && (!f[j].type || f[j].disabled || f[j].readOnly || f[j].type.toLowerCase() == "hidden"););
	            e.preventDefault(), j != i && f[j].focus();
	        }
	    });
    }
    else
    {
    	f.addEventListener("keypress", function(e){
    		
	        var l, i, f, j, o = e.target;
	        if(e.keyCode == 13 && (a || !/textarea|submit|reset/i.test(o.type))){ //select
	            for(i = l = (f = o.form.elements).length; f[--i] != o;);
	            for(j = i; (j = (j + 1) % l) != i && (!f[j].type || f[j].disabled || f[j].readOnly || f[j].type.toLowerCase() == "hidden"););
	            e.preventDefault(), j != i && f[j].focus();
	        }
	    },false);
    }
};

function number_format( number, decimals, dec_point, thousands_sep ) {
    // http://kevin.vanzonneveld.net
    // +   original by: Jonas Raoni Soares Silva (http://www.jsfromhell.com)
    // +   improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +     bugfix by: Michael White (http://getsprink.com)
    // +     bugfix by: Benjamin Lupton
    // +     bugfix by: Allan Jensen (http://www.winternet.no)
    // +    revised by: Jonas Raoni Soares Silva (http://www.jsfromhell.com)
    // +     bugfix by: Howard Yeend
    // +    revised by: Luke Smith (http://lucassmith.name)
    // +     bugfix by: Diogo Resende
    // +     bugfix by: Rival
    // +     input by: Kheang Hok Chin (http://www.distantia.ca/)
    // +     improved by: davook
    // +     improved by: Brett Zamir (http://brett-zamir.me)
    // *     example 1: number_format(1234.56);
    // *     returns 1: '1,235'
    // *     example 2: number_format(1234.56, 2, ',', ' ');
    // *     returns 2: '1 234,56'
    // *     example 3: number_format(1234.5678, 2, '.', '');
    // *     returns 3: '1234.57'
    // *     example 4: number_format(67, 2, ',', '.');
    // *     returns 4: '67,00'
    // *     example 5: number_format(1000);
    // *     returns 5: '1,000'
    // *     example 6: number_format(67.311, 2);
    // *     returns 6: '67.31'
    // *     example 7: number_format(1000.55, 1);
    // *     returns 7: '1,000.6'
    // *     example 8: number_format(67000, 5, ',', '.');
    // *     returns 8: '67.000,00000'
    // *     example 9: number_format(0.9, 0);
    // *     returns 9: '1'
    var n = number, prec = decimals;
    var toFixedFix = function (n,prec) {
        var k = Math.pow(10,prec);
        return (Math.round(n*k)/k).toString();
    };
 
    n = !isFinite(+n) ? 0 : +n;
    prec = !isFinite(+prec) ? 0 : Math.abs(prec);
    var sep = (typeof thousands_sep === 'undefined') ? ',' : thousands_sep;
    var dec = (typeof dec_point === 'undefined') ? '.' : dec_point;
 
    var s = (prec > 0) ? toFixedFix(n, prec) : toFixedFix(Math.round(n), prec); //fix for IE parseFloat(0.55).toFixed(0) = 0;
 
    var abs = toFixedFix(Math.abs(n), prec);
    var _, i;
 
    if (abs >= 1000) {
        _ = abs.split(/\D/);
        i = _[0].length % 3 || 3;
 
        _[0] = s.slice(0,i + (n < 0)) +
              _[0].slice(i).replace(/(\d{3})/g, sep+'$1');
        s = _.join(dec);
    } else {
        s = s.replace('.', dec);
    }
    if (s.indexOf(dec) === -1 && prec > 1) {
        s += dec+new Array(prec).join(0)+'0';
    }
    return s;
}

function serialize( mixed_value ) {
    // http://kevin.vanzonneveld.net
    // +   original by: Arpad Ray (mailto:arpad@php.net)
    // +   improved by: Dino
    // +   bugfixed by: Andrej Pavlovic
    // +   bugfixed by: Garagoth
    // +      input by: DtTvB (http://dt.in.th/2008-09-16.string-length-in-bytes.html)
    // +   bugfixed by: Russell Walker
    // %          note: We feel the main purpose of this function should be to ease the transport of data between php & js
    // %          note: Aiming for PHP-compatibility, we have to translate objects to arrays
    // *     example 1: serialize(['Kevin', 'van', 'Zonneveld']);
    // *     returns 1: 'a:3:{i:0;s:5:"Kevin";i:1;s:3:"van";i:2;s:9:"Zonneveld";}'
    // *     example 2: serialize({firstName: 'Kevin', midName: 'van', surName: 'Zonneveld'});
    // *     returns 2: 'a:3:{s:9:"firstName";s:5:"Kevin";s:7:"midName";s:3:"van";s:7:"surName";s:9:"Zonneveld";}'
 
    var _getType = function( inp ) {
        var type = typeof inp, match;
        var key;
        if (type == 'object' && !inp) {
            return 'null';
        }
        if (type == "object") {
            if (!inp.constructor) {
                return 'object';
            }
            var cons = inp.constructor.toString();
            match = cons.match(/(\w+)\(/);
            if (match) {
                cons = match[1].toLowerCase();
            }
            var types = ["boolean", "number", "string", "array"];
            for (key in types) {
                if (cons == types[key]) {
                    type = types[key];
                    break;
                }
            }
        }
        return type;
    };
    var type = _getType(mixed_value);
    var val, ktype = '';
    
    switch (type) {
        case "function": 
            val = ""; 
            break;
        case "undefined":
            val = "N";
            break;
        case "boolean":
            val = "b:" + (mixed_value ? "1" : "0");
            break;
        case "number":
            val = (Math.round(mixed_value) == mixed_value ? "i" : "d") + ":" + mixed_value;
            break;
        case "string":
            val = "s:" + encodeURIComponent(mixed_value).replace(/%../g, 'x').length + ":\"" + mixed_value + "\"";
            break;
        case "array":
        case "object":
            val = "a";
            /*
            if (type == "object") {
                var objname = mixed_value.constructor.toString().match(/(\w+)\(\)/);
                if (objname == undefined) {
                    return;
                }
                objname[1] = serialize(objname[1]);
                val = "O" + objname[1].substring(1, objname[1].length - 1);
            }
            */
            var count = 0;
            var vals = "";
            var okey;
            var key;
            for (key in mixed_value) {
                ktype = _getType(mixed_value[key]);
                if (ktype == "function") { 
                    continue; 
                }
                
                okey = (key.match(/^[0-9]+$/) ? parseInt(key, 10) : key);
                vals += serialize(okey) +
                        serialize(mixed_value[key]);
                count++;
            }
            val += ":" + count + ":{" + vals + "}";
            break;
    }
    if (type != "object" && type != "array") {
        val += ";";
    }
    return val;
}
// EJECUTA LA FUNCIÓN func CUANDO SE TERMINA LA CARGA DEL DOM (parecido al window.onload)
/*Con este método simplemente deberemos esperar a que se cargue la estructura del documento, sin tener que esperar a que se carguen los scripts o las imágenes. Puede ser útili, por ejemplo, para realizar una precarga de las imágenes de nuestra página web. http://blog.ejdesigner.com/2008/12/ejecutar-script-despues-de-la-carga-del-dom/*/
function ready(func,parametro)
{
	if (document.all && !window.opera)
	{ 
		document.write('<script id="contentloadtag"><\/script>')  
		var contentloadtag=document.getElementById("contentloadtag")
		contentloadtag.onreadystatechange=function()
		{    
			if (this.readyState=="complete")      
				func(parametro);
		}
	}
	if(/Safari/i.test(navigator.userAgent))
	{
		var _timer=setInterval(function()
		{
			if(/loaded|complete/.test(document.readyState))
			{
				clearInterval(_timer)
		   		func(parametro);
		 	}
		 }, 10)
	}
	if(document.addEventListener && !/Safari/i.test(navigator.userAgent))
		document.addEventListener("DOMContentLoaded", function(){func(parametro);}, false)
}

function in_array (needle, haystack, argStrict) {
    // http://kevin.vanzonneveld.net
    // +   original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +   improved by: vlado houba
    // *     example 1: in_array('van', ['Kevin', 'van', 'Zonneveld']);
    // *     returns 1: true
    // *     example 2: in_array('vlado', {0: 'Kevin', vlado: 'van', 1: 'Zonneveld'});
    // *     returns 2: false
    // *     example 3: in_array(1, ['1', '2', '3']);
    // *     returns 3: true
    // *     example 3: in_array(1, ['1', '2', '3'], false);
    // *     returns 3: true
    // *     example 4: in_array(1, ['1', '2', '3'], true);
    // *     returns 4: false
 
    var key = '', strict = !!argStrict;
 
    if (strict) {
        for (key in haystack) {
            if (haystack[key] === needle) {
                return true;
            }
        }
    } else {
        for (key in haystack) {
            if (haystack[key] == needle) {
                return true;
            }
        }
    }
 
    return false;
}
/* 
// BetterInnerHTML v1.15 - by Craig Buckler, 
function BetterInnerHTML(_1,_2,_3){function Load(_4){var _5;if(typeof DOMParser!="undefined"){_5=(new DOMParser()).parseFromString(_4,"application/xml");}else{var _6=["MSXML2.DOMDocument","MSXML.DOMDocument","Microsoft.XMLDOM"];for(var i=0;i<_6.length&&!_5;i++){try{_5=new ActiveXObject(_6[i]);_5.loadXML(_4);}catch(e){}}}return _5;}function Copy(_8,_9,_a){if(typeof _a=="undefined"){_a=1;}if(_a>1){if(_9.nodeType==1){var _b=document.createElement(_9.nodeName);for(var a=0,attr=_9.attributes.length;a<attr;a++){var _d=_9.attributes[a].name,aValue=_9.attributes[a].value,evt=(_d.substr(0,2)=="on");if(!evt){switch(_d){case "class":_b.className=aValue;break;case "for":_b.htmlFor=aValue;break;default:_b.setAttribute(_d,aValue);}}}_8=_8.appendChild(_b);if(evt){_8[_d]=function(){eval(aValue);};}}else{if(_9.nodeType==3){var _e=(_9.nodeValue?_9.nodeValue:"");var _f=_e.replace(/^\s*|\s*$/g,"");if(_f.length<7||(_f.indexOf("<!--")!=0&&_f.indexOf("-->")!=(_f.length-3))){_8.appendChild(document.createTextNode(_e));}}}}for(var i=0,j=_9.childNodes.length;i<j;i++){Copy(_8,_9.childNodes[i],_a+1);}}_2="<root>"+_2+"</root>";var _11=Load(_2);if(_1&&_11){if(_3!=false){while(_1.lastChild){_1.removeChild(_1.lastChild);}}Copy(_1,_11.documentElement);}}
*/

/*
BetterInnerHTML(element, HTMLstring, clearfirst);
Where:
	element is a DOM node
	HTMLstring is the HTML you want to insert, and
	clearfirst is an optional argument – set it to false to keep the existing child nodes and append the new HTML 			below them
For example:
	BetterInnerHTML( document.getElementById("element"),  "<p>A standard <strong>HTML</strong> string.</p>");
*/
// BetterInnerHTML v1.2, (C) OptimalWorks.net http://www.optimalworks.net/
function BetterInnerHTML(o,p,q){function r(a){var b;if(typeof DOMParser!="undefined")b=(new DOMParser()).parseFromString(a,"application/xml");else{var c=["MSXML2.DOMDocument","MSXML.DOMDocument","Microsoft.XMLDOM"];for(var i=0;i<c.length&&!b;i++){try{b=new ActiveXObject(c[i]);b.loadXML(a)}catch(e){}}}return b}function s(a,b,c){a[b]=function(){return eval(c)}}function t(b,c,d){if(typeof d=="undefined")d=1;if(d>1){if(c.nodeType==1){var e=document.createElement(c.nodeName);var f={};for(var a=0,g=c.attributes.length;a<g;a++){var h=c.attributes[a].name,k=c.attributes[a].value,l=(h.substr(0,2)=="on");if(l)f[h]=k;else{switch(h){case"class":e.className=k;break;case"for":e.htmlFor=k;break;default:e.setAttribute(h,k)}}}b=b.appendChild(e);for(l in f)s(b,l,f[l])}else if(c.nodeType==3){var m=(c.nodeValue?c.nodeValue:"");var n=m.replace(/^\s*|\s*$/g,"");if(n.length<7||(n.indexOf("<!--")!=0&&n.indexOf("-->")!=(n.length-3)))b.appendChild(document.createTextNode(m))}}for(var i=0,j=c.childNodes.length;i<j;i++)t(b,c.childNodes[i],d+1)}p="<root>"+p+"</root>";var u=r(p);if(o&&u){if(q!=false)while(o.lastChild)o.removeChild(o.lastChild);t(o,u.documentElement)}}

/*Crear evento con javascript
evento ejemplo "click"
funcion ejemplo function(){alert(this.innerHTML);}
*/
function crearEvento(id_elemento, evento, funcion) 
{
      if ($(id_elemento).addEventListener) 
      {
            $(id_elemento).addEventListener(evento, funcion, false);
      } else 
      {
            $(id_elemento).attachEvent("on" + evento, funcion);
      }
}


var LibraryManager = Class.create({ 
    initialize: function(){ 
        var carpetaBase = miWebRoot; 
        this._rutaArchivos = new Array(); // ruta según tipo de archivo (manejado por extensión) 
        this._rutaArchivos["css"] = carpetaBase + "css/"; 
        this._rutaArchivos["js"] = carpetaBase + "js/"; 
        this._archivosCargandose = new Array(); // archivos que actualmente se están cargando 
        this._archivosCargados = new Array(); // archivos que ya se han cargado 
    }, 
   /** 
    * Método reiterativo. Carga un archivo por cada llamada. 
    * @param {Object} libreria (Array) -> Listado de archivos a cagar 
    * @param {Object} callback (Function) -> Se llamará esta función al terminar la carga de todos los archivos 
    */ 
    cargar: function(libreria, callback){ 
        if (libreria.length == 0)  
            callback.call(); 
        else { 
            // si no se ha cargado 
            if (!this._archivosCargados[libreria.first()]) { 
                var scope = this; 
                // si ya se está cargando, esperar a que esté listo antes de continuar 
                // (ésto es útil en caso de cargar múltiples librerías a la vez que requieran ese mismo archivo) 
                if (this._archivosCargandose[libreria.first()]) { 
                    var interval = setInterval(function(){ 
                        if (scope._archivosCargados[libreria.first()]) { 
                            libreria.shift(); 
                            clearInterval(interval); 
                            scope.cargar(libreria, callback); 
                        } 
                    }, 10); 
                } 
                else { 
                    var tipo = libreria.first().split(".").last(); 
                    this._archivosCargandose[libreria.first()] = true; 
                    switch (tipo) { 
                        case "css": 
                            var nodoCss = document.createElement('link'); 
                            with (nodoCss) { 
                                type = 'text/css'; 
                                rel = 'stylesheet'; 
                                media = 'screen'; 
                            } 
                            nodoCss.href = this._rutaArchivos[tipo] + libreria.first(); 
                            document.getElementsByTagName("head")[0].appendChild(nodoCss); 
                            this._archivosCargados[libreria.first()] = true; 
                            libreria.shift(); 
                            this.cargar(libreria, callback); 
                            break; 
                        case "js": 
                            new Ajax.Request(this._rutaArchivos[tipo] + libreria.first(), { 
                                method: 'get', 
                                onComplete: function(){ 
                                    scope._archivosCargados[libreria.first()] = true; 
                                    libreria.shift(); 
                                    scope.cargar(libreria, callback); 
                                } 
                            }); 
                            break; 
                        default: 
                            libreria.shift(); 
                            this.cargar(libreria, callback); 
                    } 
                } 
            } 
            // si ya se ha cargado 
            else { 
                libreria.shift(); 
                this.cargar(libreria, callback); 
            } 
        } 
    } 
}); 
var libraryManager = new LibraryManager(); 


/**
 * Event.simulate(@element, eventName[, options]) -> Element
 * 
 * - @element: element to fire event on
 * - eventName: name of event to fire (only MouseEvents and HTMLEvents interfaces are supported)
 * - options: optional object to fine-tune event properties - pointerX, pointerY, ctrlKey, etc.
 *
 *    $('foo').simulate('click'); // => fires "click" event on an element with id=foo
 *
 **/
(function(){
  
  var eventMatchers = {
    'HTMLEvents': /^(?:load|unload|abort|error|select|change|submit|reset|focus|blur|resize|scroll)$/,
    'MouseEvents': /^(?:click|mouse(?:down|up|over|move|out))$/
  }
  var defaultOptions = {
    pointerX: 0,
    pointerY: 0,
    button: 0,
    ctrlKey: false,
    altKey: false,
    shiftKey: false,
    metaKey: false,
    bubbles: true,
    cancelable: true
  }
  
  Event.simulate = function(element, eventName) {
    var options = Object.extend(Object.clone(defaultOptions), arguments[2] || { });
    var oEvent, eventType = null;
    
    element = $(element);
    
    for (var name in eventMatchers) {
      if (eventMatchers[name].test(eventName)) { eventType = name; break; }
    }
 
    if (!eventType)
      throw new SyntaxError('Only HTMLEvents and MouseEvents interfaces are supported');
 
    if (document.createEvent) {
      oEvent = document.createEvent(eventType);
      if (eventType == 'HTMLEvents') {
        oEvent.initEvent(eventName, options.bubbles, options.cancelable);
      }
      else {
        oEvent.initMouseEvent(eventName, options.bubbles, options.cancelable, document.defaultView, 
          options.button, options.pointerX, options.pointerY, options.pointerX, options.pointerY,
          options.ctrlKey, options.altKey, options.shiftKey, options.metaKey, options.button, element);
      }
      element.dispatchEvent(oEvent);
    }
    else {
      options.clientX = options.pointerX;
      options.clientY = options.pointerY;
      oEvent = Object.extend(document.createEventObject(), options);
      element.fireEvent('on' + eventName, oEvent);
    }
    return element;
  }
  
  Element.addMethods({ simulate: Event.simulate });
})()

