function getObject(id) { return document.getElementById(id); }

function idle() {}

/** List Tables ***************************************************************/

function isActive(tr)
{
   var imgs = tr.getElementsByTagName('img');
   for (var i = 0; i < imgs.length; i++)
   {
      if (imgs[i].src.match('-deactivated.') != null) return false;
      else if (imgs[i].src.match('-activated.') != null) return true;
   }
   return false;
}

function isOpen(tr)
{
   if (!tr) return true;
   var imgs = tr.getElementsByTagName('img');
   return imgs ? imgs[0].src.match('open') != null : true;
}

/**
 * Expande/contrae los elementos de un grupo en la tabla.
 * @param object a: Vinculo asociado al icono de grupo clickeado.
 * @param bool noRefresh: TRUE para que las filas de la tabla no sean refrescadas.
 */
function expand(a,noRefresh)
{
   var tr      = a.parentNode.parentNode.nextSibling;

   var img     = a.firstChild;
   var is_open = img.src.match('open') != null;
   img.title   = is_open ? ETQjs_st_open : ETQjs_st_close;
   img.src     = 'picsV2/' + (is_open ? 'close' : 'open') + '.gif';
   var display = is_open ? 'none' : '';

   while (tr && (!tr.title || tr.title != ' '))
   {
      if (tr.style)
      {
         if (GLOBAL_showInactives_mode || isActive(tr))
            tr.style.display = display;
      }
      tr = tr.nextSibling;
   }
   if (!noRefresh) refresh_table_rows();
}

/**
 * Expande o contrae (según el modo indicado) los elementos de la tabla.
 * @param enum mode: Modo. 'open' para expandir, 'close' para contraer.
 */
function expandAll(mode)
{
   var td; var a; var img;
   var trs = getObject("rows").getElementsByTagName('tr');
   for (var i=0; i < trs.length; i++) if (trs[i].title == ' ')
   {
      td  = trs[i].getElementsByTagName('td')[0];
      a   = td.getElementsByTagName('a')[0];
      img = a.firstChild;
      if (img.src.match(mode) == null) expand(a,true);
   }
   refresh_table_rows();
}

/**
 * Muestra/oculta las filas cuyos elementos aparecen con estado inactivo.
 * @param bool stGrPos: Posición en la tabla de la columna de estado para grupos. -1 si no la hay.
 * @param bool stElPos: Posición en la tabla de la columna de estado para elementos. -1 si no la hay.
 * @param object aObj: Referencia al vinculo clickeado.
 */
function showInactives(stGrPos,stElPos,aObj)
{
   if (GLOBAL_showInactives_mode = (aObj.innerHTML.match(ETQjs_mo) != null)) // Muestro
   {
      aObj.innerHTML = '[' + ETQjs_oc + ']'; //aObj.innerHTML.replace(ETQjs_mo,ETQjs_oc);
      mode = '';
   }
   else // Oculto
   {
      aObj.innerHTML = '[' + ETQjs_mo + ']'; //aObj.innerHTML.replace(ETQjs_oc,ETQjs_mo);
      mode = 'none';
   }

   var td; var icon; var prevGrPos; var pos;
   var trs = getObject("rows").getElementsByTagName('tr');
   for (var i=0; i < trs.length; i++)
   {
      if (trs[i].title == ' ') prevGrPos = i;
      if (prevGrPos == i || isOpen(trs[prevGrPos]))
      {
         pos = trs[i].title == ' ' ? stGrPos : stElPos;
         if (pos != -1)
         {
            td = trs[i].getElementsByTagName('td')[pos];
            icon = td.firstChild.firstChild.src.split('-')[1];
            if  (icon != 'activated.gif') trs[i].style.display = mode;
         }
      }
   }
   refresh_table_rows();
}
var GLOBAL_showInactives_mode = true;

/**
 * Refresca los colores de las filas de la tabla, intercalándolos entre gris y blanco.
 */
function refresh_table_rows()
{
   var rows = getObject('rows').getElementsByTagName('tr');
   var name = '';
   for (var i=0; i < rows.length; i++)
   {
      if (rows[i].style.display != 'none')
      {
         name = (name == '') ? 'odd' : '';
         rows[i].className = name;
      }
   }
}

function popup(url, width, height, name)
{
   var anchoVent; var altoVent; var topVent; var leftVent;
   var w = window.screen.width; var h = window.screen.height;

   if (name==null) name='popup';

   anchoVent = width; altoVent = height;
   leftVent  = (w - anchoVent) / 2;
   topVent   = (h - altoVent)  / 3;

   obj_popup = window.open(url, name, 'buttons=0, toolbar=0, location=0, status=0, directories=0, menubar=0, scrollbars=1, resizable=0, width='+anchoVent+', height='+altoVent+', top='+topVent+', left='+leftVent);  // 'titlebar=0
   obj_popup.opener = self;

   if (obj_popup == null || typeof(obj_popup) == "undefined")
   {
      alert(ETQjs_su);
   }
}

function csv(mode, tbid, id, data, append)
{
   switch (mode)
   {
      case 'sv': // Save
         var trs = getObject(tbid).getElementsByTagName('TR');
         var tds; var line; var file = '';
         for (var i=1; i < trs.length; i++)
         {
            tds = trs[i].getElementsByTagName('TD');
            line = '';
            for (var j=0; j < tds.length - 1; j++)
            {
               line += (line ? ';' : '') + tds[j].firstChild.value;
            }
            file += line + '[EOLn]';
         }
         var html = '<input type="hiden" name="id"   value="'+id+'"/>';
         html    += '<input type="hiden" name="body" value="'+file+'"/>';
         html    += '<input type="submit" id="hform_submit" name="save" value="1"/>';
         getObject('hform').innerHTML += html;
         getObject('hform').action = "/content_csv.php";
         getObject("hform_submit").click();
         break;

      case 'ld': // Load
         popup('/content_csv.php?load&id='+id+'&tbid=' + tbid,400,150,'load');
         break;

      case 'fl': // Fill
         var tbody = getObject(tbid);
         var trs   = tbody.getElementsByTagName('TR');
         var lines = data.split('&lt;EOL&gt;');
         var values; var tr; var tds;
         if (!append) for (var i=1; i < trs.length; i++) tbody.removeChild(trs[i]);
         for (var i=0; i < lines.length; i++)
         {
            values = lines[i].split(';');
            tr = trs[0].cloneNode(1); tr.style.display = '';
            trs[0].parentNode.appendChild(tr);
            tds = tr.getElementsByTagName('TD');
            for (var j=0; j < values.length; j++)
            {
               if (tds[j].firstChild.nodeName == 'INPUT')
               {
                  tds[j].firstChild.value = values[j];
                  tds[j].firstChild.style.backgroundColor = '#FFFFFF';
                  try { shift_options(tds[j].firstChild); } catch (e) { /* Si no es una Tivia, pasa por acá. */ };
               }
               else // nodeName == 'SELECT'
               {
                  setSelectValue(tds[j].firstChild,values[j]);
               }
            }
         }
         var thead = tbody.parentNode.getElementsByTagName('THEAD')[0];
         var ths = thead.getElementsByTagName('TR')[0].getElementsByTagName('TH');
         if (append)
            ths[ths.length-1].firstChild.innerHTML = (ths[ths.length-1].firstChild.innerHTML - 0) + lines.length;
         else
            ths[ths.length-1].firstChild.innerHTML = lines.length;
         break;
   }
}

/** Selects y Radiobuttons ****************************************************/

function isMaxLength(obj)
{
   var mlength = obj.getAttribute ? parseInt(obj.getAttribute("maxlength")) : "";
   if (obj.getAttribute && obj.value.length > mlength) obj.value = obj.value.substring(0,mlength);
}

/**
 * Dado un array de radiobuttons, retorna el valor del radiobutton seleccionado.
 * @param array: Array de radiobuttons.
 * @return: Valor asociado al radiobutton seleccionado. De no haberlo, retorna ''.
 */
function getRadioValue(array)
{
	for (var i = 0; i < array.length; i++)
		if (array[i].checked) return array[i].value;
	return '';
}

/**
 * Dado un array de radiobuttons, selecciona el radiobutton cuyo valor es el indicado.
 * @param array: Array de radiobuttons.
 * @param value: Valor del radiobutton a seleccionar.
 */
function setRadioValue(array,value)
{
   value = value.toLowerCase();
	for (var i = 0; i < array.length; i++)
	{
		if (array[i].value.toLowerCase() == value) array[i].checked = true;
		else array[i].checked = false;
	}
}

/**
 * Dado un objeto select, retorna su objeto option seleccionado.
 * @param array: Objeto select.
 * @param value: (opcional) Si se lo indica, retorna el option asociado a ese valor.
 * @return: Objeto option seleccionado, NULL en caso de error.
 */
function getSelectOption(array,value)
{
   if (value)
   {
      try { value = value.toLowerCase() } catch (ex) { value = value.toString().toLowerCase() } ;
   	for (var i = 0; i < array.options.length; i++)
   		if (array.options[i].value.toLowerCase() == value)
   		   return array.options[i];
   }
   else if ((array.selectedIndex >= 0) && (array.selectedIndex < array.options.length))
   	return array.options[array.selectedIndex];
   return null;
}

/**
 * Dado un objeto select, retorna el valor de la opción seleccionada.
 * @param array: Objeto select.
 * @return: Valor asociado a la opción seleccionada.
 */
function getSelectValue(array)
{
   if ((opt = getSelectOption(array)) != null)
   	return opt.value;
   return false;
}

/**
 * Dado un objeto select, retorna el texto de la opción seleccionada.
 * @param array: Objeto select.
 * @param value: (opcional) Si se lo indica, retorna el texto de la opción asociada a ese valor.
 * @return: Texto asociado a la opción seleccionada.
 */
function getSelectText(array,value)
{
   if ((opt = getSelectOption(array,value)) != null)
      return opt.text;
   return false;
}

/**
 * Dado un objeto select, selecciona la opción cuyo valor es el indicado.
 * @param array: Objeto select.
 * @param value: Valor de la opción a seleccionar.
 */
function setSelectValue(array,value)
{
   if ((opt = getSelectOption(array,value)) != null)
      array.selectedIndex = opt.index;
}

/**
 * Dado un objeto select, selecciona la opción cuyo texto es el indicado.
 * @param array: Objeto select.
 * @param value: Texto de la opción a seleccionar.
 */
function setSelectText(array,text)
{
	var ok = false;
	for (var i = 0; (i < array.options.length) && !ok; i++)
	{
		if (array.options[i].text == text)
		{
			array.selectedIndex = array.options[i].index;
			ok = true;
		}
	}
}

/**
 * Agrega una nueva opción al objeto select indicado.
 * @param select: Objeto select.
 * @param txt: Texto de la opción a mostrar.
 * @param val: Valor de la opción.
 * @param sel: Booleano que indica si la opción debe estar o no seleccionada.
 */
function addSelectOption(select,txt,val,sel)
{
   select.options[select.length] = new Option(txt,val,false,sel);
}

/**
 * Quita una opción al objeto select indicado.
 * @param select: Objeto select.
 * @param ind: Posición de la opción a eliminar (entre 0 y select.length - 1)
 */
function delSelectOption(select,ind)
{
   select.options[ind] = null;
}

/**
 * Quita todas las opciones al objeto select indicado.
 * @param select: Objeto select.
 */
function cleanSelect(select)
{
   for (var i = select.options.length - 1; i >= 0; i--)
      select.options[i] = null;
}

/** Validators ****************************************************************/

/**
 * Verifica que el string ingresado sea un número natural.
 * @param str: String a verificar.
 * @return: TRUE en caso que 'str' sea un natural, FALSE en caso contrario.
 */
function natural(str)
{
	if (str.length == 0 || str == '0') return false;
	for (var i = 0; i < str.length; i++)
		if (str.charAt(i) < '0' || str.charAt(i) > '9')
			return false;
	return true;
}

/**
 * Verifica que el string ingresado sea un número entero.
 * @param str: String a verificar.
 * @return: TRUE en caso que 'str' sea un entero, FALSE en caso contrario.
 */
function integer(str)
{
	if (str.length == 0) return false;
	for (var i = 0; i < str.length; i++)
		if (str.charAt(i) < '0' || str.charAt(i) > '9')
			return false;
	return true;
}

/**
 * Verifica que el string ingresado sea una constante de color hexadecimal (#rrggbb).
 * @param str: String a verificar.
 * @return: TRUE en caso que 'str' sea un color, FALSE en caso contrario.
 */
function isColor(color)
{
   return ((color.length == 7) && (color.match("#([0-9a-fA-F]{6})") != null));
}

/** Messages ******************************************************************/

/**
 * Exhibe un cuadro de diálogo con el mensaje indicado.
 * Dicho cuadro se oculta automáticamente luego de 10 segundos o clickeando sobre él.
 * Estructura del cuadro de dialogo:
 *    <div id="div_msg"><div><span></span></div></div>
 *
 * @param txt: Texto a mostrar.
 * @param success: Indica si el texto es informativo (true) o de error (false).
 *                     Dependiendo de ello se aplica un class diferente al div div_class (okay o errorm).
 *                     Si no se lo especifica, se asume que el texto es de error.
 * @param focusId: Id del objeto donde focalizar el documento en caso de error.
 *                     Si no se lo especifica, no se produce ningún intento de focalización.
 */
function showMessage(txt, success, focusId, suffix)
{
   var a = getObject( 'div_msg' + (!suffix ? '' : '.' + suffix) );
   var panel = a.firstChild.cloneNode(1);

   panel.firstChild.firstChild.innerHTML = txt;
   panel.firstChild.firstChild.title = !focusId ? '' : focusId;
   panel.firstChild.className = success ? "ok" : "nok";

   panel.style.position = 'relative';
   panel.style.cursor   = 'pointer';
   panel.style.display  = 'block';

   //if (panel.firstChild.id) clearTimeout(panel.firstChild.id);
   //panel.firstChild.id = setTimeout("getObject('"+pid+"').style.display = 'none'",10000);

   document.location.href = '#div_msg' + (!suffix ? '' : '.' + suffix);
   a.appendChild(panel)
}

/**
 * Quita el cuadro de diálogo generado con showMessage.
 */
function quitMessages(suffix)
{
   var a = getObject( 'div_msg' + (!suffix ? '' : '.' + suffix) );
   for (var i = a.childNodes.length - 1; i > 0; i--)
   {
      //if (a.childNodes[i].firstChild.id) clearTimeout(a.childNodes[i].firstChild.id);
      a.removeChild(a.childNodes[i]);
   }
   if (a.childNodes[0].style.display != 'none') a.childNodes[0].style.display = 'none';
}
