Criando menu expansível com jQuery
Neste tutorial você vai aprender a criar um menu que se expande usando jQuery.
Preview Online
Baixar Arquivos
Em primeiro lugar devemos criar a estrutura necessária para que nosso aplicativo possa viver. Para isso criei um arquivo chamado expand.html, que será responsável pela estruturação do código, um arquivo chamando expand.css, que será responsável pelo visual de uma maneira geral, e um arquivo chamado expand.js, que será responsável pelos efeitos, além da pasta com as imagens que serão usadas no menu.
Começando pelo começo, nada é mais importante que o arquivo HTML, então vamos à ele.
a estrutura básica para iniciar o projeto é vista a seguir (repare como o framework jQuery já está carregado através da tag script):
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <title>expandindo menu com jQuery</title> <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script> </head> <body> </body> </html>
Em seguida precisaremos de uma lista, onde cada item representará um item do menu.
dentro de cada item teremos uma imagem, um título e uma descrição.
<ul id="expand"> <li> <img src="drupal.jpg" alt="" width="80" height="80" /> <h2>Drupal</h2> <p>Drupal is a free and open source[1] Content Management System (CMS) written in PHP. It is used as a back-end system for many different types of websites, ranging from small personal blogs to large corporate and political sites. It is distributed under the GNU GPL.</p> </li> <li> <img src="expressionengine.jpg" alt="" width="80" height="80" /> <h2>Expression Engine</h2> <p>EllisLab is a software developer based in Bend, Oregon which develops applications written in PHP. The company is privately owned and has to date accepted no venture capital funding of any kind. Since the company's founding in January 2002.</p> </li> <li> <img src="frog.jpg" alt="" width="80" height="80" /> <h2>Frog CMS</h2> <p>Frog CMS is an open source content management system originally developed by the company Philippe Archambault. The design decision taken from its start was to use PHP5 as the language for the software, along with a MySQL database backend, although it also has support for SQLite (version 3). It is a port of the Ruby on Rails CMS known as Radiant, although Frog has begun to take its own development direction.</p> </li> <li> <img src="joomla.jpg" alt="" width="80" height="80" /> <h2>Joomla!</h2> <p>Joomla! is a content management system platform for publishing content on the World Wide Web and intranets as well as a Model-view-controller (MVC) Web Application Development framework. The system includes features such as page caching to improve performance, RSS feeds, printable versions of pages, news flashes, blogs, polls, website searching, and language internationalization. It is written in the PHP programming language and uses the MySQL database system to store information. Joomla is the result of a fork of Mambo. Released under the terms of the GNU General Public License, Joomla is free software.</p> </li> <li> <img src="magento.jpg" alt="" width="80" height="80" /> <h2>Magento</h2> <p>Magento is an Open Source ecommerce web application launched on March 31, 2008. It was created by Varien, building on components of the Zend Framework. Magento is available under the Open Software License version 3.0. Since version 1.1.7 some parts are licensed under the Academic Free License version 3.0. Magento Enterprise Edition, a paid for version of Magento aimed at larger companies, was launched on April 15, 2009.</p> </li> <li> <img src="modx.jpg" alt="" width="80" height="80" /> <h2>MODx</h2> <p>MODx is a free, open source content management system and web application framework for publishing content on the world wide web and intranets. MODx is licensed under the GPL. MODx is written in the PHP programming language and uses the MySQL database.</p> </li> </ul>
Feito isso devemos estilizar nosso trabalho, então é hora de visitar o arquivo expand.css.
as instruções linha a linha são a seguinte:
- Zerar margin e padding de todos os elementos, além das bolinhas padrão que vem nas listas
- Dar um tamanho à div que será usada mais afrente.
- Dar uma cor de fundo à página
- Mostrar o menu na horizontal e dimensioná-lo, a fim de mostrar todo o conteúdo de todos os itens, além de dar um visual legal pra cada item.
- Estilizar a imagem e flutua-la para a esquerda, assim o título e a descrição podem fluir em volta dela.
- Estilizar a descrição. Repare que a propriedade margin-left é igual à distância do texto à extrema esquerda de seu pai, e isso serve para que o mesmo não flua para baixo da imagem.
- Estilizar o título.
- Dar background rosa aos itens pares da lista.
- Dar background verde aos itens impares da leta.
*{
margin:0;
padding:0;
list-style:none;
}
div{
overflow:hidden;
width:450px;
}
html{
background:#ccc;
}
#expand li{
float:left;
width:390px;
height:170px;
margin:2px;
overflow:hidden;
border:1px solid #555;
-moz-border-radius:10px;
-webkit-border-radius:10px;
}
#expand img{
border:3px solid #686;
background: #aaa;
padding:3px;
float:left;
margin:3px 5px;
}
#expand p{
font:normal normal normal 11px/1.4 arial,sans-serif;
float:none;
padding:3px 12px 0 5px;
margin:5px 0 0 102px;
}
#expand h2{
font:bold italic normal 15px/1 georgia,serif;
margin:3px 0 0 108px;
}
#expand li:nth-child(even){
background: #dff;
}
#expand li:nth-child(odd){
background: #fdf;
}
Repare que as duas últimas linhas são formadas por propriedades presentes somente em CSS3, mas são reconhecidas em todos os navegadores modernos (ou seja, Firefox, Safari, Chrome e Opera). Por último devemos criar o efeito usando jQuery. Abrindo arquivo expand.js, o primeiro que devemos fazer é iniciar o jQuery.
$(document).ready(function(){
});
O segundo passo é criar uma div que vai envolver todo o conteúdo dos itens. Esta parte é importante para que o texto não flua quando o item expandir e retrair.
$('#expand li').wrapInner('<div>');
Em seguida usamos jQuery para diminuir todos os itens, e mostrar somente a imagem.
$('#expand li').css({
width: '102px'
,height: '100px'
});
Cada item tem uma altura diferente, e para podermos expandir uma altura suficiente para mostrar todo o conteúdo devemos primeiro conhecer a altura do maior deles, então um loop é criado para rodar todos as divs e pegar a maior altura encontrada
var alturaMax = 100;
$('#expand li div').each(function(){
alturaDiv = $(this).height();
if(alturaDiv > alturaMax){
alturaMax = alturaDiv;
}
});
A seguir vem a animação em si
$('#expand li').hover(/*mouse em cima*/,/*mouse saindo*/);
Quando o mouse estiver em cima, queremos expandir o item para 450px de largura e para a altura do maior dos itens, mas somente depois de parar o que estava fazendo.
$('#expand li').hover(function(){
$(this).stop().animate({
width: '450px'
,height: alturaMax + 5 + 'px'
});
},/*mouse saindo*/);
Quando o mouse deixa o item, queremos que o mesmo pare o que estiver fazendo e volte a animar retornando à posição inicial
$('#expand li').hover(function(){
$(this).stop().animate({
width: '450px'
,height: alturaMax + 5 + 'px'
});
},function(){
$(this).stop().animate({
width: '102px'
,height: '100px'
});
});
Nesse ponto o script já funciona e faz exatamente o que queremos, mas bons programadores sempre retornam ao seu código e tentam o tornar melhor. O arquivo criado, apesar de funcionar, apresentam um monte de más práticas quando se diz respeito a javascript, e a seguir tentaremos contornar esses problemas.
A primeira parte que devemos notar é que o seguinte fragmento do código é chamada inúmeras vezes
$('#expand li')
Chamadas por elementos do DOM são demasiadamente penosas em javascript, e como fazemos estas chamadas várias vezes usando jQuery, nosso script acaba se tornando bastante lento. Para solucionar este problema devemos armazenar todos as chamadas em cache, mas só faz sentido fazer isso caso esta chamada seja feita mais de uma vez. O mesmo deve ser feito com a variável $(this), porém nesse caso elas são chamadas somente uma vez em cada loop, então não se deve tocar nelas. Corrigindo este problema, nosso código fica da seguinte maneira
$(document).ready(function(){
var $item = $('#expand li');
$item.wrapInner('<div>');
$item.css({
width: '102px'
,height: '100px'
});
var alturaMax = 100;
$item.children('div').each(function(){
alturaDiv = $(this).height();
if(alturaDiv > alturaMax){
alturaMax = alturaDiv;
}
});
$item.hover(function(){
$(this).stop().animate({
width: '450px'
,height: alturaMax + 5 + 'px'
});
},function(){
$(this).stop().animate({
width: '102px'
,height: '100px'
});
});
});
Um passo adicional que podemos tomar é usar o que é conhecido em javascript como chaining. Isto significa aplicar seguidas funções sem sair de um contexto. Talvez fique mais claro no código abaixo
$(document).ready(function(){
var $item = $('#expand li');
var alturaMax = 100;
$item.wrapInner('<div>')
.css({
width: '102px'
,height: '100px'
})//não se usa ';' aqui, para que os métodos possam ser acorrentados
.children('div').each(function(){
alturaDiv = $(this).height();
if(alturaDiv > alturaMax){
alturaMax = alturaDiv;
}
})//não se usa ';' aqui, para que os métodos possam ser acorrentados
.hover(function(){
$(this).stop().animate({
width: '450px'
,height: alturaMax + 5 + 'px'
});
},function(){
$(this).stop().animate({
width: '102px'
,height: '100px'
});
});
});
Neste momento o script já está bem mais rápido, e agora podemos criar mais um efeito onde a altura do item será animado o suficiente para mostrar todo o seu conteúdo, então se o item tiver pouco conteúdo a sua altura expandirá pouco ou não expandirá, e caso o item tenha bastante conteúdo a sua altura expandirá o necessário para que mostre todo o texto.
Para este efeito devemos descobrir a altura da div quando passamos o mouse por cima do item (repare que comentei o código que não será mais usado e modifiquei a variável que dá a altura do item da lista) .
$(document).ready(function(){
var $item = $('#expand li');
var alturaMax = 100,altura;
$item.wrapInner('<div>')
.css({
width: '102px'
,height: '100px'
})//não se usa ';' aqui, para que os métodos possam ser acorrentados
// .children('div').each(function(){
// alturaDiv = $(this).height();
// if(alturaDiv > alturaMax){
// alturaMax = alturaDiv;
// }
// })
.hover(function(){
altura = $(this).children('div').height();
$(this).stop().animate({
width: '450px'
,height: altura + 5 + 'px'
});
},function(){
$(this).stop().animate({
width: '102px'
,height: '100px'
});
});
});
Abaixo está o conteúdo de todos os arquivos criados.
xHTML
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" /> <title>sem título</title> <link type="text/css" href="expand.css" rel="stylesheet"/> <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script> <script type="text/javascript" src="expand.js"></script> </head> <body> <ul id="expand"> <li> <img src="imagens/drupal.jpg" alt="" width="80" height="80" /> <h2>Drupal</h2> <p>Drupal is a free and open source[1] Content Management System (CMS) written in PHP. It is used as a back-end system for many different types of websites, ranging from small personal blogs to large corporate and political sites. It is distributed under the GNU GPL.</p> </li> <li> <img src="imagens/expressionengine.jpg" alt="" width="80" height="80" /> <h2>Expression Engine</h2> <p>EllisLab is a software developer based in Bend, Oregon which develops applications written in PHP. The company is privately owned and has to date accepted no venture capital funding of any kind. Since the company's founding in January 2002.</p> </li> <li> <img src="imagens/frog.jpg" alt="" width="80" height="80" /> <h2>Frog CMS</h2> <p>Frog CMS is an open source content management system originally developed by the company Philippe Archambault. The design decision taken from its start was to use PHP5 as the language for the software, along with a MySQL database backend, although it also has support for SQLite (version 3). It is a port of the Ruby on Rails CMS known as Radiant, although Frog has begun to take its own development direction.</p> </li> <li> <img src="imagens/joomla.jpg" alt="" width="80" height="80" /> <h2>Joomla!</h2> <p>Joomla! is a content management system platform for publishing content on the World Wide Web and intranets as well as a Model-view-controller (MVC) Web Application Development framework. The system includes features such as page caching to improve performance, RSS feeds, printable versions of pages, news flashes, blogs, polls, website searching, and language internationalization. It is written in the PHP programming language and uses the MySQL database system to store information. Joomla is the result of a fork of Mambo. Released under the terms of the GNU General Public License, Joomla is free software.</p> </li> <li> <img src="imagens/magento.jpg" alt="" width="80" height="80" /> <h2>Magento</h2> <p>Magento is an Open Source ecommerce web application launched on March 31, 2008. It was created by Varien, building on components of the Zend Framework. Magento is available under the Open Software License version 3.0. Since version 1.1.7 some parts are licensed under the Academic Free License version 3.0. Magento Enterprise Edition, a paid for version of Magento aimed at larger companies, was launched on April 15, 2009.</p> </li> <li> <img src="imagens/modx.jpg" alt="" width="80" height="80" /> <h2>MODx</h2> <p>MODx is a free, open source content management system and web application framework for publishing content on the world wide web and intranets.</p> </li> </ul> </body> </html>
CSS
*{
margin:0;
padding:0;
list-style:none;
}
div{
overflow:hidden;
width:450px;
}
html{
background:#ccc;
}
#expand li{
float:left;
width:390px;
height:220px;
margin:2px;
overflow:hidden;
border:1px solid #555;
-moz-border-radius:10px;
-webkit-border-radius:10px;
}
#expand img{
border:3px solid #686;
background: #aaa;
padding:3px;
float:left;
margin:3px 5px;
}
#expand p{
font: normal normal normal 11px/1.4 arial,sans-serif;
padding:3px 12px 0 5px;
margin:5px 0 0 102px;
}
#expand h2{
font:bold italic normal 15px/1 georgia,serif;
margin:3px 0 0 108px;
}
#expand li:nth-child(even){
background: #dff;
}
#expand li:nth-child(odd){
background: #fdf;
}
jQuery
/**
* @author http://tutorial-city.net/
*/
$(document).ready(function(){
var $item = $('#expand li');
var alturaMax = 100;
$item.wrapInner('<div>')
.css({
width: '102px'
,height: '100px'
})
.hover(function(){
altura = $(this).children('div').height();
$(this).stop().animate({
width: '450px'
,height: altura + 5 + 'px'
});
},function(){
$(this).stop().animate({
width: '102px'
,height: '100px'
});
});
});
O resultado final pode ser visualizado no link abaixo.
Preview Online
Baixar Arquivos
Espero que tenha aprendido bastante com este tutorial, e sinta-se à vontade para comentar e acrescentar ao que foi passado. Abraços e até a próxima!
David CHC • 07/09/2009
Muito show a vídeo aula e tbm o tutorial. Uma das coisas q gosto do jquery é a possibilidade da concatenação de efeitos, eventos, etc. As dicas q ia colocar, vc já fez as alterações no posts, rs.
abrs