29
Jul/09
7
Espectacular tooltip con jQuery

Espectacular tooltip con jQuery

[¡Actualizado!] Voy a ser sincero: es la primera vez que me pongo en serio con jQury. Por eso meatrevo a deciros que este puede ser vuestro tutorial introductorio a este lenguaje. Vamos a aprender a hacer una espectacular burbuja informativa que aparecerá y desaparecerá elegantemente cuando entremos y salgamos del icono.

Autor: Jack Bach

Bach es el autor principal de este blog. A los 15 años le dio por hacer un juego en flash y eso le llevó a hacer una web para mostrarlo al mundo. Ahora ya han pasado unos años y ha aprendido sobre todo XHTML y CSS para maquetar sus diseños web.




Este tutorial ha sido posteado a menéame. Si te ha gustado puedes ayudarme votandome (no hace falta registrarse).
¡Muchas gracias!

Objetivo

Que cuando pasemos por encima de un icono aparezca una burbuja informativa animada mediante jQuery. Podéis ver la demo.

preview

El HTML

El archivo html es realmente simple. Consta de cuatro divs. Uno será el que contendrá el tooltip y el icono (que a su vez serán un div cada uno) y otro para el footer.

<div id="contenido">
<div class="tooltip">
<h2>Bienvenid@ a casa</h2>
<p>Jack Bach te ha enseñado a hacer espectaculares tooltips con jQuery, totalmente customizables ¡Para que tus diseños sean exactamente como tu quieres!</p>
<p>Si te ha gustado el tutorial, puedes encontrar muchos más en el blog, <b>Tinnta.com</b>, y suscribirte al feed.</p>
</div><!-- fin tooltip -->
<div id="icono"></div>
</div><!-- fin contenido -->
<div id="footer">
Icono de <a href="#">Softfacade</a> para <a href="#">SmashingMagazine</a> | Código por Jack Bach para <a href="http://www.tinnta.com">Tinnta</a>
</div><!-- fin footer -->

Lo importante es acordarse de llamar la librería de jQury (que podéis descargar aquí) y al archivo java que se encargará de toda la animación. Són estas dos líneas que hace falta insertar entre las etiquetas de <header>:

<script type="text/javascript" src="js/jquery-1.3.2.js"></script>
<script type="text/javascript" src="js/tooltips.js"></script>

El CSS

El css es un poco más complejo ya que tenemos que pensar en que luego sea compatible  con jQuery – lo bueno de seguir los standars es esto, que luego puedes interactuar con otros lenguajes. Esta vez, como el tutorial no tiene como objetivo el css y no quiero alargar demasiado el post me voy a saltar toda la parte obvia (body, h2, párrafo y footer). Si alguien tiene alguna duda la puede preguntar en los comentarios.

Para empezar, al div #contenido le vamos a definir un ancho de 275px (lo que mide el icono) y lo vamos a centrar:

#contenido {
width: 275px;
margin: 0 auto;
}

Vamos a por el tooltip. Por una parte le ponemos de fondo una imagen de la burbuja, le determinamos el ancho y el alto y le damos un padding para que el texto quede dentro de la imagen.

.tooltip {
background: transparent url('img/tooltip.png') no-repeat;
width: 290px;
height: 300px;
padding: 30px 60px;
...

Hasta aquí todo bien, lo interesante viene en las siguientes líneas. Por una parte vamos a hacer que se colque en la parte superior izquierda del div en que se encuentra sin tener encuenta nada más de lo que haya en este div que lo contiene. Esto se hace dandole posotion absolute. Así tenemos el control de .tooltip sin molestarnos por ver como le afectan los demás elementos de la página. Luego vamos a colocarlo donde queremos ajustando los margenes.

...
position: absolute;
margin: 55px -70px;
...

Si tenemos en cuenta la vista previa, vemos que el tooltip tapa el icono el icono – está encima. Pero si nos fijamos en el HTML, el tooltip aparece antes que el icono, por tanto, en una situación normal el segundo taparía al primero ya que es el que sale más tarde en el código. Para arreglar esto existe la propiedad z-index. Esta puede tomar un valor numérico, siendo 1 la capa superior – que tapa a las demás – y tapando las etiquetas que tomen el valor 2, 3, 4…

...
z-index: 1;
...

Como lo que queremos es que al principio no se vea el tooltip, vamos a darle a la propiedad display el valor none. Además vamos a hacer que su opacidad sea 0. Hace falta tener en centa que si solo pusiésemos la opacidad a 0, el texto del tooltip seguiría siendo seleccionable aunque no se viera.

...
display: none;
opacity: 0;
filter: alpha(opacity = 0); /* Para el señor IE*/
-moz-opacity:0; /* Para los firefox de la edad de piedra */
}

El icono es mucho más sencillo. Por una parte le ponemos el fondo deseado y le damos valores al ancho y a la altura (los que mide la imagen). Luego le aplicamos el position absolute, así a la hora de posicionarlo con los márgenes no se ve afectado por el tooltip. Esto es muy importante, ya que al ir jugando con hacer aparecer y desaparecer el tooltip, si el margen fuera relativo a los demas objetos se iría moviendo. De esta manera lo tenemos fijo.

#icono {
background: transparent url('img/icono.png') no-repeat;
height: 215px;
width: 275px;
position: absolute;
margin:350px auto;
}

Introducción a jQuery

Antes de empezar con esta parte recomiendo encarecidamente a los que no hayan visto nunca jQuery leer el este tutorial. No os llebará más de 10 minutos.

Lo que ahy que tener claro es que todo el código, que se ejecutará cuando se haya cargado el documento, irá dentro de estas líneas:

$(document).ready(function (){
  // Aquí va todo el código
});

También hace falta saber que lo que esté entre las siguientes líneas se ejecutará cuando el puntero del ratón esté encima de el div que digamos (en nuestro caso sera #icono):

$('#icono').mouseover(function (){
  // Aquí va el código
});

Y el código que va entre las siguientes líneas se ejecutará cuando el puntero salga de la zona del div:

$('#icono').mouseover(function (){
  // Aquí va el código
});

Además hace falta conocer las siguientes estructuras. Para dar estilo a un div con css (se modificará el que se le haya dado en la oja de estilo), se utiliza el código como el siguiente:

$('____').css({
  top: 0, // Los numeros no llevan comillas
  display: 'block', // Las palabras sí
  opacity: 0, // Y fijaros que no se pone punto y coma sino una coma
});

Y para animarlo de una manera personalizada se sigue el siguiente esquema:

$('____').animate({_____}, “velocidad”, callback);

En la primera parte dentro de las propiedades del animate, entre las llaves, damos el estilo final del css. Así podemos hacer que se mueva modificando los margins, que cambie su opacidad, que cambie de dimensiones, que se mueva su fondo..
Pasará de los valores que tenía en el css a los nuevos que se le den, y para definir la velocidad podemos pooner un valor numérico (en milisegundos) o ‘slow’, ‘normal’ o ‘fast’.

El callback nos permite ejecutar una funcion cuando se haya acabado la animación. Un ejemplo de como quedaría:

$('____').animate({
  top: '20px',
  opacity: 1,
}, 'normal', function (){
  ocupado = 0;
});

Y ya está casi todo. Solo hace falta añadir que se pueden utilizar estructuras como la de if (si alguien todavía no la controla no creo que haya llegado aquí; si es así se explica aquí).

El jQuery

Vamos a aclarar que es lo que queremos. Cuando se cargue el documento queremos que si pasamos por encima de #icono aparezca .tooltip con una opacidad 0 y que se anime hasta subir 20 px y llegue a una opacidad de 1. Cuando el puntero salga de #icono, queremos que .tooltip se anime de manera que suba 50 px más y que su opacidad pase a ser cero. Luego que desaparezca .tooltip y se situe en su posición inicial. Con esto ya nos podemos imaginar cómo será el código.

Hace falta añadir una variable que llamaremos ocupado. Al principio le daremos el valor 0 (no está ocupado). En el momento que se pase por encima de #icono se comprobará que ocupado esté en 0. Si es así se le dará valor 1 a ocupado y se pasará a hacer todo lo que habíamos planeado. Cuando acabe de hacerlo se le vuelbe a dar valor 0 a ocupado. Lo mismo pasa cuando sacamos el puntero. Solo se llebará a cabo lo planeado si no se está ocupado, si es así (else) se hace desaparecer directamente .tooltip para que no se líe el código. El resultado es el siguiente:

$(document).ready(function (){
  var ocupado = 0;
  //Cuando se pasa por encima del icono
  $('#icono').mouseover(function (){
    if (ocupado == 0){
      ocupado = 1;
      $('.tooltip').css({
        //Aparece (ya que estaba en display none)
        top: 0,
        display: 'block',
        opacity: 0,
      }).animate({
        //Sube 20px y pasa a ser opaco
        top: '-=20px',
        opacity: 1,
        }, 'normal', //a velocidad normal
        function (){
        ocupado = 0;
      });
    }
  });
  //Cuando sale de la zona del icono
  $('#icono').mouseout(function (){
    if (ocupado == 0){
      ocupado = 1;
      $('.tooltip').css({
        // Aeguramos que sea opaco
        opacity: 1,
      }).animate({
        // Sube 50 px y desaparece
        top: '-=50px',
        opacity: 0,
      }, 'slow',
      function(){
        $('.tooltip').css({
          // Lo recolocamos
          display: 'none',
          top: 0
        });
        ocupado = 0;
      });
    }else {
      // Si salimos de la zona antes de que se haya acabado la animacion
      $('.tooltip').css({
        // Pasamos de todo y desaparece
        display: 'none',
      });
      ocupado = 0;
    }
  });
});

Solución de Bugs

(30 julio 09)

Como muchos me habéis dicho que hay bugs, he estado toda la noche despierto para solucionarlos. Supongo que los que hubiérais seguido el tutorial os haríais dado cuenta de que el problema era que las animaciones duraban un tiempo determinado. Si durante el transcurso de la animación entrabamos o salíamos de la area con el puntero, líabamos el código. Para solucionar esto puse una pausa de medio segundo entre animación y animación con:

clearTimeout();

El código finalmente funciona con ie, firefox y safari (comprobado) y ha quedado así:

$(document).ready(function (){
	var ocupado = 0;
	var pausa = null;

	//Cuando se pasa por encima del icono
	$('#icono').mouseover(function (){
		if(pausa) clearTimeout(pausa);
		if (ocupado == 0){
			ocupado = 1;
			$('.tooltip').css({
				//Aparece (ya que estaba en display none)
				top: 0,
				display: 'block',
				opacity: 0
			}).animate({
				//Sube 20px y pasa a ser opaco
				top: '-=' + '20px',
				opacity: 1
			}, 'normal',
			function (){
				ocupado = 0;
			});
		}
	});
	//Cuando sale de la zona del icono
	$('#icono').mouseout(function (){

		pausa = setTimeout(function () {
			pausa = null;
			if (ocupado == 0){
				ocupado = 1;
				$('.tooltip').css({
					opacity: 1
				}).animate({
					top: '-=' + '50px',
					opacity: 0
				}, 'slow',
				function(){
				$('.tooltip').css({
						display: 'none',
						top: 0
					});
					ocupado = 0;
				});
			}else {
				$('.tooltip').css({
					display: 'none'
				});
				ocupado = 0;
			}
		}, 500)
	});

});

Demo y Descarga

En fin, espero que te haya gustado el tutorial. Acuerdate de dejar tu comentario y suscribirte a nuestro feed o a nuestro twitter.

Filed under: Tutoriales
Comentarios (7) Trackbacks (2)
  1. Jack Bach
    4:19 on Julio 30th, 2009

    Mañana este post se actualizará con la solución a los bugs :)

  2. seeal
    4:17 on Agosto 12th, 2009

    yo estoy en contra del IE6 si funciona bien en los demás navegadores cojonudo¡ muchos Developers que postean tutos en ingles dicen quien quiera que funcione en IE que realice el hack respectivo por que sinceramente es un coñazo el IE cuando no sigue las normas como los de mas navegadores :(

    En definitiva el tuto esta curradisimo y te felicito y…

    si funciona en los demás navegadores que no sean IE para mi esta terminado el tuto, si lo que quieres es que funcione bien en IE seria aplicarle un código especifico para solucionar el problema, por eso creo que se tiene que decir bug ya que no es culpa del desarrollador que el IE vaya por libre.

    un saludo.

    • Jack Bach
      20:27 on Agosto 12th, 2009

      Gracias, me alegra que te guste…
      Sobre lo de IE, estoy bastante molesto porque un tutorial sencillo se puede hacer muy largo por culpa de este. Creo que optaré por pasar de ie6, aunque la gente parece ser muy quisquillosa…
      Hasta pronto!

  3. joseluis
    2:56 on Octubre 6th, 2009

    Ante todo, gracias Jack.
    Me gustaria hacer una pregunta a ver si alguien me la podria resolver.
    Me explico: estoy desarrollando una web, muy sencilla, que consta de 5 paginas “inicio”, “empresa”, ” servicios”, “contacto” y “blog”. Pues bien, lo que deseo es integrar este tipo de tooltip, o similar, pero en vez de a un icono, directamente al menu de “contacto”, es decir, este en la pagina que este -por ejemplo “servicios”- cuando el puntero del raton se coloque encima de “contacto” directamente aparezca el tooltip sin dejar de estar en la misma pagina.
    Seguramente me direis que coloque un icono en cada pagina con esta funcion pero prefiero hacerlo de la otra manera, si verdaderamente es posible.
    Espero vuestra respuesta y os agradezco vuestro tiempo.
    Un saludo.

  4. Robinlogly
    10:46 on Octubre 6th, 2009

    Fantásticas herramientas las que presentas de una manera sencilla Jack. felicidades por tu trabajo

  5. rickardov
    6:31 on Mayo 2nd, 2010

    hola jack!! maravillosa esta aplicacion!! me ha servido de mucho, pero me gusaria poder incluir dentro del globo una lista con vinculos, que al pasar el mouse por sobre el globo no desaparezca y poder direccionarme hacia otra pagina a travez de los vinculos!
    como hago esto? es posible!!

    gracias de antemano!

Deja un comentario