// JavaScript Document
// Contiene funciones o utilerías generales para el sitio web

/* ResetButtons: Contiene código para realizar el reset de los botones del menú cuando se requiere volver al estado inicial de los mismos.
	La función recibe una matriz que contiene el nombre del archivo para el botón encendido, el nombre del archivo para el botón apagado y 	el nombre de la imagen que funciona como el botón propiamente. También recibe un índice que indica qué botón del arreglo quedará
	activo. */
function ResetButtons(btnMatrix, btnActivar, lunidimensional) {
	var i;
	var j;
	var curObj;

	if (!lunidimensional) {
		for (i=0; i<btnMatrix.length; i++) {
			curObj = document.getElementById(btnMatrix[i][0]);
			
			if (curObj != null) {					
				if ((i+1) == btnActivar) {
					curObj.src=btnMatrix[i][1];
				}
				else {
					curObj.src=btnMatrix[i][2];
				}
			}
		}
	}
	else {
		for (i=0; i<btnMatrix.length; i+=3) {		
			curObj = window.parent.document.getElementById(btnMatrix[i]);

			if (curObj != null) {
				if (((i/3)+1) == btnActivar) {
					curObj.src=btnMatrix[i+1];
				}
				else {
					curObj.src=btnMatrix[i+2];
				}
			}
		}
	}
}

// Carga una página determinada dentro de un DIV.
function ahah(url, target) {
	document.getElementById(target).innerHTML = '<div class="style18b"> Cargando... </div>';
  	
	if (window.XMLHttpRequest) {
    	req = new XMLHttpRequest();
  	} else if (window.ActiveXObject) {
    	req = new ActiveXObject("Microsoft.XMLHTTP");
  	}
	
	if (req != undefined) {
    	req.onreadystatechange = function() {ahahDone(url, target);};
	    req.open("GET", url, true);
    	req.send("");
	}
}  
function ahahDone(url, target) {
	if (req.readyState == 4) { // only if req is "loaded"
    	if (req.status == 200) { // only if "OK"
      		document.getElementById(target).innerHTML = req.responseText;
    	} else {
    		document.getElementById(target).innerHTML="Error:\n"+ req.status + "\n" +req.statusText;
    	}
  	}
}
function load(name, div) {
	ahah(name,div);
	return false;
}

function iFrameLoad(container, url){
	var el=document.getElementById(container);
	el.innerHTML="<iframe src="+url+" width=850 height=490 frameborder=0 scrolling='auto'></iframe>";
}
//-------------------------------------------------------------------------------------------------
/* Ordena una tabla HTML dada según su ID:
	tableid: Nombre o id de la tabla HTML que se va a ordenar.
	colord: Número de columna que se tomará como base para ordenar la tabla.
	colbase: Número de columna base para tomarse como segundo criterio de ordenación cuando elementos en colord son iguales.
	sorttype: 'asc' o 'desc' según se requiera ascendente o descendente respectivamente.
	colordtype: Tipo de dato de la columna colord. Puede ser string, number, date o datetime.
	colbasetype: Tipo de dato de la columna colbase. Puede ser string, number, date o datetime.  
	
	¡DESCARTADA! */
//-------------------------------------------------------------------------------------------------
/*function SortHtmlTable(tableid, colord, colbase, sorttype, colordtype, colbasetype) {				
	var oTabla;
	var aTempTab = new Array();
	var aTempRes = new Array(); 	// Contiene los resultados en texto.
	var aTmpInput = new Array();	// Contiene el texto interno de los input.
	var aRows = new Array();
	var aInputs = new Array();
	var sText = "";
	var oTemp;
	var oTmpInput;
	var Compara = 0;
	
	oTabla = document.getElementById(tableid);		// Obtener objeto de tabla

	// aTempTab queda como el arreglo temporal para el ordenamiento.
	for (var row=0; row<oTabla.rows.length; row++) {
		// Verificar si no nos encontramos en la última posición del arreglo
		if (row+1 < oTabla.rows.length) {	
			Compara = CompareValues(oTabla.rows[row].cells[colord].innerText,oTabla.rows[row+1].cells[colord].innerText,colordtype);
			if (Compara == 0) {
				Compara = CompareValues(oTabla.rows[row].cells[colbase].innerText,oTabla.rows[row+1].cells[colbase].innerText,colbasetype);	
			}
								
			if (sorttype.toLowerCase() == "asc") {
				if (Compara == 1) {			// Valor 1 mayor que valor 2
					swapRowDown(oTabla.rows[row],tableid);
					if (row > 0) { row-=2; }
				}	
			}
			else if (sorttype.toLowerCase() == "desc") {
				if (Compara == -1) {		// Valor 2 mayor que valor 1
					swapRowDown(oTabla.rows[row],tableid);
					if (row > 0) { 
						row-=2; 
					}
				}											
			}
		} // fin "if" para verificar si estamos al final del arreglo
	}// fin "for" para recorrido de tabla
}*/
//-------------------------------------------------------------------------------------------------

//-------------------------------------------------------------------------------------------------
/* Ordena una tabla HTML dada según su ID:
	tableid: Id de la tabla HTML que se va a ordenar.
	Columna1: 	Arreglo de tres valores: {# de columna a ordenar, tipo de datos de columna, propiedad base para ordenar}
				Ésta columna es considerada como la primaria para el ordenamiento.
	Columna2: 	Arreglo de tres valores: {# de columna a ordenar, tipo de datos de columna, propiedad base para ordenar}
				Ésta columna es considerada como la secundaria para el ordenamiento cuando los valores de la primaria son iguales.
	sorttype: 'asc' o 'desc' según se requiera ascendente o descendente respectivamente.
  ------------------------------------------------------------------------------------------------- */
function SortHtmlTable(tableid, Columna1, Columna2, sorttype) {				
	var oTabla;
	var aTempTab = new Array();
	var aTempRes = new Array(); 	// Contiene los resultados en texto.
	var aTmpInput = new Array();	// Contiene el texto interno de los input.
	var aRows = new Array();
	var aInputs = new Array();
	var sText = "";
	var oTemp;
	var oTmpInput;
	var Compara = 0;
	var valueString1 = "";
	var valueString2 = "";
	
	oTabla = document.getElementById(tableid);		// Obtener objeto de tabla

	// aTempTab queda como el arreglo temporal para el ordenamiento.
	for (var row=0; row<oTabla.rows.length; row++) {
		// Verificar si no nos encontramos en la última posición del arreglo
		if (row+1 < oTabla.rows.length) {	
			valueString1 = "oTabla.rows[row].cells[Columna1[0]]."+Columna1[2];
			valueString2 = "oTabla.rows[row+1].cells[Columna1[0]]."+Columna1[2];
			Compara = CompareValues(eval(valueString1),eval(valueString2),Columna1[1]);
			
			if (Compara == 0) {
				valueString1 = "oTabla.rows[row].cells[Columna2[0]]."+Columna2[2];
				valueString2 = "oTabla.rows[row+1].cells[Columna2[0]]."+Columna2[2];
				Compara = CompareValues(eval(valueString1),eval(valueString2),Columna2[1]);	
			}
								
			if (sorttype.toLowerCase() == "asc") {
				if (Compara == 1) {			// Valor 1 mayor que valor 2
					swapRowDown(oTabla.rows[row],tableid);
					if (row > 0) { row-=2; }
				}	
			}
			else if (sorttype.toLowerCase() == "desc") {
				if (Compara == -1) {		// Valor 2 mayor que valor 1
					swapRowDown(oTabla.rows[row],tableid);
					if (row > 0) { 
						row-=2; 
					}
				}											
			}
		} // fin "if" para verificar si estamos al final del arreglo
	}// fin "for" para recorrido de tabla
}
//-------------------------------------------------------------------------------------------------

//-------------------------------------------------------------------------------------------------
// Compara dos valores según el tipo indicado. Indica mediante un 1, -1 y 0 si a>b, a<b o a=b respectivamente.
// Regresará -2 si existió algún error.
//-------------------------------------------------------------------------------------------------
// Los tipos pueden ser: number, string, date o datetime
function CompareValues(a,b,type) {
	switch(type) {
		case "number": 
			if (typeof(a) == "string") {
				a = parseFloat(a);
			}
			if (typeof(b) == "string") {
				b = parseFloat(b);
			}
			if (typeof(a)=="number" && typeof(b)=="number") {
				if (a > b) {
					return 1;
				}
				else if(a < b) {
					return -1;
				}
			}
			else if (typeof(a)=="string" && typeof(b)=="string") {
				if (parseFloat(a) > parseFloat(b)) {
					return 1;
				}
				else if(a < b) {
					return -1;
				}
			}
		break;
		case "string":
			if ( (typeof(a)=="string" && typeof(b)=="string") ) {
				if (a.toLowerCase() > b.toLowerCase()) {
					return 1;
				}
				else if (a.toLowerCase() < b.toLowerCase()) {
					return -1;
				}						
			}
		break;
		case "date":
			if ( (typeof(a)=="string" && typeof(b)=="string") ) {
				var DateA = new Date(a.substring(6),a.substring(3,5)-1,a.substring(0,2),0,0,0,0);
				var DateB = new Date(b.substring(6),b.substring(3,5)-1,b.substring(0,2),0,0,0,0);

				if (DateA.getTime() > DateB.getTime()) {
					return 1;
				}
				else if(DateA.getTime() < DateB.getTime()) {
					return -1;
				}
			}
		break;
		case "datetime":
			if ( (typeof(a)=="string" && typeof(b)=="string") ) {
				var DateA = new Date(a.substring(6,10),a.substring(3,5)-1,a.substring(0,2),a.substring(11,13),a.substring(14,16));
				var DateB = new Date(b.substring(6,10),b.substring(3,5)-1,b.substring(0,2),b.substring(11,13),b.substring(14,16));
				if (DateA.getTime() > DateB.getTime()) {
					return 1;
				}
				else if(DateA.getTime() < DateB.getTime()) {
					return -1;
				}
			}
		break;
	}
	return 0;
}
//-------------------------------------------------------------------------------------------------

//-------------------------------------------------------------------------------------------------
// clonar: Ojo: "constructor" no funciona en todos los navegadores. Incluso no funciona en algunas 
// versiones de IE.
//-------------------------------------------------------------------------------------------------
function clonar(obj){
        if(obj == null || typeof(obj) != 'object') return obj;

        if(obj.constructor == Array) {
                var temp = [];
                for(var i = 0; i < obj.length; i++) {
                        if(typeof(obj[i]) == 'object')   temp.push(clonar(obj[i]));
                        else temp.push(obj[i]);
                }
                return temp;
        }

        var temp = {};
        for(var key in obj) temp[key] = clonar(obj[key]);
        return temp;
}
//-------------------------------------------------------------------------------------------------
// Dada una tabla y un renglón determinado de la misma, mueve la fila indicada una posición hacia arriba.
//-------------------------------------------------------------------------------------------------
function swapRowUp(chosenRow, tableid){
	if (chosenRow.rowIndex != 0) {
    	moveRow(chosenRow, chosenRow.rowIndex-1, tableid);
	}
}
//-------------------------------------------------------------------------------------------------
// Dada una tabla y un renglón determinado de la misma, mueve la fila indicada una posición hacia abajo.
//-------------------------------------------------------------------------------------------------
function swapRowDown(chosenRow, tableid) {       
	var mainTable = document.getElementById(tableid);
	
	if (chosenRow.rowIndex != mainTable.rows.length-1) {                           
		moveRow(chosenRow, chosenRow.rowIndex+1, tableid); 
	}                                                                              
}                                                                                
//-------------------------------------------------------------------------------------------------
// Simula el movimiento de una fila hacia el nuevo índice indicado dentro de la tabla. 
// Crea un nuevo renglón, copia los datos del renglón origen y elimina el origen.
//-------------------------------------------------------------------------------------------------
//moves the target row object to the input row index
function moveRow(targetRow, newIndex, tableid) { 
 //since we are not actually swapping
 //but simulating a swap, have to "skip over"
 //the current index
	if (newIndex > targetRow.rowIndex) {
   		newIndex++;
	}
 //establish proper reference to the table
 	var mainTable = document.getElementById(tableid);

 //insert a new row at the new row index
 	var theCopiedRow = mainTable.insertRow(newIndex);

 //copy all the cells from the row to move
 //into the new row
 	for (var i=0; i<targetRow.cells.length; i++) {
   		var oldCell = targetRow.cells[i];
   		var newCell = document.createElement("TD");
   		newCell.innerHTML = oldCell.innerHTML;
		newCell.className = oldCell.className; 
		newCell.bgColor = oldCell.bgColor;
		newCell.height = oldCell.height;
		newCell.width = oldCell.width;
		newCell.style.backgroundColor = oldCell.style.backgroundColor;
		newCell.title = oldCell.title;
   		theCopiedRow.appendChild(newCell);
 	}

 //delete the old row
 	mainTable.deleteRow(targetRow.rowIndex); 
}
//-------------------------------------------------------------------------------------------------
// Crea una nueva opción para una lista de elementos o menú existente.
//-------------------------------------------------------------------------------------------------
function CreateSelRow(selName, optLabel, optValue) {
	document.getElementById(selName).options[document.getElementById(selName).options.length] = new Option(optLabel, optValue, false, false);
}
//-------------------------------------------------------------------------------------------------
// Regresa el índice del botón de radio seleccionado en un grupo pasado como parámetro, -1 si no lo encuentra.
// Importante: Utilizar la función getElementsByAttribute para enviar la lista de radios como parámetro
// 		ya que dicha función incluye los radios que se encuentren desactivados evitando errores de vali-
//		dación.
//-------------------------------------------------------------------------------------------------
function getSelectedRadio(buttonGroup) {
	if (buttonGroup != null) {
		if (buttonGroup.length >= 1) {		
			for (var i=0; i<buttonGroup.length; i++) {			
				if (buttonGroup[i].checked) {
					return i;
			 	}
		  	}
		}
	}
   // if we get to this point, no radio button is selected
   return -1;
} // Ends the "getSelectedRadio" function
//-------------------------------------------------------------------------------------------------

//-------------------------------------------------------------------------------------------------
// Elimina la selección de todos los botones de radio encontrados en el grupo.
//-------------------------------------------------------------------------------------------------
function UncheckRadios(buttonGroup) {
	if (buttonGroup != null) {
		if (buttonGroup.length >= 1) {		
			for (var i=0; i<buttonGroup.length; i++) {	
				buttonGroup[i].checked = false;
		  	}
		}
		else {	// Al no existir el grupo pero buttonGroup tener un valor, se asume que solo tenemos un radiobutton.
			buttonGroup.checked = false;
		}
	}
} 
//-------------------------------------------------------------------------------------------------

//-------------------------------------------------------------------------------------------------
/* This script and many more are available free online at
   The JavaScript Source :: http://javascript.internet.com 
   Copyright Robert Nyman, http://www.robertnyman.com
   Free to use if this text is included */

function getElementsByAttribute(oElm, strTagName, strAttributeName, strAttributeValue){
	var arrElements = (strTagName == "*" && document.all) ? document.all : oElm.getElementsByTagName(strTagName);
    var arrReturnElements = new Array();
    var oAttributeValue = (typeof strAttributeValue != "undefined")? new RegExp("(^|\\s)" + strAttributeValue + "(\\s|$)") : null;
    var oCurrent;
    var oAttribute;
	
    for(var i=0; i<arrElements.length; i++){
        oCurrent = arrElements[i];
        oAttribute = oCurrent.getAttribute(strAttributeName);
        if(typeof oAttribute == "string" && oAttribute.length > 0){
            if(typeof strAttributeValue == "undefined" || (oAttributeValue && oAttributeValue.test(oAttribute))){
                arrReturnElements.push(oCurrent);
            }
        }
    }
    return arrReturnElements;
}
//-------------------------------------------------------------------------------------------------
/* Elimina los espacios al principio y al final en una cadena. */
//-------------------------------------------------------------------------------------------------
function trim(cadena)
{
	for(i=0; cadena.charAt(i)==" "; i++){} 
	cadena=cadena.substring(i); 
	
	for(i=cadena.length-1;cadena.charAt(i)==" "; i--){} 
	return cadena.substring(0,i+1); 
}
//-------------------------------------------------------------------------------------------------
/* Determina si una variable cualquiera está vacía. */
//-------------------------------------------------------------------------------------------------
function empty (mixed_var) {    
    var key;
    
    if (mixed_var === "" ||
        mixed_var === 0 ||
        mixed_var === "0" ||
        mixed_var === null ||
        mixed_var === false ||
        mixed_var === undefined
    ){
        return true;
    }
 
    if (typeof mixed_var == 'object') {
        for (key in mixed_var) {
            return false;
        }
        return true;
    }
 
    return false;
}
//-------------------------------------------------------------------------------------------------
/* Determina si una variable cualquiera en forma de cadena equivale a un valor numérico entero o
   flotante. */
//-------------------------------------------------------------------------------------------------
function IsNumeric(sText)
{
   var ValidChars = "0123456789.";
   var IsNumber=true;
   var Char;

   for (i = 0; i < sText.length && IsNumber == true; i++) { 
      Char = sText.charAt(i); 
	  
      if (ValidChars.indexOf(Char) == -1) {
         IsNumber = false;
      }
   }
   return IsNumber;   
}
//---------------------------------------------------------------------------
// Realiza la ordenación de la tabla indicada en base a la columna pasada como
// parámetro.
// col1 = Columna en base a la cual se realizará el ordenamiento de datos.
// col2 = Segundo criterio de ordenamiento.
// datType1 y datType2 = Tipo de dato de col1 y col2 respectivamente.

// *********** NOTA: ÉSTA FUNCIÓN NO ESTÁ EN USO YA QUE NO SE HA ESTANDARIZADO PARA TODOS LOS CASOS **************
// Se incluye para cada rutina de manera individual.
//---------------------------------------------------------------------------
/*function SortColumn(cellObj, tabName, hdrName, col1, col2, datType1, datType2) {
	if (sortedCol != col1) {
		document.getElementById(hdrName).rows[1].cells[sortedCol].getElementsByTagName('span')[0].innerText='';
		sortedCol=col1;
	}
	else {
		if (sortOrder == "asc") {
			sortOrder = "desc";
		}
		else {
			sortOrder = "asc";
		}
	}	

	if(sortOrder == 'asc') {
		SortHtmlTable(tabName,col1,col2,'ASC',datType1,datType2);
		cellObj.getElementsByTagName('span')[0].innerText = 'p';		
	}
	else{
		SortHtmlTable(tabName,col1,col2,'DESC',datType1,datType2);								
		cellObj.getElementsByTagName('span')[0].innerText = 'q';
	}	
} */
//---------------------------------------------------------------------------

//---------------------------------------------------------------------------
// Verifica que una fecha sea correcta.
//---------------------------------------------------------------------------
function IsValidDate(Day,Mn,Yr){
	var dt = new Date(Yr,Mn-1,Day,00,00,00);

	if(dt.getDate()!=Day) {
		return(false);
	}
    else if (dt.getMonth() != (Mn-1)) {
		return(false);
	}
    else if (dt.getFullYear() != Yr) {
		return(false);
	}        
    return(true);
 }
//-------------------------------------------------------------------------------------------------

//---------------------------------------------------------------------------
// Aplica un formato de tipo dd/mm/aaaa a un dato de tipo fecha (Date)
//---------------------------------------------------------------------------
function FormatDate(dt) {
	var dia = dt.getDate();
	var mes = (dt.getMonth()+1);
	var year = dt.getFullYear();
	var fecha = "";
	
	if (!empty(dia) && !empty(mes) && !empty(year) && !empty(dt)) {	
		if (dia < 10) {
			dia = "0"+dia;
		}
		if (mes < 10) {
			mes = "0"+mes;
		}
		
		fecha = dia+"/"+mes+"/"+year;
	}
	else {
		fecha = "--";
	}
	return (fecha);
 }
//-------------------------------------------------------------------------------------------------

//---------------------------------------------------------------------------
/* Analiza los datos de un proyecto y devuelve un valor de status para el mismo
   que puede ser: (A)bierto, (E)n proceso, a(U)torizando, (D)etenido, (C)errado.
   Recibe como parámetros una lista de entregables del proyecto con sus estados,
   que pueden ser: (E)n proceso, a(U)torizando, (D)etenido o (C)entregado. El 
   arreglo de entregables solamente es una lista de status de los entregables 
   del proyecto.
   
   Supuesto: El status del proyecto depende en su totalidad del status de sus
   entregables. Una alerta de proyecto es distinta del status de proyecto. */
//---------------------------------------------------------------------------
function GetPrjStatus(listaEnt) {
	var i = 0;
	var detenidos = 0;
	var entregados = 0;
	var autorizando = 0;
	var abiertos = 0;
		
	for (i=0; i<listaEnt.length; i++) {
		switch (listaEnt[i]) {
			case "E": abiertos++; break;
			case "U": autorizando++; break;
			case "D": detenidos++; break;
			case "C": entregados++; break;
		}
	}
	
	if (detenidos > 0) {		// Cuando hay entregables detenidos, tienen prioridad en la afectación del status de proyecto.
		return "D";
	}
	if (autorizando > 0) {		// Su se está autorizando un entregable éste tiene prioridad sobre los abiertos y entregados.
		return "U";
	}
	if (entregados == 0) {
		return "A";
	}
	if (abiertos == 0 && entregados > 0) {	// No hay abiertos y los demás están entregados
		return "C";							// Proyecto cerrado.
	}
	if (entregados > 0 && abiertos > 0) {	// Hay entregados y otros en abierto
		return "E";
	}
	return "";		// Regresa vacío cuando no se identifica el status.
}
//------------------------------------------------------------------------------------------------------	

//------------------------------------------------------------------------------------------------------	
// AlertaPrj: Indica un estado de alerta para un proyecto determinado según lo siguiente:
// 0=Terminado, 1=Verde, 2=Amarillo, 3=Rojo, -1=error. La alerta varía según se trate de un cliente o un asesor.
/* Recibe los siguientes parámetros: 
		listaEnts: Una matriz listando los entregables con dos datos: 
					listaEnts[0]=status,listaEnts[1]=vencimiento del entregable   
		avance: Avance total del proyecto al momento. 
		inicio: Fecha de inicio del proyecto.
		status: Estado actual del proyecto, "A","E","U","D" o "C".  
		venc: Fecha de vencimiento del proyecto.	(dd/mm/aaaa)
		hoy: fecha actual (dd/mm/aaaa)
		esCliente: Indica T o F si la alerta será emitida a un cliente o no (asesor, supervisor o admin).*/
//------------------------------------------------------------------------------------------------------	
function AlertaPrj(listaEnts, avance, inicio, status, venc, hoy, esCliente) {
	if (empty(venc) || empty(inicio) || empty(status) || empty(hoy)) {
		return -1;
	}
	var dthoy = new Date(hoy.substring(6),hoy.substring(3,5)-1,hoy.substring(0,2));
	var dtvenc = new Date(venc.substring(6),venc.substring(3,5)-1,venc.substring(0,2));
	var dtinicio = new Date(inicio.substring(6),inicio.substring(3,5)-1,inicio.substring(0,2));
	var one_day = 1000*60*60*24;
	var porcdeseado = 0;		// Porcentaje deseado tiene una tolerancia del 10% respecto al porcentaje de avance previsto según el tiempo transcurrido.
	
	if (avance == 100) {		// Proyecto terminado
		return 0;
	}			
	// Detectar atrasos en proyecto que se muestran tanto al cliente como al asesor.
	if (CompareValues(venc,hoy,"date") < 0) {
		return 3;
	}
	else {
		for (var i=0; i<listaEnts.length; i++) {
			if (listaEnts[i][0] != "C" && CompareValues(listaEnts[i][1],hoy,"date") < 0) {	// No cerrado y vencimiento menor a hoy.
				return 3;
			}		
		}			
	}

	if (!esCliente) {	
		// De acuerdo a la duración del proyecto.
		var duracion = Math.ceil((dtvenc.getTime()-dtinicio.getTime())/(one_day));
		var transcurrido = Math.ceil((dthoy.getTime()-dtinicio.getTime())/(one_day))-1; // Se le resta 1 para no considerar el día actual como transcurrido.
		
		if (transcurrido > 0) {									// El proyecto ya inició
			porcDeseado = ((transcurrido*100)/duracion)-10;		// Tiene una tolerancia de 10%
			
			if (porcDeseado > avance) {
				return 2;										// Amarillo, aunque no vencido, tiene tendencia a retrasarse.
			}
		}
		if (status == 'D' || status == 'U') {					// Detenido o autorizando devuelve status amarillo.
			return 2;
		}
		return 1;	// Ok
	}
	else {														// Tratándose de un cliente quien consulta el status
		if (status == 'U' || status == 'D') {					// Detenido o Autorizando devuelve amarillo.
			return 2;
		}
		return 1;	// Ok		
	}
}
//------------------------------------------------------------------------------------------------------

//------------------------------------------------------------------------------------------------------	
// AlertaHito: Indica un estado de alerta para un entregable determinado según lo siguiente:
// 0=Terminado, 1=Verde, 2=Amarillo, 3=Rojo. La alerta varía según se trate de un cliente o un asesor.
//------------------------------------------------------------------------------------------------------	
function AlertaHito(inicioPrj, status, venc, hoy, esCliente) {
	var dthoy = new Date(hoy.substring(6),hoy.substring(3,5)-1,hoy.substring(0,2));
	var dtvenc = new Date(venc.substring(6),venc.substring(3,5)-1,venc.substring(0,2));
	var dtinicio = new Date(inicioPrj.substring(6),inicioPrj.substring(3,5)-1,inicioPrj.substring(0,2));
	var one_day = 1000*60*60*24;
	var cadena = "";
	
	if (status == "C") {		// Hito entregado
		return 0;
	}		
	// Detectar vencimiento en entregable
	if ( CompareValues(hoy,venc,"date") > 0 )  {	// Cuando la fecha actual es mayor que la de vencimiento 
		return 3;			// Rojo
	}
	if (status == "D") {	// Detenido
		return 2;			// Amarillo
	}
	
	if (!esCliente) {			
		// Cuando no está vencido o detenido, detectar estados amarillos		
		var duracion = Math.ceil((dtvenc.getTime()-dtinicio.getTime())/(one_day));
		var umbral = Math.round(duracion*0.10);				// Umbral de 10% de la duración para alertar antes del vencimiento
		
		var fchUmbral = new Date();	
		fchUmbral = dtvenc;
		fchUmbral.addDays((umbral*-1));
//		var milisegs = dtvenc.getTime()-(umbral * one_day);	// Calcular fecha de tolerancia restando el umbral del vencimiento.
//		fchUmbral.setTime(milisegs);						// Transformar la fecha de tolerancia a "DATE";
		var strUmbral = FormatDate(fchUmbral);				// Expresar la fecha umbral en el formato dd/mm/aaaa

		if ( CompareValues(hoy,strUmbral,"date") >= 0 || status == "U") {	// La fecha entra en el umbral previo al vencimiento
			return 2;				// Amarillo
		}		
		return 1;
	}
	else {
		if (status == 'U') {		// Detenido o autorizando.
			return 2;
		}
		return 1;			
	}
}
//------------------------------------------------------------------------------------------------------	

//------------------------------------------------------------------------------------------------------	
/* Prototipo del objeto "Date" para permitir la suma y resta de días a una fecha determinada. 
   Ej: fecha.addDays(1); */
//------------------------------------------------------------------------------------------------------	
Date.prototype.addDays = function(days) {
	this.setDate(this.getDate()+days);
}
//------------------------------------------------------------------------------------------------------	

//------------------------------------------------------------------------------------------------------	
/*  InputVsTableIndex: Ésta función recibe como parámetros un nombre asignado a un conjunto de controles
    de tipo "input" (inputName) que funcionan como "radio buttons" y un arreglo (dataList) que contiene 
	una lista de datos referentes a esos "radio buttons". 
	El propósito de la función será el de regresar el índice del arreglo en donde se encuentran los datos 
	del "radio button" seleccionado en ese momento.
	Su aplicación está enfocada al manejo de tablas de datos con "radio buttons" para seleccionar sus
	renglones y en donde tenemos la tabla en un arreglo "caché" en donde hacemos consultas y modifica-
	ciones locales antes de afectar la base de datos. Para ésto, necesitamos localizar el registro que
	ha sido seleccionado para recibir éstas operaciones.
	El parámetro idIndex indicará el índice de cada renglón del arreglo en donde se encuentra el "id"
	del registro correspondiente de la tabla, para compararlo con el valor del control "input" y deter-
	minar si corresponden.
	Regresa el índice del arreglo en caché en donde se encuentran los datos del input seleccionado.
*/
//------------------------------------------------------------------------------------------------------	
function InputVsTableIndex(inputName, dataList, idIndex) {
	var inputGroup = getElementsByAttribute(document,'input','name',inputName);		// Obtener los botones de radio que correspondan con el nombre
	var selInput = -1;																// Almacena el índice del control input seleccionado en ese momento.
	var inputValue = -1;															// Almacena el valor del input seleccionado.
	var index = -1;																	// Almacena el índice del arreglo que corresponde con el input seleccionado.
	
	if (inputGroup != null) {
		selInput = getSelectedRadio(inputGroup);									// Obtiene el índice del input seleccionado y lo almacena.	

		if (selInput >= 0) {
			inputValue = inputGroup[selInput].value;								// Almacenar el valor del input seleccionado
	
			for (var i=0; i<dataList.length; i++) {									// Compara valor del input con id en arreglo de datos.
				if (dataList[i][idIndex] == inputValue) {
					index = i;														// Encontrado, almacenamos el índice
					i = dataList.length;
				}
			}
		}
	}
	return index;
}
//------------------------------------------------------------------------------------------------------	

//------------------------------------------------------------------------------------------------------	
/*  SelInputByValue: Recibidos un valor cualquiera y un nombre de un conjunto de controles "input", ésta
	función seleccionará el primer control input que coincida con el valor señalado en los parámetros.*/
//------------------------------------------------------------------------------------------------------	
function SelInputByValue(inputName, inputValue) {
	var inputGroup = getElementsByAttribute(document,'input','name',inputName);		// Obtener los botones de radio que correspondan con el nombre
	
	if (inputGroup != null) {
		if (inputGroup.length >= 1) {		
			for (var i=0; i<inputGroup.length; i++) {			
				if (inputGroup[i].value == inputValue) {
					inputGroup[i].checked = true;
					i = inputGroup.length;
			 	}
			}
		}
	}	
}
//------------------------------------------------------------------------------------------------------	

//------------------------------------------------------------------------------------------------------	
/*  GetRowInputs: Obtiene todos los controles input encontrados en el renglón de una tabla.
	La función recibe como parámetro el renglón mismo de la tabla o cualquier elemento que se encuentre
	dentro del renglón como una celda, un div, un label, etc. Solo elementos contenidos en el row.
	La función regresará un error si se pasa una tabla o cualquier elemento no contenido en un renglón
	de tabla (tr), también regresa null si no encuentra ningún input en el renglón. */
//------------------------------------------------------------------------------------------------------	
function GetRowInputs(xObj) {
	var rowObj = xObj;
	var oInputs;

	while (rowObj != null && typeof(rowObj)!="undefined" && rowObj.tagName.toString()!="TR" ) {
		rowObj = rowObj.parentNode;
	}		
	if (rowObj != null && rowObj.tagName.toString() == "TR") {
		oInputs = rowObj.getElementsByTagName("input");
		
		if (oInputs.length > 0) {
			return oInputs;
		}
		else {
			return null;
		}
	}
	else {
		return null;
	}
}
//------------------------------------------------------------------------------------------------------	

//------------------------------------------------------------------------------------------------------	
function addslashes(str) {
	str=str.replace(/\\/g,'\\\\');
	str=str.replace(/\'/g,'\\\'');
	str=str.replace(/\"/g,'\\"');
	str=str.replace(/\0/g,'\\0');
	return str;
}
//------------------------------------------------------------------------------------------------------	

//------------------------------------------------------------------------------------------------------	
function stripslashes(str) {
	str=str.replace(/\\'/g,'\'');
	str=str.replace(/\\"/g,'"');
	str=str.replace(/\\0/g,'\0');
	str=str.replace(/\\\\/g,'\\');
	return str;
}
//------------------------------------------------------------------------------------------------------	

//------------------------------------------------------------------------------------------------------	
/*  PopulateList: Recibe como parámetro el objeto de lista al cual se agregará la información y un arreglo
	con la información a ser agregada el cual contiene la clave del item y el nombre a mostrar en la lista
	en las posiciones 0 y 1 respectivamente.
	Regresa "true" al tener éxito y "false" si no se pudo cargar la información. */
//------------------------------------------------------------------------------------------------------	
function PopulateList(listObj, infoArray) {
	if (infoArray.length > 0) {
		for (var i=0; i<infoArray.length; i++) {
			CreateSelRow(listObj.id,infoArray[i][1],infoArray[i][0]);
		}
		return true;
	}
	return false;
}
//---------------------------------------------------------------------------

//---------------------------------------------------------------------------
// Busca un valor en el objeto de lista de selección enviada como parámetro y 
// lo selecciona de encontrarlo en la misma.
//---------------------------------------------------------------------------
function selOptionByValue(selObj, value) {
	var i = 0;
	var exit = false;
	
	for (i=0; i<selObj.options.length && !exit; i++) {
		if (selObj.options[i].value == value) {
			selObj.options[i].selected = true;
			exit = true;
		}
	}
}
//---------------------------------------------------------------------------

//---------------------------------------------------------------------------
// Regresa true si existe el objeto con el ID enviado como parámetro y false
// en caso contrario.
//---------------------------------------------------------------------------
function Exist(objId) {
	if (document.getElementById(objId) != null) {
    	return true;
    }
    else {
    	return false;
    }
}
//---------------------------------------------------------------------------