Пожалуй порадую вас еще одной плюшкой.
Tooltips(Подсказки).
С начала о реализации:
jQuery:
/*-------------------------------------------------------------------*/
/* Tooltip */
/*-------------------------------------------------------------------*/
(function($){
jQuery.fn.tooltip = function(options){
var e, tTimer;
/*-------------------------------------------------------------------*/
var handler = function(){
e = $(this);
initialize(e);
e.unbind();
for(event in options.eShow) { e.bind(options.eShow[event], function(){ show(e); }); }
for(event in options.eHide) { e.bind(options.eHide[event], function(){ hide(e); }); }
}
/*-------------------------------------------------------------------*/
var initialize = function(e){
OIS.setID(e);
nOptions = { attr: e.data('attr'), removeAttr: e.data('removeAttr'), eShow: e.data('eShow'), eHide: e.data('eHide'), delay: e.data('delay'), hAlign: e.data('hAlign'), vAlign: e.data('vAlign'), correction: e.data('correction'), width: e.data('width') }
options = $.extend({
attr: 'title',
removeAttr: true,
eShow: 'mouseover',
eHide: 'mouseleave',
delay: 100,
hAlign: 'center',
vAlign: 'top',
correction: [0, 0],
width: '200px'
}, nOptions, options);
setAttr(e);
if(!(options.eShow instanceof Array)) options.eShow = [options.eShow];
if(!(options.eHide instanceof Array)) options.eHide = [options.eHide];
e.data('initialized', true).data('attr', options.attr).data('removeAttr', options.removeAttr).data('eShow', options.eShow).data('eHide', options.eHide).data('delay', options.delay).data('vAlign', options.vAlign).data('hAlign', options.vAlign).data('correction', options.correction).data('width', options.width);
}
/*-------------------------------------------------------------------*/
var setAttr = function(e){
if(!e.attr(options.attr))
return true;
e.attr('oistooltip', e.attr(options.attr));
!options.removeAttr || e.removeAttr(options.attr);
}
/*-------------------------------------------------------------------*/
var show = function(e){
if($('section.ois-tooltip[eid=' + OIS.getID(e) + ']').length)
return true;
var tElement = $('<section></section>').addClass('ois-tooltip').attr('eid', OIS.getID(e)).html(e.attr('oistooltip')).appendTo($('body'));
$('<section></section>').addClass('ois-arrow-top').appendTo(tElement);
$('<section></section>').addClass('ois-arrow-bottom').appendTo(tElement);
setPosition(e);
tTimer = setTimeout(function(){
tElement.fadeIn(200);
}, options.delay);
tElement.bind({
mouseover: function(){ $(this).animate({opacity: 0}, 100); },
mouseleave: function(){ $(this).animate({opacity: 1}, 100); }
});
}
/*-------------------------------------------------------------------*/
var hide = function(e){
clearTimeout(tTimer);
var tElement = $('section.ois-tooltip[eid=' + OIS.getID(e) + ']');
if(!tElement.length)
return true;
tElement.fadeOut(200, function(){ tElement.remove(); });
}
/*-------------------------------------------------------------------*/
var setPosition = function(e){
var tElement = $('section.ois-tooltip[eid=' + OIS.getID(e) + ']').css('max-width', options.width);
vAlign = options.vAlign
if(vAlign == 'bottom')
{
if(e.offset().top + e.height() + tElement.height() + 30 > $(window).scrollTop() + $(window).height())
vAlign = 'top';
}
else if(e.offset().top - $(window).scrollTop() < tElement.height())
vAlign = 'bottom';
if(vAlign == 'top')
{
tElement.css('top', (e.offset().top - tElement.height() - parseInt(e.css('padding-top')) + parseInt(options.correction[0]) - 15) + 'px');
tArrow = tElement.find('section.ois-arrow-bottom');
}
else
{
tElement.css('top', (e.offset().top + e.height() + parseInt(e.css('padding-bottom')) - parseInt(options.correction[0]) + 15) + 'px');
tArrow = tElement.find('section.ois-arrow-top');
}
if(options.hAlign == 'center')
{
tElement.css('left', (e.offset().left + (e.width() / 2) - (tElement.width() / 2) + parseInt(options.correction[1])) + 'px');
tArrow.css('left', (tElement.width() / 2 + 3) + 'px');
}
else if(options.hAlign == 'right')
{
tElement.css('left', (e.offset().left + e.width() - tElement.width() + parseInt(options.correction[1])) + 'px');
tArrow.css('left', (tElement.width() - 7) + 'px');
}
else
tElement.css('left', (e.offset().left) + 'px');
tArrow.show();
}
/*-------------------------------------------------------------------*/
return this.each(handler);
}
})(jQuery);
CSS:
/* Контейнер с подсказкой */
.ois-tooltip{
background: #000;
border-radius: 3px;
color: #fff;
cursor: default;
display: none;
font-family: Segoe UI, Helvetica;
padding: 5px 10px;
position: absolute;
text-align: center;
top: 0; left: 0;
max-width: 200px;
z-index: 2;
}
/* Стрелочка вверх */
.ois-tooltip .ois-arrow-top{
border-left: 5px solid transparent;
border-right: 5px solid transparent;
border-bottom: 5px solid #000;
display: none;
position: absolute;
top: -5px; left: 10px;
}
/* Стрелочка вниз */
.ois-tooltip .ois-arrow-bottom{
border-left: 5px solid transparent;
border-right: 5px solid transparent;
border-top: 5px solid #000;
display: none;
position: absolute;
bottom: -5px; left: 10px;
}
Плагин позволяет создавать динамические подсказки для элементов, при чем вряд ли вы найдете более гибкие подсказки чем эти.
Итак, самое интересное: привязка подсказок.
$('*[title]').tooltip({
attr: 'title',
removeAttr: true,
eShow: 'mouseover',
eHide: 'mouseleave',
delay: 100,
hAlign: 'center',
vAlign: 'top',
correction: [0, 0],
width: '200px'
});
О свойствах по порядку:
attr -- название атрибута, в котором хранится текст подсказки
removeAttr -- определяет удалять ли атрибут после кеширования его содержимого(если этого не сделать для title, например, то при наведении мы будем видеть и стандартную подсказку и нашу)
eShow -- массив событий либо одно событие при котором подсказка будет показана
eHide -- то же, что и предыдущий пункт, но для скрытия
delay -- задержка в миллисекундах перед показом
hAlign -- горизонтальное выравнивание по блоку, к которому крепится подсказка(left, center или right)
vAlign -- Вертикальное выравнивание(top или bottom) определяет где показывать подсказку: сверху или снизу(если выйдет за экран, то будет инвертировано)
correction -- массив из двух элементов(вертикаль, горизонталь), корректирующий положение блока(например, вам надо, чтобы он был по-центру, но сдвинут на 50px левей: [0, -50])
width -- определяет максимальную ширину блока(если получится меньше, то будет меньше)
В контрольном примере значения параметров те, что ставятся по умолчанию.
Рассмотрим реализацию примера с картинки:
$('input[name=request]').tooltip({
delay: 3000,
correction: [-6, -60],
eShow: 'focus',
eHide: ['blur', 'keypress'],
hAlign: 'center',
vAlign: 'bottom'
});
Как мы видим подсказка будет показана под полем ввода при передаче ему фокуса через 3 секунды после этого, а скрыта при отборе фокуса либо при нажатии любой клавиши, при чем если клавиша будет нажата в течение этих 3 секунд, то подсказка не будет показана. Отобразится она снизу поля и отпозиционируется по его центру, а также будет откорректирована его позиция: на 6 пикселов ближе к полю чем было бы стандартно и на 60 пикселов влево. Таким образом мы получаем подсказку, появляющуюся только замешкавшимся юзерам, которые за 3 секунды не додумались что надо делать.
Также стоит отметить, что плагин каскадный. То есть вы можете определить подсказку, а потом переопределить её с другими параметрами, которые будут объеденены с ранее заданными.