/*
Hint library
Biblioteca JavaScript para mostrar hints

Para usarla, incluirla dentro del tag BODY antes de los elementos con hint,
y agregar el llamado a la función hl_show() en el evento onmouseover:
<body>
  <script language="Javascript" src="hl.js"></script>
  <span onmouseover="hl_show(event,'Texto del hint')">Texto</span>
</body>

Esta biblioteca usa ideas de wz_tooltip.js v. 3.24 (http://www.walterzorn.com),
por lo que debe tener la siguiente licencia:

This program is free software;
you can redistribute it and/or modify it under the terms of the
GNU General Public License as published by the Free Software Foundation;
either version 2 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY;
without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License
at http://www.gnu.org/copyleft/gpl.html for more details.
*/

// ****************** Parametros ******************
var hl_offX = 0;    // px, desplazamiento horizontal desde el puntero del mouse
var hl_offY = 19;   // px, desplazamiento vertical desde el puntero del mouse
var hl_delay = 200; // millisegundos, el tiempo de espera antes de mostrar el hint
var hl_borderColor = '#333333';
var hl_borderWidth = '1px';
var hl_backgroundColor = 'white';
var hl_fontFamily = 'Verdana, Arial, Helvetica, sans-serif';
var hl_fontSize = '10px';
var hl_color = '#333333';
var hl_shadowColor = '#333333';
var hl_shadowSize = '2';
var hl_shadowDirection = 135;
var hl_padding = 3;
// ************* Fin de los parametros ************

// Funciona para Internet Explorer 5.x y superiores, y Netscape Navigator 7.x y superiores.
// Se verificó la compatibilidad mediante consultar:
// http://msdn.microsoft.com/workshop/author/dhtml/reference/dhtml_reference_entry.asp
// http://www.w3schools.com/css/css_reference.asp
// El libro "JavaScript: The Definitive Guide, Fourth Edition", David Flanagan, O'Reilly and Associates, 2002.

// IE4 = Internet Explorer 4
// NN4 = Netscape Navigator 4
// NN6 = Netscape Navigator 6
// Compatibilidad:
// document.all        IE4
// style.visibility    IE4 NN6
// style.left          IE4 NN4
// style.top           IE4 NN4
// style.cursor        IE4 NN6
// style.cursor=pointer IE6 NN6
// style.cursor=hand    IE5
// style.pixelWidth    IE4 N/A
// style.pixelHeight   IE4 N/A
// offsetWidth         IE4 ?    (Es un atributo del elemento DOM HTMLElement)
// offsetHeight        IE4 ?    (Es un atributo del elemento DOM HTMLElement)
// getAttribute        IE4 ?    (Es un atributo del elemento DOM HTMLElement)
// body.clientWidth    IE4
// body.clientHeight   IE4
// option.offsetLeft   IE4
// option.offsetTop    IE4
// option.offsetParent IE4
// option.offsetParent IE4
// span.innerHTML      IE4 NN6
// window.pageXOffset     NN
// window.pageYOffset     NN
// window.innerWidth      NN
// window.innerHeight     NN
// window.event           IE
// document.captureEvents NN
// document.releaseEvents NN
// body.scrollLeft        IE
// body.scrollTop         IE
// body.clientWidth       IE
// body.clientHeight      IE
// event.pageX            NN
// event.clientX          IE
// event.srcElement       IE
// event.target           NN
// event.pageY            NN
// event.clientY          IE

var hl_evX; // coordenada X donde está el puntero del mouse
var hl_evY; // coordenada X donde está el puntero del mouse
var hl_txt; // texto a mostrar en el hint
var hl_selects = new Array();   // elementos con el tag SELECT a ser escondidos en IE debido a un bug que impide que los div estén encima de ellos

var hl_body = (document.compatMode && document.compatMode != "BackCompat") ? document.documentElement : document.body; // el elemento BODY real
var hl_hint; // elemento hl_hint

var hl_userAgent = navigator.userAgent.toLowerCase();
var hl_msieIndex = hl_userAgent.indexOf("msie");
var hl_ie = document.all; // es IE
var hl_ie5 = hl_ie && hl_msieIndex != -1 && hl_body && ( ! (window.opera && document.getElementById))
             && parseFloat ( hl_userAgent.substring ( hl_msieIndex+5, hl_userAgent.indexOf ( ";", hl_msieIndex ) ) )
             >= 5.00; // es IE 5.x o superior
var hl_ns6 = document.getElementById && ! hl_ie; // es NN6

function hl_init() {
  document.write('<style type="text/css">'+
                 '#hl_hint {'+
                 '  z-index:1010;'+
                 '  position: absolute;'+
                 '  left:-1000px;'+
                 '  top:-1000px;'+
                 '  visibility:hidden;'+
                 '  border: '+hl_borderWidth+' solid '+hl_borderColor+';'+
                 '  background-color: '+hl_backgroundColor+';'+
                 '  font-family: '+hl_fontFamily+';'+
                 '  font-size: '+hl_fontSize+';'+
                 '  color:#000000;'+
                 '  filter: progid:DXImageTransform.Microsoft.Shadow(color='+hl_shadowColor+',direction='+hl_shadowDirection+',strength='+hl_shadowSize+');'+
                 '}'+
                 '.hl_hint_class {'+
                 '  font-size: '+hl_fontSize+';'+
                 '  color: '+hl_color+';'+
                 '}'+
                 '</style>'+
                 '<!-- Los estilos CSS van inline pues Netscape al menos en la versión 7 no los lee si se ponen en una clase -->'+
                 '<div id="hl_hint"></div>');
  hl_hint = hl_ie ? document.all["hl_hint"] : hl_ns6 ? document.getElementById("hl_hint") : ""; // elemento hl_hint
}

// se prepara para mostrar el hint
function hl_show(evt) {
  if ( ! hl_soportado()) return;

  // grabar las coordenadas del puntero del mouse
  hl_grabaCoordenadas(evt);

  // grabar las coordenadas del puntero del mouse cuando se mueva
  if (document.captureEvents) document.captureEvents(Event.MOUSEMOVE);
  document.onmousemove = hl_grabaCoordenadas;

  hl_handPointer(evt);

  var el = hl_getEl(evt);
  el = hl_getParentWithAttribute(el, 'hl_hint');
  // guarda el texto a mostrar en el hint
  var hl_hint_code = el.getAttribute('hl_hint');
  var hl_hint_function = new Function(hl_hint_code); // ejecuta el código JavaScript definido en el atributo hl_hint del elemento
  hl_txt = hl_hint_function();

  // registra la función para desaparecer el hint
  el.onmouseout = hl_doHide;

  // registra la función para desaparecer el hint, debido a un bug en Internet Explorer, al menos en su versión 6.0.2900,
  // en el cual después de hacer "Atrás" y regresar a unaa página que muestra hints descompone las tablas anidadas que están
  // en dicha página.
  if (el.tagName == 'A') {
    el.onclick = hl_doHide;
  }

  // registra el timeout para mostrar el hint
  window.hl_timeout = window.setTimeout('hl_doShow();', hl_delay);
}

function hl_doHide() {
  // deja de grabar las coordenadas del puntero del mouse cuando se mueva
  if (document.releaseEvents) document.releaseEvents(Event.MOUSEMOVE);
  document.onmousemove = null;

  // desregistra el timeout para mostrar el hint
  if (window.hl_timeout) {
    window.clearTimeout(hl_timeout);
    window.hl_timeout = null;
  };

  // esconde el hint
  hl_hint.style.visibility = 'hidden';
  hl_hint.style.left = "-1000px";
  hl_hint.style.top = "-1000px";
  hl_hint.innerHTML = '';

  // muestra los tags SELECT, que fueron escondidos debido a un error en IE
  hl_hideSelects(false, 0, 0, 0, 0);
} // hl_doHide

// muestra el hint
function hl_doShow() {
  // desregistra el timeout para mostrar el hint
  if (window.hl_timeout) {
    window.clearTimeout(hl_timeout);
    window.hl_timeout = null;
  };

  hl_hint.innerHTML = '<table cellpadding="' + hl_padding + '" cellspacing="0"><tr><td class="hl_hint_class">'+hl_txt+'</td></tr></table>';

  var divWidth = hl_getWidth(hl_hint);
  var divHeight = hl_getHeight(hl_hint);

  var evX = hl_evX; // recupera la coordenada X donde está el puntero del mouse
  var evY = hl_evY; // recupera la coordenada Y donde está el puntero del mouse

 // desplaza con el offset especificado como parámetro
  evX += hl_offX;
  evY += hl_offY;

  // desplaza la coordenada X si es necesario para que se vea completo el hint
  var xMax = hl_Int((hl_body && hl_body.clientWidth) ? hl_body.clientWidth : window.innerWidth) // primero verifica para IE y luego para NN
             + hl_Int(window.pageXOffset || (hl_body ? hl_body.scrollLeft : 0) || 0)
             - divWidth;
  var xMin = hl_Int(window.pageXOffset || (hl_body ? hl_body.scrollLeft : 0) || 0); // averigua la coordenada X mínima en la que se puede poner el hint y todavía verse completo // primero verifica para NN y luego para IE
  if (evX > xMax) evX = xMax;
  if (evX < xMin) evX = xMin;

  // desplaza la coordenada Y si es necesario para que se vea completo el hint
  var yMax = hl_Int((hl_body && hl_body.clientHeight) ? hl_body.clientHeight : window.innerHeight) // primero verifica para IE y luego para NN
             + hl_Int(window.pageYOffset || (hl_body ? hl_body.scrollTop : 0) || 0)
             - divHeight;
  var yMin = hl_Int(window.pageYOffset || (hl_body ? hl_body.scrollTop : 0) || 0); // averigua la coordenada Y mínima en la que se puede poner el hint y todavía verse completo // primero verifica para NN y luego para IE
  if (evY > yMax) evY -= (divHeight + hl_offY + 5); // pone el hint arriba del puntero del mouse
  if (evY < yMin) evY = yMin;

  // mueve y muestra el hint
  hl_hint.style.left = evX;
  hl_hint.style.top = evY;
  hl_hint.style.visibility = 'visible';

  // esconde los tags SELECT, debido a un error en IE
  hl_getSelects();
  hl_hideSelects(true, evX, evY, divWidth, divHeight);
} // hl_doShow

function hl_getSelects() {
  if ( ! hl_ie) return; // sólo es necesario en IE

  var t_i = document.all.tags('select').length;
  while (t_i--)
    hl_selects[t_i] = document.all.tags('select')[t_i];

  var t_i = hl_selects.length;
  while (t_i--) {
    hl_selects[t_i].x = 0;
    hl_selects[t_i].y = 0;
    var t_o = hl_selects[t_i];
    while (t_o) {
      hl_selects[t_i].x += t_o.offsetLeft || 0;
      hl_selects[t_i].y += t_o.offsetTop || 0;
      t_o = t_o.offsetParent;
    }
  }
}

// esconde los elementos SELECT que están debajo del hint, y muestra todos los demás
function hl_hideSelects(visible, divX, divY, divWidth, divHeight) {
  if ( ! hl_ie || ! hl_selects) return;
  var t_o;
  var t_i = hl_selects.length;
  while (t_i--) {
    t_o = hl_selects[t_i];
    if (visible &&
        divX + divWidth > t_o.x &&
        divX < t_o.x + t_o.offsetWidth &&
        divY + divHeight > t_o.y &&
        divY < t_o.y + t_o.offsetHeight)
      t_o.style.visibility = 'hidden';
    else
      t_o.style.visibility = 'visible';
  }
}

function hl_grabaCoordenadas(evt) {
  // reinicia el timeout para mostrar el hint
  if (window.hl_timeout) {
    // desregistra el timeout
    window.clearTimeout(hl_timeout);
    // registra el timeout
    window.hl_timeout = window.setTimeout('hl_doShow();', hl_delay);
  };

  var ev = hl_getEv(evt);

  // obtiene la coordenada X del evento, con origen en la esquina superior izquierda de la ventana del browser
  hl_evX = hl_Int(ev.pageX || ev.clientX || 0) + // primero verifica para NN, luego para IE, y por default pone cero
           hl_Int(hl_ie ? hl_body.scrollLeft : 0); // agrega el ancho de la barra de desplazamiento si es IE

  // obtiene la coordenada Y del evento, con origen en la esquina superior izquierda de la ventana del browser
  hl_evY = hl_Int(ev.pageY || ev.clientY || 0) + // primero verifica para NN, luego para IE, y por default pone cero
           hl_Int(hl_ie ? hl_body.scrollTop : 0); // agrega el alto de la barra de desplazamiento si es IE

  // para depurar: window.status = "("+hl_evX+", "+hl_evY+")";
}

function hl_getEv(evt) {
  // compatibilidad:
  // window.event IE
  return evt || window.event; // primero verifica para NN, luego para IE
}

// obtiene el elemento padre que tiene el atributo attributeName
function hl_getParentWithAttribute(el, attributeName) {
  if (el == null) {
    return null;
  }
  if (el.getAttribute('hl_hint') != null) {
    return el;
  }
  return hl_getParentWithAttribute(el.parentNode, attributeName);
}
// obtiene el elemento donde se originó el evento
function hl_getEl(evt) {
  var ev = hl_getEv(evt);

  var el;
  if (hl_ie) {
    el = ev.srcElement;
  } else { // hl_ns6
    el = ev.target;
    if (el.nodeType == 3) el = el.parentNode;
  }
  return el;
}

function hl_getWidth(el) {
  return el.style.pixelWidth ? el.style.pixelWidth : el.offsetWidth;
}

function hl_getHeight(el) {
  return el.style.pixelHeight ? el.style.pixelHeight : el.offsetHeight;
}

function hl_handPointer(evt) {
  var el = hl_getEl(evt);
  el.style.cursor = (hl_ie5 ? 'hand' : 'pointer');
}

// convierte a entero
function hl_Int(t_x) {
  var t_y;
  return isNaN(t_y = parseInt(t_x))? 0 : t_y;
}

// el navegador es soportado
function hl_soportado() {
 return (hl_ie5 || hl_ns6);
}

hl_init();

