Самые простейшие всплывающие подсказки с использованием jQuery 1.4 и CSS3

Четверг, 28 января 2010 года, 21:11. Напечатано в категориях CSS, CSS3, JavaScript, jQuery, Плагины, Штучки11

Привет, привет!

Сегодня вот решил показать, как пишутся самые простейшие всплывающие подсказки c использованием библиотеки jQuery и CSS3 :)

Для показа примеров буду использовать codeEvaluator :)

Для основы нам понадобится HTML документ с подключённой jQuery 1.4, блоками с заполненным атрибутом title.

<style type="text/css">body{padding:50px;}.block{float:left;padding:15px;margin:15px;background-color:#DDD;border:1px solid #EEE;width:40%;}</style>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4/jquery.min.js"></script>
<script type="text/javascript">
  // Наш будущий JS код
</script>
<div class="block" title="Это подсказка 1">Блок с подсказкой - 1</div>
<div class="block">Блок без подсказки</div>
<div class="block" title="Это подсказка 2">Блок с подсказкой - 2</div>
<div class="block">Ещё один блок без подсказки</div>
<div class="block" title="Это подсказка 3">Блок с подсказкой - 3</div>

Ага, есть!
Теперь пишем код, который будет находить после загрузки страницы все элементы с заполненным атрибутом title, сохраняем этот атрибут в переменную и удаляем этот атрибут с элемента. Дальше вешаем обработчик события mouseover на наш элемент, который при наступлении события будет нам показывать в окне alert подсказку(title):

<style type="text/css">body{padding:50px;}.block{float:left;padding:15px;margin:15px;background-color:#DDD;border:1px solid #EEE;width:40%;}</style>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4/jquery.min.js"></script>
<script type="text/javascript">
(function( $ ){
  // Функция вызывается при загрузке страницы
  $(
    function(){
      // Выбираем все элементы, в которых присутствует атрибут title
      $( '[title]' )
      .each(
        function(){
          if( this.title.length == 0 )
            return;
          var
            // Кешируем this
            $this = $( this ),
            title = $this.attr( 'title' );
          $this
          // Удаляем уже ненужный атрибут title с элемента
          .removeAttr( 'title' )
          // Вешаем обработчик события при наведении мышкой
          .mouseover(
            function(){
              // Показываем подсказку
              alert( title );
            }
          );          
        }
      );
    }
  );
})( jQuery );
</script>
<div class="block" title="Это подсказка 1">Блок с подсказкой - 1</div>
<div class="block">Блок без подсказки</div>
<div class="block" title="Это подсказка 2">Блок с подсказкой - 2</div>
<div class="block">Ещё один блок без подсказки</div>
<div class="block" title="Это подсказка 3">Блок с подсказкой - 3</div>

Всё правильно, и при наведении на блок у нас показывается подсказка посредством alert :)

Но это же не дело, показывать подсказки посредством alert :D Приходится лишний раз кликать!
Возьмём CSS3 и создадим красивый html блок, который будет всплывать при наведении над элементом!

<style type="text/css">body{padding:50px;}.block{float:left;padding:15px;margin:15px;background-color:#DDD;border:1px solid #EEE;width:40%;}</style>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4/jquery.min.js"></script>
<script type="text/javascript">
(function( $ ){
  // Функция вызывается при загрузке страницы
  $(
    function(){
      // Выбираем все элементы, в которых присутствует атрибут title
      $( '[title]' )
      .each(
        function(){
          if( this.title.length == 0 )
            return;
          var
            // Кешируем this
            $this = $( this ),
            // Создаём с помощью jQuery 1.4 блок для подсказки
            splash = $(
              '<div/>',
              {
                class: 'splashBlock',
                // Украшаем CSS свойствами
                style: 'position:absolute;display:inline-block;padding:10px;padding-left:18px;padding-right:18px;max-width:200px;border:1px solid #CCC;background-color:rgba( 170, 180, 200, 0.9 );border-radius:6px;-moz-border-radius:6px;-webkit-border-radius:6px;box-shadow:0 0 10px #DEF0FE;-moz-box-shadow:0 0 10px 0 #DEF0FE;-webkit-box-shadow:0 0 10px #DEF0FE;display:none;',
                text: $this.attr( 'title' )
              }
            );
          $this
          // Удаляем уже ненужный атрибут title с элемента
          .removeAttr( 'title' )
          // Вешаем обработчик события при наведении мышкой
          .mouseover(
            function(){
              // Добавляем блок в документ
              splash
              .prependTo( 'body' )
              // Показываем подсказку
              .fadeIn( 500 )
              // Определяемся с положением
              .css(
                {
                   top: $this.offset().top,
                   left: $this.offset().left
                }
              );
            }
          );          
        }
      );
    }
  );
})( jQuery );
</script>
<div class="block" title="Это подсказка 1">Блок с подсказкой - 1</div>
<div class="block">Блок без подсказки</div>
<div class="block" title="Это подсказка 2">Блок с подсказкой - 2</div>
<div class="block">Ещё один блок без подсказки</div>
<div class="block" title="Это подсказка большая 3. Тут очень много разного текста!">Блок с подсказкой - 3</div>

Теперь стало ещё лучше!)
Нам осталось только приделать эффект выплывания и эффект затухания через 4 секунды. А также отцентрировать подсказку!

<style type="text/css">body{padding:50px;}.block{float:left;padding:15px;margin:15px;background-color:#DDD;border:1px solid #EEE;width:40%;}</style>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4/jquery.min.js"></script>
<script type="text/javascript">
(function( $ ){
  // Функция вызывается при загрузке страницы
  $(
    function(){
      // Выбираем все элементы, в которых присутствует атрибут title
      $( '[title]' )
      .each(
        function(){
          if( this.title.length == 0 )
            return;
          var
            timeout,
            // Кешируем this
            $this = $( this ),
            // Создаём с помощью jQuery 1.4 блок для подсказки
            splash = $(
              '<div/>',
              {
                // Украшаем CSS свойствами
                style: 'position:absolute;display:inline-block;padding:10px;padding-left:18px;padding-right:18px;max-width:200px;border:1px solid #CCC;background-color:rgba( 170, 180, 200, 0.9 );border-radius:6px;-moz-border-radius:6px;-webkit-border-radius:6px;box-shadow:0 0 10px #DEF0FE;-moz-box-shadow:0 0 10px 0 #DEF0FE;-webkit-box-shadow:0 0 10px #DEF0FE;display:none;',
                // Записываем подсказку
                text: $this.attr( 'title' )
              }
            );
          $this
          // Удаляем уже ненужный атрибут title с элемента
          .removeAttr( 'title' )
          // Вешаем обработчик события при наведении мышкой
          .mouseover(
            function(){
              if( timeout )
                return;
              // Добавляем блок в документ
              splash
              .prependTo( 'body' )
              // Определяемся с положением блока в пространстве
              .css(
                {
                   top: $this.offset().top - splash.height(),
                   left: $this.offset().left + ( $this.width() / 2 ) - ( splash.width() / 2 ),
                   opacity: 0,
                   display: 'block'
                }
              )
              // Показываем подсказку
              .animate( {top: '-=25', opacity:1 }, 1000 );
              timeout = setTimeout(function(){
                splash.animate({top:'+=20',opacity:0}, 1000, function(){
                  splash.detach();
                  timeout = null;
                });
              }, 4000 );
            }
          );          
        }
      );
    }
  );
})( jQuery );
</script>
<div class="block" title="Это подсказка 1">Блок с подсказкой - 1</div>
<div class="block">Блок без подсказки</div>
<div class="block">Ещё один блок без подсказки</div>
<div class="block" title="Это подсказка 2">Блок с подсказкой - 2</div>
<div class="block" title="Это подсказка большая 3. Тут очень много разного текста!">Блок с подсказкой - 3</div>

Вот и всё :)

Обновление 1. После этого сообщения:

Логичнее убирать подсказку может не только по таймеру, но и (например) по выходу указателя за пределы элемента…. Привычнее… А если штук 15-20 элементов с подсказками? И одним легким движением мыши по всем…. Как выпрыгнут :D

Я решил исправится :)
Организуем исчезание подсказки при выходе мыши из блока, а также поставим запасной таймер на 15 секунд для исчезания подсказки(если пользователь навёл мышью и заснул):

<style type="text/css">body{padding:50px;}.block{float:left;padding:15px;margin:15px;background-color:#DDD;border:1px solid #EEE;width:40%;}</style>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4/jquery.min.js"></script>
<script type="text/javascript">
(function( $ ){
  // Функция вызывается при загрузке страницы
  $(
    function(){
      // Выбираем все элементы, в которых присутствует атрибут title
      $( '[title]' )
      .each(
        function(){
          if( this.title.length == 0 )
            return;
          var
            timeout,
            // Кешируем this
            $this = $( this ),
            // Создаём с помощью jQuery 1.4 блок для подсказки
            splash = $(
              '<div/>',
              {
                // Украшаем CSS свойствами
                style: 'position:absolute;display:inline-block;padding:10px;padding-left:18px;padding-right:18px;max-width:200px;border:1px solid #CCC;background-color:rgba( 170, 180, 200, 0.9 );border-radius:6px;-moz-border-radius:6px;-webkit-border-radius:6px;box-shadow:0 0 10px #DEF0FE;-moz-box-shadow:0 0 10px 0 #DEF0FE;-webkit-box-shadow:0 0 10px #DEF0FE;display:none;',
                // Записываем подсказку
                text: $this.attr( 'title' )
              }
            );
          $this
          // Удаляем уже ненужный атрибут title с элемента
          .removeAttr( 'title' )
          // Вешаем обработчик события на события mouseover/mouseout
          .hover(
            function(){
              if(  $( 'body' ).find( '*' ).filter(  splash ).size() == 0 ){
                // Добавляем блок в документ
                splash
                .prependTo( 'body' )
                // Определяемся с положением блока в пространстве
                .css(
                  {
                     top: $this.offset().top - splash.height(),
                     left: $this.offset().left + ( $this.width() / 2 ) - ( splash.width() / 2 ),
                     opacity: 0,
                     display: 'block'
                  }
                );
                timeout = setTimeout(function(){
                  splash.animate({top:'+=20',opacity:0}, 1000, function(){
                    splash.detach();
                    timeout = null;
                  });
                }, 15000 );
              };
              // Показываем подсказку
              splash
              .stop( true ).animate( {top: '-=25', opacity:1 }, 800 );
            },
            function(){
              timeout = null;
              splash.stop( true ).animate({top:'+=20',opacity:0}, 800, function(){
                splash.detach();
              });
            }
          );          
        }
      );
    }
  );
})( jQuery );
</script>
<div class="block" title="Это подсказка 1">Блок с подсказкой - 1</div>
<div class="block">Блок без подсказки</div>
<div class="block">Ещё один блок без подсказки</div>
<div class="block" title="Это подсказка 2">Блок с подсказкой - 2</div>
<div class="block" title="Это подсказка большая 3. Тут очень много разного текста!">Блок с подсказкой - 3</div>

А вот минимизированная версия ;)

<style type="text/css">body{padding:50px;}.block{float:left;padding:15px;margin:15px;background-color:#DDD;border:1px solid #EEE;width:40%;}</style>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4/jquery.min.js"></script>
<script type="text/javascript">
(function(b){b(function(){b("[title]").each(function(){if(this.title.length!=0){var d,c=b(this),a=b("<div/>",{style:"position:absolute;display:inline-block;padding:10px;padding-left:18px;padding-right:18px;max-width:200px;border:1px solid #CCC;background-color:rgba( 170, 180, 200, 0.9 );border-radius:6px;-moz-border-radius:6px;-webkit-border-radius:6px;box-shadow:0 0 10px #DEF0FE;-moz-box-shadow:0 0 10px 0 #DEF0FE;-webkit-box-shadow:0 0 10px #DEF0FE;display:none;",text:c.attr("title")});c.removeAttr("title").hover(function(){if(b("body").find("*").filter(a).size()== 0){a.prependTo("body").css({top:c.offset().top-a.height(),left:c.offset().left+c.width()/2-a.width()/2,opacity:0,display:"block"});d=setTimeout(function(){a.animate({top:"+=20",opacity:0},1E3,function(){a.detach();d=null})},15E3)}a.stop(true).animate({top:"-=25",opacity:1},800)},function(){d=null;a.stop(true).animate({top:"+=20",opacity:0},800,function(){a.detach()})})}})})})(jQuery);
</script>
<div class="block" title="Это подсказка 1">Блок с подсказкой - 1</div>
<div class="block">Блок без подсказки</div>
<div class="block">Ещё один блок без подсказки</div>
<div class="block" title="Это подсказка 2">Блок с подсказкой - 2</div>
<div class="block" title="Это подсказка большая 3. Тут очень много разного текста!">Блок с подсказкой - 3</div>

P. S. Если вам интересно, как создать простое модальное окно на jQuery, то милости просим ;)



Комментарии(11)

Lemurian пишет в четверг, 28.01.2010 в 21:39 Ответить
Подсказки в alert'е - это жестоко =)
А статья, имхо, будет полезна как начинающим, так и тем, кто просто еще не знаком с CSS3.
Regent пишет в четверг, 28.01.2010 в 22:30 Ответить
@Lemurian, да, с alert`ами это ещё то
WertJ пишет в пятницу, 29.01.2010 в 22:55 Ответить
Прекрасное оформление примеров, сразу видно старания автора, в общем спасибо... в закладки)
Regent пишет в пятницу, 29.01.2010 в 23:33 Ответить
@WertJ, спасибо, но всё же оформление примеров пока далеко от идеалов =)
h1 пишет в понедельник, 01.02.2010 в 18:37 Ответить
интересно, спасибо.
только вот нужно предусмотреть случай повторного наведения на элемент вызывающий подсказку и в этом случае не изменять top-координату. иначе подсказка улетает в небо
Regent пишет в понедельник, 01.02.2010 в 18:58 Ответить
@h1, да, можно просто сохранять top-координату как переменную, на ровне с таймаутом
Александр пишет в среду, 03.03.2010 в 13:12 Ответить
5+
BuRn пишет в пятницу, 07.05.2010 в 15:58 Ответить
Привет, код очень полезный, немного модификаций и подточил под себя. Вопрос возник, и бьюсь как об стену. Как модернизировать код, чтобы в подсказке можно было прописывать ещё и теги? Сделать жирным, например, или ссылку проставить? Есть идеи? Буду признателен
Regent пишет в воскресенье, 09.05.2010 в 9:14 Ответить
@BuRn, надо заменить строку
text: $this.attr( 'title' )

на
html: $this.attr( 'title' )

Если вы смогли подточить код под себя, как вы не смогли такое элементарное действие сделать?
Интернет-блондинка пишет в воскресенье, 16.05.2010 в 5:21 Ответить
Шикарная статья, даже мне, блондинке по складу ума, удалось разобраться. Сейчас попробую прикрутить эту красоту и буду спрашивать, если что не получится. Автор, спасибо большое!
BuRn пишет в воскресенье, 16.05.2010 в 21:12 Ответить
@Regent, спасибо.. скушал тупишку от Данон похоже, проникла в кровь
Уведомлять меня о новых комментариях по почте
Для корректной работы отправки комментариев необходимо включить JavaScript
Либо скачать новый нормальный браузер