// ---------------------------------------------------------
// -------------  API Libreria JavaScript  -----------------
// ---------------------------------------------------------
// ------------------ (C) 2000 DUALmt ----------------------
// -----------------  info@dualmt.com  ---------------------
// ---------------------------------------------------------
// -------------- Programado por Carlos Fierro -------------
// -----------------  carlos@dualmt.com  -------------------
// ---------------------------------------------------------

// -------------  Variables globales del API  --------------
// Modelo de Navegador:
//   "ms"  :  Microsoft Internet Explorer
//   "nv"  :  Netscape Navigator
//   "ot"  :  Otro
var Navegador = "ms";

// Version del navegador (Numero mayor)
var Version = 4;

// Sistema operativo:
//   "w32"  :  Windows 32 bits
//   "mac"  :  Mac OS
//   "unx"  :  Unix
//   "os2"  :  OS/2
//   "des"  :  desconocido
var SistOp = "w32";

// Llamamos a la rutina de inicializacion, antes de que se cargue la pagina
InicializaTodo();

// ------------------  Funciones del API  ------------------

// Funcion que inicializa la libreria
function InicializaTodo()
{
var ss;

	// El navegador
	ss = navigator.appName.toLowerCase();
	if(ss.indexOf("microsoft") != -1)
	  Navegador = "ms";
	else if(ss.indexOf("netscape") != -1)
	  Navegador = "nv";
	else
	  Navegador = "ot";

	// El sistema operativo
	ss = navigator.appVersion.toLowerCase();
	if(ss.indexOf("win") != -1)
	  SistOp = "w32";
	else if(ss.indexOf("os/2") != -1)
	  SistOp = "os2";
	else if (ss.indexOf("unix") != -1)
	  SistOp = "unx";
	else if(ss.indexOf("mac") != -1)
	  SistOp = "mac";
	else 
	  SistOp = "des";
	  
	// La version del navegador
	Version = parseInt(ss);
	// El navegador de Microsoft necesita ajustes para reconocer la version 5
	if(Navegador == "ms")
	  if(navigator.userAgent.indexOf('MSIE 5') > 0)
	    Version = 5;
}

// Cambia el origen de un objeto IMG (imagen) por el archivo indicado
var ultimaIMG = "";
var ultimoArchivo = "";
function CambiaIMG(nombre, archivo)
{
	var obj = ObjetoCapa(nombre);
	if(obj)
	  if(obj.src) {
		  // Guarda los datos previos
		  ultimaIMG = nombre;
			ultimoArchivo = obj.src;
			// Cambia la imagen
	    obj.src = archivo;
		}
}

// Restaura la ultima imagen cambiada con CambiaIMG
function RestauraIMG()
{
	if(ultimaIMG != ""  &&  ultimoArchivo != "")
	  CambiaIMG(ultimaIMG, ultimoArchivo);
}

// Busca un objeto en cualquier nivel de capas anidadas
function ObjetoCapa(nombre, doc)
{
var i, n, obj;

  	if(!doc) {
	    doc = document;
		}
		
    if(!(obj=doc[nombre]))
	    if(doc.all)
	      obj = doc.all[nombre];
	    else if(doc.getElementById)
	      obj = doc.getElementById(nombre);

    for(i=0; !obj  &&  doc.layers  &&  i < doc.layers.length; i++)
	    obj = ObjetoCapa(nombre, doc.layers[i].document);
			
		for(i=0; !obj  &&  doc.forms  &&  i < doc.forms.length; i++) {
		  for(n=0; n < doc.forms[i].length; n++) {
		    if(doc.forms[i][n].name == nombre) {
				  obj = doc.forms[i][n];
				  break;
				}
			}
	    //obj = ObjetoCapa(nombre, doc.forms[i]);
		}
	  
	return obj;
}

// Busca la capa cuyo nombre se pasa y devuelve el objeto correspondiente para cambiar
// sus propiedades (o sea, en MS explorer devolvera capa.style)
function BuscaCapa(nombre)
{
var obj;

	obj = ObjetoCapa(nombre);
	if(obj)
	  if(obj.style) {
	    obj = obj.style;
	  }

	return obj;
}

// Inicializa los datos de una capa. Es necesario llamar a esta rutina una vez para cada capa
// que se vaya a animar y antes de iniciar cualquier animacion con ella.
//   nombre   ---> Nombre de la capa
//   px       ---> Posicion X inicial
//   py       ---> Posicion Y inicial
//   pw       ---> Anchura inicial
//   ph       ---> Altura inicial
//   cl       ---> Clipping Left
//   ct       ---> Clipping Top
//   cr       ---> Clipping Right
//   cb       ---> Clipping Bottom
//   visible  ---> true/false , indica si la capa es visible u oculta
function IniciaCapa(nombre, px, py, pw, ph, cl, ct, cr, cb, visible)
{
var obj;

	obj = BuscaCapa(nombre);
	if(obj != null) {
	  PosicionaObjeto(obj, px, py);
	  DimensionaObjeto(obj, pw, ph);
	  if(arguments.length >= 9  &&  cl != null  &&  ct != null  &&
	                                cr != null  &&  cb != null)
	    RecortaObjeto(obj, cl, ct, cr, cb);
	  else {
	    obj.RecX1 = 0;	  obj.RecY1 = 0;
	    obj.RecX2 = pw;	  obj.RecY2 = ph;
	  }
	  if(arguments.length >= 10  &&  visible != null)
	    if(visible == true)
		  MuestraObjeto(obj);
		else
		  OcultaObjeto(obj);
	}
}

// Valores para controlar la escritura en capas con el MS explorer
var CuentaLineas = 0;      // Cuenta el numero de lineas escritas
var Lineas = new Array();  // Las lineas de texto
var CapaDestino = null;     // La capa donde se esta escribiendo
// Inicia la escritura de informacion
function AbreCapa(nombre)
{
var obj;

	obj = ObjetoCapa(nombre);
	if(obj != null) {
	  CapaDestino = obj;
	  if(Navegador == "nv"  &&  Version <= 4)
	    obj.document.open();
	  else
	    CuentaLineas = 0;
	}
}

// Cierra y termina con la escritura de informacion
function CierraCapa()
{
var obj, n, ss;

	obj = CapaDestino;
	if(obj != null) {
	  if(Navegador == "nv"  &&  Version <= 4)
	    obj.document.close();
	  else {
	    ss = "";
	    for(n = 0; n < CuentaLineas; n++) {
		  ss = ss + Lineas[n]; // + "\n";
		}
		obj.innerHTML = ss;
	    CuentaLineas = 0;
	  }
	}
	CapaDestino = null;
}

// Escribe informacion de texto en la capa abierta
function EscribeCapa(texto)
{
	obj = CapaDestino;
	if(obj != null) {
	  if(Navegador == "nv"  &&  Version <= 4)
	    obj.document.writeln(texto);
	  else
	    Lineas[CuentaLineas++] = texto;
	}
}

// Desplaza un objeto capa
function DesplazaObjeto(capa, dx, dy)
{
	if(dx != 0) {
	  capa.coorx += dx;
	  capa.left = capa.coorx;
	}
	if(dy != 0) {
	  capa.coory += dy;
	  capa.top = capa.coory;
	}
}

// Desplaza una capa dado su nombre
function DesplazaCapa(nombre, dx, dy)
{
var obj;

	obj = BuscaCapa(nombre);
	if(obj != null)
	  DesplazaObjeto(obj, dx, dy);
}

// Muestra un objeto capa
function MuestraObjeto(capa)
{
var v;

	if (capa != null) {
      if (Navegador == "ms"  ||  Version > 4) {   // Para MS Explorer o Netscape 6+
		v = "inherit";  //"visible";
	  }
	  else               // Para Netscape
	    v = "inherit";  //"show";
      capa.visibility=v; 
	}
}

// Muestra una capa dado su nombre
function MuestraCapa(nombre)
{
var v, obj;

	obj = BuscaCapa(nombre);
	MuestraObjeto(obj);
}

// Oculta un objeto capa
function OcultaObjeto(capa)
{
var v;

	if (capa != null) {
      if (Navegador == "ms"  ||  Version > 4) {   // Para MS Explorer o Netscape 6+
		v = "hidden";
	  }
	  else               // Para Netscape
	    v = "hide";
      capa.visibility = v; 
	}
}

// Oculta una capa dado su nombre
function OcultaCapa(nombre)
{
var obj;

	obj = BuscaCapa(nombre);
	OcultaObjeto(obj);
}

// Obtiene la coordenada X de un objeto capa
function PosObjetoX(capa)
{
	return capa.coorx;
}

// Obtiene la coordenada Y de un objeto capa
function PosObjetoY(capa)
{
	return capa.coory;
}

// Obtiene la coordenada X de una capa, dado su nombre
function CapaX(nombre)
{
	var obj = BuscaCapa(nombre);
	if(obj != null)
	  return PosObjetoX(obj);
}

// Obtiene la coordenada Y de una capa, dado su nombre
function CapaY(nombre)
{
	var obj = BuscaCapa(nombre);
	if(obj != null)
	  return PosObjetoY(obj);
}

// Obtiene la anchura de una capa, dado su nombre
function CapaAncho(nombre)
{
	var obj = BuscaCapa(nombre);
	if(obj != null)
	  return obj.ancho;
}

// Obtiene la altura de una capa, dado su nombre
function CapaAlto(nombre)
{
	var obj = BuscaCapa(nombre);
	if(obj != null)
	  return obj.alto;
}

// Devuelve true si una capa es visible
function EsVisible(nombre)
{
var obj;

	obj = BuscaCapa(nombre);
	if(obj != null) {
	  if (Navegador == "ms"  ||  Version > 4) {   // Para MS Explorer
		if(obj.visibility == "hidden")
		  return false;
		else
		  return true;
	  }
	  else {               // Para Netscape
	    if(obj.visibility == "hidde")
		  return false;
		else
		  return true;
	  }
	}
	else
	  return false;
}

// Desplaza horizontalmente un objeto capa
function DesplazaObjetoX(capa, dx)
{
	if(dx != 0) {
	  capa.coorx += dx;
	  capa.left = capa.coorx;
	}
}

// Desplaza horizontalmente una capa dado su nombre
function DesplazaCapaX(nombre, dx)
{
	var obj = BuscaCapa(nombre);
	if(obj != null)
	  DesplazaObjetoX(obj, dx);
}

// Desplaza verticalmente un objeto capa
function DesplazaObjetoY(capa, dy)
{
	if(dy != 0) {
	  capa.coory += dy;
	  capa.top = capa.coory;
	}
}

// Desplaza verticalmente una capa dado su nombre
function DesplazaCapaY(nombre, dy)
{
	var obj = BuscaCapa(nombre);
	if(obj != null)
	  DesplazaObjetoY(obj, dy);
}

// Dimensiona (ancho, alto) un objeto capa
function DimensionaObjeto(capa, anch, alt)
{
	if(anch != null) {
	  capa.width = anch;
	  capa.ancho = anch;
	}
	if(alt != null) {
	  capa.height = alt;
	  capa.alto = alt;
	}
}

// Dimensiona (ancho, alto) una capa dado su nombre
function DimensionaCapa(nombre, ancho, alto)
{
	var obj = BuscaCapa(nombre);
	if(obj != null)
	  DimensionaObjeto(obj, ancho, alto);
}

// Posiciona (x, y) un objeto capa
function PosicionaObjeto(capa, px, py)
{
	capa.coorx = px;
	capa.coory = py;
	capa.left = px;
	capa.top = py;
}

// Posiciona (x, y) una capa dado su nombre
function PosicionaCapa(nombre, px, py)
{
	var obj = BuscaCapa(nombre);
	if(obj != null)
	  PosicionaObjeto(obj, px, py);
}

// Posiciona verticalmente un objeto capa
function PosicionaObjetoY(capa, py)
{
	capa.coory = py;
	capa.top = py;
}

// Posiciona verticalmente una capa dado su nombre
function PosicionaCapaY(nombre, py)
{
	var obj = BuscaCapa(nombre);
	if(obj != null)
	  PosicionaObjetoY(obj, py);
}

// Posiciona horizontalmente un objeto capa
function PosicionaObjetoX(capa, px)
{
	capa.coorx = px;
	capa.left = px;
}

// Posiciona verticalmente una capa dado su nombre
function PosicionaCapaX(nombre, px)
{
	var obj = BuscaCapa(nombre);
	if(obj != null)
	  PosicionaObjetoX(obj, px);
}

// Recorta (clip) un objeto capa
function RecortaObjeto(capa, le, to, ri, bo)
{
	if(Navegador == "nv"  &&  Version <= 4) {
	  if(to != null)
	    capa.clip.top = to;
	  if(ri != null)
	    capa.clip.right = ri;
	  if(bo != null)
	    capa.clip.bottom = bo;
	  if(le != null)
	    capa.clip.left = le;
	}
	else {
	  if(to == null)
	    to = capa.RecY1;
	  if(ri == null)
	    ri = capa.RecX2;
	  if(bo == null)
	    bo = capa.RecY2;
	  if(le == null)
	    le = capa.RecX1;
	  capa.clip = "rect("+to+", "+ri+", "+bo+", "+le+")";
	}
	// Actualiza las propiedades internas
	if(le != null)
	  capa.RecX1 = le;
	if(to != null)
	  capa.RecY1 = to;
	if(ri != null)
	  capa.RecX2 = ri;
	if(bo != null)
	  capa.RecY2 = bo;
}

// Recorta (clip) una capa dado su nombre
function RecortaCapa(nombre, le, to, ri, bo) 
{
	var obj = BuscaCapa(nombre);
	if(obj != null)
	  RecortaObjeto(obj, le, to, ri, bo);
}

function GetClipLeft(capa)
{
	var n = capa.RecX1;
	if(n == NaN)
	  n = 0;
	return n;
}

function CapaClipX1(nombre)
{
	var obj = BuscaCapa(nombre);
	if(obj != null)
	  return GetClipLeft(obj);
	else
	  return 0;
}

function GetClipTop(capa)
{
	var n = capa.RecY1;
	if(n == NaN)
	  n = 0;
	return n;
}

function CapaClipY1(nombre)
{
	var obj = BuscaCapa(nombre);
	if(obj != null)
	  return GetClipTop(obj);
	else
	  return 0;
}

function GetClipRight(capa)
{
	var n = capa.RecX2;
	if(n == NaN)
	  n = CapaAncho(capa)
	return n;
}

function CapaClipX2(nombre)
{
	var obj = BuscaCapa(nombre);
	if(obj != null)
	  return GetClipRight(obj);
	else
	  return 0;
}

function GetClipBottom(capa)
{
	n = capa.RecY2
	if(n == NaN)
	  n = CapaAlto(capa)
	return n;
}

function CapaClipY2(nombre)
{
	var obj = BuscaCapa(nombre);
	if(obj != null)
	  return GetClipBottom(obj);
	else
	  return 0;
}

// Valores para controlar las animaciones de capas
var AnimandoTimer = false;
var ObjetoAnim = [null, null, null, null, null, null, null, null, null, null, null,
				  null, null, null, null, null];
// Anima una capa desplazandola
//  nombre    --> Nombre de la capa
//  px, py    --> Coordenadas finales del desplazamiento
//  tiempo    --> Duracion, en milisegundos, del desplazamiento
//  flags     --> Cadena de flags. Secuencia de caracteres, el orden no importa. Valores:
//                   "c"   --->  Se conserva el clipping de la capa durante la animacion.
//					 "p"   --->  En vez de moverse, se extienden los clippings (ClipRight y ClipBottom).
//  funfin    --> Funcion que se llamara al finalizar la anim. P. ej.: "FinAnim()"
//  retorna un numero que identifica al sprite animado.
function AnimacionCapa(nombre, px, py, tiempo, flags, funfin)
{
var obj, ind, n;

	px = Math.round(px);
	py = Math.round(py);
	// Busca un hueco libre para los datos de la animacion
	ind = -1;
	for(n = 0; n < 16; n++)
	  if(ObjetoAnim[n] == null) {
	    ind = n;
	    break;
	  }
	if(ind >= 0) {
	  obj = BuscaCapa(nombre);
	  if(obj != null) {
	    ObjetoAnim[ind] = obj;
	    obj.InicioX = PosObjetoX(obj);
	    obj.InicioY = PosObjetoY(obj);
	    obj.FinalX = px;
	    obj.FinalY = py;
		obj.RecoLeft = GetClipLeft(obj);
		obj.RecoTop = GetClipTop(obj);
		obj.RecoRight = GetClipRight(obj);
		obj.RecoBottom = GetClipBottom(obj);
	    obj.ElTiempo = tiempo;
	    obj.CuentaAnim = 0;
		if(arguments.length < 5  ||  flags == null)
		  obj.FlagsAnim = "";
		else
		  obj.FlagsAnim = flags;
		if(arguments.length < 6  || funfin  == null)
		  obj.FuncionFinal = "";
		else
		  obj.FuncionFinal = funfin;
		if(!AnimandoTimer) {
		  AnimandoTimer = true;
	      AnimaDespla();
		}
	  }
	}
	return ind;
}

// Lo mismo, pero dando un desplazamiento relativo
function AnimacionCapaRelativa(nombre, dx, dy, tiempo, flags, funfin)
{
var px, py, obj;
var ind = -1;

	obj = BuscaCapa(nombre);
	if(obj != null) {
	  if(flags != null  &&  flags.indexOf("p") != -1) {
	    px = GetClipRight(obj) + dx;
	    py = GetClipBottom(obj) + dy;
	  }
	  else {
	    px = PosObjetoX(obj) + dx;
	    py = PosObjetoY(obj) + dy;
	  }
	  ind = AnimacionCapa(nombre, px, py, tiempo, flags, funfin)
	}
	return ind;
}

var FlagAnimando = true;  // Las animaciones funcionaran solo si es "true"
var DentroDelMeollo = false;
// La funcion que procesa las animaciones dentro de un temporizador
function AnimaDespla()
{
var n, x, y, flags;
var ix, iy, fx, fy, cta, tt;
var le, to, ri, bo;
var obj, ftodo, fle, fto, fri, fbo;
var objetos = new Array();

	if(DentroDelMeollo)
	  return;
	DentroDelMeollo = true;
	if(FlagAnimando) {
	  for(n = 0; n < 16; n++) {
	    objetos[n] = null;
	    if(ObjetoAnim[n] != null) {
	      obj = ObjetoAnim[n];
	      obj.CuentaAnim += 50;    // Incrementamos 50 milisegundos

		  // Calculamos la posicion actual
		  cta = obj.CuentaAnim;
		  tt = obj.ElTiempo;
		  flags = obj.FlagsAnim;
		  if(flags != null  &&  flags.indexOf("p") != -1) {
		    ix = obj.RecoRight;
			iy = obj.RecoBottom;
		  }
		  else {
		    ix = obj.InicioX;
	        iy = obj.InicioY;
		  }
		  fx = obj.FinalX;
	      fy = obj.FinalY;
	      if(cta >= tt) {
		    x = fx;
		    y = fy;
	        obj.CuentaAnim = 0;
		    ObjetoAnim[n] = null;  // Libera el espacio para una animacion
	      }
	      else {
	        x = ix + ((fx - ix) * cta) / tt;
	        y = iy + ((fy - iy) * cta) / tt;
	      }
		  obj.recorta = false;
		  obj.mueve = true;
		  // Posicionamos la capa en la posicion calculada
		  obj.nuevo_x = x;
		  obj.nuevo_y = y;
		  if(flags != null  &&  flags.indexOf("p") != -1) {
		    obj.nuevo_px1 = obj.RecoLeft;
		    obj.nuevo_py1 = obj.RecoTop;
			obj.nuevo_px2 = x;
		    obj.nuevo_py2 = y;
			obj.recorta = true;
			obj.mueve = false;
		  }
		  // Actualiza el Clip
		  ftodo = (flags.indexOf("c") != -1);  // Hay que mantener fijo TODO el clipping??
		  fle = (flags.indexOf("l") != -1);  // Hay que mantener fijo el clipping isquierdo??
		  fto = (flags.indexOf("t") != -1);  // Hay que mantener fijo el clipping superior??
		  fri = (flags.indexOf("r") != -1);  // Hay que mantener fijo el clipping derecho??
		  fbo = (flags.indexOf("b") != -1);  // Hay que mantener fijo el clipping inferior??
		  if(ftodo || fle || fto || fri || fbo) {
		    obj.recorta = true;
		    if(ftodo || fle)
		      le = obj.RecoLeft - (x - ix);
			else
			  le = obj.RecoLeft;
		    if(ftodo || fto)
		      to = obj.RecoTop - (y - iy);
			else
			  to = obj.RecoTop;
			if(ftodo || fri)
		      ri = obj.RecoRight - (x - ix);
			else
			  ri = obj.RecoRight;
			if(ftodo || fbo)
		      bo = obj.RecoBottom - (y - iy);
			else
			  bo = obj.RecoBottom;
			obj.nuevo_px1 = le;
		    obj.nuevo_py1 = to;
			obj.nuevo_px2 = ri;
		    obj.nuevo_py2 = bo;
		    //RecortaObjeto(obj, le, to, ri, bo);
		  }
		  objetos[n] = obj;
	    }
		
	  }
	  //  Actualiza efectivamente las nuevas posiciones. Lo hace aqui, despues de los calculos,
	  // para evitrar parpadeos
	  for(n = 0; n < 16; n++) {
	    if(objetos[n] != null) {
	      obj = objetos[n];
		  if(obj.mueve)
		    PosicionaObjeto(obj, obj.nuevo_x, obj.nuevo_y);
		  if(obj.recorta)
		    RecortaObjeto(obj, obj.nuevo_px1, obj.nuevo_py1, obj.nuevo_px2, obj.nuevo_py2);
		  // Si se ha terminado, llamamos a la funcion final
		  if(ObjetoAnim[n] == null)
		    if(obj.FuncionFinal != "") {
			  setTimeout(obj.FuncionFinal, 10);
		      //eval(obj.FuncionFinal);
			}
		}
	  }  
	}
	DentroDelMeollo = false;
	setTimeout("AnimaDespla()", 50);
}

// Cancela definitivamente la animacion de un sprite concreto
function CancelaAnimacion(num)
{
var obj;

	if(DentroDelMeollo)
	  return false;
	if(num >= 0  &&  num <= 16) {
	  obj = ObjetoAnim[num];
	  if(obj != null) {
	    obj.CuentaAnim = 0;
	    ObjetoAnim[num] = null;
	  }
	}
	return true;
}

// Detiene el procesado de las animaciones
//  (Util para sincronizar animaciones de varias capas diferentes)
function PararAnimaciones()
{
	FlagAnimando = false;
}

// Continua procesando las animaciones
function ContinuarAnimaciones()
{
	FlagAnimando = true;
}

// Devuelve 'true' si el sprite de indice "ind" esta animandose o 'false' si ha terminado
function EstaAnimando(ind)
{
	if(ind >= 0  &&  ind < 16) {
	  obj = ObjetoAnim[ind];
	  return (obj != null);
	}
	else
	  return false;
}


