
//D:\Work\Proyectos\OCNPOU\applications\ocnpou\web\js>perl d:\Software\JSDoc-1.10.1\jsdoc.pl   kc.js

/**
 * @fileoverview Este fichero contiene un conjunto de utilidades más o menos
* genéricas, utilizadas en diferentes proyectos realizados por <strong>Knowledge Control Solutions</strong>.
 * <br>La documentación ha sido generada mediante la herramienta  {@link http://sourceforge.net/projects/jsdoc JSDoc}.
 *
 * @author Fernando Martínez - <i>Fernando.Martinez@kcl.es</i>
 * @version 1.0
 */

if ( typeof (es)=="undefined") es = new Object();
if ( typeof(es.kcs)=="undefined") es.kcs = new Object();


/**
 * Clase de utilidades
 * @class Clase de utilidades.
 * Aglutina todo un conjunto de métodos estáticos que se utilizan en caso de necesidad
 * sin necesidad de instanciar ningún objeto (aunque es igualmente posible instanciarlo).
* Para su correcto funcionamiento es necesario incluir la libreria prototype.js
 * @constructor
 */
es.kcs.Util=function(){
  this.version="1.0";
}

//es.kcs.Util = new Object();



/**
 * Obtiene la fecha actual en formato dd/mm/yyyy
 * <br>Ejemplo de llamada: <i>es.kcs.Util.getCurrentDate(); </i>
 *  @param {String} separator Carácter separador. Por defecto se utiliza '/'
 * @returns Una cadena representando la fecha actual. Por ejemplo : 10/12/2009
 * @type String
 */
es.kcs.Util.getCurrentDate = function (separator) {
    var sep="/";
    if (separator) sep=separator;
    var D = new Date();
    var str="";
    if (D.getDate()<10) str+="0"+D.getDate();
    else str+=D.getDate();
    if (D.getMonth()<9) str+=sep+"0"+(D.getMonth()+1);
    else str+=sep+(D.getMonth()+1);
    str+=sep+D.getFullYear();
    return str;
}
/**
 * @ignore
 * Nos permite trabajar tanto en modo estatico como en modo instancia
 */
es.kcs.Util.prototype.getCurrentDate = es.kcs.Util.getCurrentDate;




/**
 * Obtiene la hora actual en formato hh:mm:ss
 * <br>Ejemplo de llamada: <i>es.kcs.Util.getCurrentTime(); </i>
 *  @param {String} separator Carácter separador. Por defecto se utiliza ':'
 * @returns Una cadena representando la hora actual. Por ejemplo : 10:12:09
 * @type String
 */
es.kcs.Util.getCurrentTime = function (separator) {
    var sep=':';
    if (separator) sep=separator;
    var D = new Date();
    var str="";
    if (D.getHours()<10) str+="0"+D.getHours();
    else str+=D.getHours();
    if (D.getMinutes()<10) str+=sep+"0"+D.getMinutes();
    else str+=sep+D.getMinutes();
    if (D.getSeconds()<10) str+=sep+"0"+D.getSeconds();
    else str+=sep+D.getSeconds();
    return str;
}
/**
 * @ignore
 * Nos permite trabajar tanto en modo estatico como en modo instancia
 */
es.kcs.Util.prototype.getCurrentTime = es.kcs.Util.getCurrentTime;




/**
 * Función inversa a las dos anteriores: obtiene un objeto Date a partir
 * de un String conteniendo una fecha (yyyy/MM/dd) y/o una hora (hh:mm:ss).
 * <br>Ejemplo de llamada: <i>es.kcs.Util.string2Date('2007/06/18 07:30:00'); </i>
 * @param {String} cadena String conteniendo una fecha y/o hora
 * @returns Un objeto Date a partir de la entrada
 * @type Date
 */
es.kcs.Util.string2DateYMD = function (f) {
    var D = new Date();
	var pos = f.indexOf('/');
	if (pos!=-1) {
        D.setFullYear(f.substr(pos-4,4));
		D.setMonth   (f.substr(pos+1,2)-1);
		D.setDate    (f.substr(pos+4,2));
    }
	pos = f.indexOf(':');
	if (pos!=-1) {
        D.setHours   (f.substr(pos-2,2));
		D.setMinutes (f.substr(pos+1,2));
		D.setSeconds (f.substr(pos+4,2));
    }
	return D;
}
/**
 * @ignore
 * Nos permite trabajar tanto en modo estatico como en modo instancia
 */
es.kcs.Util.prototype.string2DateYMD = es.kcs.Util.string2DateYMD;


/**
 * Función muy parecida a la anterior: obtiene un objeto Date a partir
 * de un String conteniendo una fecha (dd/MM/yyyy) y/o una hora (hh:mm:ss).
 * <br>Ejemplo de llamada: <i>es.kcs.Util.string2Date('18/06/2007 07:30:00'); </i>
 * @param {String} cadena String conteniendo una fecha y/o hora
 * @returns Un objeto Date a partir de la entrada
 * @type Date
 */
es.kcs.Util.string2DateDMY = function (f) {
    var D = new Date();
	var pos = f.indexOf('/');
	if (pos!=-1) {
        D.setDate    (f.substr(pos-2,2));
		D.setMonth   (f.substr(pos+1,2)-1);
		D.setFullYear(f.substr(pos+4,4));
    }
	pos = f.indexOf(':');
	if (pos!=-1) {
        D.setHours   (f.substr(pos-2,2));
		D.setMinutes (f.substr(pos+1,2));
		D.setSeconds (f.substr(pos+4,2));
    }
	return D;
}
/**
 * @ignore
 * Nos permite trabajar tanto en modo estatico como en modo instancia
 */
es.kcs.Util.prototype.string2DateDMY = es.kcs.Util.string2DateDMY;





/**
 * Valida una fecha.
* <br>Devuelve <strong>true </strong> si la fecha pasada como argumento corresponde a una fecha válida
 * <br>Ejemplo de llamada: <i> es.kcs.Util.valiDate('10-10-2003','-'); </i>
 * @param {String} fecha Fecha a validar en formato dd/mm/yyyy (o dd/mm/yy)
*  @param {String} separador Carácter separador (opcional). Por defecto se utiliza '/'
*  @param {boolean} extenderAnyo (opcional). Por defecto vale <strong>false</strong>.
*  Si vale <strong>true</strong>, entonces se aceptan fechas que especifiquen el año con 2 dígitos
* en lugar de 4. No se recomienda utilizar esta caracteristica, puesto que lo único que hace
* es sumarle 1900 al año.

 * @returns <strong> true </strong> o <strong>false</strong>
 * @type boolean
 */
es.kcs.Util.valiDate= function(fecha,separador,extenderAnyo){
   if (!separador)
       separador="/";

   // Si extenderAnyo==true => se aceptan años de 2 digitos
   if (!extenderAnyo)
      extenderAnyo=false;


    var a, mes, dia, anyo, febrero;

    return validar(fecha,separador);

    function anyoBisiesto(anyo)
    {
        if (anyo < 100)
            var fin = anyo + 1900;
        else
            var fin = anyo ;

        /*
        * primera condicion: si el resto de dividir el a?o entre 4 no es cero > el a?o no es bisiesto
        * es decir, obtenemos a?o modulo 4, teniendo que cumplirse anyo mod(4)=0 para bisiesto
        */
        if (fin % 4 != 0)
            return false;
        else
        {
            if (fin % 100 == 0)
            {
                /**
                * si el a?o es divisible por 4 y por 100 y divisible por 400 > es bisiesto
                */
                if (fin % 400 == 0)
                {
                    return true;
                }
                /**
                * si es divisible por 4 y por 100 pero no lo es por 400 > no es bisiesto
                */
                else
                {
                    return false;
                }
            }
            /*
            * si es divisible por 4 y no es divisible por 100 > el a\uFFFDo es bisiesto
            */
            else
            {
                return true;
            }
        }
    }

    /*
    * funcion principal de validacion de la fecha
    * argumento fecha > cadena de texto de la fecha introducida por el usuario
    */
    function validar( )
    {
       /*
       * obtenemos la fecha introducida y la separamos en dia, mes y a?o
       */
       a=fecha;
       if (!a)
         return false;
       dia=a.split(separador)[0];
       mes=a.split(separador)[1];
       anyo=a.split(separador)[2];
       if (!extenderAnyo && (anyo==null || anyo.length != 4))
          return false;
    if( (isNaN(dia)==true) || (isNaN(mes)==true) || (isNaN(anyo)==true) )
    {
     return false;
       }
       if(anyoBisiesto(anyo))
           febrero=29;
       else
           febrero=28;
       /*
       * si el mes introducido es negativo, 0 o mayor que 12 > alertamos y detenemos ejecucion
       */
       if ((mes<1) || (mes>12))
       {
           return false;
       }
       /*
       * si el mes introducido es febrero y el dia es mayor que el correspondiente
       * al a?o introducido > alertamos y detenemos ejecucion
       */
       if ((mes==2) && ((dia<1) || (dia>febrero)))
       {
           return false;
       }
       /*
       * si el mes introducido es de 31 dias y el dia introducido es mayor de 31 > alertamos y detenemos ejecucion
       */
       if (((mes==1) || (mes==3) || (mes==5) || (mes==7) || (mes==8) || (mes==10) || (mes==12)) && ((dia<1) || (dia>31)))
       {
                return false;
       }
       /*
       * si el mes introducido es de 30 dias y el dia introducido es mayor de 301 > alertamos y detenemos ejecucion
       */
       if (((mes==4) || (mes==6) || (mes==9) || (mes==11)) && ((dia<1) || (dia>30)))
       {
           return false;
       }
       return true;
    }


}

/**
 * @ignore
 * Nos permite trabajar tanto en modo estatico como en modo instancia
 */
es.kcs.Util.prototype.valiDate = es.kcs.Util.valiDate;

/**
 * Habilita la ventana de depuración.
* <br>Después de habilitar el modo de depuración, la ventana de depuración mostrará el contenido de
* las llamadas al método {@link es.kcs.Util#debug}
* @see es.kcs.Util#debug
* @see es.kcs.Util#disableDebug
 */

es.kcs.Util.enableDebug=function (){
   es.kcs.Util.debugIsEnabled=true;
}
/**
 * @ignore
 * Nos permite trabajar tanto en modo estatico como en modo instancia
 */
es.kcs.Util.prototype.enableDebug = es.kcs.Util.enableDebug;

/**
 * Inhabilita la ventana de depuración.
* <br>Después de inhabilitar el modo de depuración, la ventana de depuración dejará de mostrar
* cualquier contenido de las llamadas al método {@link es.kcs.Util#debug}
* @see es.kcs.Util#debug
* @see es.kcs.Util#enableDebug
 */


es.kcs.Util.disableDebug=function (){
   es.kcs.Util.debugIsEnabled=false;
}

/**
 * @ignore
 * Nos permite trabajar tanto en modo estatico como en modo instancia
 */
es.kcs.Util.prototype.disableDebug = es.kcs.Util.disableDebug;


/**
 * Muestra un mensaje en la pantalla de depuración.
* <br>Después de habilitar el modo de depuración, la ventana de depuración mostrará
* cualquier mensaje enviado como parámetro a este método.
* @param {String} msg Mensaje a mostrar en la ventana de depuración
* @param {String} pre (opcional) Tag HTML de apertura y cierre de cada mensaje enviado
* @see es.kcs.Util#enableDebug
* @see es.kcs.Util#disableDebug
 */

es.kcs.Util.debug=function(msg,pre){
var tagopen="";
var tagclose="";

if (pre){
     tagopen="<" + pre +">";
     tagclose="</" + pre + ">";
}
var date=new Date();
var prefix="[DEBUG " + date.getHours() + ":" + date.getMinutes()+":"+date.getSeconds() + " ] ";
msg=prefix + tagopen+msg+"\n"+tagclose+"<br>";

if (es.kcs.Util.debugIsEnabled  && es.kcs.Util.debugIsEnabled ==true){

    try{
         es.kcs.Util.debugWindow.document.write(msg);
         es.kcs.Util.debugWindow.scrollTo(0,9999999);
    }
    catch (e){
      /*
          var r = '';
          for (var p in e)
              r += p + ': ' + e[p] + '\n';
          alert(r);
      */
        es.kcs.Util.debugWindow=window.open('','KC_DEBUG_WINDOW','scrollbars=yes,width=550,height=450');

        es.kcs.Util.debugWindow.document.write(msg);
        es.kcs.Util.debugWindow.scrollTo(0,9999999);
    }

}

}

/**
 * @ignore
 * Nos permite trabajar tanto en modo estatico como en modo instancia
 */
es.kcs.Util.prototype.debug = es.kcs.Util.debug;

/**
 * Muestra un mensaje en la pantalla de depuración.
* <br>Llama a {@link es.kcs.Util#debug}
* @param {String} msg Mensaje a mostrar en la ventana de depuración
* @param {String} pre (opcional) Tag HTML de apertura y cierre de cada mensaje enviado
* @see es.kcs.Util#debug
* @see es.kcs.Util#enableDebug
* @see es.kcs.Util#disableDebug
 */

debug=es.kcs.Util.debug


/**
 * Permite añadir un gestor de evento a un objeto.
*
* @param {Object} obj Objeto al que se quiere añadir el gestor de evento
* @param {String} evento Evento que se quiere gestionar (scroll, click, change, etc.)
* @param {Function} handler Función de manejo del evento

* @see es.kcs.Util#detachEvent
 */

es.kcs.Util.attachEvent = function (obj,evento,handler){

	if (obj.attachEvent)
	    obj.attachEvent('on'+evento,handler);
	else
		obj.addEventListener(evento,handler,false);
}

/**
 * @ignore
 * Nos permite trabajar tanto en modo estatico como en modo instancia
 */
es.kcs.Util.prototype.attachEvent = es.kcs.Util.attachEvent;


/**
 * Permite eliminar un gestor de evento a un objeto.
*
* @param {Object} obj Objeto del que se quiere eliminar el gestor de evento
* @param {String} evento Evento  (scroll, click, change, etc.)
* @param {Function} handler Función de manejo del evento

* @see es.kcs.Util#attachEvent
 */

es.kcs.Util.detachEvent = function (obj,evento,handler){
	if (obj.detachEvent)
	    obj.detachEvent('on'+evento,handler);
	else
		obj.removeEventListener(evento,handler,false);

}

/**
 * @ignore
 * Nos permite trabajar tanto en modo estatico como en modo instancia
 */
es.kcs.Util.prototype.detachEvent = es.kcs.Util.detachEvent;





/**
 * Obtiene el primer elemento DIV en la lista de ancestors del elemento.
*
* @param {HTMLElement} el Elemento para el que se quiere obtener su DIV padre

* @see es.kcs.Util#detachEvent
 */

es.kcs.Util.getParentDiv = function (el){

	var a=$(el).ancestors();

	for (var i=0;i<a.length;i++){
		if (a[i].tagName.toLowerCase()=='div'){
			alert("El padre de la criatura es " + a[i].id);
			return a[i];
		}
	}
	return null;
}

/**
 * @ignore
 * Nos permite trabajar tanto en modo estatico como en modo instancia
 */
es.kcs.Util.prototype.getParentDiv = es.kcs.Util.getParentDiv;





/*
*  //====================================================================================
 * // BLOQUEOS
*  //====================================================================================
*/


/*
* //=================================================================================================
* Bloquea todos los formularios de un documento, incluyendo los objetos BUTTON
* //=================================================================================================
*/


/**
 * Bloquea todos los formularios de un documento
* <br>La llamada a este método motivará la inhabilitación de todos los formularios
* presentes en el documento. Para ello, el método deshabilita todos los objetos <i>INPUT</i>
* y todos los objetos <i>BUTTON</i>
* @see es.kcs.Util#lockAll
* @see es.kcs.Util#unlockAll
 * @see es.kcs.Util#unlockAllForms
 */

es.kcs.Util.lockAllForms=function(){

/*
  for (var i=0;i<document.forms.length;i++){
    //alert(document.forms[i].id + ", " + document.forms[i].action);
        if (typeof(document.forms[i].id)=="undefined" || document.forms[i].id.length==0){
          document.forms[i].id="ID-" + Math.random();
        }
    Form.disable(document.forms[i].id);
  }
*/

  var inputs = document.getElementsByTagName("INPUT");
  for (var i=0;i<inputs.length;i++) inputs[i].disabled=true;

  var buttons = document.getElementsByTagName("button");
  for (var i=0;i<buttons.length;i++) buttons[i].disabled=true;
}

/**
 * Esta función ha sido deprecada. En su lugar utilice {@link es.kcs.Util#lockAllForms}.
 * @see es.kcs.Util#lockAllForms
* @see es.kcs.Util#lockAll
* @see es.kcs.Util#unlockAll


* @deprecated
*/


function lockAllForms(){
  es.kcs.Util.lockAllForms();
}
/**
 * @ignore
 * Nos permite trabajar tanto en modo estatico como en modo instancia
 */
es.kcs.Util.prototype.lockAllForms=es.kcs.Util.lockAllForms;

/**
 * Desbloquea todos los formularios de un documento
* <br>La llamada a este método activará todos los formularios
* presentes en el documento que previamente fueron desactivados mediante la llamada a {@link es.kcs.Util#lockAllForms}. * @see es.kcs.Util#lockAll
* @see es.kcs.Util#unlockAll
* @see es.kcs.Util#lockAll
* @see es.kcs.Util@lockAllForms
 */


es.kcs.Util.unlockAllForms = function (){
/*
  for (var i=0;i<document.forms.length;i++){
        if (typeof(document.forms[i].id)=="undefined" || document.forms[i].id.length==0){
          document.forms[i].id="ID-" + Math.random();
        }

    Form.enable(document.forms[i].id);
  }
  for (var i=0;i<document.getElementsByTagName("button").length;i++)
  	document.getElementsByTagName("button")[i].disabled='';
  	*/
  var inputs = document.getElementsByTagName("INPUT");
  for (var i=0;i<inputs.length;i++) inputs[i].disabled=false;

  var buttons = document.getElementsByTagName("button");
  for (var i=0;i<buttons.length;i++) buttons[i].disabled=false;
}

/**
 * @ignore
 * Nos permite trabajar tanto en modo estatico como en modo instancia
 */
es.kcs.Util.prototype.unlockAllForms = es.kcs.Util.unlockAllForms;


/**
 * Esta función ha sido deprecada. En su lugar utilice {@link es.kcs.Util#unlockAllForms}.
 * @see es.kcs.Util#unlockAllForms
* @see es.kcs.Util#lockAll
* @see es.kcs.Util#unlockAll


* @deprecated
*/


function unlockAllForms(){
  return es.kcs.Util.unlockAllForms();
}




/**
 * Bloquea todos los links de un documento
* <br>La llamada a este método motivará la inhabilitación de todos los enlaces
* presentes en el documento. Para ello, el método deshabilita todos los objetos <i>A</i>
*
* @see es.kcs.Util#lockAll
* @see es.kcs.Util#unlockAll
 * @see es.kcs.Util#unlockAllLinks
 */


es.kcs.Util.lockAllLinks=function (){

	es.kcs.Util.DisableEnableLinks(true);
}
/**
 * @ignore
 * Nos permite trabajar tanto en modo estatico como en modo instancia
 */

es.kcs.Util.prototype.lockAllLinks=es.kcs.Util.lockAllLinks;

/**
 * Esta función ha sido deprecada. En su lugar utilice {@link es.kcs.Util#unlockAllLinks}.
 * @see es.kcs.Util#unlockAllLinks
* @see es.kcs.Util#lockAll
* @see es.kcs.Util#unlockAll


* @deprecated
*/


function lockAllLinks(){
	es.kcs.Util.lockAllLinks();
}

/**
 * Desbloquea todos los links de un documento
* <br>La llamada a este método motivará la activación de todos los enlaces
* presentes en el documento previamente deshabilitados mediante la llamada a {@link es.kcs.Util#lockAllLinks}.
* Es muy importante no llamar a este método si previamente no se llamó a {@link es.kcs.Util#lockAllLinks} o pueden
* experimentarse comportamientos inesperados.
*
* @see es.kcs.Util#lockAll
* @see es.kcs.Util#unlockAll
 * @see es.kcs.Util#lockAllLinks
 */

es.kcs.Util.unlockAllLinks = function(){
	es.kcs.Util.DisableEnableLinks(false);
}

/**
 * @ignore
 * Nos permite trabajar tanto en modo estatico como en modo instancia
 */

es.kcs.Util.prototype.unlockAllLinks=es.kcs.Util.unlockAllLinks;

/**
 * Esta función ha sido deprecada. En su lugar utilice {@link es.kcs.Util#unlockAllLinks}.
 * @see es.kcs.Util#unlockAllLinks
* @see es.kcs.Util#lockAll
* @see es.kcs.Util#unlockAll


* @deprecated
*/

function unlockAllLinks(){
	es.kcs.Util.unlockAllLinks();
}


/**
 * Bloquea todos los menús de la página. Necesita la librería de menús {@link kc_menu.js}
* pendiente de documentar
 * @see es.kcs.Util#lockAll
* @see es.kcs.Util#unlockAll
* @see es.kcs.Util#unlockAllMenus
*/

es.kcs.Util.lockAllMenus = function(){
  disableAllMenus();
}
/**
 * @ignore
 * Nos permite trabajar tanto en modo estatico como en modo instancia
 */

es.kcs.Util.prototype.lockAllMenus= es.kcs.Util.lockAllMenus;

/**
 * Bloquea todos los menús de la página.
*  Esta función ha sido deprecada.
*  <br>Este método no debería estar en esta librería. De momento se mantiene por compatibilidad
*  con versiones anteriores, aunque se está en espera de ubicarla en otra librería.


* @deprecated
*/

function lockAllMenus(){
  es.kcs.Util.lockAllMenus();
}

/**
 * Desbloquea todos los menús de la página. Necesita la librería de menús {@link kc_menu.js}
* Pendiente de documentar.
 * @see es.kcs.Util#lockAll
* @see es.kcs.Util#unlockAll
* @see es.kcs.Util#lockAllMenus
*/

es.kcs.Util.unlockAllMenus=function(){
 enableAllMenus();
}
/**
 * @ignore
 * Nos permite trabajar tanto en modo estatico como en modo instancia
 */

es.kcs.Util.prototype.unlockAllMenus=es.kcs.Util.unlockAllMenus;

/**
 * Desbloquea todos los menús de la página.
*  Esta función ha sido deprecada.
*  <br>Este método no debería estar en esta librería. De momento se mantiene por compatibilidad
*  con versiones anteriores, aunque se está en espera de ubicarla en otra librería.


* @deprecated
*/

function unlockAllMenus(){
 es.kcs.Util.unlockAllMenus();
}

/**
 * Bloquea todos los objetos de la página. <br>
* Bloquea links, formularios y menús. Necesita la librería de menús {@link kc_menu.js}
* Pendiente de documentar.
* @see es.kcs.Util#unlockAll
 * @see es.kcs.Util#lockAllForms
* @see es.kcs.Util#lockAllLinks
* @see es.kcs.Util#lockAllMenus
*/

es.kcs.Util.lockAll = function () {
	es.kcs.Util.lockAllForms();
        es.kcs.Util.lockAllLinks();
        es.kcs.Util.lockAllMenus();
}

/**
 * @ignore
 * Nos permite trabajar tanto en modo estatico como en modo instancia
 */

es.kcs.Util.prototype.lockAll = es.kcs.Util.lockAll ;
/**
 * Bloquea todos los objetos  de la página.
*  Esta función ha sido deprecada. En su lugar utilice {@link es.kcs.Util#lockAll}.
* @see es.kcs.Util#lockAll


* @deprecated
*/

function lockAll(){
	es.kcs.Util.lockAll();
}
/**
 * Desbloquea todos los objetos de la página. <br>
* Desbloquea links, formularios y menús previamente bloqueados mediante {@link es.kcs.Util#lockAll}. Necesita la librería de menús {@link kc_menu.js}
* Pendiente de documentar.
* @see es.kcs.Util#lockAll
 * @see es.kcs.Util#lockAllForms
* @see es.kcs.Util#lockAllLinks
* @see es.kcs.Util#lockAllMenus
*/

es.kcs.Util.unlockAll = function (){

	unlockAllForms();
        unlockAllLinks();
        unlockAllMenus();
}

/**
 * @ignore
 * Nos permite trabajar tanto en modo estatico como en modo instancia
 */


es.kcs.Util.prototype.unlockAll = es.kcs.Util.unlockAll;

/**
 * Desbloquea todos los objetos  de la página.
*  Esta función ha sido deprecada. En su lugar utilice {@link es.kcs.Util#unlockAll}.
* @see es.kcs.Util#unlockAll


* @deprecated
*/

function unlockAll(){
  es.kcs.Util.unlockAll();
}







/**
* Utilidades para la captura de eventos de teclado.
* La captura de eventos de teclado se aplica a todo el objeto document.
* Se pueden recoger los codigos de las teclas pulsadas mediante el acceso a las variables:<br>
* {@link es.kcs.Util#charCode}: contiene la tecla pulsada actualmente<br>
* {@link es.kcs.Util#lastCharCode}: contiene la ultima tecla que se pulsó.
* El parámetro handler es opcional. Únicamente se ha de especificar cuando necesitemos
* recuperar el evento, por ejemplo para anular el refresco de pantalla en algunas condiciones.
* <br> A continuacion se muestra un ejemplo para evitar que el usuario pueda refrescar la pantalla
* pulsando la tecla F5 o pulsando la tecla backspace, por ejemplo:<br>
*
* <br><br>// Llamada a la funcion de captura de teclado<br><br>
* <pre>
* <b>es.kcs.Util.captureKeys</b>(kcKeyManager);
* <br><br>//Definicion del manejador
* <b>function </b>kcKeyManager(evt){

        var elem = (evt.target) ? evt.target : evt.srcElement;

        if (evt.keyCode==116 || (evt.keyCode==8 ) && ( elem.tagName=='BODY' || elem.tagName=='HTML')) {

// Si la tecla pulsada es F5 o BACKSPACE y en este ultimo caso, si ademas el evento
// se aplica al documento y no a un elemento de formulario por ejemplo, entonces hay que cancelar
// el evento.
      if (evt.preventDefault)
         evt.preventDefault();
       else {
            evt.keyCode=0;
            return false;
       }
</pre>
*
* @type void
* @param {Function} handler (opcional) Manejador de captura del evento.
* @see es.kcs.Util#charCode
* @see es.kcs.Util#lastCharCode
*/


es.kcs.Util.captureKeys=function (handler){
   if (handler)
      es.kcs.Util.handlerEventCaptureKeys=handler;
   if (document.body.addEventListener){
      document.addEventListener('keydown',kc_aux_captura,true);
      document.addEventListener('keyup',kc_aux_libera,true);
      if (frames['top'].document!=document) {
            frames['top'].document.addEventListener('keydown',kc_aux_captura,true);
            frames['top'].document.addEventListener('keyup',kc_aux_libera,true);
      }
   } else {
      document.attachEvent('onkeydown',kc_aux_captura);
      document.attachEvent('onkeyup',kc_aux_libera);
      if (frames['top'].document!=document) {
            frames['top'].document.attachEvent('onkeydown',kc_aux_captura);
            frames['top'].document.attachEvent('onkeyup',kc_aux_libera);
      }
   }
}

/**
 * Variable que nos indica el valor (código ASCII) de la tecla que actualmente está pulsada.
* <br>Previamente es necesario haber llamado a {@link es.kcs.Util#captureKeys}
* @type int
* @see es.kcs.Util#captureKeys
* @see es.kcs.Util#lastCharCode
 */

es.kcs.Util.charCode=null;

/**
 * Variable que nos indica el valor (código ASCII) de la última tecla que se pulsó.
* <br>Previamente es necesario haber llamado a {@link es.kcs.Util#captureKeys}
* @type int
* @see es.kcs.Util#captureKeys
* @see es.kcs.Util#charCode

 */

es.kcs.Util.lastCharCode=null;


/**
 * @ignore
 * Nos permite trabajar tanto en modo estatico como en modo instancia
 */

es.kcs.Util.prototype.captureKeys=es.kcs.Util.captureKeys;

// Funciones auxiliares
/**
 * @private
 */
function kc_aux_libera(evt){
	es.kcs.Util.charCode=null;
}
/**
 * @private
 */

function kc_aux_captura(evt){
  //  alert(evt.keyCode);
    evt = (evt) ? evt : event;
    es.kcs.Util.lastCharCode=es.kcs.Util.charCode = (evt.charCode) ? evt.charCode : ((evt.keyCode) ? evt.keyCode :
        ((evt.which) ? evt.which : 0));
  // alert(charCode + " " + String.fromCharCode(charCode));
  if (es.kcs.Util.handlerEventCaptureKeys)
     es.kcs.Util.handlerEventCaptureKeys(evt);
}




/**
* @private
* Sirve para habilitar/inhabilitar un link

*/

es.kcs.Util.DisableEnableLink=function (objLink,xHow){


    objLink.disabled = xHow;
    //link with onclick

//    try {

    if(objLink.onclick && xHow){
        objLink.onclick = new Function("return false;" + objLink.onclick.toString().getFuncBody());
        //alert(1);
    }
    //link without onclick
    else if(xHow){
      //alert(2);

      objLink.onclick = function(){return false;}
    }
    //remove return false with link without onclick
    else if (!xHow && objLink.onclick && objLink.onclick.toString().replace(/\s/g,"").indexOf("function(){returnfalse;}") != -1){
        //alert(3);
        objLink.onclick = null;
      }

    //remove return false link with onclick
    else {
         //alert(4);

         if(!xHow && objLink.onclick && objLink.onclick.toString().replace(/\s/g,"").indexOf("returnfalse;") != -1){

            strClick = objLink.onclick.toString().replace(/\s/g,"").getFuncBody().replace("returnfalse;","")
            //alert(strClick);
            objLink.onclick = new Function(strClick);
      }
    }
/*
    }
    catch (e){

      alert(e);
      alert(objLink.id);
      alert(objLink.href);
   //   for (var p in objLink)
   //     alert(p + "=" + objLink[p]);
    }
*/
}




/**
* @private
*/
es.kcs.Util.LinksAreDisabled=false;

/**
* @private
* Sirve para habilitar/inhabilitar todos los links de un documento

*/
es.kcs.Util.DisableEnableLinks=function (xHow){
  if (xHow){
      if (es.kcs.Util.LinksAreDisabled)
        return;
      es.kcs.Util.LinksAreDisabled=true;
  }
  else {
      if (!es.kcs.Util.LinksAreDisabled)
        return;
      es.kcs.Util.LinksAreDisabled=false;
  }
  var objLinks = document.links;
  for(i=0;i<objLinks.length;i++){
			es.kcs.Util.DisableEnableLink(objLinks[i],xHow);
  }
}


/**
* Sirve para habilitar/inhabilitar todos los links de un documento
* (Creo que esta funcion debe eliminarse)
* @private
*/

es.kcs.Util.DisableEnableLinks=function (xHow){
  var objLinks = document.links;
  for(i=0;i<objLinks.length;i++){
			es.kcs.Util.DisableEnableLink(objLinks[i],xHow);
  }
}



/**
 * Utilidad para inhabilitar la seleccion de texto en la pagina
* Si se pasa el ID de un objeto, solo se aplica al objeto. Si no se pasa argumento, se aplica al document
* ATENCION, sobreescribe los métodos onclick y onmousedown del objeto
@param {String} id (Opcional) ID del objeto
 * @see es.kcs.Util#EnableTextSelection
*/


es.kcs.Util.DisableTextSelection=function(id){
  var obj=document;

  if (id && document.getElementById(id))
       obj=document.getElementById(id);

//if IE4+
  obj.onselectstart=new Function ("return false");
//if NS6
  if (window.sidebar)
 {
   obj.onmousedown=disableselect
   obj.onclick=reEnable
 }

}

/**
 * Utilidad para habilitar la seleccion de texto en la pagina

* Si se pasa el ID de un objeto, solo se aplica al objeto. Si no se pasa argumento, se aplica al document
* ATENCION, sobreescribe los métodos onclick y onmousedown del objeto
@param {String} id (Opcional) ID del objeto
 * @see es.kcs.Util#EnableTextSelection
*/

es.kcs.Util.EnableTextSelection=function(id){
  var obj=document;

  if (id && document.getElementById(id))
       obj=document.getElementById(id);

//if IE4+
  obj.onselectstart="";
//if NS6
  if (window.sidebar)
 {
   obj.onmousedown="";
   obj.onclick="";
 }

}

/**
 * Funciones auxilixares para la inhabilitacion de la seleccion del texto en la pagina
* @private
 */
function disableselect(e){return false;}
/**
* @private
 */
function reEnable(){return true;}




/**
* Extender el prototipo de String. Necesario para la utilidad de habilitar/inhabilitar links
* @private
*/

String.prototype.getFuncBody = function(){
  var str=this.toString();
  str=str.replace(/[^{]+{/,"");
  str=str.substring(0,str.length-1);
  str = str.replace(/\n/gi,"");
  if(!str.match(/\(.*\)/gi))str += ")";
  return str;
}

/**
* Extender el prototipo de String.
* El metodo capitalizeFirst devuelve un String pasando a mayusculas la primera letra. El resto lo devuelve tal cual
* @type String
* @return Devuelve el String capitalizado
*/

String.prototype.capitalizeFirst = function(){
 return this.charAt(0).toUpperCase() + this.substring(1);
}


/**
* Extender el prototipo de Math. Necesario para obtener el numero cuyo valor absoluto es mayor.
* Se devuelve el numero respetando su signo.
* Si son iguales en valor absoluto, pero de signo distinto, entonces se devuelve el positivo
* @private
*/

Math.maxAbs = function(a,b){

  if (a==0)
  	return b;
  if (b==0)
  	return a;
  var aAbs = Math.abs(a);
  var bAbs = Math.abs(b);
  if (aAbs > bAbs)	return a; // a es mayor en valor absoluto
  if (bAbs > aAbs)  return b; // b es mayor en valor absoluto

  if (a/b>0) // Tienen el mismo signo y mismo valor absoluto
  	return a;

   if (a>b)  // Tienen signo distinto pero mismo valor absoluto. a es positivo y b negativo
   	return a;

	return b; // Tienen signo distinto pero mismo valor absoluto. b es positivo y a negativo

}


es.kcs.Util.preLoadImages =function() {
  if(document.images){
  	if(!_preLoaded) _preLoaded=new Array();
    var i,j=_preLoaded.length,a=arguments;
	for(i=0; i<a.length; i++){
		_preLoaded[j]=new Image;
		_preLoaded[j++].src=a[i];
	}
  }
}




es.kcs.swapImage=function(img,imgPath) {
  //alert(img.src)
  img.oSrc=img.src;
  img.src=imgPath;
  }
es.kcs.restoreSwapImage=function(img) {
  img.src=img.oSrc;
  }


/**
* Objeto con la informacion de usuario
* <br>Se utiliza como objeto con información de intercambio (relativa a la sesión de usuario) entre
* el espacio de sesión del servidor  y el espacio de sesión del cliente (browser).
* <br>Tras instanciar un objeto de tipo User, éste puede ir añadiendo tantos atributos como sea
* necesario según las necesidades de cada aplicación desarrollada.

*/


es.kcs.User= function (){
this.properties=new Object();
}


/**

* Establece las propiedades del objeto User
* @param {Object} properties  Objeto con las propiedades del objeto User
* @type void
*/

es.kcs.User.prototype.setProperties=function(properties){
	this.properties=properties;
  	for (var p in properties){
// En caso de estar utilizando prototype, se nos habra incluido el metodo extend. Lo saltamos
              if (p=='extend')
              		continue;
          		this[p]=properties[p];
          }

}

/**

* Obtiene una propiedad  concreta del objeto kcUser
* @param  {String} propertyPropiedad cuyo valor se desea obtener
@type Object
*/
es.kcs.User.prototype.getProperty=function(property){
	  return this.properties[property];
}

/**

* Establece una propiedad  concreta del objeto kcUser
 @param {String} property  Propiedad que se desea establecer
 @param {Object} value  Valor a asignar a la propiedad
*/
es.kcs.User.prototype.setProperty=function(property,value){
	  this.properties[property]=value;
    this[property]=value;
}


/**

* Muestra las propiedades establecidas para el objeto User
* Mediante un alert() muestra en pantalla todas las propiedades del objeto User
* @type void
*/

es.kcs.User.prototype.showProperties=function(){
	var str="Propiedades del usuario\n" +
          "======================\n";
// Recorrido de las propiedades del objeto de usuario
          for (var p in this.properties){
// En caso de estar utilizando prototype, se nos habra incluido el metodo extend. Lo saltamos
              if (p=='extend')
              		continue;
          		str += p + ":" + this.properties[p] +"\n";
          }

  alert(str);

}

/**
* //=================================================================================================
* Establece las propiedades del objeto UserInfo.
* userProperties es un objeto con atributos que se estableceran/susituiran a los existentes
* para el objeto UserInfo
* //=================================================================================================
*/


function kcSetUserProperties (userProperties){


   	if ( typeof (top.kcUserInfo)=="undefined"){
       	// alert("El objeto kcUserInfo no existe todavia. Se procede a crearlo ");
	// Creacion del objeto UserInfo
       		top.kcUserInfo=new es.kcs.User();
    	}

    	top.kcUserInfo.setProperties(userProperties);

}








/*
 * //=====================================================================================
*   AJAX AJAX AJAX AJAX
*  //=====================================================================================
 */

/**
* Lanza una peticion AJAX a partir de un formulario capturando la respuesta en la DIV cuyo ID se ha especificado.
* @param f  objeto FORM
* @param id  ID de la DIV destino
* @param evalThis Parametro opcional con codigo javascript a ejecutar tras el volcado en la DIV
* @requires es.kcs.net
* @type es.kcs.net.ContentLoader
*/


function AJAXSubmit(f,id,evalThis){
var loader=kcSendForm(f.id,onLoadHandlerToDIV,onErrorHandler);
loader.outWindow=$(id);
loader.evalThis=evalThis;
}

//=================================================================================================
// Permite crear una peticion AJAX lanzar un formulario f y capturar la respuesta en la id
//=================================================================================================

/**
* Lanza una peticion AJAX a partir de una accion y conjunto de parametros capturando la respuesta en la DIV cuyo ID se ha especificado.
* @param id  ID de la DIV destino
* @param action URI/URL de la accion a ejecutar
* @param parameters  Parametros de la accion
* @param evalThis Parametro opcional con codigo javascript a ejecutar tras el volcado en la DIV
* @requires es.kcs.net
* @type es.kcs.net.ContentLoader
*/

function AJAXSendRequest(id,action,parameters,evalThis){
var loader=kcSendRequest(action, parameters,onLoadHandlerToDIV,onErrorHandler);
loader.outWindow=$(id);
loader.evalThis=evalThis;
}


/**
* Lanza una peticion AJAX a partir de una accion y conjunto de parametros capturando la respuesta en la DIV cuyo ID se ha especificado.
* @param action URI/URL de la accion a ejecutar
* @param parameters  Parametros de la accion
* @param evalThis Parametro opcional con codigo javascript a ejecutar tras el volcado en la DIV
* @requires es.kcs.net
* @type es.kcs.net.ContentLoader
*/

function AJAXSendRequestEval(action,parameters,evalThis){
var loader=kcSendRequest(action, parameters,onLoadHandlerEval,onErrorHandler);
	if (typeof (evalThis) != "undefined") loader.evalThis=evalThis;
}



/**
* Lanza una peticion AJAX a partir de un formulario.
* @param fid  ID del objeto FORM o bien el propio objeto FORM
* @param {Function} onLoadHandler   Funcion handler de la carga
* @param {Function} onErrorHandler  Funcion handler del error
* @param {Boolean} bloquear  (Opcional) true/false para indicar si se quieren bloquear todos los forms, menus y links del documento
* @param {String} title  (Opcional) Título de la ventana de espera. Si no se env?a, no se muestra mensaje de espera
* @param {String} msg   (Opcional) Mensaje de espera
* @requires es.kcs.net
* @type es.kcs.net.ContentLoader
*/

function kcSendForm(fid,onLoadHandler,onErrorHandler,bloquear,title,msg) {
// Si se pasa un titulo para la ventana de espera, entonces se muestra la ventana de
// espera.

  if (title)
     kcDrawWaitMessage(true,title,msg);

// Obtener el objeto formulario correspondiente a la ID pasada como argumento
  var f=$(fid);


//alert(f.name + "\n" +f.id + "\n" + f.action + "\n" + f.method);
  var method;
  if (f.method)
     method=f.method.toUpperCase();
  else method="POST";
  //alert(f + "\n" + f.action + "\n" + method + "\n" + Form.serialize(f.name));
  var loader =
          new es.kcs.net.ContentLoader(
            f.action,
            onLoadHandler,
            onErrorHandler,
            method,
            //Form.serialize(f.name)
            kcSerialize(f)
          );


 if (bloquear==true){
     lockAll();
     loader.hasLocks=true;
 }

  return loader;
}
/**
* Serializa un formulario para el envío vía AJAX de sus campos como parámetros
* <br>Esta función se utiliza en lugar de Form.serialize presente en prototype.js porque
* se ha comprobado que en determinadas circunstancias (algunos formularios creados dinámicamente)
* la serialización ofrecía algún problema utilizando aquella librería.
* @param {HTMLFormObject} f Formulario que se quiere serializar
* @private
* @type String
*/
function kcSerialize(f){

  var parameters="";

	for (var i=0;i<f.elements.length;i++){
           if (f.elements[i].type=="select-multiple"){
             for (var j=0;j<f.elements[i].options.length;j++){
                 if (f.elements[i].options[j].selected){
                      parameters+=f.elements[i].name+"="+f.elements[i].options[j].value+"&";
                 }
             }
           }
           else {
                 parameters+=f.elements[i].name+"="+f.elements[i].value+"&";
           }
	}
  return parameters;
}

/**
* Lanza una petición AJAX.
* @param {String} action URI (o URL) correspondiente a la acción a ejecutar
* @param {String} parameters String con la concatenación de los parámetros a enviar junto a la petición
* @param {Function} onLoadHandler   Funcion handler de la carga
* @param {Function} onErrorHandler  Funcion handler del error
* @param {Boolean} bloquear  (Opcional) true/false para indicar si se quieren bloquear todos los forms, menus y links del documento
* @param {String} title  (Opcional) Título de la ventana de espera. Si no se env?a, no se muestra mensaje de espera
* @param {String} msg   (Opcional) Mensaje de espera
* @requires es.kcs.net
* @type es.kcs.net.ContentLoader
*/
function kcSendRequest(action,parameters,onLoadHandler,onErrorHandler,bloquear,title,msg) {
// Si se pasa un titulo para la ventana de espera, entonces se muestra la ventana de
// espera.
  if (title)
     kcDrawWaitMessage(true,title,msg,null,document.body.scrollTop+150);


  var loader =
          new es.kcs.net.ContentLoader(
            action,
            onLoadHandler,
            onErrorHandler,
            "POST",
            parameters
          );


 if (bloquear==true){
     lockAll();
     loader.hasLocks=true;
 }

  return loader;
}





/**
* Manejador de error AJAX genérica.
*/
function onErrorHandler() {
// Ocultar la ventana de mensaje si está visible
   kcDrawWaitMessage(false);
// Mensaje de error
  alert("Error grave e inesperado. Problemas de conexión con el servidor");
// Desbloquear todo
 	if (this.hasLocks)
       unlockAll();
}



/**
* Manejador AJAX genérico de carga en objeto KCWINDOW
*/
function onLoadHandler() {
  var v=null;
// Ocultar el mensaje de espera
  kcDrawWaitMessage(false);
// Asignar el valor de la variable Objeto KC_WINDOW
  if (this.outWindow)
     v=this.outWindow;

  try {
// Si la respuesta obtenida es HTML, entonces la funcion eval generar? una excepcion y se recoger?
// en el catch. Si no se produce la excepcion, significa que se ha devuelto un objeto expresado
// en formato JSON que representar? el (o los) errores obtenidos.
    var response = eval ( "(" + this.req.responseText + ")" );
    if (response.status=='ERROR') {
         var msgError="";
         for (var i=0;i<response.errors.length;i++) {
           if (typeof(response.errors[i])!="undefined" && typeof(response.errors[i].key) != "undefined")
      		        msgError+= response.errors[i].desc +"\n";
                 // alert(response.errors[i].key + "=" + response.errors[i].desc);
         }
         if (msgError!="")
           alert(msgError);
         if (this.evalOnError){
             eval(this.evalOnError);
         }
         	if (this.hasLocks)
              unlockAll();

    } else {
      // Ponemos el else por seguridad, aunque si la respuesta no es un objeto JSON, siempre saltara
      // al catch al petar la funcion eval
              if (v!=null){

                   v.setContent(this.req.responseText);
                   v.show();
              }
              else {

                 alert("ERROR! No existe objeto KC_WINDOW");
                	if (this.hasLocks)
                     unlockAll();
              }

    }
  } catch (e) {

              // Si entra por aqui, es que todo ha ido bien en el servidor.
              if (v!=null){
                 v.setContent(this.req.responseText);
                 v.show();
              }
              else {
                alert("ERROR! No existe objeto KC_WINDOW");
                	if (this.hasLocks)
                      unlockAll();
              }
  }
}



/**
* Manejador AJAX genérico de carga en objeto DIV.
*/
function onLoadHandlerToDIV() {

  var div=null;
// Ocultar el mensaje de espera
  kcDrawWaitMessage(false);
// Asignar el valor de la variable Objeto KC_WINDOW
  if (this.outWindow)
     div=this.outWindow;

  try {
// Si la respuesta obtenida es HTML, entonces la funcion eval generar? una excepcion y se recoger?
// en el catch. Si no se produce la excepcion, significa que se ha devuelto un objeto expresado
// en formato JSON que representar? el (o los) errores obtenidos.
    var response = eval ( "(" + this.req.responseText + ")" );
    if (response.status=='ERROR') {
         var msgError="";
         for (var i=0;i<response.errors.length;i++) {
           if (typeof(response.errors[i])!="undefined" && typeof(response.errors[i].key) != "undefined")
      		        msgError+= response.errors[i].desc +"\n";
                 // alert(response.errors[i].key + "=" + response.errors[i].desc);
         }
         if (msgError!="")
           alert(msgError);


         if (this.evalOnError){
             eval(this.evalOnError);
         }

//         	if (this.hasLocks)
  //              unlockAll();
    } else {
      // Ponemos el else por seguridad, aunque si la respuesta no es un objeto JSON, siempre saltara
      // al catch al petar la funcion eval
              if (div!=null){
              // Para que tras cargar en la DIV, se posicione en el top (por si tiene scrollbar)
                 div.scrollTop=0;
                   div.innerHTML="<form style='display:none;'></form>"+this.req.responseText;
                   top.refreshScripts(div.id);
                    if (this.evalThis){
                     // alert("evaluando " + this.evalThis)
                     eval(this.evalThis);
                   }

              }
              else {
                 alert("ERROR! No existe objeto DIV "+ this.outWindow);
    //             	if (this.hasLocks)
      //               unlockAll();
              }

    }
  } catch (e) {


              // Si entra por aqui, es que todo ha ido bien en el servidor.
              if (div!=null){
              // Para que tras cargar en la DIV, se posicione en el top (por si tiene scrollbar)
                div.scrollTop=0;
              var zz="";
              //for (var pp in this.req) zz+=pp+" ";
              //alert(zz);
                 div.innerHTML="<form style='display:none;'></form>"+this.req.responseText;
                 top.refreshScripts(div.id);
                 if (this.evalThis){
                    eval(this.evalThis);
                 }
              }
              else {
                alert("ERROR! No existe objeto DIV "+this.outWindow);
        //        	if (this.hasLocks)
          //            unlockAll();
              }
  }

         	if (this.hasLocks)
                unlockAll();

}




/**
* Manejador AJAX genérico con evaluación de código e interfaz KC.
* <br>  Asume un objeto en la respuesta que implementara la 'interface'
* de objetos de respuesta KC. Incorporara el metodo 'start' que sera el punto de inicio
* de la ejecución del objeto de respuesta.
* Adicionalmente, al finalizar ejecutará el código pasado en el atributo evalThis del objeto ContentLoader
* al cual pertenece el manejador.
*/
function onLoadHandlerEval() {
// Ocultar el mensaje de espera
  kcDrawWaitMessage(false);
//  w=window.open("","","");
//  w.document.write(this.req.responseText);

  try {
    var response = eval ( "(" + this.req.responseText + ")" );
    if (response.status && response.status=='ERROR') {
         var msgError="";
         for (var i=0;i<response.errors.length;i++) {
           if (typeof(response.errors[i])!="undefined" && typeof(response.errors[i].key) != "undefined")
      		        msgError+= response.errors[i].desc +"\n";
                 // alert(response.errors[i].key + "=" + response.errors[i].desc);
         }
         if (msgError!="")
           alert(msgError);

         if (this.evalOnError){
             eval(this.evalOnError);
         }

    } else {
      // Ponemos el else por seguridad, aunque si la respuesta no es un objeto JSON, siempre saltara
      // al catch al petar la funcion eval

			if (response.status && response.status=='OK'){
                            if (typeof(response.start)!="undefined")
                                 response.start();
                            if (this.evalThis){
                              // alert("evaluando " + this.evalThis)
                               eval(this.evalThis);
                              // alert("Fin evaluacion");
                            }
      			}
                        else if (!response.status && this.evalThis){
                          eval(this.evalThis);
                        }
    }
  } catch (e) {
      try {
        // Por aqui pasa cuando la respuesta a evaluar no es JSON
        var response = eval (  this.req.responseText  );
        if (this.evalThis)
           eval(this.evalThis);
      }
      catch (e2){
      alert("Error inesperado en el servidor. La aplicaci?n se cerrar?. P?ngase en contacto con el administrador del sistema");
      alert(e + "\nevalThis=" + this.evalThis );
      kcExitAction();

      }
  }

	if (this.hasLocks)
       unlockAll();
}




// Esta funcion devuelve true si el objeto object cuelga jerarquicamente
// del objeto DIV especificado.

/**
* Averigua si un objeto cuelga jerárquicamente de la DIV pasada como argumento
* @param {HTMLDivObject} DIVobject Objeto DIV del que se quiere averiguar si es ancestro del objeto pasado como argumento
* @param {Object} object Objeto que se quiere averiguar si cuelga o no de la DIV pasada como argumento
* @type Boolean
* @return Devuelve <b>true</b> si el objeto cuelga jerárquicamente de la DIV pasados como argumento.
* <b> false </b> en otro caso.
*
*/

function esHijoDelDIV(DIVobject,object){

    if (!object)
      return false;

    if (object.parentNode==DIVobject){

       return true;
    }
    else {
          return esHijoDelDIV(DIVobject,object.parentNode);
    }
}


/**
* Refresca los objetos script del documento
 <br>Esta funcion obtiene todos los objetos script del documento.
 Para cada uno de ellos, comprueba si dicho objeto cuelga del objeto DIV cuya id se especifica
 en idDIV, o bien cuelga de alguno de sus objetos hijos. En caso afirmativo, recarga el
 script llamando a la funcion reloadScript() para ese script.

* @param {String} idDIV ID de la DIV a comprobar
* @param {HTMLObject} doc (Opcional) Normalmente un objeto HTMLDocument aunque puede ser cualquier otro. Si no se pasa como argumento, por defecto actúa sobre el objeto <i>document</i>
@type void
*/

function refreshScripts(idDIV, doc){

	var theDocument = doc ? doc : document;
	var todoslosscripts = theDocument.getElementsByTagName('script');
	var scriptsToRefresh = new Array();

	// Asume que el identificador idDIV es ?nico y que ning?n otro objeto
	// del documento tiene el mismo valor para la propiedad id. En caso  contrario,
	// la funcion tendra un comportamiento impredecible.

	var DIVobject = theDocument.getElementById(idDIV);

	for (var i = 0; i < todoslosscripts.length; i++) {
		//alert("Checking ... " + todoslosscripts[i].text);

		if (esHijoDelDIV(DIVobject,todoslosscripts[i])==true){
			//alert("el script " + todoslosscripts[i].id + " es hijo de " + idDIV);
			scriptsToRefresh[scriptsToRefresh.length] = todoslosscripts[i];
			//reloadScript(DIVobject,todoslosscripts[i]);
		}
	}

	for(var i=0; i<scriptsToRefresh.length; i++ ) {
		reloadScript(scriptsToRefresh[i]);
	}

}


/**
* Refresca los objetos script del documento
 <br>
 Esta funcion recarga el objeto script. Para ello, crea un nuevo objeto tipo script. Le asigna
las propiedades del objeto script previo. Elimina el previo y añade el nuevo.
* @param {ScriptObject} scriptObjectOld Objeto Script

@type void
*/

function reloadScript(scriptObjectOld) {
        var objetoPadre;
	if(scriptObjectOld){
		var script = document.createElement('script');
		script.type = scriptObjectOld.type;
		script.text = scriptObjectOld.text;
                objetoPadre=scriptObjectOld.parentNode;
		//theDiv.removeChild(scriptObjectOld);
                objetoPadre.removeChild(scriptObjectOld);
		script.id = scriptObjectOld.id;
		//theDiv.appendChild(script);
                objetoPadre.appendChild(script);
                //alert("cargando el script:******************\n"+script.text);
	}
}


/**

* Muestra/oculta una ventana con un mensaje

*@param {boolean} mostrar  true/false
* @param {String} titulo título de la ventana
* @param {String} pie Pie del mensaje
* @param {String} cuerpo Cuerpo del mensaje.
* @type void
*/


function kcDrawWaitMessage(mostrar,titulo,pie,cuerpo,top,left){

  var theDiv = document.getElementById("divMensajeEspera");
// Si no existe pero hay que mostrarlo, entonces se crea
	if(!theDiv && mostrar) {
	    theDiv = document.createElement("div");
            // set div attributes
            theDiv.id = "divMensajeEspera";
            theDiv.style.position = "absolute";
            if (left)
               theDiv.style.left = left +"px";
            else
               theDiv.style.left = "290px";
            if (top)
               theDiv.style.top = top + "px";
            else
               theDiv.style.top = "116px";
            theDiv.style.width = "321px";
            theDiv.style.height = "162px";
            document.body.appendChild(theDiv);
            try{
       // PROVISIONAL WINDOW NO VA
      //      ADD_DHTML("divMensajeEspera"+NO_DRAG);
            }
            catch(e){
                alert("Error al intentar a?adir el mensaje WAIT\n"+e);
     // PROVISIONAL WINDOW NO VA
    //            SET_DHTML("divMensajeEspera"+NO_DRAG);
            }
  	}

// PROVISIONAL    WINDOW NO VA


	if (theDiv)
	// Hay Mensaje  y hay que mostrarlo
	   if (mostrar){
      if (left)
         theDiv.style.left = left +"px";
      else
         theDiv.style.left = "290px";
      if (top)
         theDiv.style.top = top + "px";
       else
         theDiv.style.top = "116px";
		theDiv.style.display = "block";
		if (titulo==null) titulo="&nbsp;"
		if (pie==null) pie="&nbsp;"
		if (cuerpo == null) cuerpo = '<img src="images/reloj6.gif" >';

                var str='<table style="border: 1px solid #003399;background-color: #d3e3f6;" width="100%" height="100%" border="0" cellpadding="0" cellspacing="0">' +
		        '<tr><th style="font-family: Arial, Helvetica, sans-serif;font-size: 12px;color: #FFFFFF;background-color: #003399;font-weight: bold;" height="11%" scope="col">' + titulo +
		        '</th></tr><tr><td style="font-family: Arial, Helvetica, sans-serif;font-size: 12px;text-align: center;color: #003399;" height="76%">' + cuerpo +
		        '</td></tr><tr> <td style="font-family: Arial, Helvetica, sans-serif;font-size: 12px;text-align: center;color: #003399;" height="13%">' + pie +
		        '</td></tr></table>';

//alert(divMsg.innerHTML);
		theDiv.innerHTML=str;
		theDiv.style.display="block";
    theDiv.style.zIndex=999999;
   // dd.elements["divMensajeEspera"].maximizeZ();
    //dd.elements["divMensajeEspera"].write(str);
    //dd.elements["divMensajeEspera"].show();
           }
// Hay mensaje pero hay que ocultarlo
	   else {
  		theDiv.style.display = "none";
      theDiv.style.zIndex = 0;
     // dd.elements["divMensajeEspera"].hide();
    //  dd.elements["divMensajeEspera"].setZ(1);
	   }
}




/**
 La plantilla xslt debe añadir objetos a partir de los nodos targetDef de la siguiente manera:


var targetDefs=new Object();

targetDefs['main'+0]={name:'submain',order:0,parent:'main'};
targetDefs['0']={name:'container',order:0};
targetDefs['container'+0]={name:'header',order:0,parent:'container'};
targetDefs['container'+1]={name:'main',order:1,parent:'container'};
targetDefs['container'+2]={name:'footer',order:2,parent:'container'};
targetDefs['1']={name:'pepito',order:0};

*/


/**
Crea una estructura de objetos DIV
<br>Esta funcion dibuja la estructura DOM de objetos DIV definida en el objeto targetDefs
pasado como argumento.
El objeto targetDefs debe tener tantas propiedades como objetos DIV se quieren
dibujar. Cada una de estas propiedades es a su vez un objeto que representa la informacion
del objeto DIV a dibujar.
Cada objeto tiene los siguientes atributos:

name: ID de la DIV
order: Orden de la DIV dentro de su DIV padre
parent: ID de la DIV padre. Si no tiene padre, parent ha de valer '' o no existir como atributo

Las propiedades del objeto targetDefs tienen por nombre la concatenacion del ID de la DIV
correspondiente al DIV padre + su numero de orden.

A continuacion se muestra un ejemplo de creacion del objeto targetDefs:

var targetDefs=new Object();
targetDefs['main'+0]={name:'submain',order:0,parent:'main'};
targetDefs['0']={name:'container',order:0};
targetDefs['container'+0]={name:'header',order:0,parent:'container'};
targetDefs['container'+1]={name:'main',order:1,parent:'container'};
targetDefs['container'+2]={name:'footer',order:2,parent:'container'};
targetDefs['1']={name:'container2',order:0};

La llamada a la funcion drawDivChilds(targetDefs) dara lugar a la siguiente estructura
de objetos DIV

<div id="container">
   <div id="header"></div>
   <div id="main">
      <div id="submain"></div>
   </div>
   <div id="footer"></div>
</div>
<div id="container2"></div>

**/

function drawDivChilds(targetDefs,parentName){
	if (!parentName)
	   parentName='';
	for (var i=0;i<100;i++){
		if (!targetDefs[parentName + i]){
		    continue;
		}
		var targetDef=targetDefs[parentName + i];
		if (targetDef.parent && targetDef.parent!=''){
			addDiv(targetDef.name,document.getElementById(targetDef.parent));
	//		alert("drawDivChilds Dibujando DIV=" + targetDef.name +  ' colgando de '+ targetDef.parent);
		}
		else {
		   addDiv(targetDef.name);
	//	   alert("drawDivChilds Dibujando DIV=" + targetDef.name +  ' colgando de document');
		   }

		drawDivChilds(targetDefs,targetDef.name);
	}

}
/**
 Esta funcion añade un objeto DIV a la pagina HTML actual.
 <BR>Si no se especifica elemento parent, lo añade directamente sobre el body
 @param {String} id ID del objeto DIV a añadir
 @param {HTMLObject} el (Opcional) Objeto HTML sobre el que se quiere añadir la nueva DIV
 @type HTMLDivObject
 @return Devuelve el objeto DIV creado
**/

function addDiv(id,el){

    var childEl=document.createElement("div");
    if (el)
        el.appendChild(childEl);
    else
        document.body.appendChild(childEl);
    childEl.id=id;
    return childEl;
}



/**
 * Devuelve un objeto con las propiedades width y heigth, referentes al documento entero.
 * La ventaja de esta función es que se rumorea que funciona en cualquier explorador.
 */
function getSize() {
	var o = new Object();
	if (self.innerWidth) {
		o.width = self.innerWidth;
		o.height = self.innerHeight;
	} else if (document.documentElement && document.documentElement.clientWidth) {
		o.width = document.documentElement.clientWidth;
		o.height = document.documentElement.clientHeight;
	} else if (document.body) {
		o.width = document.body.clientWidth;
		o.height = document.body.clientHeight;
	}
	return o;
}


/**
 * Centra el objeto (especialmente una DIV) en la pantalla. Éste debería tener definida la
 * propiedad position=absolute.
 * @param {Object} id ID del objeto o el objeto en sí.
 */
function kc_center(id) {
	o = getSize();
	id = $(id);
	id.style.top = (o.height-id.clientHeight)/2;
	id.style.left = (o.width-id.clientWidth)/2;
}




// Extiende el tipo String con la función trim.
// ATENCIÓN: ¡¡No poner ";" al final!!
String.prototype.trim = function() {
    return this.replace(/^[\s]+|[\s]+$/g,'')
}


