Всплывающие подсказки на веб-страницах

24 Окт
2011

Опишу простейший способ добавления «всплывающих подсказок» на веб-страницах.
Этот способ я использую для создания простой контекстной справки в веб-интерфейсах.

Итак, изначальный замысел таков: на веб-странице размещается элемент (меню, гиперссылка, «кнопка» или сочетание клавиш), активируя который мы входим в режим показа контекстной справки для элемента, по которому будет выполнен следующий щелчок левой кнопкой мыши (ЛКМ). При щелчке по подсказке либо нажатии клавиши ESC подсказка исчезает.

Как вы понимаете, задача наиэлементарнейшая. Нам необходимо лишь активировать обработку события onclick при входе в режим отображения подсказок. Идентификатор элемент, по которому мы щелкнули, поступает в функцию обработки щелчка, которая выводит всплывающий блок с подсказкой для заданного элемента.

Для включения режима контекстной помощи добавим в тело веб-страницы ссылку на функцию startHelp, например, так:
<a href='#' onclick="startHelp(event);"  id='helper'>Контекстная помощь</a>


Сама функция startHelp:
function startHelp(evt){
evt.stopPropagation();
evt.preventDefault();
document.body.style.cursor = "help";
document.body.onclick = Help;
document.body.onmouseover = stoponclick;
}

Здесь мы запрещаем дальнейшую обработку щелчка ЛКМ, изменяем внешний вид курсора, устанавливаем обработчик щелчка и дополнительный обработчик события наведения указателя на объект (функция stoponclick). Обработку события onmouseover я использовал для того, чтобы изменять обработчик события onclick элемента, над которым находится указатель мыши (при этом старый обработчик запоминается и восстанавливается впоследствии).

Сама функция Help отображает подсказку и возвращает все обработчики «на круги своя»:
function Help(evt){
evt.stopPropagation();
evt.preventDefault();
if(!helptip(evt)) return;
document.body.onclick = '';
document.body.style.cursor = "default";
document.body.onmouseover = '';
}

Функция helptip (ее я приведу ниже) как раз и служит для отображения подсказки для элемента, по которому вы щелкнули ЛКМ. Обработчики событий onclick и onmouseover для тела веб-страницы сбрасываются. Если вам это не нужно, можно в функции startHelp сохранить эти обработчики можно сохранить в глобальные переменные (как это делается в фукнции stoponclick).

Функция stoponclick использует две глобальные переменные для хранения функций-обработчиков событий onclick и onmouseout блока, над которым находится курсор мыши (понятно, что слой с этим блоком должен быть самым верхним, т.е. в сложных случаях надо будет позаботиться о z-index), а также назначает новые обработчики (на onclick — вывод посказки, на onmouseout — восстановление предыдущих обработчиков):
var oldclc, oldmout; // глобальные переменные
function stoponclick(evt){
var obj = evt.target;
if(obj == document.body) return;
oldclc = obj.onclick;
oldmout = obj.onmouseout;
obj.onclick = Help;
obj.onmouseout = releaseonclick;
obj.style.cursor = "help";
}

И сразу же приведу функцию releaseonclick, восстанавливающую обработчики:
function releaseonclick(evt){
var obj = evt.target;
obj.onmouseout = oldmout;
obj.onclick = oldclc;
obj.style.cursor = "default";
}


Функция helptip генерирует блок с подсказкой. Для упрощения позиционирования этого блока я использую глобальную переменную tipobj для его хранения. Эта функция получает значение текста подсказки из функции helpgen и, если текст существует, создает блок, добавляет для него обработчик onclick (который уничтожает блок), вставляет текст подсказки в блок, а также добавляет дополнительный текст (который говорит пользователю, как уничтожить блок с подсказкой), позиционирует блок около места щелчка ЛКМ. Далее происходит восстановление стандартных обработчиков для блока, по которому мы щелкнули ЛКМ и возвращается длина текста подсказки. Функция:
function helptip(evt){
var ss = helpgen(evt), helper;
if(ss.length > 0){
tipobj = document.createElement("DIV");
tipobj.id = 'helptip';
tipobj.setAttribute("name", "helptip");
tipobj.onclick = rmtip;
tipobj.innerHTML = ss;
helper = document.createElement("DIV");
helper.className = 'redtxt';
helper.innerHTML = "Чтобы закрыть это окно, щелкните по нему левой кнопкой мыши или нажмите клавишу ESCAPE";
helper.onclick = function(evt){evt.stopPropagation();
document.body.removeChild(evt.target.parentNode);};
tipobj.appendChild(helper);
document.body.appendChild(tipobj);
positiontip(evt);
}
releaseonclick(evt);
return (ss.length);
}

Функцию rmtip, удаляющую блок подсказки при щелчке на нем ЛКМ, можно вынести в отдельную:
function rmtip(evt){
document.body.removeChild(evt.target);
}

А можно вставить ее вместо rmtip в функции helptip.

Генерация текста подсказки в зависимости от элемента, по которому мы щелкнули, производится этой функцией:
function helpgen(evt){
var obj = evt.target;
var objid, objname, ss="", nm;
onkey(27);
objid = obj.id; objname = obj.name;
if(objid == "" && objname == null){
objid = obj.parentNode.id;
objname = obj.parentNode.name;
}
if(objid == "" && objname == null) return (ss);
if(objid == "" && objname != null) nm = objname;
else nm = objid;
ss = HelpText[nm];
if(ss == null) ss = HelpText[obj.parentNode.id];
return (ss);
}

Здесь сразу же выполняется onkey(27) для удаления предыдущих подсказок (если они еще не были удалены) — эту функцию я приведу ниже. Далее мы узнаēм идентификатор и имя объекта, по которому был выполнен щелчок. Если ни того, ни другого нет, проверяется идентификатор и имя родителя этого объекта. Если и там пусто, возвращается пустая строка. Иначе мы получаем строку подсказки из массива HelpText. Последняя проверка — если подсказки для этого элемента нет, пытаемся вызывать подсказку для идентификатора родительского элемента.

Позиционирование подсказки выполняется элементарно:
function positiontip(e){
var wd = tipobj.offsetWidth, ht = tipobj.offsetHeight;
var curX = e.clientX + 25;
var curY = e.clientY - ht/2;
var btmedge = document.body.clientHeight - curY - 15;
var rightedge = document.body.clientWidth - curX - 15;
if(rightedge < wd) curX -= wd+50;
if(btmedge < ht) curY -= ht-btmedge+15;
if(curY < 15) curY = 15;
tipobj.style.left = curX+"px";
tipobj.style.top = curY+"px";
}

Мы просто узнаем координаты щелчка, немного смещаемся относительно их (чтобы вместить блок с подсказкой), а затем проверяем, не вылезает ли наш блок за края экрана. Если вылезает — подправляем соответствующим образом координаты. Далее вносим соответствующие изменения в стиль блока с подсказкой.

Чтобы уничтожать блок с подсказкой еще и по нажатию ESC, добавим эту функцию:
function onkey(code){
if(code != 27) return;
var helps = document.getElementsByName('helptip');
var l = helps.length-1;
for(var i=l; i>-1; i--) document.body.removeChild(helps[i]);
}

В тег body нашего html-документа надо будет добваить
onkeydown="onkey(event.keyCode);

чтобы эта функция работала (либо можно вызвать обработчик позже).

Поля массива с подсказками будут иметь вид «идентификатор: «Текст подсказки»», например,
const HelpText = {
Sout: "Отобразить данные по внешней температуре.",
Sin: "Отобразить данные по внутренней температуре."

}


Ну и конечно же надо будет добавить стили в общий CSS-файл (или создать отдельный стилевой файл):
#helptip{
position: fixed; background-color: #BFE; -moz-border-radius: 5px;
color: black; max-width: 400px; max-height: 500px; padding: 5px;
}
.redtxt {color: red; margin-top: 20px;}


Выглядеть подсказка будет примерно так:
image
По материалам Хабрахабр.



загрузка...

Комментарии:

Наверх