Anuncios

Bienvenidos sean e este post, hoy les «prometo» que veremos un tema muy interesante. 😉

Anuncios

Antes de comenzar con este tema vamos a trabajar con un pequeño ejemplo pero para ello necesitaremos el codigo del post anterior, en caso de no tenerlo les dejo un link para descargarlo:

Anuncios

Simplemente deben extraer los archivos en un directorio, con esto realizado nuestro primer paso sera ir al archivo animar.html y agregaremos la siguiente linea dentro de head antes del llamado al archivo codigo.js:

<script src="jquery-ui-1.8.13.custom.min.js"></script>
Anuncios

Nuestro siguiente paso es descargar esta version personalizada de jQuery UI para poder implementar unos efectos en nuestros proximos codigos:

Anuncios

Extraigan el archivo en la raiz de nuestro directorio, con esto realizado continuemos con el proyecto y para ello iremos al archivo estilo.css y agregaremos el siguiente segmento de codigo:

#movible {
  z-index: 0;
  padding: 10px;
  background-color: #888;
  -moz-border-radius: 0 5px 5px 0;
  -webkit-border-radius: 0 5px 5px 0;
  border-radius: 0 5px 5px 0;
  visibility: visible;
  position: absolute;
  overflow: hidden;
  top: -1000em;
  left: 0;
  width: 75px;
  height: 75px;
}
#movible .sinopsis {
  position: static;
}
Anuncios

Este sera un estilo para un elemento que trabajaremos mas adelante y a la sinopsis que existe ya en nuestra pagina, nuestro siguiente paso sera ir al archivo codigo.js y modificaremos la funcion mostrarDet de la siguiente manera:

function mostrarDet() {
	var $libro = $(this);
	if ($libro.hasClass('activo')){
		return;
	}

	$('div.libro.activo')
		.removeClass('activo')
		.children('div').fadeOut();
	$libro.addClass('activo');

	$libro.find('div').css({
		display: 'block',
		left: '-600px',
		top: 0
	}).each(function(indice) {
		$(this).animate({
			left: 100,
			top: 25 * indice
		}, {
			duration: 'slow',
			specialEasing: {
				top: 'easeInQuart'
			}
		});
	});
}
Anuncios

En este caso la modificacion que realizamos es minima dado que solo modificamos el segmento encargado de la animacion, veamos en detalle:

$(this).animate({
	left: 100,
	top: 25 * indice
}, {
	duration: 'slow',
	specialEasing: {
		top: 'easeInQuart'
	}
});
Anuncios

En este caso agregamos la duracion y una propiedad nueva llamada specialEasing y en este aplicamos el valor easeInQuart, por eso debimos agregar la nueva libreria,, pero solo para el top, esto hara que el elemento siga un camino curvo en lugar de uno recto, todo gracias a specialEasing porque nos pemite establecer distintos tipos de curva de aceleracion para las propiedades que incluyamos en este y las que no esten usaran el easing ordinario, si lo probamos ahora trabajara de la siguiente manera

Anuncios

Aqui podemos ver como mejoro el efecto pero vamos a tener un inconveniente en la pagina ahora, no podremos mostrar la sinopsis del libro, para solucionar esto debemos aplicar el tema del titulo.

Anuncios

En realidad sobre internet nosotros no tenemos un control total sobre el tiempo de duracion de una operacion, inclusive no sabemos si es exitosa o no, y en algunas ocasiones puede fallar y nosotros no recibir una notificacion sobre esto, aqui entran en accion los objetos diferidos los cuales encapsulan una operacion que toma un tiempo en completar y devolvernos una respuesta.

Anuncios
Anuncios

Para crear los objetos diferidos se utiliza al constructor $.deferred, con el objeto creado podemos aplicarle operaciones de larga duracion y despues mediante los metodos resolve y reject para terminarlo o rechazarlo respectivamente, aunque este es muy inusual que lo hagamos manualmente, por lo general esto se lo delega a jQuery tanto para la creacion de los objetos como la finalizacion exitosa o no, lo unico que deberiamos centrarnos es como usarr el objeto creado.

Anuncios

Se considera que todo objeto diferido hace una promesa de proveer datos a otro codigo, a su vez esta promesa esta representada por un objeto con sus propios metodos, para obtener la promesa podemos usar al metodo promise, despues podemos adjuntar algunos metodos de promise para saber cual fue el estado de salida de la promesa, veamos algunos:

  • .done(), este metodo es llamado cuando la promesa termino bien
  • .fail(), este en cambio es llamado cuando la promesa termino mal
  • .always(), este es llamado siempre que se termina la tarea, exitoso o no
Anuncios
Anuncios

Estos son muy similares a las funciones callback del metodo on donde son llamadas cuando un evento ocurre, a su vez podemos adjuntar todas las queramos y se ejecutaran a su debido momento, pero su principal diferencia es que no puede ser llamado por segunda vez, es decir una vez que se resolvio la promesa se llamara inmediatamente al metodo adjuntado, para aplicarlo vamos a volver al ejemplo que vimos al comienzo, para ello en el bloque donde esta la funcion mostrarDet antes de esta agregaremos este siguiente segmento de codigo:

var $movible = $('<div id="movible"></div>')
	.appendTo('body');
var sinopBaseEstilo = {
	display: 'none',
	height: '5px',
	width: '25px'
},
sinopEfectos = {
	duration: 800,
	easing: 'easeOutQuart',
	specialEasing: {
		opacity: 'linear'
	}
};
Anuncios
Anuncios

Aqui definiremos tres objetos, el primero sera un div, si les parece familiar es el agregado al comienzo en estilo.css, aca por medio del selector lo establececremos y lo agregaremos al body, el siguiente son unas propieddes que almacenaremos en un objeto para usarlo como estilo base para la sinopsis, el siguiente es lo mismo pero orientado para los efectos sobre el parrafo sinopsis, en este ultimo volvemos a usar el efecto propio de jQueryUI, nuestro siguiente paso sera agregar una nueva funcion despues de estos y antes de mostrarDet:

	function mostrarSinop() {
		var $libro = $(this).parent(),
			$sinop = $libro.find('p.sinopsis'),
			estIni = $.extend(sinopBaseEstilo, $libro.offset()),
			estFin = {
				width: $sinop.width(),
				top: $libro.offset().top + 5,
				left: $libro.width()+$libro.offset().left-150,
				opacity: 'show'
			};
		$movible
			.html($sinop.clone())
			.css(estIni)
			.animate(estFin, sinopEfectos)
			.animate({ height: $sinop.height() },
				{ easing: 'easeOutQuart' });
	}
Anuncios
Anuncios

Esta funcion la usaremos para mostrar la sinopsis de cada libro, primero definiremos una serie de objetos, el primero para almacenar al libro (padre), el siguiente sera para almacenar el parrafo sinopsis del elemento seleccionado, despues tendremos otro para contener los estilos iniciales donde seran los del estilo base que definimos anteriormente, el ultimo objeto sera para el estilo final donde guardaremos varias propiedades, tanto como el ancho, la parte superior, la ubicacion a la izqquierda y la opacidad del elemento, despues tomaremos el objeto donde tenemos al div movible y en el cargaremos una copia del contenido de $sinop, lo siguiente sera aplicarle un estilo a traves de css y estIni, le aplicaremos una animacion con el objeto definido anteriormente y despues con uno de los anteriores, y finalmente usamos animate nuevamente para aplicar otra forma de aceleracion, nuestro siguiente paso sera modificar la funcion mostrarDet de la siguiente manera:

function mostrarDet() {
	var $libro = $(this).parent();
	if ($libro.hasClass('activo')){
		return;
	}
	$movible.fadeOut();

	$('div.libro.activo')
		.removeClass('activo')
		.children('div').fadeOut();
	$libro.addClass('activo');

	$libro.find('div').css({
		display: 'block',
		left: '-600px',
		top: 0
	}).each(function(indice) {
		$(this).animate({
			left: 100,
			top: 25 * indice
		}, {
			duration: 'slow',
			specialEasing: {
				top: 'easeInQuart'
			}
		});
	}).promise().done(mostrarSinop);
}
Anuncios
Anuncios

Los cambios son pocos pero notables, el primero es $libro donde le agregamos el metodo parent para que tome al padre, despues del condicional donde verifica si tiene la clase activo agregamos un fadeOut para que desaparezca a movible si existe, el resto sigue igual que el anterior pero antes del final de la funcion agregamos un promise para verificar si este se proceso bien y en caso de ser asi llamara a la funcion anterior,, es decir mostrara el titulo y al autor y finalmente la sinopsis del libro, nuestro siguiente paso sera tomar la siguiente linea:

$('div.libro').click(mostrarDet);
Anuncios

Y la pueden eliminar o comentar, una vez hecho esto solo nos resta modificar el siguiente bloque de codigo:

$('div.libro').on('mouseenter mouseleave', function(ev) {
	var tam = ev.type == 'mouseenter' ? 160 : 150;
	var pad = ev.type == 'mouseenter' ? 0 : 5;
	$(this).find('img').stop().animate({
		width: tam,
		height: tam,
		paddingTop: pad,
		paddingLeft: pad
	});
});
Anuncios

De la siguiente manera:

$('div.libro').on('mouseenter mouseleave', function(ev) {
	var tam = ev.type == 'mouseenter' ? 160 : 150;
	var pad = ev.type == 'mouseenter' ? 0 : 5;
	$(this).find('img').stop().animate({
		width: tam,
		height: tam,
		paddingTop: pad,
		paddingLeft: pad
	});
}).find('img').click(mostrarDet);
Anuncios

Aqui solo agregamos un find para encontrar a img y a este le asociamos el evento click para llamar a mostrarDet, antes de ver como funciona pasemos a ver el codigo final de este bloque:

$(document).ready(function() {
	var $movible = $('<div id="movible"></div>')
		.appendTo('body');
	var sinopBaseEstilo = {
		display: 'none',
		height: '5px',
		width: '25px'
	},
	sinopEfectos = {
		duration: 800,
		easing: 'easeOutQuart',
		specialEasing: {
			opacity: 'linear'
		}
	};

	function mostrarSinop() {
		var $libro = $(this).parent(),
			$sinop = $libro.find('p.sinopsis'),
			estIni = $.extend(sinopBaseEstilo, $libro.offset()),
			estFin = {
				width: $sinop.width(),
				top: $libro.offset().top + 5,
				left: $libro.width()+$libro.offset().left-150,
				opacity: 'show'
			};
		$movible
			.html($sinop.clone())
			.css(estIni)
			.animate(estFin, sinopEfectos)
			.animate({ height: $sinop.height() },
				{ easing: 'easeOutQuart' });
	}

	function mostrarDet() {
		var $libro = $(this).parent();
		if ($libro.hasClass('activo')){
			return;
		}
		$movible.fadeOut();

		$('div.libro.activo')
			.removeClass('activo')
			.children('div').fadeOut();
		$libro.addClass('activo');

		$libro.find('div').css({
			display: 'block',
			left: '-600px',
			top: 0
		}).each(function(indice) {
			$(this).animate({
				left: 100,
				top: 25 * indice
			}, {
				duration: 'slow',
				specialEasing: {
					top: 'easeInQuart'
				}
			});
		}).promise().done(mostrarSinop);
	}

	$('div.libro').on('mouseenter mouseleave', function(ev) {
		var tam = ev.type == 'mouseenter' ? 160 : 150;
		var pad = ev.type == 'mouseenter' ? 0 : 5;
		$(this).find('img').stop().animate({
			width: tam,
			height: tam,
			paddingTop: pad,
			paddingLeft: pad
		});
	}).find('img').click(mostrarDet);
});
Anuncios

Con todo esto comentado veamos como es la nueva salida:

Anuncios

Aqui tenemos una animacion final mucho mas interesante y sobre todo ahora cumplimos nuestra promesa, este concepto esta pensado para evitar inconvenientes con el uso de internet y solicitudes al servidor, y recuerden asi como utilizamos esta aceleracion de jQuery UI se puede usar de otras librerias disponibles en javascript, antes de finalizar les dejo los archivos y codigos finales de este post:

Anuncios

En resumen, hoy hemos visto como son los objetos diferidos, despues hablamos de las promesas, como trabajan, como usarlas y finalmente un ejemplo para verlo en accion, espero les haya sido de utilidad sigueme en tumblr, Twitter o Facebook para recibir una notificacion cada vez que subo un nuevo post en este blog, nos vemos en el proximo post.

Anuncios

Donación

Es para mantenimento del sitio, gracias!

$1.50