Создайте всплывающую подсказку, следующую за курсором.
- Подсказка должна появляться при наведении на элемент, на небольшом расстоянии справа-снизу от курсора.
- При передвижении курсора подсказка следует за ним.
- Если курсор слишком низко/справа, то чтобы подсказка не вылезла за нижнюю/правую границу экрана — пусть отображается сверху/слева от курсора.
Вы можете посмотреть поведение подсказки в ифрейме ниже, наведя курсор на правый-нижний угол.
Способ добавления подсказки к элементу:
new Tooltip(elem, "Вот <b>такая</b> подсказка!");
Естественные пожелания:
- Подсказка не должна «моргать» при движении мыши.
- Подсказка должна правильно работать, если у страницы есть прокрутка.
- В подсказке и элементе, на который она поставлена, может быть произвольный HTML. Оформление подсказки должно задаваться CSS.
- Не надо рассматривать случай, когда у вложенного элемента своя подсказка, отдельная от родителя, т.к. такого не бывает.
- Объект подсказки не должен иметь публичных методов, только приватные.
Исходный документ: tutorial/browser/events/tooltip-moving-src/index.html.
К нему подключён файл с функцией fixEvent.
Три события имеют отношение к подсказке:
- При
mouseover— показать. - При
mousemove— показать на новом месте. - При
mouseout— спрятать.
…Но при заходе на элемент происходят сразу оба события: mouseover и mousemove на нём же. Зачем вызывать код для показа два раза? Можно оставить его только в mousemove.
Стиль элемента подсказки:
.tooltip {
position:absolute;
left: -9999px; /* изначально спрятана за пределы экрана */
z-index:100; /* подсказка должна перекрывать другие элементы */
...
}
Скелет кода:
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; // (**)
}
Здесь есть еще две тонкости.
- Для того, чтобы можно было получить
offsetHeight/offsetWidth, подсказка должна быть скрыта при помощиvisibility:hiddenилиleft/topза пределами экрана, но неdisplay:none. - В строках
(*)и(**)подсказку сдвигаем немного левее/выше курсора (на 2 пикселя).Главное чтобы подсказка не оказалась под курсором. Если такое произойдет, то подсказка перекроет элемент, и в результате события
mousemoveстанут происходить уже на подсказке, а не на элементе, и их обработка сломается.
Полное решение: tutorial/browser/events/tooltip-moving/index.html.