regresar a la lección

Tooltip "inteligente"

Escribe una función que muestre un tooltip sobre un elemento solamente si el visitante mueve el mouse hacia él, pero no a través de él.

En otras palabras, si el visitante mueve el mouse hacia el elemento y para ahí, muestra el tooltip. Y si solamente mueve el mouse a través, entonces no lo necesitamos. ¿Quién quiere parpadeos extra?

Técnicamente, podemos medir la velocidad del mouse sobre el elemento, y si es lenta podemos asumir que el mouse viene “sobre el elemento” y mostramos el tooltip, si es rápida – entonces lo ignoramos.

Hay que crear un objeto universal new HoverIntent(options) para ello.

Sus options:

  • elem – elemento a seguir.
  • over – una función a llamar si el el mouse viene hacia el elemento: o sea, si viene lentamente o para sobre él.
  • out – una función a llamar cuando el mouse abandona el elemento (si over fue llamado).

Un ejemplo de dicho objeto siendo usado para el tooltip:

//  Un tooltip de muestra
let tooltip = document.createElement('div');
tooltip.className = "tooltip";
tooltip.innerHTML = "Tooltip";

// El objeto va a rastrear al mouse y llamar a over/out
new HoverIntent({
  elem,
  over() {
    tooltip.style.left = elem.getBoundingClientRect().left + 'px';
    tooltip.style.top = elem.getBoundingClientRect().bottom + 5 + 'px';
    document.body.append(tooltip);
  },
  out() {
    tooltip.remove();
  }
});

El demo:

Si mueves el mouse sobre el “reloj” rápido no pasará nada, y si lo haces lento o paras sobre él entonces habrá un tooltip.

Toma en cuenta que el tooltip no “parpadea” cuando el cursor se mueve entre subelementos del reloj.

Abrir en entorno controlado con pruebas.

El algoritmo se ve simple:

  1. Coloca los controladores onmouseover/out en el elemento. Aquí también podemos usar onmouseenter/leave, pero son menos universales, no funcionan si introducimos delegaciones.
  2. Cuando el cursor ingrese al elemento debes medir la velocidad en mousemove.
  3. Si la velocidad es lenta hay que ejecutar over.
  4. Si estamos saliendo del elemento, y over ya se había ejecutado, ahora ejecutamos out.

¿Pero cómo mediremos la velocidad?

La primera idea puede ser: correr una función cada 100ms y medir la distancia entre la coordenada anterior y la actual. Si es pequeña entonces la velocidad fue rápida.

Desafortunadamente no hay manera para obtener las coordenadas actuales del mouse en JavaScript. No existe algo así como getCurrentMouseCoordinates().

La única manera es registrando los eventos del mouse, como mousemove, y tomar las coordenadas del objeto del evento.

Entonces configuremos un mousemove para registrar las coordenadas y recordarlas. Y entonces las comparamos, una por cada 100ms.

PD. Toma nota: El test de la solución usa dispatchEvent para ver si el tooltip funciona bien.

Abrir la solución con pruebas en un entorno controlado.