// Browser Detect  v2.1.6
// documentation: http://www.dithered.com/javascript/browser_detect/index.html
// license: http://creativecommons.org/licenses/by/1.0/
// code by Chris Nott (chris[at]dithered[dot]com)


function BrowserDetect() {
  var ua = navigator.userAgent.toLowerCase();

  // browser engine name
  this.isGecko       = (ua.indexOf('gecko') != -1 && ua.indexOf('safari') == -1);
  this.isAppleWebKit = (ua.indexOf('applewebkit') != -1);

  // browser name
  this.isKonqueror   = (ua.indexOf('konqueror') != -1);
  this.isSafari      = (ua.indexOf('safari') != - 1);
  this.isOmniweb     = (ua.indexOf('omniweb') != - 1);
  this.isOpera       = (ua.indexOf('opera') != -1);
  this.isIcab        = (ua.indexOf('icab') != -1);
  this.isAol         = (ua.indexOf('aol') != -1);
  this.isIE          = (ua.indexOf('msie') != -1 && !this.isOpera && (ua.indexOf('webtv') == -1) );
  this.isMozilla     = (this.isGecko && ua.indexOf('gecko/') + 14 == ua.length);
  this.isFirebird    = (ua.indexOf('firebird/') != -1);
  this.isNS          = ( (this.isGecko) ? (ua.indexOf('netscape') != -1) : ( (ua.indexOf('mozilla') != -1) && !this.isOpera && !this.isSafari && (ua.indexOf('spoofer') == -1) && (ua.indexOf('compatible') == -1) && (ua.indexOf('webtv') == -1) && (ua.indexOf('hotjava') == -1) ) );

  // spoofing and compatible browsers
  this.isIECompatible = ( (ua.indexOf('msie') != -1) && !this.isIE);
  this.isNSCompatible = ( (ua.indexOf('mozilla') != -1) && !this.isNS && !this.isMozilla);

  // rendering engine versions
  this.geckoVersion = ( (this.isGecko) ? ua.substring( (ua.lastIndexOf('gecko/') + 6), (ua.lastIndexOf('gecko/') + 14) ) : -1 );
  this.equivalentMozilla = ( (this.isGecko) ? parseFloat( ua.substring( ua.indexOf('rv:') + 3 ) ) : -1 );
  this.appleWebKitVersion = ( (this.isAppleWebKit) ? parseFloat( ua.substring( ua.indexOf('applewebkit/') + 12) ) : -1 );

  // browser version
  this.versionMinor = parseFloat(navigator.appVersion);

  // correct version number
  if (this.isGecko && !this.isMozilla) {
    this.versionMinor = parseFloat( ua.substring( ua.indexOf('/', ua.indexOf('gecko/') + 6) + 1 ) );
  }
  else if (this.isMozilla) {
    this.versionMinor = parseFloat( ua.substring( ua.indexOf('rv:') + 3 ) );
  }
  else if (this.isIE && this.versionMinor >= 4) {
    this.versionMinor = parseFloat( ua.substring( ua.indexOf('msie ') + 5 ) );
  }
  else if (this.isKonqueror) {
    this.versionMinor = parseFloat( ua.substring( ua.indexOf('konqueror/') + 10 ) );
  }
  else if (this.isSafari) {
    this.versionMinor = parseFloat( ua.substring( ua.lastIndexOf('safari/') + 7 ) );
  }
  else if (this.isOmniweb) {
    this.versionMinor = parseFloat( ua.substring( ua.lastIndexOf('omniweb/') + 8 ) );
  }
  else if (this.isOpera) {
    this.versionMinor = parseFloat( ua.substring( ua.indexOf('opera') + 6 ) );
  }
  else if (this.isIcab) {
    this.versionMinor = parseFloat( ua.substring( ua.indexOf('icab') + 5 ) );
  }

  this.versionMajor = parseInt(this.versionMinor);

  // dom support
  this.isDOM1 = (document.getElementById);
  this.isDOM2Event = (document.addEventListener && document.removeEventListener);

  // css compatibility mode
  this.mode = document.compatMode ? document.compatMode : 'BackCompat';

  // platform
  this.isWin    = (ua.indexOf('win') != -1);
  this.isWin32  = (this.isWin && ( ua.indexOf('95') != -1 || ua.indexOf('98') != -1 || ua.indexOf('nt') != -1 || ua.indexOf('win32') != -1 || ua.indexOf('32bit') != -1 || ua.indexOf('xp') != -1) );
  this.isMac    = (ua.indexOf('mac') != -1);
  this.isUnix   = (ua.indexOf('unix') != -1 || ua.indexOf('sunos') != -1 || ua.indexOf('bsd') != -1 || ua.indexOf('x11') != -1)
  this.isLinux  = (ua.indexOf('linux') != -1);

  // specific browser shortcuts
  this.isNS4x = (this.isNS && this.versionMajor == 4);
  this.isNS40x = (this.isNS4x && this.versionMinor < 4.5);
  this.isNS47x = (this.isNS4x && this.versionMinor >= 4.7);
  this.isNS4up = (this.isNS && this.versionMinor >= 4);
  this.isNS6x = (this.isNS && this.versionMajor == 6);
  this.isNS6up = (this.isNS && this.versionMajor >= 6);
  this.isNS7x = (this.isNS && this.versionMajor == 7);
  this.isNS7up = (this.isNS && this.versionMajor >= 7);

  this.isIE4x = (this.isIE && this.versionMajor == 4);
  this.isIE4up = (this.isIE && this.versionMajor >= 4);
  this.isIE5x = (this.isIE && this.versionMajor == 5);
  this.isIE55 = (this.isIE && this.versionMinor == 5.5);
  this.isIE5up = (this.isIE && this.versionMajor >= 5);
  this.isIE6x = (this.isIE && this.versionMajor == 6);
  this.isIE6up = (this.isIE && this.versionMajor >= 6);

  this.isIE4xMac = (this.isIE4x && this.isMac);
}

function addslashes( str ) {
    /* 
    // Emula el addslashes() de PHP
    // http://kevin.vanzonneveld.net
    // +   original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +   improved by: Ates Goral (http://magnetiq.com)
    // *     example 1: addslashes("kevin's birthday");
    // *     returns 1: "kevin\\'s birthday"
    // *     example 2: addslashes("\"'\\\0");
    // *     returns 2: "\\\"\\\'\\\\\\0"
    */

    return str.replace(/(["'\\])/g, "\\$1").replace(/\0/g, "\\0");
}

// funcion para obtener la posicion absoluta en X de un objeto
function findPosX(obj)
{
  var curleft = 0;
  if (obj.offsetParent)
  {
    while (obj.offsetParent)
    {
      curleft += obj.offsetLeft
      obj = obj.offsetParent;
    }
  }
  else if (obj.x)
  curleft += obj.x;
  return curleft;
}

// funcion para obtener la posicion absoluta en Y de un objeto
function findPosY(obj)
{
  var curtop = 0;
  if (obj.offsetParent)
  {
    while (obj.offsetParent)
    {
      curtop += obj.offsetTop
      obj = obj.offsetParent;
    }
  }
  else if (obj.y)
  curtop += obj.y;
  return curtop;
}

//funcion para hacer trim de una cadena
function trimString (str)
{
  str = this != window? this : str;
  return str.replace(/^\s+/g, '').replace(/\s+$/g, '');
}

// Determinar si un año es bisiesto
function EsBisiesto(year)
{
  return (((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0));
}

// Validar la fecha
// FirstYear y LastYear permiten pasar un rango de anos a validar y
// si su valor es cero no se tienen en cuenta.
function IsValidDate(day, month, year, FirstYear, LastYear)
{
  // Basic error checking
  //alert(day + '-' + month + '-' + year + '-' + FirstYear + '-' + LastYear);
  if (month < 1 || month > 12)
  return false;
  if (day < 1 || day > 31)
  return false;
  if (FirstYear && year < FirstYear)
  return false;
  if (LastYear && year > LastYear)
  return false;

  // Advanced error checking
  // Months with 30 days
  if ((month == 4 || month == 6 || month == 9 || month == 11) && (day > 30))
  {
    return false;
  }

  // February, leap year
  if (month == 2)
  {
    if (EsBisiesto(year))
    {
      if (day > 29)
      {
        return false;
      }
    }
    else
    {
      if (day > 28)
      {
        return false;
      }
    }
  }
  return true;
}

// Validar una hora en formato 24
function IsValidTime24(h, m, s)
{
  if (h < 0 || h > 23)
  {
    return false;
  }
  if (m < 0 || m > 59)
  {
    return false;
  }
  if (s < 0 || s > 59)
  {
    return false;
  }
  return true;
}

function MatchRegExp(objRegExp)
{
  //var objRegExp = /^(([1-6]\.[0-9]{1,2})|([7]\.[0]{1,2})|([1-7]))$/;
  //var objRegExp = /^([1-6]\.[0-9]{1,2}|[7]\.[0]{1,2}|[1-7])$/;
  return objRegExp.test(nota);
}

//esta funcion obtiene un objeto a
function obtenerObjeto(nombre)
{
  //probamos obtenerlo a traves del id
  if(document.getElementById)
  {
    aux = document.getElementById(nombre);
    if (aux)
    {
      return aux;
    }
    else
    {
      if (document.getElementsByName)
      {
        aux = document.getElementsByName(nombre);
        if (aux.length>0)
        {
          return aux.item(0);
        }
        else
        {
          if(document.all)
          {
            return document.all[nombre];
          }
        }
      }
    }
  }
}

/*
	Esta función obtiene un control a través de su "id" y resetea el valor ingresado por el usuario
*/
function unSetControlOfForm(id_obj){
	/*
		Obtenemos el objeto en base al id del control.
		Hay que recordar que en un objeto es multiopción, por ejemplo:
			<input type="radio" id="opt0" name="control_radio" value="0" />
			<input type="radio" id="opt1" name="control_radio" value="0" />
			<input type="radio" id="opt2" name="control_radio" value="0" />
			
		el atributo "name" identifica a todo el control, pero sus opciones pueden tener atributos "id" diferentes,
		entonces habrá que recorrerlo de modo general
	*/
	y = obtenerObjetoCompleto(id_obj);
	
	z = obtenerObjetoCompleto(y.name);//Obtiene el objeto en base al name del control
	
	switch(y.type)
	{
		case 'radio':
			//Para ie
			if(z.form)
			{
				for(i=0;i < z.form[y.name].length; i++)
				{
					//alert('atributo: '+y.form[n_key][i].id+' === '+y.form[n_key][i].checked);
					z.form[y.name][i].checked = false;
				}
			}
			
			//Este recorrido es para FIREFOX
			for(var i = 0; i < z.length; i++) {
				//alert(y.item(i).checked);
				z.item(i).checked = false;
			}
			break;
	}
}

/*
	Este método es un clon del método "obtenerObjeto".
	Este método se hizo para poder obtener objetos html completos,
	pero en particular poder obtener todas las opciones de los objetos multiopción de los formularios.
	
	Ahora indicamos la diferencia en código:
	Método "obtenerObjeto":
	-----------------------------------------------
	if (aux.length>0)
  {
    return aux.item(0); -> como se aprecia este método sólo optiene la primera opción de un objeto multiopción
  }
	
	Método "obtenerObjetoCompleto":
	-----------------------------------------------
	if (aux.length>0)
  {
  	return aux; -> obtiene todo el objeto sin importar que ocurra en su interior, el recorrido se realiza en otro método
  									por ejemplo en el método "unSetControlOfForm".
  }
	
	
*/
function obtenerObjetoCompleto(nombre)
{
  //probamos obtenerlo a traves del id
  if(document.getElementById)
  {
    aux = document.getElementById(nombre);
    if (aux)
    {
      return aux;
    }
    else
    {
      if (document.getElementsByName)
      {
        aux = document.getElementsByName(nombre);
        if (aux.length>0)
        {
        	return aux;
        }
        else
        {
          if(document.all)
          {
            return document.all[nombre];
          }
        }
      }
    }
  }
}

function KeySupress(event, chars, keycodes)
{
  /*
  CHARS:    se escriben aqui los caracteres que seran suprimidos
  se escriben uno a continuacion del otro sin ningun separador
  si no hay, se deja la cadena vacia
  KEYCODES: se escriben aqui los keycodes que seran suprimidos
  se escriben separados por un guion, incluido un guion al inicio y al final
  si no hay, se deja la cadena vacia
  */

  /* averiguamos que tecla presiono */
  var whichCode    = (window.Event) ? event.which : event.keyCode;

  /* caracteres a obviar */
  chars.toString;
  if (chars.length > 0 && chars.match(String.fromCharCode(whichCode)))
  {
    return false;
  }

  /* key codes a obviar */
  /* 13(enter), 32(barra espaciadora), */
  keycodes.toString;
  whichCode.toString;
  if (keycodes.length > 0 && keycodes.match('-' + whichCode + '-'))
  {
    return false;
  }
}

/**
* Función para convertir una cadena de texto conteniendo una
* fecha en formato DD/MM/YYYY en un objeto Date.
* @author Grover Campos
**/
function string2date(cadena)
{
  if (typeof(cadena) == 'string')
  {
    if (cadena.length>=8)
    {
      re = /^(\d{1,2})\/(\d{1,2})\/((19|20)\d{2})$/;
      re_iso = /^(\d{4})\-(\d{2})\-(\d{2})$/;
      if( re.test(cadena) )
      {
        fech = re.exec(cadena);
        if (IsValidDate(fech[1], fech[2], fech[3], 0, 0))
        {
          return new Date(fech[3], fech[2]-1, fech[1]);
        }
        else
        {
          return false;
        }
      }
      else if( re_iso.test(cadena) )
      {
        fech = re_iso.exec(cadena);
        if (IsValidDate(fech[3], fech[2], fech[1], 0, 0))
        {
          return new Date(fech[1], fech[2]-1, fech[3]);
        }
        else
        {
          return false;
        }
      }
      else
      {
        return false;
      }
    }
    else
    {
      return false;
    }
  }
}

/**
* Funcion que hace que un campo simule que una caja de texto
* es de tipo numérico.
* Rango es un objeto que debe tener valores para:
*
* rango = { min_abierto   : int, # indica que no incluye este numero
*           min_inclusive : int, # indica que si incluye este numero
*           max_inclusive : int,
*           max_abierto   : int
*         }
*
* El valor predeterminado para rango es:
* rango = { min_abierto : Number.NEGATIVE_INFINITY,
*           max_abierto : Number.POSITIVE_INFINITY}
*
* @param event e Objeto event en el onkeypress
* @param bool decimal Determina si se acepta el símbolo de decimales
* @author Grover Campos
*/
function campoNumerico(e, decimal)
{
  decimal = decimal || null;
  var evt=(e)?e:(window.event)?window.event:null;
  if(evt)
  {
    /* vemos cual fue el target */
    var target = (evt.target) ? evt.target : (evt.srcElement);
    /* averiguamos que tecla presiono */
    var key=(evt.charCode)?evt.charCode:
    ((evt.keyCode)?evt.keyCode:((evt.which)?evt.which:0));

    var KEYENTER  = 13;
    var KEYTAB    = 9;
    var KEYESC    = 27;
    var KEYBACKSPACE  = 8;
    var KEYDEL        = 46;
    if (key==KEYENTER || key==KEYTAB ||
        key==KEYESC   || key==KEYBACKSPACE ||
        key==KEYDEL)
    {
      return true;
    }
    caracter = String.fromCharCode(key);
    if (!decimal)
    {
      if(/^\d$/.test(caracter))
      {
        return true;
      }
    }
    else
    {
      if(/^[\d|\,|\.]$/.test(caracter))
      {
        return true;
      }
    }
    evt.cancelBubble = true;
    evt.returnValue  = false;
    if (evt.cancelable)
    {
      if(evt.stopPropagation) evt.stopPropagation();
      if(evt.preventDefault)  evt.preventDefault();
    }
    return false;
  }
}

/**
 * Verifica que lo ingresado en un input text esté conforme a una máscara dada
 * El parámetro de máscara es una cadena que contiene la máscara a verificar, los
 * caracteres soportados son:
 * 9 : Representa un campo numérico
 * a : Representa un campo alfabético
 * # : Representa un campo alfanumérico
 * Cualquier otro caracter se asume como literal.
 *
 * Ejemplos:
 *   mascara      texto    valor
 * 99/99/9999  22/22/2222  true
 *
 * @param event e Objeto event en el onkeypress
 * @param string mascara Máscara a verificar
 * @author Grover Campos
 */
function mask(e, mascara)
{
  var evt=(e)?e:(window.event)?window.event:null;
  if(evt)
  {
    /* vemos cual fue el target */
    var target = (evt.target) ? evt.target : (evt.srcElement);
    /* averiguamos que tecla presiono */
    var key=(evt.charCode)?evt.charCode:
            ((evt.keyCode)?evt.keyCode:((evt.which)?evt.which:0));


    var KEYENTER  = 13;
    var KEYTAB    = 9;
    var KEYESC    = 27;
    var KEYBACKSPACE  = 8;
    var KEYDEL        = 46;
    if (key==KEYENTER || key==KEYTAB ||
        key==KEYESC   || key==KEYBACKSPACE ||
        key==KEYDEL)
    {
      return true;
    }

    texto = target.value;
    n     = texto.length;
    for(i=0; i<n; i++)
    {
      mask_caracter = mascara.substring(i, i+1);
      caracter      = texto.substring(i, i+1);
      switch(mask_caracter)
      {
        case '9':
          reg = new RegExp("\\d"); break;
        case 'a':
          reg = new RegExp("\\w", i); break;
        case '#':
          reg = new RegExp("[\\w|\\d]", i); break;
        default:
          reg = new RegExp("\\"+mask_caracter); break;
      }

      if(!reg.test(caracter))
      {
        switch(mask_caracter)
        {
          case '9':
          case 'a':
          case '#':
            target.value = texto.substring(0, i); break;
          default:
            target.value = texto.substring(0, i)+mask_caracter; break;
        }
      }
    }
    return true;
  }
  return false;
}

/**
* Funcion que hace que un input text acepte sólo números y /
* @param event e Objeto event en el onkeypress
* @author Grover Campos
*/
function campoFecha(e)
{
  var evt=(e)?e:(window.event)?window.event:null;
  if(evt)
  {
    /* vemos cual fue el target */
    var target = (evt.target) ? evt.target : (evt.srcElement);
    /* averiguamos que tecla presiono */
    var key=(evt.charCode)?evt.charCode:
    ((evt.keyCode)?evt.keyCode:((evt.which)?evt.which:0));

    var KEYENTER  = 13;
    var KEYTAB    = 9;
    var KEYESC    = 27;
    var KEYBACKSPACE  = 8;
    var KEYDEL        = 46;
    if (key==KEYENTER || key==KEYTAB ||
        key==KEYESC   || key==KEYBACKSPACE ||
        key==KEYDEL)
    {
      return true;
    }
    caracter = String.fromCharCode(key);
    if(/^[\d|\/]$/.test(caracter))
    {
      return true;
    }
    evt.cancelBubble = true;
    evt.returnValue  = false;
    if (evt.cancelable)
    {
      if(evt.stopPropagation) evt.stopPropagation();
      if(evt.preventDefault)  evt.preventDefault();
    }
    return false;
  }
}

/**
* Funcion que sirve para añadir un nodo de texto a un elemento html
* @param elemento Elemento HTML a establecer el texto
* @param nuevo_valor texto a establecer
* @author Grover Campos
*/
function reemplazarValor(elemento, nuevo_valor)
{
  try
  {
    if(elemento.hasChildNodes)
    {
      while(elemento.hasChildNodes())
      {
        elemento.removeChild(elemento.lastChild);
      }
      if(typeof(nuevo_valor)=='string' || typeof(nuevo_valor)=='number')
      {
        elemento.appendChild(document.createTextNode(nuevo_valor));
      }
      else if (typeof(nuevo_valor) == 'object')
      {
        elemento.appendChild(nuevo_valor);
      }
    }
  }
  catch(e){};
}

/**
* Funcion que crea un elemento HTML dinámicamente
* @param string elemento Nombre del elemento HTML a crear
* @param Array atributos Array de pares nombre valor con los atributos a establecer al elemento
* @param string texto a establecer en el elemento
* @param HTMLElement padre Elemento HTML que será padre del elemento
* @author Grover Campos
*/
function crearElemento(elemento, atributos, texto, padre)
{
  element = document.createElement(elemento);
  if(typeof(atributos)!='undefined' && atributos != null)
  {
    brwsr = new BrowserDetect();
    for(var i=0; i<atributos.length; i++)
    {
      nombre = atributos[i][0];
      valor = atributos[i][1];
      if(nombre=='class' && brwsr.isIE5up)
      {
        nombre = 'className';
      }
      element.setAttribute(nombre, valor);
    }
  }
  if(texto!=null &&
     (typeof(texto)=='string' || typeof(texto)=='number'))
  {
    reemplazarValor(element, texto);
  }
  if(typeof(padre)!='undefined')
  {
    padre.appendChild(element);
  }
  return element;
}

/**
* Añade un evento a un objeto
*
* @param HTMLObject target
* @param string eventName nombre del evento, sin el on
* @param string handler funcion que manejara el evento
* @param Array  parametros array que contiene parametros para el handler
* @internal La funcion handler debe existir y debe ser atachada como
*           miembro al target antes de hacer llamar a la funcion
* @example
*   function manipulador(e, parametros) { alert('algo');};
*   elemento = obtenerObjeto('idElemento');
*   XBrowserAddHandler(elemento, 'click', manipulador);
*/
function XBrowserAddHandler(target, eventName, handler, parametros)
{
  parametros = parametros || null;
  if ( target.addEventListener )
  {
    target.addEventListener(eventName, function(e){handler(e, parametros);}, false);
  }
  else if ( target.attachEvent )
  {
    target.attachEvent("on" + eventName, function(e){handler(e, parametros);});
  }
  else
  {
    var originalHandler = target["on" + eventName];
    if ( originalHandler )
    {
      target["on" + eventName] = function(e){originalHandler(e);handler(e, parametros);};
    }
    else
    {
      target["on" + eventName] = handler;
    }
  }
}

/**
 * Función para darle sombra a una fila de una tabla cuando el mouse se asoma
 * sobre él.
 *
 * Para usarlo hay que insertarlo en los métodos onmouseover y onmouseout.
 *
 * @example:
 *  <tr class="{cycle values='blanco,gris'}" onmouseover="sombrear(this, true);" onmouseout="sombrear(this, false);">
 *
 * @autor Grover Campos
 */
var __colorTd__;
var __colorTd2__;

var __colorSombreadoClickHex__ = '#fdd6c3';
var __colorSombreadoClickRGB__ = 'rgb(253, 214, 195)';
var __colorSombreadoHex__      = '#e3e6e9';
var __colorSombreadoRGB__      = 'rgb(227, 230, 233)';

function sombrear(tr, mostrar)
{
  // rgb(227, 230, 233) = #e3e6e9
  if (mostrar)
  {
    __colorTd__ = tr.style.backgroundColor;
    tr.style.backgroundColor = __colorSombreadoHex__;
  }
  else
  {
    if (typeof(tr.seleccionado)!='undefined')
    {
      color = tr.style.backgroundColor;
      if(!tr.seleccionado && (color == __colorSombreadoRGB__ || color == __colorSombreadoHex__) )
      {
        tr.style.backgroundColor = __colorTd__;
      }
      else if(tr.seleccionado && (color == __colorSombreadoRGB__ || color == __colorSombreadoHex__) )
      {
        tr.style.backgroundColor = __colorSombreadoClickHex__;
      }
    }
    else
    {
      tr.style.backgroundColor = __colorTd__;
    }
  }
}

function sombrear_click(tr)
{
  // rgb(253, 214, 195) = #fdd6c3
  color = tr.style.backgroundColor;
  if (!tr.seleccionado && (color != __colorSombreadoClickHex__ || color != __colorSombreadoClickRGB__))
  {
    tr.style.backgroundColor = __colorSombreadoClickHex__;
    tr.seleccionado = true;
  }
  else
  {
    tr.seleccionado = false;
    if (tr.className == 'blanco')
    {
      color = '#ffffff';
    }
    else if(tr.className == 'gris')
    {
      color = '#f0f4f7';
    }
    else
    {
      color = __colorTd__;
    }
    tr.style.backgroundColor = color;
  }
}


function sombrearHandler(e, mostrar)
{
  var evt=(e)?e:(window.event)?window.event:null;
  if(evt)
  {
     /* vemos cual fue el target */
     var target = (evt.target) ? evt.target : (evt.srcElement);
     if(target.tagName=='TD')
     {
       sombrear(target.parentNode, mostrar[0]);
     }

  }
}


/**
función para calcular la edad.
DateFechNac: objeto tipo Date (fecha de nacimiento)
DateFechBase: objeto tipo Date (fecha de base para cálculo de la edad),
por defecto usa la fecha actual.
**/
function calcularEdad(DateFechNac, DateFechBase)
{
  //validamos parametros
  if(!(DateFechNac instanceof Date))
  {
    return false;
  }

  if(typeof(DateFechBase)=='undefined' || !(DateFechNac instanceof Date))
  {
    //fecha base por defecto: fecha de hoy
    DateFechBase = new Date();
  }

  //validamos fecha de nacimiento
  var hoy = new Date();
  if((DateFechNac > hoy) || (DateFechNac > DateFechBase))
  {
    return false;
  }

  //calculamos la edad
  var monarr  = new Array(31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);
  if (EsBisiesto(DateFechBase.getFullYear()))
  {
    monarr[1] = "29";
  }

  var diaFN   = DateFechNac.getDate();
  var mesFN   = DateFechNac.getMonth();
  var yearFN  = DateFechNac.getFullYear();
  var diaB    = DateFechBase.getDate();
  var mesB    = DateFechBase.getMonth();
  var yearB   = DateFechBase.getFullYear();

  edad  = yearB - yearFN;
  meses = mesB - mesFN;
  dias  = diaB - diaFN;

  if(meses < 0)
  {
    edad = edad - 1;
    meses = 12 + (meses);
  }

  if(dias < 0)
  {
    if(meses == 0)
    {
      edad = edad - 1;
      meses = 11;
    }
    else
    {
      meses = meses - 1;
    }
    if(mesB == 0)
    {
      mesB = 12;
    }
    dias = monarr[mesB-1] - diaFN + diaB;
  }
  var strEdad = edad + ' años, ' + meses + ' meses, ' + dias + ' dias';
  return (strEdad);
}

// Sirve para poder tener un array en javascript y pasarlo a un
// input hidden para enviarlo en post o get
function array2input(data, control, separador)
{
  var packed = "";
  separador = separador || ",";
  for (i = 0; (i < data.length); i++)
  {
    if (i > 0)
    {
      packed += separador;
    }
    packed += escape(data[i]);
  }
  control.value = packed;
}

function validar_run(run)
{
  re_run = /^(\d{4,8})\-(\d|\K|\k)$/;
  if(!re_run.test(run))
  {
    return false;
  }
  var run_ = RegExp.$1;
  var dv_  = RegExp.$2;
  var dv_teorico = ObtenerDV(run_);
  return (dv_teorico == dv_.toLowerCase());
}

function ObtenerDV(run)
{
	var M=0, S=1;
	for(; run; run=Math.floor(run/10))
	{
	  S= (S+run%10*(9-M++%6))%11;
	}
	return S ? S-1 : 'k';
}
/**
 * Función para sobreescribir el onfocus de cada control, para poder después
 * determinar qué control tuvo el foco.
 *
 * Author: Grover Campos
 * Date:   04 de Junio de 2007
 */
function set_hasFocus()
{
  document.lastFocus = null;
  var form, f = 0, el, e, old_focus_handler, old_blur_handler, left_curly, right_curly;
  for (f; f < document.forms.length; ++f)
  {
    form = document.forms[f];
    for (e = 0; e < form.elements.length; ++e)
    {
      el = form.elements[e];
      if (el.className != 'exception')
      {
        old_focus_handler = null;
        if (el.onfocus != null)
        {
          old_focus_handler = String(el.onfocus);
          left_curly = old_focus_handler.indexOf('{') + 1;
          right_curly = old_focus_handler.indexOf('}');
          old_focus_handler = old_focus_handler.slice(left_curly, right_curly);
        }
        /*old_blur_handler = null;
        if (el.onblur != null)
        {
          old_blur_handler = String(el.onblur);
          left_curly = old_blur_handler.indexOf('{') + 1;
          right_curly = old_blur_handler.indexOf('}');
          old_blur_handler = old_blur_handler.slice(left_curly, right_curly);
        }*/
        el.onfocus = new Function( 'document.lastFocus=this;' + ( (old_focus_handler) ? old_focus_handler : '') );
        //el.onblur = new Function('document.hasFocus=null;'+((old_blur_handler)?old_blur_handler:''));
      }
    }
  }
}

function ValidarNumero(e, decimal)
{
  var evt=(e)?e:(window.event)?window.event:null;
  if(evt)
  {
     /* vemos cual fue el target */
     var target = (evt.target) ? evt.target : (evt.srcElement);
     /* averiguamos que tecla presiono */
     var key=(evt.charCode)?evt.charCode:
     ((evt.keyCode)?evt.keyCode:((evt.which)?evt.which:0));

     var KEYENTER  = 13;
     var KEYTAB    = 9;
     var KEYESC    = 27;
     var KEYBACKSPACE  = 8;
     var KEYDEL        = 46;
     if (key==KEYENTER || key==KEYTAB ||
         key==KEYESC   || key==KEYBACKSPACE ||
         key==KEYDEL)
     {
       return true;
     }
     caracter = String.fromCharCode(key);

     if (!decimal)
     {
       if(/^\d$/.test(caracter))
       {
         return true;
       }
     }
     else
     {
       if(/^[\d|\.]$/.test(caracter))
       {
         return true;
       }
     }

     evt.cancelBubble = true;
     evt.returnValue  = false;
     if (evt.cancelable)
     {
       if(evt.stopPropagation) evt.stopPropagation();
       if(evt.preventDefault)  evt.preventDefault();
     }
     return false;
  }
}

function ValidarRango(e, min, max)
{
  var evt=(e)?e:(window.event)?window.event:null;
  if(evt)
  {
    /* vemos cual fue el target */
    var target = (evt.target) ? evt.target : (evt.srcElement);

    if((parseFloat(target.value) < min) ||
       (parseFloat(target.value) > max))
    {
      alert("El valor " + target.value + " está fuera del rango de entre " + min + " y " + max);
      target.value = "";
      target.focus();

      evt.cancelBubble = true;
      evt.returnValue  = false;
      if (evt.cancelable)
      {
        if(evt.stopPropagation) evt.stopPropagation();
        if(evt.preventDefault)  evt.preventDefault();
      }
      return false;
    }
    else
    {
      return true;
    }
  }
}

function getVar(name)
{
	get_string = document.location.search;
	return_value = '';
	
	do { //This loop is made to catch all instances of any get variable.
	  name_index = get_string.indexOf(name + '=');
	  
	  if(name_index != -1)
	    {
	    get_string = get_string.substr(name_index + name.length + 1, get_string.length - name_index);
	    
	    end_of_value = get_string.indexOf('&');
	    if(end_of_value != -1)                
	      value = get_string.substr(0, end_of_value);                
	    else                
	      value = get_string;                
	      
	    if(return_value == '' || value == '')
	       return_value += value;
	    else
	       return_value += ', ' + value;
	    }
	  } while(name_index != -1)
	  
	//Restores all the blank spaces.
	space = return_value.indexOf('+');
	while(space != -1)
	    { 
	    return_value = return_value.substr(0, space) + ' ' + 
	    return_value.substr(space + 1, return_value.length);
			 
	    space = return_value.indexOf('+');
	    }
	
	return(return_value);        
}

function smscierre()
{
	setInterval("window.close();",1980);
	
	window.opener.location.href = window.opener.location.href;
}

var mostrar_div_conexion;

function PosicionarDivNotificacionProblemaConexion() 
{
	(document.getElementById) ? dom = true : dom = false;
  
	//Variable que indica el desplazamiento del DIV en la coordenada Y 
	var desp_div_y = 0; 
	
	if (dom && !document.all) 
	{
		document.getElementById("notificacion_conexion").style.top = window.pageYOffset + (window.innerHeight - (window.innerHeight-desp_div_y)) + "px";
	}
	
  if (document.all) 
  {
  	document.all["notificacion_conexion"].style.top = document.documentElement.scrollTop + (document.documentElement.clientHeight - (document.documentElement.clientHeight-desp_div_y)) + "px";
  }
  
  id_reloj_posicionamiento = setTimeout("PosicionarDivNotificacionProblemaConexion()", 10); 

}


function MostrarDivNotificacionProblemaConexion() 
{
	(document.getElementById) ? dom = true : dom = false;
  
	if (dom) 
  {
  	document.getElementById("notificacion_conexion").style.visibility='visible';
		mostrar_div_conexion = true;
  	PosicionarDivNotificacionProblemaConexion();  
  }
}

function OcultarDivNotificacionProblemaConexion() 
{
	(document.getElementById) ? dom = true : dom = false;
  
	if (dom) 
  {
  	document.getElementById("notificacion_conexion").style.visibility='hidden';
 		
  	if(mostrar_div_conexion)
 		{
 			clearTimeout(id_reloj_posicionamiento); 
 		}
  }
}

var mostrar_div_borrador;

function PosicionarDivNotificacionGuardadoBorrador() 
{
	(document.getElementById) ? dom = true : dom = false;
  
	//Variable que indica el desplazamiento del DIV en la coordenada Y 
	var desp_div_y_b = 0; 
	
	if (dom && !document.all) 
	{
		document.getElementById("notificacion_borrador").style.top = window.pageYOffset + (window.innerHeight - (window.innerHeight-desp_div_y_b)) + "px";
	}
	
  if (document.all) 
  {
  	if(document.documentElement.scrollTop)
  	{
	  	document.getElementById("notificacion_borrador").style.top = document.documentElement.scrollTop + (document.documentElement.clientHeight - (document.documentElement.clientHeight-desp_div_y_b)) + "px";
  	}
  	else
  	{
	  	document.getElementById("notificacion_borrador").style.top = document.body.scrollTop + (document.body.clientHeight - (document.body.clientHeight-desp_div_y_b)) + "px";
  	}
  }
  
  id_reloj_posicionamiento_borrador = setTimeout("PosicionarDivNotificacionGuardadoBorrador()", 10); 

}


function MostrarDivNotificacionGuardadoBorrador() 
{
	(document.getElementById) ? dom = true : dom = false;
  
	if (dom) 
  {
  	document.getElementById("notificacion_borrador").style.visibility='visible';
  	document.getElementById("notificacion_borrador").style.display='block';
		mostrar_div_borrador = true;
  	PosicionarDivNotificacionGuardadoBorrador();
  	setTimeout("OcultarDivNotificacionGuardadoBorrador()", 10000);   
  }
}

function OcultarDivNotificacionGuardadoBorrador() 
{
	(document.getElementById) ? dom = true : dom = false;
  
	if (dom) 
  {
  	document.getElementById("notificacion_borrador").style.visibility='hidden';
 		
  	if(mostrar_div_borrador)
 		{
 			clearTimeout(id_reloj_posicionamiento_borrador); 
 		}
  }
}

function ObtenerValorControlRadio(id_obj)
{
	y = obtenerObjetoCompleto(id_obj);
	z = obtenerObjetoCompleto(y.name);//Obtiene el objeto en base al name del control
	
	switch(y.type)
	{
		case 'radio':
		//Para ie
		if(z.form)
		{
			for(i=0;i < z.form[y.name].length; i++)
			{
				if(z.form[y.name][i].checked)
				{
					return z.form[y.name][i].value;
				}
			}
		}

		//Este recorrido es para FIREFOX
		for(var i = 0; i < z.length; i++)
		{
			if(z.item(i).checked)
			{
				return z.item(i).value;
			}
			z.item(i).checked = false;
		}
		break;
	}
}
