Implementamos efectos en el navegador desplegable jQuery, aplicando conocimientos de colas de efectos, para hacer un plugin de navegación más vistoso.
Ya que en el Manual de jQuery hemos aprendido a realizar diversos efectos en jQuery y a lidiar con colas de efectos, en este artículo vamos a mostrar cómo hacer unas mejoras sencillas en el plugin para utilizar efectos especiales.
Realmente veremos que lo que hemos estudiado para aprender a hacer efectos es incluso bastante más de lo que necesitaremos en ejemplos medianamente avanzados como el que tenemos entre manos.
Antes de empezar con las explicaciones de los cambios realizados, dejamos un enlace al ejemplo en funcionamiento.
Cambio método css("display", "block") por efecto slideDown()
En el evento mouseover definido para los enlaces principales hemos cambiado el método:submenu.css("display", "block");
Por un efecto que abre el submenú con una cortinilla hacia abajo, con:
submenu.slideDown("slow");
Cambio método submenu.css('display', 'none') por efecto con slideUp()
De manera similar, cambiamos el evento mouseout para los enlaces principales, para que se oculten con una cortinilla hacia arriba. Esto se hizo cambiando las instrucciones:retardo = setTimeout("submenu.css('display', 'none');",1000)
Por:
retardo = setTimeout("submenu.slideUp('slow');",1000)
Además, en el evento mouseout de las capas de los submenús, también hacemos este cambio de sentencias, también para que se oculten al salír de los submenús con un retardo y con un efecto.
Cambios en la función que oculta todos los submenús
Esta función es interesante, porque tiene un par de cambios importantes.
function ocultarTodosSubmenus(noOcultar){
$.each(arrayCapasSubmenu, function(ind){
if (ind!=noOcultar){
this.stop(true, true);
this.css("display", "none");
}
});
}
Este método oculta todas las capas de submenús y se invoca cuando mostramos un menú desde un enlace principal, para asegurarnos que no haya dos menús abiertos al mismo tiempo. Para empezar, ahora recibe un índice de submenú que no deseamos ocultar (porque deba permanecer abierto).
Pero lo imporante es que hemos colocado un método stop(true, true), que sirve para hacer que se interrumpan todos los efectos de mostrar o ocultar una capa que pudieran haber en funcionamiento. Además marcamos con los dos true que la cola de efectos se limpie y que los efectos que se estaban ejecutando pasen directamente a su estado final.
Código completo del plugin navegador desplegable con efectos
Para que se pueda ver todo de una manera más global, dejamos el código completo de este plugin, una vez realizadas todas las modificaciones para aplicar los efectos.
////////////////////////////////////////////////////////////////////////////
//creación del plugin generaMenu.
//envío el menú de opciones como parámetro
////////////////////////////////////////////////////////////////////////////
(function($) {
$.fn.generaMenu = function(menu) {
this.each(function(){
var retardo;
var capaMenu = $(this);
//creo e inserto la lista principal
var listaPrincipal = $('<ul></ul>');
capaMenu.append(listaPrincipal);
//enlaces principales
var arrayEnlaces = [];
var arrayCapasSubmenu = [];
var arrayLiMenuPrincipal = [];
//recorro los elementos del menú
jQuery.each(menu, function(ind) {
//ahora en this tengo cada uno de los elementos.
var elementoPrincipal = $('<li></li>');
listaPrincipal.append(elementoPrincipal);
//creo el enlace e inserto
var enlacePrincipal = $('<a href="' + this.url + '">' + this.texto + '</a>');
elementoPrincipal.append(enlacePrincipal);
var capaSubmenu = $('<div class="submenu"></div>');
//guardo la capa submenu en el elemento enlaceprincipal y su indice
enlacePrincipal.data("capaSubmenu",capaSubmenu);
enlacePrincipal.data("indice",ind);
//creo una lista para poner los enlaces
var subLista = $('<ul></ul>');
//añado la lista a capaMenu
capaSubmenu.append(subLista);
//para cada elace asociado
jQuery.each(this.enlaces, function() {
//en this tengo cada uno de los enlaces
//creo el elemento de la lista del submenú actual
var subElemento = $('<li></li>');
//meto el elemento de la lista en la lista
subLista.append(subElemento);
//creo el enlace
var subEnlace = $('<a href="' + this.url + '">' + this.texto + '</a>');
//cargo el enlace en la lista
subElemento.append(subEnlace);
});
//inserto la capa del submenu en el cuerpo de la página
$(document.body).append(capaSubmenu);
/////////////////////////////////////////
//EVENTOS
/////////////////////////////////////////
//defino el evento mouseover para el enlace principal
enlacePrincipal.mouseover(function(e){
var enlace = $(this);
clearTimeout(retardo);
indice = enlace.data("indice");
ocultarTodosSubmenus(indice);
//recupero la capa de submenu asociada
submenu = enlace.data("capaSubmenu");
//la muestro
//submenu.css("display", "block");
submenu.slideDown("slow");
});
//defino el evento para el enlace principal
enlacePrincipal.mouseout(function(e){
var enlace = $(this);
//recupero la capa de submenu asociada
submenu = enlace.data("capaSubmenu");
//la oculto
clearTimeout(retardo);
//retardo = setTimeout("submenu.css('display', 'none');",1000)
retardo = setTimeout("submenu.slideUp('slow');",1000)
});
//evento para las capa del submenu
capaSubmenu.mouseover(function(){
clearTimeout(retardo);
})
//evento para las capa del submenu
capaSubmenu.mouseout(function(){
clearTimeout(retardo);
submenu = $(this);
retardo = setTimeout("submenu.slideUp('slow');",1000)
})
//evento para cuando se redimensione la ventana
if(arrayEnlaces.length==0){
//Este evento sólo lo quiero ejecutar una vez
$(window).resize(function(){
colocarCapasSubmenus();
});
}
/////////////////////////////////////////
//FUNCIONES PRIVADAS DEL PLUGIN
/////////////////////////////////////////
//una función privada para ocultar todos los submenus
function ocultarTodosSubmenus(noOcultar){
$.each(arrayCapasSubmenu, function(ind){
if (ind!=noOcultar){
this.stop(true, true);
this.css("display", "none");
}
});
}
function colocarCapasSubmenus(){
$.each(arrayCapasSubmenu, function(i){
//coloco la capa en el lugar donde me interesa
var posicionEnlace = arrayLiMenuPrincipal[i].offset();
this.css({
left: posicionEnlace.left,
top: posicionEnlace.top + 28
});
});
}
//guardo el enlace y las capas de submenús y los elementos li en arrays
arrayEnlaces.push(enlacePrincipal);
arrayCapasSubmenu.push(capaSubmenu);
arrayLiMenuPrincipal.push(elementoPrincipal);
//coloco inicialmente las capas de submenús
colocarCapasSubmenus();
});
});
return this;
};
})(jQuery);
El resultado, como decimos, es bastante más atractivo y los efectos no resultan incómodos en la operativa del menú, como podemos ver en la página donde mostramos el menú desplegable en marcha.
Miguel Angel Alvarez
Fundador de DesarrolloWeb.com y la plataforma de formación online EscuelaIT. Com...