Мастер-классы по Javascript Екатеринбург Ростов-на-Дону Москва Узнать больше...
Содержание (скрыть) Содержание (показать)

Подсказка, следующая за курсором

Создайте всплывающую подсказку, следующую за курсором.

  • Подсказка должна появляться при наведении на элемент, на небольшом расстоянии справа-снизу от курсора.
  • При передвижении курсора подсказка следует за ним.
  • Если курсор слишком низко/справа, то чтобы подсказка не вылезла за нижнюю/правую границу экрана — пусть отображается сверху/слева от курсора.

Вы можете посмотреть поведение подсказки в ифрейме ниже, наведя курсор на правый-нижний угол.

Открыть в новом окне

Способ добавления подсказки к элементу:

new Tooltip(elem, "Вот <b>такая</b> подсказка!");

Естественные пожелания:

  • Подсказка не должна «моргать» при движении мыши.
  • Подсказка должна правильно работать, если у страницы есть прокрутка.
  • В подсказке и элементе, на который она поставлена, может быть произвольный HTML. Оформление подсказки должно задаваться CSS.
  • Не надо рассматривать случай, когда у вложенного элемента своя подсказка, отдельная от родителя, т.к. такого не бывает.
  • Объект подсказки не должен иметь публичных методов, только приватные.

Исходный документ: tutorial/browser/events/tooltip-moving-src/index.html.

К нему подключён файл с функцией fixEvent.

Решение, шаг 1
Решение
Решение, шаг 1

Три события имеют отношение к подсказке:

  1. При mouseover — показать.
  2. При mousemove — показать на новом месте.
  3. При mouseout — спрятать.

…Но при заходе на элемент происходят сразу оба события: mouseover и mousemove на нём же. Зачем вызывать код для показа два раза? Можно оставить его только в mousemove.

Стиль элемента подсказки:

.tooltip {
  position:absolute;
  left: -9999px; /* изначально спрятана за пределы экрана */
  z-index:100; /* подсказка должна перекрывать другие элементы */
  ...
}

Решение, шаг 2
Решение, шаг 2

Скелет кода:

function Tooltip(elem, text) {

  var offsetFromCursor = 10; // отступ от курсора 10px
  var tooltipElem; // тут будет элемент-подсказка

  elem.onmouseout = function() {
    hide();                   // спрятать подсказку
  };

  elem.onmousemove = function(e) {
    e = fixEvent(e);
    show(e.pageX, e.pageY);   // показать рядом с курсором
  };

  function getTooltipElem() { // создать элемент-подсказку
    if (!tooltipElem) {
      tooltipElem = document.createElement('div');
      tooltipElem.className = 'tooltip'; // CSS подсказки
      tooltipElem.innerHTML = text;
    }
    return tooltipElem;
  }

  function hide() {
    document.body.removeChild(getTooltipElem());
  };

  function show(pageX, pageY) {
    показать getTooltipElem() для координат курсора pageX/pageY
  }
}

Для показа на нужном месте — как правило, подойдут простые вычисления. Функция show ниже сдвигает элемент на offsetFromCursor относительно переданных её координат курсора:

function show(pageX, pageY) {
  var tooltipElem = getTooltipElem();

  var newLeft = pageX + offsetFromCursor;
  var newTop = pageY + offsetFromCursor;

  tooltipElem.left = newLeft + 'px';
  tooltipElem.top = newTop + 'px';
}

Основной сложный момент здесь — определить, когда подсказка вылезает за правую/нижнюю границы окна. Для этого нужно эти границы вычислить:

var scrollY = window.pageYOffset || document.documentElement.scrollTop;
var winBottom = scrollY + document.documentElement.clientHeight;

var scrollX = window.pageXOffset || document.documentElement.scrollLeft;
var winRight  = scrollX + document.documentElement.clientWidth;

Соответствующие свойства, использованные для вычисления, описаны в статье Размеры и прокрутка элементов.

Проверим, не вылезет ли подсказка за границы, и если это так — перенесём ее:

if (newLeft + tooltipElem.offsetWidth > winRight) {
  // правая граница подсказки вылезает за экран
  newLeft -= tooltipElem.offsetWidth;
  newLeft -= offsetFromCursor+2; // (*)
}

if (newTop + tooltipElem.offsetHeight > winBottom) {
  // нижняя граница подсказки вылезает за экран
  newTop -= tooltipElem.offsetHeight;
  newTop -= offsetFromCursor+2;  // (**)
}

Здесь есть еще две тонкости.

  1. Для того, чтобы можно было получить offsetHeight/offsetWidth, подсказка должна быть скрыта при помощи visibility:hidden или left/top за пределами экрана, но не display:none.
  2. В строках (*) и (**) подсказку сдвигаем немного левее/выше курсора (на 2 пикселя).

    Главное чтобы подсказка не оказалась под курсором. Если такое произойдет, то подсказка перекроет элемент, и в результате события mousemove станут происходить уже на подсказке, а не на элементе, и их обработка сломается.

Полное решение: tutorial/browser/events/tooltip-moving/index.html.

#401
Наверх

Реклама

Нашли опечатку?

Нашли опечатку на сайте? Что-то кажется странным?
Выделите соответствующий текст и нажмите Ctrl+Enter!

Последние Комментарии

Помоги другим!

Помоги другим узнать о хорошей статье!