
/**
* Precarga imágenes a mi manera
*
* @author Lucas Fonzalida
* @arg    String  path  Ruta donde se encuentran las imágenes
* @arg    String        Listado de imágenes (cantidad indefinida)
* @return Array
*/
function preloadImages(path){
    var imgs = new Array();
    var args = preloadImages.arguments;
    for(i = 1; i < args.length; i++) {
        imgs[i]     = new Image();
        imgs[i].src = path + args[i];
    }
    return imgs;
}


/**
* Para abrir nuevas ventanas en el navegador
* Versión genérica
*
* @access public
* @param string url Url
* @param string n   Nombre
* @param string p   Parámetros
* @see              http://msdn.microsoft.com/workshop/author/dhtml/reference/methods/open_0.asp?frame=true
* @return void
*/
function winopen(url,n,p){
	newwin=window.open(url,n,p);
}

/**
* Submit para botones img en modo post
* 
* @access public
* @param  string  url
* @return void
*/
function send(url,mode){
    // selecciona el modo
    if(mode == "href"){
        top.location.href = url;
    }else{
    	document.forms[0].method  = mode;
    	document.forms[0].action += url;
    	document.forms[0].submit();
    }
}

/**
* Para abrir nuevas ventanas en el navegador utilizando 
* "named parameter sets".
*
* @access public
* @param  String  url  Url
* @param  String  n    Nombre
* @param  String  ps   Nombre del Parameter Set
* @return Window
*/
function popup(url,n,ps){
    // Crea un nuevo HashMap para almacenar los named parameters
    var map = new HashMap();
    // Agrega los parámetros
    map.put("volante","top=15,left=15,screenX=15,screenY=15,width=1024,height=563,menubar=no,scrollbars=n,status=no,resizable=no");
    map.put("tapa","top=15,left=15,screenX=15,screenY=15,width=517,height=700,menubar=no,scrollbars=n,status=no,resizable=no");
    // Obtiene los parámetros
    var params = map.get(ps);
    // Abre una nueva ventana y almacena la referencia
    var w = window.open(url,n,params);
}





//
//
// A partir de acá, clases del sistema RTF.
// Verificar versiones en los encabezados.
//
//





/**
* SiteConfig
* Mantiene datos de configuración para todas las aplicaciones de este sitio.
* NOTA: Ver si este objeto debe ir en un '.js' aparte ya que es específico de un sitio
*
*
* METODOS PUBLICOS:
* -----------------
* + getWindowFeatures(String winName) : WindowFeatures
*
*
*
*
*
* @autor Lucas Fonzalida <contacto@lucasfonzalida.com.ar>
* @see   'JSRTF.doc'
*/
function SiteConfig(){
    
    // Variables objeto
    this.windowFeatures         = new HashMap();    // parámetros de ventanas

    // Métodos
    this.getWindowFeatures      = getWindowFeatures;
    
    // Inicializa los parámetros
    this.windowFeatures.put("radioplayer",new WindowFeatures("posX=350,posY=300,width=302,height=306,menubar=0,scrollbars=0,status=0,resizable=0"));

    /**
    * Permite recuperar objetos WindowFeatures almacenados en el HashMap
    *
    *
    * @access public
    * @param  String           winName  Nombre del parameter set
    * @retrun WindowFeatures
    */    
    function getWindowFeatures(winName){
        // Verifica si los datos existen
        if(this.windowFeatures.containsKey(winName)){
            // Obtiene los parámetros como objeto y los retorna
            return this.windowFeatures.get(winName);
        }else{
            // Obtiene los parámetros como objeto
            alert("WindowFeatures :: El set: '" + winName + "', no existe.");
        }
    }
}

/**
* Busca las coordenadas X e Y de un objeto
*
* METODOS PUBLICOS:
* -----------------
* + getPosition(Object obj) : Position
* + getCursorPosition(Event evnt) : Position
*
* @version 1.0
* @author  Lucas Fonzalida <contacto@lucasfonzalida.com.ar>
*/
function PositionFinder(){

    // Métodos
	this.getPosition        = getPosition;
	this.getCursorPosition  = getCursorPosition;
	
    /**
    * Retorna un objeto Position con las coordenadas del objeto
    * relativas al documento.
    *
    * @access public
    * @param  Object   obj  Objeto DOM
    * @return Position
    */
    function getPosition(obj){
        // Define e inicializa variables XY
    	var curX = 0;
    	var curY = 0;
        // Mientras exista un offsetParent
        while (obj.offsetParent){
    		curX += obj.offsetLeft;
    		curY += obj.offsetTop;
    		obj   = obj.offsetParent;
    	}
    	// Crea y retorna un objeto Position
    	return new Position(curX,curY);
    }
    
    /**
    * Retorna la posición del cursor del momento en el que ocurrió el evento
    * pasado como parámetro.
    *
    * @access public
    * @param  Event   evnt  Objeto Event DOM
    * @return Position
    */
    function getCursorPosition(evnt){
        // Crea y retorna un objeto Position con la posición del cursor.
        return new Position(evnt.screenX, evnt.screenY);
    }

    /**
    * CLASE INTERNA
    * Almacena un par de coordenadas X e Y
    *
    * @param int x Coordenada X
    * @param int y Coordenada Y
    */
    function Position(x,y){

        // Atributos
    	this.x = x;
    	this.y = y;

    	// Métodos
    	this.getX = getX;
    	this.getY = getY;
    	
    	/**
    	* Retorna el valor de X
    	*
    	* @access public
    	* @return int
    	*/
    	function getX(){
    	    return this.x;
    	}
    	
    	/**
    	* Retorna el valor de Y
    	*
    	* @access public
    	* @return int
    	*/
    	function getY(){
    	    return this.y;
    	}
    }
}


/**
* Emula la implementación HashMap de Java
* NOTA: Se puede mejorar
*
*
* METODOS:
* --------
* + get(Object key) : Object
* + put(Object key, Object value) : Object
* + remove(Object key) : Object
* + size() : int
* + containsKey(Object key) : boolean
* - getIndex(Object key) : int
*
*
*
*
* @version 1.0
* @author Lucas Fonzalida <contacto@lucasfonzalida.com.ar>
*/
function HashMap(){

    // Atributos
    this.data = new Array();
    
    // Metodos
    this.get          = get;
    this.put          = put;
    this.remove       = remove;
    this.size         = size;
    this.containsKey  = containsKey;
    this.getIndex     = getIndex;

          
    /**
    * Returns the value to which the specified key is mapped in this
    * identity hash map, or null if the map contains no mapping for this key. 
    *
    * @access public
    * @param  Object  key    
    * @return Object
    */ 
    function get(key){
        // Obtiene el index del key
        var i = this.getIndex(key);
        // Si el key no existe retorna null
        if(i == -1){
            return null;
        }
        // Retorna el valor para el key indicado
        return this.data[i][1];
    }  
    
    /**
    * Associates the specified value with the specified key in this map. 
    * If the map previously contained a mapping for this key, the old value is replaced. 
    * Returns: previous value associated with specified key, or null if there was no mapping for key.
    *
    * @access public
    * @param  Object  key    Objeto clave
    * @param  Object  value  Objeto valor
    * @return Object
    */    
    function put(key, value){
        // Obtiene el index del key
        var i = this.getIndex(key);
        // Si el key no existe se agrega un elemento al final
        if(i == -1){
            // Agrega un nuevo item al final del array
            this.data.push(new Array(key,value));
        }else{
            // Obtiene el objeto actual
            var obj = this.get(key);
            // Sobreescribe el key actual
            this.data[i] = new Array(key,value);
            // Retorna el valor asociado al key anterior
            return obj;
        }
        return null;
    }

    /**
    * Associates the specified value with the specified key in this map.
    * Returns: previous value associated with specified key, or null if
    * there was no mapping for key.
    *
    * @access public
    * @param  Object  key    
    * @return Object
    */    
    function remove(key){
        // Obtiene el index del key
        var i = this.getIndex(key);
        if(i == -1){
            return null;
        }
        // Obtiene el objeto actual
        var obj = this.get(key);
        // Elimina el elemento actual
        this.data.splice(i,1);
        // Retorna el valor asociado al key anterior
        return obj;
    }

    /**
    * Returns the number of key-value mappings in this map.
    *
    * @access public
    * @return int
    */    
    function size(){
        return this.data.length;
    }

    /**
    * Returns true if this map contains a mapping for the specified key.
    *
    * @access public
    * @param  Object 
    * @return boolean
    */ 
    function containsKey(key){
        // Obtiene el index del key
        var i = this.getIndex(key);
        // Comprueba el index obtenido
        if(i > -1){
            // Retorna: El key existe
            return true;
        }
        // Retorna: El key no existe
        return false;
    }

    /**
    * Retorna el index que corresponde al key especificado.
    * Si el key no existe retorna -1
    * NOTA: Este método no existe en la implementación original de Java
    *
    * @access private
    * @param  Object  key
    * @return int
    */    
    function getIndex(key){
        // Recorre el array en busca del objeto key
        for(var i = 0; i < this.data.length; i++){
            if(this.data[i][0] == key){
                return i;
            }
        }
        return -1;
    }
}




/**
* Fascilita la manipulación de objetos de formulario.
* Esta clase es la base de todos los formularios de tiempo real  (RTFs)
*
* METODOS PUBLICOS:
* -----------------
* + setStringDisplay(String display_id, String val) : void
* + setIntegerDisplay(String display_id, int val): void
* + setFloatDisplay(String display_id, float val, int precision) : void
* + setCurrencyDisplay(String display_id, float val, int precision) : void
* + setObjectVisibility(String object_id, boolean visible) : void
* + setImageSrc(String image_id, String src_value) : void
* + setFieldValue(String field_id, String val) : void
*
* + getObject(String field_id) : Node
* + getObjectVisibility(String object_id) : bool
* + getFieldValue(String field_id) : Node
*
*
* @author  Lucas Fonzalida <contacto@lucasfonzalida.com.ar>
* @version 1.2 (23/11/2006 17:25)
*/
function FormObjectsManager(){

    // Métodos
    this.setStringDisplay           = setStringDisplay;
    this.setIntegerDisplay          = setIntegerDisplay;
    this.setFloatDisplay            = setFloatDisplay;
    this.setCurrencyDisplay         = setCurrencyDisplay;
    this.setObjectVisibility        = setObjectVisibility;
    this.setImageSrc                = setImageSrc;
    this.setFieldValue              = setFieldValue;
    
    this.getObject                  = getObject;
    this.getObjectVisibility        = getObjectVisibility;
    this.getFieldValue              = getFieldValue;

    //
    // Setters
    //

    /**
    * Muestra un string
    *
    * @access public
    * @param  String  display_id  Id del objeto span o div
    * @param  String  val         Cadena a mostrar
    * @return void
    */
    function setStringDisplay(display_id, val){
        this.getObject(display_id).innerHTML = val;
    }

    /**
    * Muestra un valor entero
    *
    * @access public
    * @param  String  display_id  Id del objeto span o div
    * @param  int     val         Valor entero
    * @return void
    */
    function setIntegerDisplay(display_id, val){
        this.setStringDisplay(display_id, val);
    }

    /**
    * Muestra un valor decimal, si el valor no es un numero decimal
    * se ignora la precisión y se muestra como String
    *
    * @access public
    * @param  String  display_id  Id del objeto span o div
    * @param  float   val         Valor decimal
    * @param  int     precision   Precisión decimal
    * @return void
    */
    function setFloatDisplay(display_id, val, precision){
        num = new Number(val);
        // Si el valor es numérico se lo formatea
        if(!isNaN(num)){
            val = num.toFixed(precision);
        }
        this.setStringDisplay(display_id, val);
    }

    /**
    * Muestra un valor decimal, si el valor no es un numero decimal
    * se ignora la precisión y se muestra como String
    *
    * @access public
    * @param  String   display_id  Id del objeto span o div
    * @param  numeric  val         Valor numérico (entero o decimal)
    * @param  float    precision   Precisión decimal
    * @return void
    */
    function setCurrencyDisplay(display_id, val, precision){
        num = new Number(val);
        // Si el valor es numérico se lo formatea
        if(!isNaN(num)){
            val = "$" + num.toFixed(precision).replace(".",",");
        }
        this.setStringDisplay(display_id, val);
    }
    
    /**
    * Oculta o desoculta un objeto de formulario
    *
    * @access public
    * @param  String   object_id  Id del objeto
    * @param  boolean  visible    true | false
    * @return void
    */
    function setObjectVisibility(object_id, visible){
        // Se obtiene una referencia al objeto
        obj = this.getObject(object_id);
        // Oculta o desoculta el objeto
        if(visible){
            obj.style.display = "";
        }else{
            obj.style.display = "none";
        }
    }
    
    /**
    * Cambia el atributo src de un objeto IMG
    * NOTA: Es recomendable realizar una precarga de
    * las imágenes antes de ejecutar esta operación.
    *
    * @access public
    * @param  String   image_id   Id del objeto IMG
    * @param  String   src_value  Valor del atributo src
    * @return void
    */
    function setImageSrc(image_id, src_value){
        // Se obtiene una referencia al objeto
        obj = this.getObject(image_id);
        // Si el ojeto es del tipo IMG
        if(obj.nodeName == "IMG"){
            obj.src = src_value;
        }
    }
    
    /**
    * Modifica el valor del campo especificado
    *
    * @access public
    * @param  String  field_id   Id del objeto
    * @param  String  val        String con el nuevo valor
    * @return void
    */
    function setFieldValue(field_id, val){
        this.getObject(field_id).value = val;
    }
    
    //
    // Getters
    //
    
    
    /**
    * Retorna una referencia al objeto especificado.
    *
    *
    * @param  string  field_id String con el id del objeto
    * @return Node
    */
    function getObject(field_id){
        return document.getElementById(field_id);
    }

    /**
    * Obtiene el estado de visibilidad de un objeto de formulario
    *
    * @access  public
    * @param   String   object_id  Id del objeto
    * @return  bool
    *
    * @version 1.0 (23/11/2006 17:31)
    * @since   1.2
    */
    function getObjectVisibility(object_id){
        // Se obtiene una referencia al objeto
        obj = this.getObject(object_id);
        // Verifica el estado actual
        if(obj.style.display != "none"){
            // Retorna 'visible'
            return true;
        }
        // Retorna 'invisible'
        return false;
    }


    /**
    * Retorna el valor actual para el campo especificado. 
    *
    *
    * @param  string  field_id  String con el id de campo
    * @return String
    */
    function getFieldValue(field_id){
        return this.getObject(field_id).value;
    }
}






/**
* WindowsManager
* Facilita la manipulación de ventanas
*
*
* METODOS PUBLICOS:
* -----------------
* + openWindow(String url, String n, WindowFeatures featObj) : void
* + openModalWindow(String url, String n, WindowFeatures featObj) : void
* + openModelessWindow(String url,String n, WindowFeatures featObj) : void
* + closeWindow(String n) : void
*
*
*
*
* @author  Lucas Fonzalida <contacto@lucasfonzalida.com.ar>
* @version 1.0
*/
function WindowsManager(){

    // Propiedades
    this.windows                       = Array();

    // Métodos
    this.pfinder                       = new PositionFinder();

    this.openWindow                    = openWindow;
    this.openModalWindow               = openModalWindow;
    this.openModelessWindow            = openModelessWindow;
    this.closeWindow                   = closeWindow;
    this.registerWindow                = registerWindow;
    this.unregisterWindow              = unregisterWindow;
    this.getRegisteredWindow           = getRegisteredWindow;
    this.createFeatures                = createFeatures;
    this.createModalFeatures           = createModalFeatures;
    this.closeAllWindows               = closeAllWindows;
    this.isClosed                      = isClosed;

    /**
    * Para abrir una nueva ventana común
    *
    * @access public
    * @param  String          url      Url
    * @param  String          n        Nombre
    * @param  WindowFeatures  featObj  Objeto WindowFeatures
    * @return void
    */
    function openWindow(url,n,featObj){
        // Obtiene la ventana registrada utilizando el nombre
        var openedWindow = this.getRegisteredWindow(n);
        // Si la ventana no está instanciada
        if(openedWindow == null){
            // Crea el string con los features para ventanas de IE6+ & Gecko
            var sFeat = this.createFeatures(featObj);
            // Abre una nueva ventana y conserva la referencia
            var openedWindow = window.open(url,n,sFeat);
            // Almacena una referencia a la nueva ventana creada
            this.registerWindow(openedWindow);   
        }
        // Focaliza la ventana
        openedWindow.focus();
    }
    
    /**
    * Abre una nueva ventana modal de IE6+ o Gecko (según el contexto).
    *
    * @access public
    * @param  String          url      Url
    * @param  String          n        Nombre de la ventana (no se usa)
    * @param  WindowFeatures  featObj  Objeto WindowFeatures
    * @return void
    */
    function openModalWindow(url,n,featObj){
        // Crea el string con los features para ventanas modal según el navegador actual
        var sFeat = this.createModalFeatures(featObj);
        // IE6+ 
        if(window.showModalDialog){
            // Abre una nueva ventana modal al modo IE6+
            window.showModalDialog(url,self,sFeat);
        }else{
            // Abre una nueva ventana modal al modo Gecko
            newWindow = window.open(url,n,sFeat);
            // Crea una variable similar a la de IE conteniendo una referencia al parent
            newWindow.dialogArguments = self;
        }
    }

    /**
    * Abre una nueva ventana Modeless de IE6+ o Gecko (según el contexto).
    *
    * @access public
    * @param  String          url      Url
    * @param  String          n        Nombre de la ventana
    * @param  WindowFeatures  featObj  Objeto WindowFeatures
    * @return void
    */
    function openModelessWindow(url,n,feat){
        // no implementado
    }  

    /**
    * Crea un string con el set de features que requieren las ventanas modal 
    * de IE6+ y Gecko.
    *
    *
    * @access private
    * @param  WindowFeatures  featObj  Objeto WindowFeatures con los parámetros
    *                                  para crear el string.
    * @return String
    */
    function createModalFeatures(featObj){
        // Define sFeat
        var sFeat;
        // Si es IE6+ o compatible
        if(window.showModalDialog){
            // Crea un string con los features que aceptan los modal dialogs de IE6+
            sFeat = "dialogLeft:" + featObj.posX + ";dialogTop:" + featObj.posY + 
                    ";dialogHeight:" + (parseInt(featObj.height) + 46) + "px;dialogWidth:" + (parseInt(featObj.width) + 8) + 
                    "px;center:" + featObj.center + ";edge:" + featObj.edge + ";scroll:" + featObj.scrollbars +
                    ";status:" + featObj.status + ";help:" + featObj.help + ";resizable:" + featObj.resizable;
        }else{
            // Crea un string de Features común a IE6+ & Gecko
            sFeat = this.createFeatures(featObj);
            // Se le adiciona el indicador de modal para Gecko
            sFeat += ",modal=1";
        }
        // Retorna
        return sFeat;
    }

    /**
    * Crea un string con el set de features que requieren las ventanas
    * de IE6+ y Gecko.
    *
    * @access private
    * @param  WindowFeatures  featObj  Objeto WindowFeatures con los parámetros
    *                                  para crear el string.
    *
    * @access private
    * @return String 
    */
    function createFeatures(featObj){
        // Features para ventanas al modo IE+ & Gecko
        return "left=" + featObj.posX + ",top=" + featObj.posY +
                ",height=" + featObj.height + "px,width=" + featObj.width +
                "px,menubar=" + featObj.menubar + ",scrollbars=" + featObj.scrollbars +
                ",status=" + featObj.status + ",resizable=" + featObj.resizable +
                ",titlebar=" + featObj.titlebar;
    }
    
    /**
    * Para cerrar una ventana
    *
    * @access public
    * @param  String  n    Nombre
    * @return void
    */
    function closeWindow(n){

    }    

    /**
    * Almacena una referencia a una ventana satélite o hija
    *
    * @access public
    * @param  Window  childW  Objeto window
    * @return void
    */
    function registerWindow(win){
        // Almacena una referencia al objeto Window
        return this.windows.push(win);
    }
    
    /**
    * Elimina la referencia de la ventana satélite indicada
    *
    * @access public
    * @param  Window  childW  Objeto window
    * @return void
    */
    function unregisterWindow(win){

    }    

    /**
    * Retorna una referencia a la ventana indicada o null si la ventana
    * no esta registrada o fue cerrada.
    *
    * @access public
    * @param  String   n  Nombre de la ventana
    * @return Window
    */
    function getRegisteredWindow(n){
        // Recorre todas las ventanas
        for(i=0; i < this.windows.length; i++){
            // Verifica si la ventana esta cerrada
            if(this.windows[i].closed){
                // Elimina la referencia
                this.windows.splice(i,1);
            }else{
                // Verifica si coincide el nombre de la ventana
                if(this.windows[i].name == n){
                    // Retorna
                    return this.windows[i];
                }
            }
        }
        // Retorna
        return null;
    }

    /**
    * Cierra todas las ventanas registradas
    *
    * @access public
    * @return void
    */
    function closeAllWindows(){    
        // Recorre todas las ventana satélites
        for(i=0; i < this.windows.length; i++){
            // Verifica si la ventana esta cerrada
            if(!this.isClosed(this.windows[i])){
                // Cierra la ventana
                this.windows[i].close();
            }
        }
    }
    
    /**
    * Verifica si la ventana está cerrada
    * Utiliza una técnica extraida de experts-exchange.com
    *
    *
    * @see    http://www.experts-exchange.com/Web/Web_Languages/JavaScript/Q_20926025.html
    * @access public
    * @param  Window  win Ventana
    * @return boolean
    */
    function isClosed(win){
        // Verifica si la ventana esta fuera de cuadro
        // Técnica extraida de 
        if(win.screenTop > 9000){
            return true;
        }
        return false;
    }
}

/**
* WindowFeatures
* Objeto contenedor de datos de configuración (features) para ventanas
* Proporciona una forma universal para configurar las propiedades
* de las ventanas popup y modal
*
* @param  String  params  Parámetros de inicialización de las propiedades
* @access public
* @version 1.0
*/
function WindowFeatures(str){    
    
    /**
    * Se inicializan atributos utilizando el string
    * pasado como parámetro al instanciar el objeto.
    * Si no se especifica algún atributo, se inicializa utilizando un
    * valor por default.
    */
    this.posX       = finder("posX", str) ? finder("posX", str) : 0;               // IE6+ & Gecko 1.7+
    this.posY       = finder("posY", str) ? finder("posY", str) : 0;               // IE6+ & Gecko 1.7+
    this.center     = finder("center", str) ? finder("center", str) : 0;           // IE6+
    this.width      = finder("width", str) ? finder("width", str) : 0;             // IE6+ & Gecko 1.7+
    this.height     = finder("height", str) ? finder("height", str) : 100;         // IE6+ & Gecko 1.7+
    this.resizable  = finder("resizable", str) ? finder("resizable", str) : 0;     // IE6+ & Gecko 1.7+
    this.scrollbars = finder("scrollbars", str) ? finder("scrollbars", str) : 0;   // IE6+ & Gecko 1.7+
    this.status     = finder("status", str) ? finder("status", str) : 0;           // IE6+ & Gecko 1.7+
    this.titlebar   = finder("titlebar", str) ? finder("titlebar", str) : 0;       // IE6+ & Gecko 1.7+
    this.menubar    = finder("menubar", str) ? finder("menubar", str) : 0;         // IE6+ & Gecko 1.7+
    this.edge       = finder("edge", str) ? finder("edge", str) : "raised";        // IE6+
    this.help       = finder("help", str) ? finder("help", str) : 0;               // IE6+ & Gecko 1.7+
    
    /**
    *
    *
    *
    *
    *
    */
    function finder(p, str){
        // Crea una nueva expresion regular
        var re = new RegExp("(\\,|^)" + p + "=(\\w+)(\\,|$)");
        // Si hay coincidencias
        if(str.search(re) > -1){
            // Obtiene el valor
            var result = str.match(re);
            // Debug
            // alert(p + "=" + result[2]);
            // Retorna
            return result[2];
        }else{
            return false;
        }
    }
}


//
//
// FUNCIONES DE INICIALIZACION GENERALES
// Proporcionan una implementacion nula para que
// no se produzcan errores en las llamadas 'onload()'
// Las funciones de inicialización específicas, deben
// definirse en los archivos '{module}.css'
//
//


/**
* Funcion de inicialización
* Instancia e inicializa el objeto wrapper correspondiente.
* Esta fuunción debe ser llamada por el evento "onload" del formulario
*
* @author "Lucas Fonzalida" <contacto@lucasfonzalida.com.ar>
*/
function init(){
    // Definir en el JS específico del módulo
}
        
/**
* Funcion de destrucción
* Ejecuta rutinas de destruccion en el view wrapper
* Esta fuunción debe ser llamada por el evento "onunload" del formulario
*
* @author "Lucas Fonzalida" <contacto@lucasfonzalida.com.ar>
*/
function destroy(){
    // Definir en el JS específico del módulo
}