tadarank afiliados

20 novembro, 2006

Menu em árvore, cascata, como queiram

Opa. Tamo de volta.


Hoje, menuzinho em árvore, cascata, tree, explorer, etc (vários nomes né?). Existem zilhões deste modelo de menus na net, mas acredito que o diferencial deste meu é a simplicidade (e acessibilidade com o javascript desativado). Nada de loucuras mirabolantes só no Javascript, nada de adicionar itens através de linhas em Javascript. Coisa simples, fácil de ser entendida, light.

  • Os ítens do menu, sub-ítens e links são feitos no velho HTML que todo mundo já conhece. Sem burocracia.

  • Depois agente estiliza o menu através do flexível CSS. Sem complicação. (se não entende nada de CSS, vá estudar um pouco antes de sair simplesmente me perguntando "mico, como muda a imagem?")

  • Por último, é só colocar um Javascript básico pra mudar a classe dos ítens entre "aberto" e "fechado". Simplex.

Editado dia 18/09/07 de acordo com solicitação do Gustavo nos comentários.

Editado dia 23/09/08 de acordo com solicitação do 'Curioso' nos comentários.

Olha o HTML básico do menu. É onde você terá que alterar, inserir seus links e textos. Não precisa nem mexer no restante do código se achar complicado (O Javascript e o CSS):

    <ul id="menuteste">
      <li><a href="#">itens 1</a>
        <ul>
          <li><a href="#">itens 1.1</a>
            <ul>
              <li><a href="#">itens 1.1.1 </a></li>
              <li><a href="">itens 1.1.2</a></li>
              <li><a href="">itens 1.1.3</a></li>
            </ul>
          </li>
          <li><a href="">itens 1.2</a></li>
          <li><a href="">itens 1.3</a></li>
          <li><a href="">itens 1.4</a></li>
        </ul>
      </li>
       <li><a href="#">itens 2</a>
         <ul>
           <li><a href="#">itens 2.1</a></li>
           <li><a href="">itens 2.2</a></li>
           <li><a href="">itens 2.3</a></li>
           <li><a href="">itens 2.4</a></li>
         </ul>
       </li>
    </ul>

O código completo tá abaixo. Testado no FF2.0, IE 6 e Opera 8.5 (quem puder testar em outros navegadores/versões coloca um comentário aí...).

Nos comentários do código há bastante explicação sobre o que cada parte faz. É bem fácil de entender e de implementar. É só alterar os ULs e LIs do HTML. Não precisa mexer no restante se não souber (Javascript e CSS).

<head>
<style>
/* fazendo a estilização visual via CSS */
 li { list-style: square }
 .aberto{ display:block; }
 .paiaberto{ list-style: circle; list-style-image: url(folderopen.gif);  }
 /* espaçamento pro IE */
 * html .paiaberto { padding-left: 5px; }

 .fechado{ display:none; border: 1px solid  gray }
 .paifechado{ list-style: disc; list-style-image: url(folderclosed.gif);  }
 /* espaçamento pro IE */
 * html .paifechado { padding-left: 7px;}
</style>
<script>
/* atalho para o getElementById */
function ge(q){ return document.getElementById(q)}

function Menu(evt,id) {  
/* função que muda a classe CSS dos elementos da lista
   de forma a abrir e fechar a árvore */
    if(typeof(evt)=='undefined')var evt=window.event

    //pegando o li pai do link
    var lipai = id.parentNode;
    //pegando o primeiro ul
    var ulfilho = id.parentNode.getElementsByTagName ("ul")[0];
    
    if(ulfilho.className.indexOf('aberto')<0 && ulfilho.className.indexOf('fechado')<0){
        //definindo um estado inicial caso nao haja
        ulfilho.className = ulfilho.className + " aberto";
    }
    if(lipai.className.indexOf('paiaberto')<0 && lipai.className.indexOf('paifechado')<0){
        //definindo um estado inicial caso nao haja
        lipai.className = lipai.className + " paiaberto";
    }
    //fazendo a troca
    if(ulfilho.className.indexOf('aberto')>-1){
      ulfilho.className = ulfilho.className.replace("aberto","fechado");
    }else{
      ulfilho.className = ulfilho.className.replace("fechado","aberto");
    }
    //mudando a imagem do li pai
    if(lipai.className.indexOf('paiaberto')>-1){
      lipai.className = lipai.className.replace("paiaberto","paifechado");
    }else{
      lipai.className = lipai.className.replace("paifechado","paiaberto");
    }
    if(typeof(evt.preventDefault)=='undefined'){
        evt.returnValue = false;
    }else{ evt.preventDefault() }

    return false;
}
function ativaMenus(ul_pai){
/* função que ativa os menus */
 if(ul_pai.constructor == String) ul_pai = ge(ul_pai)
 //ativando os cliques
 var links = ul_pai.getElementsByTagName("a");
 for (var i=0; i < links.length ; i++){
  //vendo se é link que está dentro de um li com filhos
  if(links[i].parentNode.getElementsByTagName("ul").length>0){
   links[i].onclick = function(ev){ Menu(ev,this) }
  }
 } 
 //fechando todos os li
    var lis = ul_pai.getElementsByTagName("li");
    for (var i=0; i < lis.length ; i++){ if(lis[i].getElementsByTagName("ul").length>0){
  lis[i].className += " paifechado";  //fechando todos inicialmente     
    }}
    //fechando todos os ul inicialment
    var uls = ul_pai.getElementsByTagName("ul");
    for (var i=0; i < uls.length ; i++){
        uls[i].className += " fechado";
    }
}
//abaixo eu chamo a função pra ativar os menus, passando como parametro o ID do ul que é pai dos menus.
window.onload = function() { ativaMenus('menuteste') }
</script>
</head>
<body>
    <ul id="menuteste">
      <li><a href="#">itens 1</a>
        <ul>
          <li><a href="#">itens 1.1</a>
            <ul>
              <li><a href="#">itens 1.1.1 </a></li>
              <li><a href="">itens 1.1.2</a></li>
              <li><a href="">itens 1.1.3</a></li>
            </ul>
          </li>
          <li><a href="">itens 1.2</a></li>
          <li><a href="">itens 1.3</a></li>
          <li><a href="">itens 1.4</a></li>
        </ul>
      </li>
       <li><a href="#">itens 2</a>
         <ul>
           <li><a href="#">itens 2.1</a></li>
           <li><a href="">itens 2.2</a></li>
           <li><a href="">itens 2.3</a></li>
           <li><a href="">itens 2.4</a></li>
         </ul>
       </li>
    </ul>
</body>

Outros menus css aqui. Bugs é só comentar :)

Gostou da dica acima? Então clica nos botões de compartilhamento abaixo e me ajude a dica a subir no Google.

33 comentários:

  1. Poxa valeu mesmo!

    Tava de saco cheio desse menus tipo tree cheio de include -__-''


    Esse é simples, facilitou e fez bonito!

    parabéns! :-) valeu!

    ResponderExcluir
  2. El Miox... Obrigado pelo exemplo de menu tree... Adaptei o meu para menu horizontal mas nao tenho muito conhecimento em js... Gostaria de saber se vc pode me ajudar o seguinte. A partir do seu exmplo quando o item1 esta aberto gostaria q ele fechasse quando eu clicasse no item 2 e visse versa porque como meu menu é horizontal os sub menus ficam sobrepostos se eu naum fechar eles antes.... add meu msn rodsacchi@hotmail.com

    ResponderExcluir
  3. Valeu Micox!!! Adaptei seu script e funcionou 100% no IE. Agora no Firefox a margem esquerda ficou diferente! Cê tem alguma dica para que meu menu abra igual em qualquer browser.
    Mais uma vez obrigado e parabéns pelos artigos...
    Rivaldo.
    rivaldo.jr@uol.com.br

    ResponderExcluir
  4. Olá rivaldo,
    Coloque * { margin: 0; padding:0; } no início de seus scripts. Isto irá zerar todos os margins e paddings diferentes em cada navegador.

    Caso isto seja muito drástico, coloque:

    ul, ol { margin-left: 10px; /* padronizando nos navegadores */}

    ou

    ul, ol, li { margin: 10px; padding: 10px
    ;}

    ResponderExcluir
  5. Perfeito meu camarada!
    Agora ficou show...
    []s
    Rivaldo.

    ResponderExcluir
  6. achei muito bom, simples, prático e eficaz!!! Parabens

    ResponderExcluir
  7. To desenterrando o post, mas td bem..
    Entao, El Micox..
    Primeiramente obrigado pelo exemplo de menu, mas tenho um menu bem extenso e qndo eu clico em um link em qlquer parte mais baixa (sem a barra de rolagem estar no topo), o menu abre corretamente porem a pagina vai para o topo.
    Gostaria de saber o que eu faço para q qndo eu clique num link na parte d baixo da pagina ela permaneça no local.
    Se puder me ajudar eu agradeço =)
    Gustavo (br.gustavo @ gmail.com)

    ResponderExcluir
  8. Este menu é óptimo...
    Porque será que funciona com todo o mundo e não funciona no meu blog?
    O que estou fazendo errado???
    ...quando faço click no "pai" os "filhos" nem abrem nem fecham! pura e simplesmente mantêm-se todos visíveis, sem qualquer alteração.
    Se tiver paciência e generosidade agradecia que me ajudasse

    portugasuave@gmail.com

    ResponderExcluir
  9. Opa portuga, dá uma lida neste tópico aqui que fiz outro menu.
    Aí é só adaptar.

    Em breve um novo tutorial com este novo menu.
    té mais.

    ResponderExcluir
  10. O link para os outros menus esta quebrado

    André Barcelos
    Criação de sites

    ResponderExcluir
  11. Olá Micox, descobri que no Opera 9.25 quando eu clicava num sub-item ele fechava.
    Então a solução meio gambiarra que fiz é essa:

    return false no evento on click dos subitens

    ResponderExcluir
  12. Opa velho, valeu o aviso.
    vou ver o que faço.
    Jà tá passando da hora de atualizar este script. valeus.

    ResponderExcluir
  13. Amigo.
    Não tá funcionando.
    O que estou fazendo de errado?
    No Internet explorer tá dando erro na linha 22
    caractere 5
    Erro: 'parentNode' é nulo ou não é um objeto.

    ResponderExcluir
  14. Olá Anônimo.
    por favor seja mais específico.
    Poste sua dúvida no fórum webly e informe qual a versão do IE e como está seu código.

    ResponderExcluir
  15. Meu Internet Explorer é o 7.0.
    Copiei e colei, mas clicando no item, ele não abre.
    Não fiz nada diferente, copiei e colei.

    ResponderExcluir
  16. Aí fiquei curioso sobre o menu... mas no ff3 e no ie7 não consegui ver nada ??? se puder publicar de novo para os dois navegadores que mencionei... Valeu!

    ResponderExcluir
  17. VAleu pelo aviso cara.
    Corrigi e em breve publico a nova versao.

    ResponderExcluir
  18. No IE funciona normal, mas no FF3 o submenu abre por cima do menu pai qdo eu uso a propriedade "height" nas "li" pra mudar o tamanho...

    ResponderExcluir
  19. Bom dia, deu certo aqui e agradeço muito, o meu problema, se voce puder ajudar é, meu menu tree é muito grande, e cheio de submenus, toda vez que uma página é acessada, o menu tree volta para o inicio, gostaria de saber se tem como ele ficar expandido de acordo do link da página. Se for o caso até dependendo da variável que eu jogar na URL;

    ResponderExcluir
  20. Sim marcelo, é só usar links internos: http://www.nomer.com.br/ajuda/390.htm

    ResponderExcluir
  21. Ola Micox, usei este estilo, deixando dinamicamente de acordo com http://forum.webly.com.br/lofiversion/index.php/t10068.html postado por você.

    Funcionou muito bem, só tem uma coisa que tentei fazer e não consegui: Os menus só expandem e retraem ao clicar em cima do link, tem alguma forma de fazer isto ao clicar em cima da imagem? Obrigado. Abraço e parabéns!

    ResponderExcluir
  22. Olá mário, por favor poste sua dúvida (com mais detalhes, se possível link) lá no fórum webly.

    Té mais.

    ResponderExcluir
  23. Estou usando o Chrome e as imagens folderclose e foldeopen não aparecem.
    Alguma idéia?

    ResponderExcluir
  24. Estou usando o Chrome e as imagens folderclose e foldeopen não aparecem.
    Alguma idéia?
    gilsondh-webdeveloper@yahoo.com

    ResponderExcluir
  25. Dica do próprio Micox - Náiron J. C. G..

    para que funcione no Google Chrome:
    Já achei o problema:

    Onde tem
    .paiaberto{ list-style-image: url(folderopen.gif); list-style: circle }



    .paifechado{ list-style-image: url(folderclosed.gif); list-style: disc }




    Vira

    .paiaberto{ list-style: circle; list-style-image: url(folderopen.gif); }


    .paifechado{ list-style: disc; list-style-image: url(folderclosed.gif); }

    ResponderExcluir
  26. Rapaz,
    Nota 10 seu script!
    Você sabe fazer o link fechar, quando eu clicar num outro link?
    Tipo, tenho muitas seções, muitas categorias e muitas subcategorias e tá deixando a página gigante. Clico numa seção, ela abre e vejo o que tem dentro, clico em outra, ela abre mas a anterior fecha.
    Dá pra fazê?
    Falows!
    Alekis

    ResponderExcluir
  27. tem qe mudar a classe das células pra funcionar?

    will.ac@live.com

    ResponderExcluir
  28. Caso eu queira fazer um menu com table tr td no lugar de ul li, o codigo seria o mesmo? Adaptando apenas as referencias?
    Obrigada

    ResponderExcluir
  29. @Margareth. Não vai ser o mesmo código não.

    @Will, células? você tem que usar menu ul li e colocar a classe menu-hv no ul. Apenas isso.

    ResponderExcluir
  30. OLÁ MICOX, AMIGO PRECISO DE SUA AJUDA...
    BOM, SOU TÉCNICO EM INFORMÁTICA E A POUCO TEMPO DECIDI CRIAR UM BLOG ETC... E ATÉ QUE APRENDI ALGUMAS COISAS, MAIS DESDE QUE APLIQUEI ESSE MEU NOVO TEMPLASTE E VENHO QUEBRANDO MINHA CABEÇA COM ESSE TAL DE EFEITO CASCATA OU ARVORE... JÁ TENTEI EDITAR DE VARIAS MANEIRA E NÃO DEU CERTO. JÁ ATÉ DESCOBRI O CÓDIGO DESSA PARTE ESPECIFICA... BOM GOSTARIA QUE VC ME DESSE UMA LUZ, UMA IDEIA OU ME DISSECE DE VEZ COMO POSSO REVOLVER ISSO DE UMA VEZ POR TODAS, VOU DEIXA AQUI O ENDEREÇO DA MINHA PAGINA http://www.dicainformatica.com/
    E SE VC QUISER DEPOIS POSSO ATÉ LHE PASSAR O TRECHO DO CÓDIGO PRA VC TER UMA IDEIA MELHOR... BOM AGUARDO RESPOSTAS. E DESDE JÁ FICO MUITO AGRADECIDO PELA ATENÇÃO!!!

    ResponderExcluir

Resultado! Concursos