tadarank afiliados

23 novembro, 2009

Marcar o item atual de um Menu com uma classe específica - Sem server-side

Códigozinho inspirado por uma dúvida da olhosespanhois lá no Webly

Muitas vezes, quando temos um menu qualquer, queremos marcar o item aberto com um visual diferente. Tipo, se o visitante clica em "serviços", deixar o menu "serviços" de outra cor.

Ao usar CSS (e um menu baseado em UL-LI) Agente faz isto colocando uma classe diferente no LI do "serviços", por exemplo.

Pra marcar esta classe no LI geralmente se usa programação server-side (php, asp, jsp, etc), o que dá um certo trabalho e atrapalha se formos testar localmente.

Bem, que tal uma gambiarra javascript pra resolvermos isto e sempre marcar o item atual com a classe "ativo" e os outros LI com a classe "inativo".

O script está abaixo bem comentado. É só salvar no seu PC, alterar o que quiser e testar.

Útil para fazer menus em abas e coisas do tipo.

Adiós.

<html>
<head>
 <style>
  /* os estilos css do ativo e inativo. Altere as propriedades como quiser
  só não altere os seletores */
  #menu .inativo a { color: white; background-color: black }
  #menu .ativo a { color: black; background-color: white }
 </style>
 <script>
  //função que troca a classe dos li para ativo e inativo
  function ativoinativo(quem){
   //o 'quem' original é um link, agora tô pegando o li pai
   var lipai = quem.parentNode; 
   if(lipai.className=='ativo'){
    //se ele já era ativo vira inativo
    lipai.className = 'inativo';
   }else{
    //se ele não tinha classe ainda, transformo em ativo
    lipai.className = 'ativo';
    //e também faço seus irmãos li virarem inativos
    var irmaosli = lipai.parentNode.childNodes; //pegando os irmaos li
    for(var i=0; i<irmaosli.length ; i++){ //varrendo os li
     var liatual = irmaosli[i];
     if(liatual != lipai && liatual.nodeName=='LI'){
      //se não é o li atual vai virar inativo
      irmaosli[i].className = 'inativo'
     }
    }
   }
  }
  
  //função que testa qual li que tem o link atual e marca como ativo
  function initAtivoInativo(divalvo){
   if(!divalvo.nodeName){
   //testando se o divalvo já é um objeto
   //se não for, eu uso o velho getElementById
    divalvo = document.getElementById(divalvo);
    if(!divalvo){ alert('Erro: o divalvo não existe'); return;}
   }
   //pegando os li que tão dentro do divalvo
   var ah,lis = divalvo.getElementsByTagName('li');
   for(var i=0; i<lis.length ; i++){
    
    //pegando os links que tão dentro de cada li
    ah = lis[i].getElementsByTagName('a')[0];
    if(!ah){ continue; } //se não achou o link vai pro prox li
    
    //ativando o onclick nos links pra fazer a troca de ativo/inativo
    ah.onclick = function(e){
     //pegando o alvo crossbrowser http://elcio.com.br/crossbrowser/#7
     if(typeof(e)=='undefined')var e=window.event; 
     source=e.target?e.target:e.srcElement; //
     if(source.nodeType == 3)source = source.parentNode
     //ativando o onclick nos links pra fazer a troca de ativo/inativo
     ativoinativo(source);
    }
    
    if(location.href.indexOf(ah.href)>-1){
     //se o endereço atual tem o link do li atual marco ativo
     lis[i].className = 'ativo'
    }else{
     //senão é inativo
     lis[i].className = 'inativo'
    }
   }
  }
  //ativando no onload (mas depois de um tempinho pra não bugar em alguns browsers heheh)
  //você pode usar body onload tb ou onready de libs
  window.onload = setTimeout(function(){initAtivoInativo('menu');},300);
 </script>
</head>
<body>
 <ul id='menu'>
  <li><a href="#home.htm">home</a></li>
  <li><a href="#micox.htm">Micox</a></li>
  <li><a href="#mwords.htm">mwords</a></li>
 </ul>
</body>
</html>
Gostou da dica acima? Então clica nos botões de compartilhamento abaixo e me ajude a dica a subir no Google.

7 comentários:

  1. Bom "workaround" do timer ali... coisas bizarras dos browsers!
    E mto bacana a implementação!

    ResponderExcluir
  2. Não seria mais fácil incluir um 'id' em 'body' e classe para 'li', em seguida definir seletores?

    Exemplo:
    body#micox li.micox, body#mwords li.mwords, body#home li.home {background: red; color:white;}

    Cada arquivo HTML precisaria apenas da definição de um 'id' diferente para 'body' o restante continua igual e sem troca server-side.

    ResponderExcluir
  3. Este comentário foi removido pelo autor.

    ResponderExcluir
  4. Fala kra, blz? mt legal seu site, várias dicas que estão me sendo mt úteis !!!

    crtz por css é bem mais simples, como o amigo disse acima! abraçoo

    ResponderExcluir
  5. Realmente a idéia do Willie é muito boa. Eu não tinha pensado por este lado.

    ResponderExcluir
  6. Oá lá muit bom o código mas gostaria de saber como retornar todos os menus para inativo quando eu usar outro menu, no caso o do lado esquerdo. Grato

    barros.fil@gmail.com

    ResponderExcluir
  7. tentei usar aqui, mas ficou mais de um menu selecionado.
    vc sabe o que pode ser isso... valeu

    ResponderExcluir

Resultado! Concursos