Просмотр поста

.
Onatolich

Пожалуй порадую вас еще одной плюшкой. 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 секунды не додумались что надо делать.

Также стоит отметить, что плагин каскадный. То есть вы можете определить подсказку, а потом переопределить её с другими параметрами, которые будут объеденены с ранее заданными.
Прикрепленные файлы: