назад до уроку

"Розумна" підказка

важливість: 5

Напишіть функцію, яка показуватиме спливаючу підказку над елементом лише тоді, коли користувач веде вказівник миші безпосередньо до нього, але не крізь нього.

Іншими словами, якщо користувач наводить вказівник миші на елемент і зупиняється на ньому, показується підказка. І якщо просто провели мишею, то показувати підказку взагалі не потрібно, кому може сподобатись додаткове миготіння?

Технічно ми можемо виміряти швидкість з якою рухається вказівник над елементом, і якщо вона (швидкість) повільна, ми припускаємо, що вказівник проходить “над елементом” і показуємо спливаючу підказку, якщо вона швидка, ми ігноруємо цей прохід вказівника.

У цьому завданні ви маєте описати клас і створити універсальний об’єкт new HoverIntent(options)

Його options:

  • elem – елемент для відстеження.
  • over – функція, яка викликається, якщо миша підійшла до елемента: тобто вона повільно рухається або зупиняється над ним.
  • out – функція для виклику, коли вказівник залишає елемент (якщо було викликано over).

Приклад використання такого об’єкта для підказки:

// зразок підказки
let tooltip = document.createElement('div');
tooltip.className = "tooltip";
tooltip.innerHTML = "Tooltip";

// об'єкт буде стежити за мишею та викликатиме 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();
  }
});

Як це має працювати:

Якщо наводити мишу на елемент “clock” швидко, то нічого не відбувається, а якщо ви робите це повільно або зупиняєтеся на ньому, то з’явиться спливаюча підказка.

Зверніть увагу: спливаюча підказка не “блимає”, коли вказівник переміщується між вкладенними елементами всередині “clock”.

Відкрити пісочницю з тестами.

Алгоритм виглядає просто:

  1. Додайте обробники onmouseover/out на елемент. Тут також можна використовувати onmouseenter/leave, але вони менш універсальні, і не працюватимуть, якщо ми використаємо делегування подій.
  2. Коли вказівник миші увійшов на елемент, почніть вимірювати швидкість на mousemove.
  3. Якщо швидкість низька, то запускаємо over.
  4. Коли вказівник виходить за межі елемента, і over закінчила свою роботу, запускаємо out.

Але як виміряти швидкість?

Перша ідея може бути такою: запускати функцію кожні 100ms і вимірювати відстань між попередньою та новою координатами. Якщо відстань маленька, то швидкість невелика.

На жаль, у JavaScript немає способу отримати поточні координати вказівника миші. Немає таких функцій, як getCurrentMouseCoordinates().

Єдиний спосіб отримати координати – в обробнику подій миші, наприклад mousemove, і брати координати з об’єкта події.

Отже, давайте додамо обробник на mousemove, де відстежемо і запам’ятаємо поточні координати. А далі будемо порівнювати їх раз на 100ms.

P.S. Зверніть увагу: тести рішення використовують dispatchEvent, щоб перевірити, чи підказка працює правильно.

Відкрити рішення із тестами в пісочниці.