JavaScript Tabs sem Framework ou Plugin

Postado por: Pedro Rogério em
Excessive JavaScript

Com a popularização dos Frameworks JavaScript fica a cada dia mais difícil você encontar alguma coisa na web desenvolvida com puro JavaScript. Desenvolver um sistema de Tabs com a utilização de jQuery é muito simples, mas as vezes pode ser desnecessário você utilizar tanto JavaScript para fazer simples tabs. Foi pensando nisso que resolvi efetuar a tradução do artigo do site Elated, onde ele ensina de uma forma muito simples a desenvolver um sistema de Tabs com puro JavaScript.

Criação do HTML para nossas abas

O HTML para as tabs e conteúdo é muito simples. Você armazena o conteúdo de cada tab dentro de um elemento div com uma classe chamada tabContent e um id exclusivo para referência. Aqui está como exemplo o conteúdo da primeira de 3 tabs:

<div class="tabContent" id="about">
  <h2>About JavaScript tabs</h2>
  <div>
    <p>JavaScript tabs partition your Web page content into tabbed sections. Only one section at a time is visible.</p>
    <p>The code is written in such a way that the page degrades gracefully in browsers that don't support JavaScript or CSS.</p>
  </div>
</div>

As tabs são simplesmente links dentro de uma lista desordenada:

<ul id="tabs">
  <li><a href="#about">About JavaScript tabs</a></li>
  <li><a href="#advantages">Advantages of tabs</a></li>
  <li><a href="#usage">Using tabs</a></li>
</ul>

Você deve definir que o ul tenha o id “tabs” para que o código JavaScript possa localizá-lo. Cada link dentro da lista de links faz referência a sua div conteúdo (“about”, “advantages”, e “usage”). Uma vez que eles são links padrão do HTML, também funcionam com o JavaScript desabilitado.

Você pode adicionar quantas tabs quiser a sua página. Basta criar uma nova div com um identificação única e em seguida adicionar um link a mesma dentro da lista de tabs.

Criação do CSS

O CSS é necessário para tornar as guias parecidas com abas e também tornar a sua aparência mais agradável:

body { font-size: 80%; font-family: 'Lucida Grande', Verdana, Arial, Sans-Serif; }
ul#tabs { list-style-type: none; margin: 30px 0 0 0; padding: 0 0 0.3em 0; }
ul#tabs li { display: inline; }
ul#tabs li a { color: #42454a; background-color: #dedbde; border: 1px solid #c9c3ba; border-bottom: none; padding: 0.3em; text-decoration: none; }
ul#tabs li a:hover { background-color: #f1f0ee; }
ul#tabs li a.selected { color: #000; background-color: #f1f0ee; font-weight: bold; padding: 0.7em 0.3em 0.38em 0.3em; }
div.tabContent { border: 1px solid #c9c3ba; padding: 0.5em; background-color: #f1f0ee; }
div.tabContent.hide { display: none; }

Essas regras CSS funcionam da seguinte forma:

body
Contém as regras de fonte para a página e as tabs.
ul#tabs
Definição de estilo para as guias e remoção dos bullets da lista.
ul#tabs li
O uso de display:inline é para que as tabs tenham sua disposição na horizontal.
ul#tabs li a
Aplicamos estilos aos links da lista. Cada link agora possui uma borda, exceto border-bottom para que ela combine perfeitamente com sua div conteúdo.
ul#tabs li a:hover
A tab fica em destaque ao passar o mouse sob ela.
ul#tabs li a.selected
Estilos definidos para a guia selecionada, aplicando um fundo mais claro, texto em negrito e também aumentamos o tamanho da fonte. Observe que o padding-bottom foi definido como 0.38em para que ele se funda com a sua div conteúdo.
div.tabContent
Define um estilo para as áreas de conteúdo.
div.tabContent.hide
Usado para ocultar as tabs não selecionadas.

Criação do código JavaScript

Finalmente, é claro, você precisa de JavaScript para que as tabs funcionem.

  • Adicionar a função showTab() ao evento onclick para cada um dos links das tabs.
  • Ocultar todas as divs conteúdo, exceto a primeira, de modo que só o conteúdo da primeira tab esteja visível ao carregar a página.
  • getFirstChildWithTagName() é uma função auxiliar que recupera o primeiro filho de um determinado elemento que possui um tag name.
  • gethash () é outra função auxiliar que retorna parte da URL que aparece após o símbolo #.

Veja como funciona essas funções.

Função init()

A primeira, e mais complexa, é a função init(). É chamada quando a página é carregada, graças ao evento onload no elemento body:

<body onload="init()">

Abaixo a própria função:

function init() {

      // Pega todas as tabs e as divs conteúdo da página
      var tabListItems = document.getElementById('tabs').childNodes;
      for ( var i = 0; i < tabListItems.length; i++ ) {
        if ( tabListItems[i].nodeName == "LI" ) {
          var tabLink = getFirstChildWithTagName( tabListItems[i], 'A' );
          var id = getHash( tabLink.getAttribute('href') );
          tabLinks[id] = tabLink;
          contentDivs[id] = document.getElementById( id );
        }
      }

      // Adiciona eventos onclick as tabs e destaca a primeira aba
      var i = 0;

      for ( var id in tabLinks ) {
        tabLinks[id].onclick = showTab;
        tabLinks[id].onfocus = function() { this.blur() };
        if ( i == 0 ) tabLinks[id].className = 'selected';
        i++;
      }

      // Oculta todas as divs conteúdo, exceto a primeira
      var i = 0;

      for ( var id in contentDivs ) {
        if ( i != 0 ) contentDivs[id].className = 'tabContent hide';
        i++;
      }
    }

Essa função faz 3 coisas:

  • Ele percorre todos os elementos li na lista desordenada. Para cada elemento li ele chama a função getFirstChildWithTagName() para recuperar o elemento dentro com o link. Em auxílio, ele também chama a função getHash() para extrair parte da URL do link, após o hash, que é o ID da div conteúdo correspondente. O link então é armazenado no array tabLinks, e a div de conteúdo é armazenada no array contentDivs.
  • Ele atribui o evento onclick com a função showTab() para cada link da lista e destaca a primeira tab com a classe ’selected’.
  • Ele oculta todas as divs conteúdo, exceto a primeira, definindo que as divs tenham as classes ‘tabContent hide’.

Função showTab()

showTab() é chamada toda vez que uma tab é clicada. Ele destaca a tab selecionada e mostra o conteúdo relacionado a tab. Ele também remove o destaque das outras tabs e oculta as divs com o conteúdo relacionado.

function showTab() {
      var selectedId = getHash( this.getAttribute('href') );

      // Destaca a tab selecionada e remove o destaque das outras
      // Mostra a div com o conteúdo relacionado e oculta as outras
      for ( var id in contentDivs ) {
        if ( id == selectedId ) {
          tabLinks[id].className = 'selected';
          contentDivs[id].className = 'tabContent';
        } else {
          tabLinks[id].className = '';
          contentDivs[id].className = 'tabContent hide';
        }
      }

      // Faz com que o browser não siga o link
      return false;
    }

A função estrai o ID do link selecionado e os armazena na variável selectedId. Em seguida, percorre todos os IDs. Nos selecionados ocorre o destaque a div com o conteúdo correspondente é mostrado, para as outras tabs o destaque é removido e o conteúdo relacionado é oculto.

A função possui um return false para que anule o comportamento padrão do browser de seguir o link e adicionar o mesmo ao histórico do browser.

Função getFirstChildWithTagName()

Essa função retorna o primeiro filho de um elemento especificado correspondente a tag. init() chama essa função para recuperar o link dentro de cada item da lista.

function getFirstChildWithTagName( element, tagName ) {
      for ( var i = 0; i < element.childNodes.length; i++ ) {
        if ( element.childNodes[i].nodeName == tagName ) return element.childNodes[i];
      }
    }

A função percorre os nós filho do elemento até encontrar um nó correspondente a seu tagName. Em seguida, ele retorna o nó.

Leia mais sobre as propriedades childNodes e nodeName no artigo: Looking inside DOM page elements.

Função getHash()

A função getHash() retorna parte da URL após encontrar qualquer símbolo hash(#). Usado por init() e showTab() para extrair o ID da div conteúdo relacionado com o link das tabs.

function getHash( url ) {
      var hashPos = url.lastIndexOf ( '#' );
      return url.substring( hashPos + 1 );
    }

Todas as funções em conjunto

Isso é tudo o que você precisa para desenvolver tabs com JavaScript. Veja a demonstração e olhe o código fonte da página para ver como o HTML, CSS e JavaScript aparecem.

  • O CSS e o JavaScript vão no topo da página. (Você pode colocá-los em arquivos separadados).
  • Elemento body da página que contém o manipulador de eventos onload para iniciar a função init().
  • O elemento ul que contém as tabs com os links.
  • Cada conteúdo da tab é armazenado em uma div com a classe tabContent e um id único (referenciado no link da aba correspondente).

Posts Relacionados

Confira também outros artigos interessantes postados aqui no blog.

Sobre Pedro Rogério

Pedro Rogério é desenvolvedor web por paixão, não saberia fazer melhor outra coisa. Além de escrever para o Pinceladas da Web também escreve para o CSS no Lanche, blog voltado ao desenvolvimento front-end.

8 Responses to “JavaScript Tabs sem Framework ou Plugin”

  1. Mauro George

    Fala Pedro só uma dica rápida pois estou de saida, ainda nem li o arquivo quando chegar eu leio tudo, mais no exemplo você utilizou onload=”init()” no body, não poderia ser incluido onde esta todo o Javascript assim window.onload=function(){ init() };

    • Mauro,

      O tutorial não foi desenvolvido por mim, só efetuei a tradução. Isso pode ser feito, mas resolvi deixar igual ao original para que as pessoas que estão começando agora não fiquem confusas.

      • Mauro George

        Pedro,

        Entendo seu ponto, mais pelo menos agora ficou documentado, pra quem se interessar um pouco mais e ler os comentários, fara as tabs sem JavaScript obstrutivo.

  2. É, a intenção foi boa… só o código Javascript que podia lidar melhor com os eventos, usando o objeto Event e preventDefault, por exemplo, ao invés de fazer um return false no onclick.

    Vi que no código original já está assim… mas acho importante destacar qual outra abordagem seria possível nesses casos.

  3. Social comments and analytics for this post…

    This post was mentioned on Twitter by pinceladasdaweb: JavaScript Tabs sem Framework ou Plugin: http://migre.me/gjXS #javascript…

  4. Tony Kaique

    Pedro, esses dias vi você falando no Twitter a respeito de editores HTML em JS, estou a procura de algumas ferramentas desse tipo, seu post já está ficando pronto ou nem vai rolar mais?

Leave a Reply