warning = '';

var ie 		= (navigator.appName == 'Microsoft Internet Explorer') 	? true : false;
var opera 	= (navigator.appName == 'Opera') 						? true : false;
var gecko 	= (navigator.product == 'Gecko') 						? true : false;
var baseUrl = false;
var action  = false;

var fixedDiv = false;
var fixedTop = 30;
var fixedOldTop = fixedTop;

var openedDialog = false;

/**
 * Detecta la tecla pulsada y devuelve su codigo
 *
 * 		key < 46 » Intro, control, alt, retroceso, espacio, etc....
 *		key >= 48 && key <= 57 » numeros 0 a 9
 *		key >= 96 && key <= 105 » numeros 0 a 9 ( numpad )
 *
 * @see 	http://www.geekpedia.com/Question53_A-list-of-keys-and-the-JavaScript-char-codes-they-correspond-to.html
 * @param	object		e
 * @return	int
 */
function keyCode(e)
	{
	if(e == undefined) return false;
	return key = e.keyCode ? e.keyCode : e.charCode;
	}

/**
 * Abre un cuadro de dialogo modal
 *
 * @param	string	url			URL a abrir
 * @param	string	params		ID del campo hidden con parametros
 */
function openModalDialog(url, params)
	{
	openedDialog = window.open(url, params, "width=850,height=" + screen.height * 0.7 + ",dialog,scrollbars=yes");
	}

function closeModalDialog(value)
	{
	openedDialog = false;
	params = window.opener.document.getElementById(window.name).value;
	params = params.replace('/%{3}/g', '"').parseJSON();							// decodifica los parametros
	if(params)																		// si hay que actualizar
		{
		value = params.search.replace('%id', value);								// genera el valor de la busqueda
		window.opener.document.getElementById(params.target).value = value;			// asigna el valor al campo
		window.opener.document.getElementById(params.target).focus();				// pasa el foco al campo
		}

	window.close();
	}

function openedModalDialog(name)
	{
	return openedDialog ? true : false;
	}

/**
 * 'Formatea' un numero separando miles y redondeando decimales
 *
 * @param	float
 * @param	int
 * @param	string
 */
function nf(number, decimals)
	{
	if(decimals == undefined) decimals = 2;											// por defecto, dos decimales
	if(isNaN(number)) number = 0;													// si hay error devuelve 0.00
	number = parseFloat(number);													// verifica que sea un numero
	number = number.toFixed(decimals);												// establece los decimales
	x = number.split('.');															// corta por los decimales
	x1 = x[0]; x2 = x.length > 1 ? '.' + x[1] : '';
	var regexp = /(\d+)(\d{3})/;													// expresion regular de reemplazo
	while (regexp.test(x1)) x1 = x1.replace(regexp, '$1' + ',' + '$2');				// reemplaza miles por miles con coma
	number = (x1 + x2);																// concatena los miles con los decimales

	return number;
	}

/**
 * Redirecciona el navegador a la  URL especificada, mostrando el mensaje de carga
 *
 * @param	string		url
 */
function redirect(url)
	{
	window.location.href = url;
	loading();
	}

/**
 * Muestra / oculta un mensaje animado de 'cargando'
 *
 * @param	bool	show		mostrar / ocultar
 * @return	bool
 */
function loading(show)
	{
	showHideFlash();																// oculta los elementos Flash
	if(show == undefined) show = false;												// por defecto, oculta
	$('loading').style['display'] = !show ? 'none' : 'block';						// muestra el mensaje
	return true;
	}

/**
 * Genera la URL para una busqueda
 */
function search(quick)
	{
	if(quick == undefined) searchBox = 'search-box';
	else searchBox = 'quick-search-box';

	if($('search-field').value == '')
		 url = $('search-base-url').value + $('search-field').value + $(searchBox).value
	else url = $('search-base-url').value + $('search-field').value + $('search-op').value + $(searchBox).value

	url = url.replace(/\s+/g, '+');

	redirect(url);
	}

/**
 * Restringe la pulsacion de determinadas teclas en un campo dependiendo del modo
 *
 * @param	object		field
 * @param	object		event
 * @param	string		mode
 * @return	bool
 */
function restrictField(field, event, mode)
	{
	res = false;																	// por defecto NO se permite
	key = keyCode(event);															// codigo de la tecla pulsada
	switch(mode)																	// evalua el modo
		{
		case 'float':																// flotante
			if(key == 110 || key == 188 || key == 190)								// punto o coma
				{
				if(field.value.indexOf(',')  == -1)									// si no hay ya separador decimal
					field.value = field.value + ',';								// añade una coma al campo
				}
			else if((key > 47 && key < 58) || ((key > 95 && key < 106))) res = true; // si es un numero es valido
			else if(key < 46 && key != 32) res = true;								// Enter, backspace, cursores... pero no el espacio
			break;

		case 'int':																	// entero
			if((key > 47 && key < 58) || ((key > 95 && key < 106))) res = true; 	// si es un numero es valido
			else if(key < 46 && key != 32) res = true;								// Enter, backspace, cursores... pero no el espacio
			break;
		}

	return res;
	}

/**
 * Muestra y oculta pestañas
 *
 * @param	int			tab			numero de pestaña
 * @param	string		id			identificador global ( prefijo )
 */
function showTab(tab, id, msg)
	{
	if($(id + '-tab-' + tab) == undefined) 											// si no existe el elemento
		return alert(msg);															// muestra el mensaje y sale
	
	for(i = 0; i < 20; i++)															// maximo: 20 pestañas
		if($(id + '-tab-' + i) != undefined)										// si existe ese elemento
			if($(id + '-tab-' + i).style.display != 'none')							// y esta mostrado
				{
				$(id + '-tab-' + i).style.display = 'none';							// oculta la pestaña
				$(id + '-tab-header-' + i).className = '';							// desactiva el selector de pestaña
				}

	if($(id + '-tab-' + tab) != undefined) 											// si existe el elemento indicado
		$(id + '-tab-' + tab).style.display = 'block';								// lo muestra

	if($(id + '-tab-header-' + tab) != undefined) 									// si existe el selector de pestaña
		$(id + '-tab-header-' + tab).className = 'active';							// la activa
	}

/**
 *
 */
function startAjaxAdd(url)
	{
	loading(true);
	myAjax = new Ajax.Updater('ajaxAdd', url, { onComplete: showAjaxAdd } );
	}

/**
 *
 */
function showAjaxAdd()
	{
	loading(false);
	Effect.Appear('ajaxAdd');
	}

/**
 * Muestra / oculta todos los elementos Flash
 */
function showHideFlash()
	{
	items = document.getElementsByTagName('div');									// detecta todos los div
	for(i = 0; i < items.length; i++)												// para cada elemento
		{
		if(items[i].className == 'flash')											// si la clase es 'flash'
			{
			if(items[i].innerHTML.match(/^<\!\-\-/))								// si esta oculto, lo muestra
				 items[i].innerHTML = items[i].innerHTML.substring(4, items[i].innerHTML.length - 3);
			else items[i].innerHTML = '<!--' + items[i].innerHTML + '-->';			// oculta el grafico en Flash
			}
		}
	}

/**
 * Inicia una busqueda para rellenar un <SELECT> con ajax
 *
 * @param	string		controller		controlador para identificar los campos
 * @param	string		field			nombre del campo ( el que tomara el select )
 * @param	string		search			cadena de busqueda
 */
function startAjaxSelect(controller, field, id)
	{
	//search = $(id).value;															// valor de la busqueda
	search = $F(id);																// valor de la busqueda
	if(search.replace(/\W/g, '') == '') alert('Los términos de búsqueda no son correctos');
	else																			// si es correcta
		{
		$(controller + '_miniloading').style['display'] = 'inline';					// activa el miniloading
		url = baseUrl + controller.toLowerCase() + '/search/' + search.replace(/\s+/g, '+') + '/export/htm/';					// genera la URL
		var myAjax = new Ajax.Request(url, { method: 'get', onComplete: showAjaxSelect.bind(this, field, controller, id) });	// llamada Ajax
		}
	openedDialog = false;
	}

/**
 * Muestra el select una vez procesados los datos con Ajax
 *
 * @param	string		field			nombre del campo ( el que tomara el select )
 * @param	string		controller		controlador para identificar los campos
 * @param	class		request			objeto request ( el HTML devuelto esta en responseText )
 */
function showAjaxSelect(field, controller, id, request)
	{
	$(controller + '_miniloading').style['display'] = 'none';						// desactiva el miniloading
	if(request.responseText == '0')
		{
		if(confirm('No se han encontrado coincidencias para la búsqueda realizada\n¿Quieres añadir un nuevo elemento a la tabla ' + controller + '?'))
			openModalDialog(baseUrl + controller.toLowerCase() + '/add/layout:dialog', id);
		}
	else																			// si no hay error
		{
		$('ajaxSelectButton' + controller).style['display'] = 'none';				// oculta el boton de busqueda
		$('ajaxSelectRestore' + controller).style['display'] = 'inline';			// muestra el boton de restaurar
		$('ajaxSelectShow' + controller).style['display'] = 'inline';				// muestra el boton de ver
		$('ajaxSelectNew' + controller).style['display'] = 'none';					// oculta el boton de nuevo
		$('ajaxSelectTemp' + controller).innerHTML = $('ajaxSelect' + controller).innerHTML;
		$('ajaxSelect' + controller).innerHTML = request.responseText.replace('REPLACE_ME', field + '" id="' + id);		// muestra el select con el nombre e id originales
		$('ajaxSelectShow' + controller).title = baseUrl + controller.toLowerCase() + '/show/' + $F(id);
		$(id).focus();
		}
	}

function updateAjaxSelectMultiple(url, association)
	{
	var myAjax = new Ajax.Updater(association + '_ajax_container', url, { method: 'get' } );
	}

function deleteAjaxSelectMultipleItem(url)
	{
	if(confirm('¿Seguro?'))
		{
		alert(baseUrl + url);
		var myAjax = new Ajax.Request(baseUrl + url, { method: 'get', onSuccess: alert } );
		}
	}

/**
 * Restaura el input de busqueda y el hidden con el valor original tras una busqueda
 *
 * @param	string		controller		controlador para identificar los campos
 */
function restoreAjaxSelect(controller, id)
	{
	$('ajaxSelectButton' + controller).style['display'] = 'inline';
	$('ajaxSelectRestore' + controller).style['display'] = 'none';
		$('ajaxSelectShow' + controller).style['display'] = 'none';
		$('ajaxSelectNew' + controller).style['display'] = 'inline';
	$('ajaxSelect' + controller).innerHTML = $('ajaxSelectTemp' + controller).innerHTML;
	if($(id) != undefined) $(id).id = controller + '_restored_ajax_seject';
	$('loading').style['display'] = 'none';
	}

/**
 * Actualiza el valor de un campo con el valor devuelto por una URL
 * Se ejecuta la funcion func despues de actualizar el campo
 */
function ajaxUpdateValue(id, url, mode, func)
	{
	loading(true);
	var myAjax = new Ajax.Request(url, { method: 'get', onComplete: ajaxUpdateValueSet.bind(this, id, func, mode) });
	}

function ajaxUpdateValueSet(id, func, mode, request)
	{
	loading(false);
	if(mode == undefined) $(id).value = request.responseText;
	else $(id).innerHTML = request.responseText;

	if(func != undefined) func = new func;
	if($(id).style.display == 'none') $(id).style.display = 'block';
	}

function changeDateField(id, action)
	{
	day = 0;
	month = 0;
	year = 0;

	res = false;
	items = document.getElementsByTagName('select')
	for(i = 0; i < items.length; i++)
		{
		if(items[i].id == id)
			{
			if(items[i].name.match('_year') != null) year = parseInt(items[i].options[items[i].selectedIndex].value);
			else if(items[i].name.match('_month') != null) month = parseInt(items[i].options[items[i].selectedIndex].value);
			else if(items[i].name.match('_day') != null) day = parseInt(items[i].options[items[i].selectedIndex].value);

			if(action == 'reset') items[i].selectedIndex = 0;
			}
		}

	if(action == 'age') alert(age(day, month, year) + ' años');
	return res;
	}

function showHide(id, display)
	{
	if(id == undefined) id = 'extras';
	if($(id) != undefined)
		{
		if(display != undefined)
			 $(id).style.display = display;
		else $(id).style.display = 'none';
		}
	}

/**
 *
 */
function quickValidate(id, valid, showAlert)
	{
	if(valid) $(id).className = 'good';
	else	  $(id).className = 'bad';

	if(showAlert == true)
		{
		if(valid) alert('Correcto');
		else	  alert('Incorrecto')
		}
	}

/**
 * Comprueba la validez de una cadena segun una expresion regular
 *
 * @param	string		value
 * @param	string		regexp
 * @return	bool
 */
function validRegExp(value, regexp)
	{
	return (value.match(regexp)) == null ? false : true;
	}

/**
 * Autorrellena un formulario
 */
function autoFill(request)
	{
	if(request.responseText != undefined)											// si se recibe el resultado de la consulta
		{
		data = JSONDecode(request.responseText);									// decodifica el codigo JSON
		items = document.getElementsByTagName('*');									// lista los input
		for(i = 0; i < items.length; i++)											// para cada elemento
			{
			if(items[i].id != '')													// si tiene id
				{
				item = items[i].id.replace(autoFillData.prefix, '');				// reemplaza el prefijo
				item = 'data.' + autoFillData.model + '.' + item;					// genera el nombre de la propiedad a leer
				item = eval(item);													// memoriza el valor final

				if(items[i].tagName == 'INPUT' || items[i].tagName == 'TEXTAREA')	// si es un INPUT o TEXTAREA
					{
					items[i].value = item;											// asigna el valor
					//if(items[i].onkeyup != undefined) items[i].onkeyup(5);			// si tiene validacion, comprueba
					}
				else if(items[i].id != '' && items[i].tagName == 'SELECT')			// si es un SELECT
					{
					item = items[i].id.replace(autoFillData.prefix, '');			// reemplaza el prefijo
					item = 'data.' + autoFillData.model + '.' + item;				// genera el nombre de la propiedad a leer
					item = eval(item);												// memoriza el valor a asignar

					if(item.match(/[0-9]{4}-[0-9]{2}-[0-9]{2}/) != null)			// si es una fecha
						{
						if(items[i].name.indexOf('_year') > -1) item = item.substr(0, 4);	// año
						if(items[i].name.indexOf('_month') > -1) item = item.substr(5, 2);	// mes
						if(items[i].name.indexOf('_day') > -1) item = item.substr(8, 2);	// dia
						}

					for(j = 0; j < items[i].options.length; j++)					// para cada elemento del select
						if(items[i].options[j].value == item)						// si coincide el valor
							items[i].selectedIndex = j;								// lo selecciona
					}
				}
			}
		$(autoFillData.param + '_miniloading').style['display'] = 'none';			// oculta el indicador de carga
		}
	else																			// si no se recibe el resultado de la consulta
		{
		//$(autoFillData.param + '_miniloading').style['display'] = 'inline';			// marca como cargando
		myAjax = new Ajax.Request(autoFillData.url.replace('$param', $(autoFillData.param).value), { onComplete: autoFill });					// realiza la llamada
		}
	}

/**
 * Decodifica una cadena codificada con json_encode() de PHP y parsea el resultado
 * Devuelve el resultado de parsear la cadena decodificada con parseJSON()
 *
 * @see 	json_encode()
 * @param	string		str
 * @param	mixed
 */
function JSONDecode(str)
	{
	match = str.match(/%iso[0-9]{3}/g);
	for(i = 0; i < match.length; i++)
		str = str.replace(match[i], String.fromCharCode(parseInt(match[i].replace(/%iso/, ''))));

	return str.parseJSON();
	}

/**
 * Dada una fecha calcula los años transcurridos
 *
 * @param	int		dd		dia
 * @param	int		mm		mes
 * @param	int		yy		año
 */
function age(dd, mm, yy)
	{
	var t, mon, day, year, DD, MM, YY, age;
	var MTB = [0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
	if (MTB[MM] < DD || DD < 1) return -1;
	t    = new Date();
	year = t.getFullYear();
	mon  = t.getMonth() + 1;
	day  = t.getDate();
	if (MM == 2 && DD == 29)
		if (!(((YY % 4 == 0) && (YY % 100 != 0)) || (YY % 400 == 0)))
			{
			alert("El año " +YY+ " ends at 28th of "+MM+" month\nPlease check the date.");
			return -1;
			}
	age = year - YY;
	if ((MM > mon) || (MM == mon && day < DD)) age --;

	return age;
	}

/**
 * Detecta la tecla pulsada y devuelve su codigo
 *
 * @param	strong	url			URL base ( se guarda en la variable global baseUrl
 * @param	int		timeout		tiempo en segundos para mostrar el aviso de caducidad de sesion
 */
function init(url, act, timeout)
	{
	baseUrl = url;
	action = act;
	if(timeout > 0) window.setInterval("alert('Te quedan unos minutos antes de que caduque la sesión. ¡Haz algo!');", timeout * 900);

	items = document.getElementsByTagName('input');									// busca los <input> existentes
	for(i = 0; i < items.length; i++)												// para cada elemento
		{
		if((items[i].type == 'submit' || items[i].type == 'button') && items[i].onmousedown == undefined)
			Event.observe(items[i], 'click', loading);

		if((action == 'edit' || action == 'update') && items[i].type == 'text')		// si se edita y el tipo de campo es texto
			if(items[i].onkeyup != undefined) items[i].onkeyup();					// si esta definido el metodo lo llama
		}

	items = document.getElementsByTagName('a');										// busca los <a> existentes
	for(i = 0; i < items.length; i++)												// para cada elemento
		if(items[i].onclick == undefined && items[i].href != undefined)				// excepciones
			Event.observe(items[i], 'click', loading);

	if($('search-box') != undefined) $('search-box').focus();						// pasa el foco a la caja de busqueda
	}



/**
 * Consulta el coste de un curso al crearlo y actualiza los valores
 */
function updateMoney(request)
	{
	if(request.responseText == undefined)											// si no se recibe el request
		{
		loading(true);																// muestra loading y inicia la peticion
		myAjax = new Ajax.Request(baseUrl + '/acciones/show/' + $F('curso_accion_id') + '/0/json/', { onComplete: updateMoney });
		}
	else																			// si recibe el request con JSON
		{
		loading(false);																// oculta loading
		data = JSONDecode(request.responseText);									// parsea el JSON
		if(!data) alert('Ocurrió un error al decodificar los datos');
		else
			{
			$('curso_codigo_curso').value = data.Accion.proximo_curso;				// codigo del curso autogenerado
			$('curso_alumnos_iniciales').value = data.Accion.participantes / data.Accion.cursos_estimados;		// numero de alumnos
			$('presupuesto_persona').value = data.Accion.presupuesto_persona;		// presupuesto
			validateCourse();
			}
		}
	}

// OTRAS FUNCIONES

/**
 * Emula position:fixed en Internet Explorer
 *
 * @param	string		div		ID de la capa
 * @param	int			top		top de CSS
 */
function moveFixed(div, top)
	{
	if(fixedDiv == false) fixedDiv = new getObj(div);
	if(top != undefined) fixedTop = top;

	if (window.innerHeight) pos = window.pageYOffset
	else if (document.documentElement && document.documentElement.scrollTop)
		pos = document.documentElement.scrollTop
	else if (document.body)
		pos = document.body.scrollTop

	if (pos < fixedTop) pos = fixedTop;
	else pos += 30;

	if (pos == fixedOldTop)	fixedDiv.style.top = pos;
	fixedOldTop = pos;
	temp = setTimeout('moveFixed()', 00);
	}

function getObj(name)
	{
	if (document.getElementById)
		{
		this.obj = document.getElementById(name);
		this.style = document.getElementById(name).style;
		}
	else if (document.all)
		{
		this.obj = document.all[name];
		this.style = document.all[name].style;
		}
	else if (document.layers)
		{
		this.obj = document.layers[name];
		this.style = document.layers[name];
		}
	}

function callback(obj){
   for(var i in obj.effects){
     alert(obj.effects[i]['element'].id);
   }
  }

 /*
    json.js
    2006-04-28

    This file adds these methods to JavaScript:

        object.toJSONString()

            This method produces a JSON text from an object. The
            object must not contain any cyclical references.

        array.toJSONString()

            This method produces a JSON text from an array. The
            array must not contain any cyclical references.

        string.parseJSON()

            This method parses a JSON text to produce an object or
            array. It will return false if there is an error.
*/
(function () {
    var m = {
            '\b': '\\b',
            '\t': '\\t',
            '\n': '\\n',
            '\f': '\\f',
            '\r': '\\r',
            '"' : '\\"',
            '\\': '\\\\'
        },
        s = {
            array: function (x) {
                var a = ['['], b, f, i, l = x.length, v;
                for (i = 0; i < l; i += 1) {
                    v = x[i];
                    f = s[typeof v];
                    if (f) {
                        v = f(v);
                        if (typeof v == 'string') {
                            if (b) {
                                a[a.length] = ',';
                            }
                            a[a.length] = v;
                            b = true;
                        }
                    }
                }
                a[a.length] = ']';
                return a.join('');
            },
            'boolean': function (x) {
                return String(x);
            },
            'null': function (x) {
                return "null";
            },
            number: function (x) {
                return isFinite(x) ? String(x) : 'null';
            },
            object: function (x) {
                if (x) {
                    if (x instanceof Array) {
                        return s.array(x);
                    }
                    var a = ['{'], b, f, i, v;
                    for (i in x) {
                        v = x[i];
                        f = s[typeof v];
                        if (f) {
                            v = f(v);
                            if (typeof v == 'string') {
                                if (b) {
                                    a[a.length] = ',';
                                }
                                a.push(s.string(i), ':', v);
                                b = true;
                            }
                        }
                    }
                    a[a.length] = '}';
                    return a.join('');
                }
                return 'null';
            },
            string: function (x) {
                if (/["\\\x00-\x1f]/.test(x)) {
                    x = x.replace(/([\x00-\x1f\\"])/g, function(a, b) {
                        var c = m[b];
                        if (c) {
                            return c;
                        }
                        c = b.charCodeAt();
                        return '\\u00' +
                            Math.floor(c / 16).toString(16) +
                            (c % 16).toString(16);
                    });
                }
                return '"' + x + '"';
            }
        };

    Object.prototype.toJSONString = function () {
        return s.object(this);
    };

    Array.prototype.toJSONString = function () {
        return s.array(this);
    };
})();

String.prototype.parseJSON = function () {
	try {
        return !(/[^,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]/.test(
                this.replace(/"(\\.|[^"\\])*"/g, ''))) &&
            eval('(' + this + ')');
    } catch (e) {
        return false;
    }
};