Изначально я хотел создать эффект всплывающих подсказок, сочетающий в себе плавающее позиционирование и отслеживание мыши, но обнаружил, что позиционирование и отслеживание мыши все еще различаются в некоторых ключевых местах, поэтому нам следует делать это отдельно.
Сам по себе этот эффект не очень сложен. В основном мы приложили некоторые усилия к структуре и расширению программы, чтобы сделать ее более удобной в использовании и чтобы ее можно было использовать в большем количестве мест.
Возможности программы
Загрузка полного примера (нажмите, чтобы скачать)
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" " http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd ">
<html xmlns=" http://www.w3.org/1999/xhtml ">
<голова>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312" />
<title>Эффект подсказки плавающего позиционирования JavaScript</title>
<скрипт>
вар $$ = функция (id) {
вернуть «строку» == идентификатор типа? document.getElementById(id): id;
};
var isIE = navigator.userAgent.indexOf('MSIE') != -1;
var isIE6 = isIE && ([/MSIE (d).0/i.exec(navigator.userAgent)][0][1] == "6");
var isChrome = navigator.userAgent.indexOf('Chrome') != -1;
var isSafari = navigator.userAgent.indexOf('AppleWebKit') != -1;
// при участии Тино Зийдела, Матиаса Миллера, Диего Перини
// http://dean.edwards.name/weblog/2005/10/add-event/
функция addEvent(элемент, тип, обработчик) {
если (element.addEventListener) {
element.addEventListener(тип, обработчик, ложь);
} еще {
if (!handler.$$guid) handler.$$guid = addEvent.guid++;
если (!element.events) element.events = {};
обработчики var = element.events[type];
если (!обработчики) {
обработчики = element.events[тип] = {};
if (element["on" + type]) {
обработчики[0] = элемент["on" + тип];
}
}
обработчики[handler.$$guid] = обработчик;
элемент ["on" + тип] = handleEvent;
}
};
addEvent.guid = 1;
функция RemoveEvent (элемент, тип, обработчик) {
если (element.removeEventListener) {
element.removeEventListener(тип, обработчик, ложь);
} еще {
if (element.events && element.events[type]) {
удалить element.events[тип][handler.$$guid];
}
}
};
функция handleEvent(событие) {
вар returnValue = правда;
событие = событие || fixEvent(((this.ownerDocument || this.document || this).parentWindow || window).event);
обработчики вар = this.events[event.type];
for (var i в обработчиках) {
this.$$handleEvent = обработчики[i];
if (this.$$handleEvent(event) === false) {
ВозвращаемоеЗначение = Ложь;
}
}
вернуть returnValue;
};
функция fixEvent(событие) {
event.target = event.srcElement;
if(event.type == "mouseout") {
event.latedTarget = event.toElement;
}else if(event.type == "mouseover") {
event.latedTarget = event.fromElement;
}
возвратное событие;
};
вар Extend = функция (назначение, источник) {
for (свойство var в исходном коде) {
назначение [свойство] = источник [свойство];
}
обратный пункт назначения;
}
вар Содержит = функция (а, б) {
return a.contains ? a != b && a.contains(b) : !!(a.compareDocumentPosition(b) & 16);
}
вар Bind = функция (объект, развлечение) {
var args = Array.prototype.slice.call(аргументы, 2);
функция возврата() {
return fun.apply(object, args.concat(Array.prototype.slice.call(arguments)));
}
}
вар BindAsEventListener = функция (объект, развлечение) {
var args = Array.prototype.slice.call(аргументы, 2);
возвращаемая функция (событие) {
return fun.apply(object, [event].concat(args));
}
}
вар фиксированные советы = функция (подсказка, параметры) {
this.Tip = $$(tip);//Окно подсказки
this._trigger = null; // Объект-триггер
this._timer = null;//Таймер
this._cssTip = this.Tip.style;//Упрощенный код
this._onshow = false;//Записываем текущий статус отображения
this.SetOptions(опции);
//Объект подсказки процесса
this._cssTip.margin = 0;//Избегаем проблем с позиционированием
this._cssTip.position = "абсолютный";
this._cssTip.visibility = "скрытый";
this._cssTip.display = "блокировать";
this._cssTip.zIndex = 99;
this._cssTip.left = this._cssTip.top = "-9999px";//Избегать полос прокрутки в заполнителе
//параметры коррекции смещения
вар iLeft = iTop = 0, p = this.Tip;
в то время как (p.offsetParent) {
р = p.offsetParent; iLeft += p.offsetLeft; iTop += p.offsetTop;
};
this._offsetleft = iLeft;
this._offsettop = iTop;
//Продолжаем отображение при переходе к объекту Tip
addEvent(this.Tip, "наведение курсора", BindAsEventListener(this, function(e){
//Если входит внешний элемент, это означает, что он в данный момент находится на стадии задержки скрытия, затем очистите таймер, чтобы отменить скрытие.
this.Check(e.relatedTarget) &&clearTimeout(this._timer);
}));
//ie6 обрабатывает выбор
если (isIE6) {
this._iframe = document.createElement("<iframe style='position:absolute;filter:alpha(opacity=0);display:none;'>");
document.body.insertBefore(this._iframe, document.body.childNodes[0]);
};
//Используется для скрытия по клику
this._fCH = BindAsEventListener(this, function(e) {
if (this.Check(e.target) && this.CheckHide()) {
this.ReadyHide(this._trigger.ClickHideDelay);
};
});
//Используется для запуска метода скрытия
this._fTH = BindAsEventListener(this, function(e) {
if (this.Check(e.relatedTarget) && this.CheckHide()) {
this.ReadyHide(this._trigger.TouchHideDelay);
};
});
};
фиксированные советы.прототип = {
_doc: document.documentElement, // Упрощаем код
//Установим свойства по умолчанию
SetOptions: функция (опции) {
this.options = {//Значение по умолчанию
ClickShow: true,//Отображать ли в режиме щелчка
ClickShowDelay: false,//Указывает на задержку отображения щелчка
ClickHide: true,//Скрыт ли режим щелчка
ClickHideDelay: false,//Нажимать ли, чтобы скрыть задержку
TouchShow: true,//Отображается ли режим триггера
TouchShowDelay: true, // активировать ли задержку отображения
TouchHide: true,//Скрыт ли режим триггера
TouchHideDelay: true, // активировать ли задержку скрытия
ShowDelay: 300, // Время задержки отображения
HideDelay: 300,//Скрыть время задержки
Выровнять: "clientleft",//Горизонтальное позиционирование
vAlign: "clienttop",//вертикальное позиционирование
Пользовательский: { слева: 0, вверху: 0 },//Пользовательское позиционирование
Процент: {слева: 0, сверху: 0},//Настраиваемое процентное позиционирование
Адаптивный: ложь, // Следует ли использовать адаптивное позиционирование
Сброс: false, // Следует ли менять положение во время адаптивного позиционирования
onShow: function(){}, //Выполнить при отображении
onHide: function(){}//Выполняется при скрытии
};
Extend(this.options, options || {});
},
//Проверяем элемент триггера
Проверьте: функция (элемент) {
//Возвращаем, является ли это внешним элементом (то есть объектом элемента, отличным от элемента триггера и самого объекта Tip и его внутренних элементов)
вернуть !this._trigger ||
!(
this.Tip === элемент || this._trigger.Elem === элемент ||
Содержит(this.Tip, элемент) || Содержит(this._trigger.Elem, элемент)
);
},
//Готовность к отображению
ReadyShow: функция (задержка) {
ClearTimeout(this._timer);
вар триггер = this._trigger;
//Нажмите, чтобы скрыть
триггер.ClickHide && addEvent(документ, «клик», this._fCH);
//Режим триггера скрыт
триггер.TouchHide && addEvent(this._trigger.Elem, "mouseout", this._fTH);
// Стоит ли задерживать срабатывание
если (задержка) {
this._timer = setTimeout(Bind(this, this.Show), триггер.ShowDelay);
} Еще { this.Show() };
},
//показывать
Показать: функция() {
ClearTimeout(this._timer);
this._trigger.onShow();//Поместите его впереди, чтобы можно было легко изменять атрибуты
//Рассчитываем левое и верхнее положение на основе заданного и пользовательского позиционирования
var триггер = this._trigger, rect = триггер.Elem.getBoundingClientRect(),
прокрутка = isChrome || isSafari ? document.body : this._doc,
прокруткаLeft = прокрутка.scrollLeft, прокруткаTop = прокрутка.scrollTop,
customLeft = триггер.Custom.left, customTop = триггер.Custom.top,
iLeft = this.GetLeft(rect, триггер.Align) + customLeft,
iTop = this.GetTop(rect, триггер.vAlign) + customTop;
//Пользовательское процентное позиционирование
если (trigger.Percent.left) { iLeft += .01 * триггер.Percent.left * триггер.Elem.offsetWidth };
если (trigger.Percent.top) { iTop += .01 * триггер.Percent.top * триггер.Elem.offsetHeight };
//Адаптивное позиционирование окна
если (триггер.Адаптивный) {
//Корректируем параметры позиционирования
var maxLeft = this._doc.clientWidth - this.Tip.offsetWidth,
maxTop = this._doc.clientHeight - this.Tip.offsetHeight;
если (триггер.Сброс) {
//Автоматическое изменение положения
if (iLeft > maxLeft || iLeft < 0) {
iLeft = this.GetLeft(rect, 2 * iLeft > maxLeft? "left": "right") + customLeft;
};
если (iTop > maxTop || iTop < 0) {
iTop = this.GetTop(rect, 2 * iTop > maxTop? «сверху»: «снизу») + customTop;
};
} еще {
//Исправляем соответствующую позицию
iLeft = Math.max(Math.min(iLeft, maxLeft), 0);
iTop = Math.max(Math.min(iTop, maxTop), 0);
};
};
//Устанавливаем позицию и отображаем
this._cssTip.left = iLeft + ScrollLeft - this._offsetleft + "px";
this._cssTip.top = iTop + ScrollTop - this._offsettop + "px";
this._cssTip.visibility = "видимый";
//ie6 обрабатывает выбор
если (isIE6) {
this._iframe.style.left = iLeft + ScrollLeft + «px»;
this._iframe.style.top = iTop + ScrollTop + «px»;
this._iframe.style.width = this.Tip.offsetWidth + «px»;
this._iframe.style.height = this.Tip.offsetHeight + «px»;
this._iframe.style.display = "";
};
//Режим триггера скрыт
триггер.TouchHide && addEvent(this.Tip, "mouseout", this._fTH);
},
//Получаем левую часть относительного элемента триггера
GetLeft: функция (прямоугольник, выравнивание) {
переключатель (align.toLowerCase()) {
случай «левый»:
return rect.left - this.Tip.offsetWidth;
случай «клиентлевый»:
вернуть прямоугольник влево;
корпус «центр»:
return (rect.left + rect.right - this.Tip.offsetWidth)/2;
случай «права клиента»:
вернуть rect.right - this.Tip.offsetWidth;
случай «правильный»:
по умолчанию :
вернуть прямоугольник вправо;
};
},
//Получаем верх относительно элемента триггера
GetTop: function(rect, valign) {
переключатель (valign.toLowerCase()) {
корпус «верх»:
вернуть rect.top - this.Tip.offsetHeight;
случай «клиенттоп»:
вернуть прямоугольник.топ;
корпус «центр»:
return (rect.top + rect.bottom - this.Tip.offsetHeight)/2;
случай «клиентботтом»:
return rect.bottom - this.Tip.offsetHeight;
корпус «низ»:
по умолчанию :
вернуть прямоугольник.дно;
};
},
//Приготовьтесь спрятаться
ReadyHide: функция (задержка) {
ClearTimeout(this._timer);
если (задержка) {
this._timer = setTimeout(Bind(this, this.Hide), this._trigger.HideDelay);
} Еще { this.Hide() };
},
//скрывать
Скрыть: функция() {
ClearTimeout(this._timer);
//Настраиваем скрытие
this._cssTip.visibility = "скрытый";
this._cssTip.left = this._cssTip.top = "-9999px";
//ie6 обрабатывает выбор
если (isIE6) { this._iframe.style.display = "none" };
//Обработка объекта триггера
если (!!this._trigger) {
this._trigger.onHide();
RemoveEvent(this._trigger.Elem, "mouseout", this._fTH);
}
this._trigger = ноль;
//удаляем событие
RemoveEvent(this.Tip, "mouseout", this._fTH);
RemoveEvent(документ, «клик», this._fCH);
},
//Добавляем объект триггера
Добавить: функция (элемент, параметры) {
//Создаем объект-триггер
var elem = $$(elem), триггер = Extend(Extend({ Elem: elem }, this.options), options || {});
//Нажмите, чтобы отобразить
addEvent(elem, "клик", BindAsEventListener(this, function(e){
если (триггер.ClickShow) {
если (this.CheckShow(триггер)) {
this.ReadyShow(trigger.ClickShowDelay);
} еще {
ClearTimeout(this._timer);
};
};
}));
//Отображение режима триггера
addEvent(elem, "mouseover", BindAsEventListener(this, function(e){
если (trigger.TouchShow) {
если (this.CheckShow(триггер)) {
this.ReadyShow(trigger.TouchShowDelay);
} Еще если (this.Check(e.relatedTarget)) {
ClearTimeout(this._timer);
};
};
}));
// возвращаем объект триггера
возвратный триггер;
},
//Показать чек
CheckShow: функция (триггер) {
если (триггер !== this._trigger) {
//Если это не тот же объект триггера, сначала выполните Hide, чтобы предотвратить конфликты.
this.Hide(); this._trigger = триггер вернуть истину;
} Еще {вернуть ложь};
},
//скрыть проверку
ПроверитьСкрыть: функция() {
if (this._cssTip.visibility === "скрытый") {
//Изначально это скрытое состояние, больше не нужно выполнять Hide
ClearTimeout(this._timer);
RemoveEvent(this._trigger.Elem, "mouseout", this._fTH);
this._trigger = ноль;
RemoveEvent(документ, «клик», this._fCH);
вернуть ложь;
} Еще {вернуть истину};
}
};
</скрипт>
</голова>
<тело>
<стиль>
.trigger {border: 1px Solid # 003099; цвет: # 003099; фон: # e2e7ff; ширина: 200 пикселей; высота: 100 пикселей; поле слева: 150 пикселей;}
.tip{border:1px Solid #c00000; цвет:#c00000; фон:#ffcccc; заполнение:5px; высота строки:20px;}
</стиль>
<div style="padding:50px;">
<div id="idTip" class="tip"></div>
<div id="idTrigger1" class="trigger">
<выбрать>
<option>тест</option>
</выбрать>
</div>
<br>
горизонтальное положение:
<метка>
<input name="nAlign" type="radio" value="left" />
слева </label>
<метка>
<input name="nAlign" type="radio" value="clientleft" />
клиентлевый </label>
<метка>
<input name="nAlign" type="radio" value="center" />
центр </label>
<метка>
<input name="nAlign" type="radio" value="clientright" />
права клиента </label>
<метка>
<input name="nAlign" type="radio" value="right" проверено="проверено" />
верно </label>
<br>
Вертикальное положение:
<метка>
<input name="nVAlign" type="radio" value="top" />
вверху </label>
<метка>
<input name="nVAlign" type="radio" value="clienttop" />
верхняя часть клиента </label>
<метка>
<input name="nVAlign" type="radio" value="center" />
центр </label>
<метка>
<input name="nVAlign" type="radio" value="clientbottom" />
клиентдно </label>
<метка>
<input name="nVAlign" type="radio" value="bottom"checked="checked" />
внизу </label>
<br>
<br>
Пользовательский таргетинг:
левый:
<input id="idLeft" type="text" size="5" value="0" maxlength="3" />
вершина:
<input id="idTop" type="text" size="5" value="0" maxlength="3"/>
<br>
<br>
<input id="idClick" type="checkbox" проверено="проверено" />
<label for="idClick">Метод щелчка</label>
<input id="idTouch" type="checkbox" проверено="проверено" />
<label for="idTouch">Метод триггера</label>
<br>
<br>
Время задержки:
<input id="idDelayTime" type="text" size="5" value="0" maxlength="4"/>
<input id="idDelay" type="button" value="Отменить задержку" />
<br>
<br>
Другие примеры применения: <br>
<br>
<div id="idTest1"> Используйте заголовок: <a href=" http://www.cnblogs.com/cloudgamer/archive/2008/11/17/1334778.html " title="Эффект перетаскивания"> Перетащите и перетащите Эффект</a> <a href=" http://www.cnblogs.com/cloudgamer/archive/2008/12/03/1346386.html " title="Эффект перетаскивания и масштабирования"> Перетащите и масштабируйте Эффект</a > <a href=" http://www.cnblogs.com/cloudgamer/archive/2008/07/21/1247267.html " title="Эффект обрезки изображения"> Эффект обрезки изображения</a > </дел >
<br>
<br>
Популярные эффекты отображения аватара: <br>
<br>
<div id="idTest2"> <a href=" http://www.cnblogs.com/cloudgamer/archive/2008/07/06/1236770.html " title="Эффект скользящего переключения изображения"> <img src= "/articleimg/2009/07/6852/r_mx1.jpg" border="0"/></a> <a href=" http://www.cnblogs.com/cloudgamer/archive/2008/05/ 23/1205642.html " title="Эффект трансформации изображения"><img src="/articleimg/2009/07/6852/r_mx2.jpg" border="0"/></a> <a href=" http://www.cnblogs.com/cloudgamer/archive/2008/05/13/1194272.html " title="Эффект скользящего отображения изображения"><img src="/articleimg/2009/07/6852/r_mx3.jpg " border="0"/></a> </div>
<br>
<br>
Кнопка закрытия: <a id="idTest3" href=" http://www.cnblogs.com/cloudgamer/archive/2009/05/18/TableFixed.html">Эффект позиционирования строк таблицы </a>
</div>
<скрипт>
вар forEach = функция (массив, обратный вызов, thisObject) {
если (array.forEach) {
array.forEach(обратный вызов, thisObject);
}еще{
for (var i = 0, len = array.length; i < len; i++) { callback.call(thisObject, array[i], i, array }
}
}
//////////////////////////////////////////
var ft = новые фиксированные подсказки («idTip»);
//////////////////////////////////////////
var триггер1 = ft.Add("idTrigger1", {
onShow: функция(){
//тест позиционирования
вар sAlign = this.Align, sVAlign = this.vAlign;
forEach(document.getElementsByName("nAlign"), function(o){ if(o.checked){ sAlign = o.value; } });
forEach(document.getElementsByName("nVAlign"), function(o){ if(o.checked){ sVAlign = o.value; } });
this.Align = sAlign;
this.vAlign = sVAlign;
this.Custom.left = $$("idLeft").value |
this.Custom.top = $$("idTop").value |
триггер1.ShowDelay = триггер1.HideDelay = $$("idDelayTime").value || 300;
ft.Tip.innerHTML = sAlign + "<br>" + sVAlign + "<br>" + "left: " + this.Custom.left + ", top: " + this.Custom.top;
}
});
//тест задержки
$$("idDelayTime").value = триггер1.ShowDelay;
$$("idDelay").onclick = function(){
если (trigger1.TouchShowDelay) {
триггер1.ClickShowDelay = триггер1.ClickHideDelay =
триггер1.TouchShowDelay = триггер1.TouchHideDelay = ложь;
$$("idDelayTime").disabled = true;
this.value = "Установить задержку";
}еще{
триггер1.ClickShowDelay = триггер1.ClickHideDelay =
триггер1.TouchShowDelay = триггер1.TouchHideDelay = правда;
$$("idDelayTime").disabled = false;
this.value = "Отменить задержку";
}
}
//тест метода
$$("idClick").onclick = function(){
триггер1.ClickShow = триггер1.ClickHide = this.checked;
}
$$("idTouch").onclick = function(){
триггер1.TouchShow = триггер1.TouchHide = this.checked;
}
//////////////////////////////////////////
forEach($$("idTest1").getElementsByTagName("a"), function(o){
вар заголовок = о.title; о.title = "";
ft.Add(o, { vAlign: "bottom", Percent: { left: 50, top: 0 }, onShow: function() { ft.Tip.innerHTML = title; } });
})
//////////////////////////////////////////
forEach($$("idTest2").getElementsByTagName("a"), function(o){
var img = o.getElementsByTagName("img")[0], title = o.title;
о.title = "";
ft.Add(img, { Custom: { слева: -6, вверху: -6 },
onShow: функция(){
var str = '<a href="' + o.href + '"><img src="' + img.src + '" style="padding-bottom:5px;" border="0"/></ а>';
str += '<br /><a href="' + o.href + '">' + title + '</a>';
ft.Tip.innerHTML = ул;
}
});
})
//////////////////////////////////////////
ft.Add("idTest3", { ClickHide: false, TouchHide: false, Align: "right",
onShow: функция(){
var str = ' <a href=" http://www.cnblogs.com/cloudgamer/archive/2009/03/11/1408333.html "> Цветовой градиент и эффекты градиента</a><br />';
str += ' <a href=" http://www.cnblogs.com/cloudgamer/archive/2008/10/20/1314766.html "> Имитация 163 сетевой диск без обновления системы загрузки файлов</a><br / >';
str += '<input type="button" onclick="ft.Hide();" value="Нажмите, чтобы закрыть" />';
ft.Tip.innerHTML = ул;
}
});
</скрипт>
</тело>
</html>
JavaScript, позиционирование, плавающее значение, подсказки, всплывающие подсказки, фиксированные подсказки, подсказки
Описание программы
Объект подсказки :
Объект Tip — это контейнер, используемый для отображения подсказок, а программа представлена атрибутом Tip. Никаких требований к этому нет, некоторые настройки в него будут внесены при инициализации программы.
Сначала сделайте следующие настройки:
this._cssTip.margin = 0;
this._cssTip.position = "абсолютный";
this._cssTip.visibility = "скрытый";
this._cssTip.display = "блокировать";
this._cssTip.zIndex = 99;
this._cssTip.left = this._cssTip.top = "-9999px";
Поле установлено на 0, чтобы избежать некоторых проблем с позиционированием. Видимость используется для скрытия, а не для отображения, поскольку программе необходимо получить offsetWidth и offsetHeight кончика. Также необходимо установить левое и верхнее значение, чтобы избежать появления полосы прокрутки. Совет, занимающий пространство.
Поскольку Tip может находиться внутри других позиционированных элементов, необходимо установить два параметра коррекции смещения:
вар iLeft = iTop = 0, p = this.Tip.offsetParent;
while (!(p === document.body || p === document.documentElement)) {
iLeft += p.offsetLeft iTop += p.offsetTop;
};
this._offsetleft = iLeft;
this._offsettop = iTop;
Наконец, добавьте событие при наведении курсора мыши на Совет, о чем будет рассказано позже.