retour au cours

Info-bulle "Intelligente"

importance: 5

Ecrivez une fonction qui montre une info-bulle sur un élément seulement si le visiteur déplace la souris sur celui-ci, et non pas en le traversant.

En d’autres termes, si l’usager déplace la souris sur l’élément et s’arrête dessus – afficher l’info bulle. Et si le visiteur déplace seulement la souris en traversant rapidement l’élément, pas besoin de le faire, qui a besoin d’un clignotement supplémentaire ?

Techniquement, nous pouvons mesurer la vitesse de la souris sur un élément, et si elle est lente alors nous pouvons assumer qu’elle arrive “sur l’élément” et monter l’info-bulle, si elle est rapide – alors on l’ignore.

Créer un objet universel new HoverIntent(options) pour cela.

Ses options :

  • elem – l’élément à surveiller.
  • over – une fonction à appeler si la souris arrive sur l’élément : c’est-à-dire qu’elle se déplace lentement ou s’arrête dessus.
  • out – une fonction à appeler quand la souris quitte l’élément (si over était appelé).

Un exemple d’usage d’un tel objet pour l’info-bulle:

// un example d'info-bulle
let tooltip = document.createElement('div');
tooltip.className = "tooltip";
tooltip.innerHTML = "Tooltip";

// L’objet va  suivre la souris et appeler les fonctions 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();
  }
});

La demo:

Si vous déplacez la souris rapidement sur la “montre” alors rien ne se passe, et si vous le faites lentement ou que vous vous arrêtez, alors il y aura une info-bulle.

Notez bien: l’info-bulle ne “clignote” pas lorsque le curseur se déplace entre la montre et les sous éléments.

Open a sandbox with tests.

The algorithm looks simple:

  1. Put onmouseover/out handlers on the element. Also can use onmouseenter/leave here, but they are less universal, won’t work if we introduce delegation.
  2. When a mouse cursor entered the element, start measuring the speed on mousemove.
  3. If the speed is slow, then run over.
  4. When we’re going out of the element, and over was executed, run out.

But how to measure the speed?

The first idea can be: run a function every 100ms and measure the distance between previous and new coordinates. If it’s small, then the speed is small.

Unfortunately, there’s no way to get “current mouse coordinates” in JavaScript. There’s no function like getCurrentMouseCoordinates().

The only way to get coordinates is to listen for mouse events, like mousemove, and take coordinates from the event object.

So let’s set a handler on mousemove to track coordinates and remember them. And then compare them, once per 100ms.

P.S. Please note: the solution tests use dispatchEvent to see if the tooltip works right.

Ouvrez la solution avec des tests dans une sandbox.