Sep42006

Mostrar-esconder conteúdo via DOM

Show-hide content with DOM

Um dos requisitos que declarei para o meu site foi a possibilidade de inserir conteúdo em outras línguas para as minhas postagens, em especial em inglês. Depois de alguns estudos cheguei à estrutura que desejava e desenvolvi um script em DOM para implementá-la. Como este não era um requisito de prioridade alta, deixei sua implementação para uma data futura. Eis que esta data chegou!

O conceito do script é simples: defini uma classe para todos os elementos (tags) que eu gostaria de inserir em inglês e fiz uma função em javascript para localizar todas as instâncias desta e escondê-la. Clicando em um link específico, as áreas são apresentadas. Clicando novamente no mesmo link, as áreas são escondidas.

Exemplo escondido:

This is an example of show-hide english content on <p> element

  • This is a list with english content
  • Line example
  • Line example

This is an <blockquote> element with english content.

Definindo os recursos da solução

O primeiro passo foi definir um link para esconder e mostrar as áreas. Inseri um ID para este link para poder trabalhá-lo via script.

  1. <a href="#" id="showHideTextNode"></a>

Não inseri nenhum conteúdo no link para poder manipulá-lo via script, trocando o texto, via innerHTML, de acordo com o clique efetuado ([+] Show english content para mostrar o conteúdo e [-] Hide english content para esconder o conteúdo).

Após, apenas defini uma classe para cada elemento que tivesse conteúdo em inglês. A classe foi chamada de lang-eng.

Manipulando a classe lang-eng via javascript

O primeiro passo foi definir um Array para todos os elementos que poderiam receber a classe lang-eng.

  1. var arrEls = new Array(”h1″,”h2″,”h3″,”h4″,”h5″,”h6″,”p”,”span”,”ul”,”blockquote”)

Após, foi preciso apenas uma função para localizar a classe lang-eng e efetuar as alterações nas páginas em que ela foi instanciada. Utilizei como base o script getElementByClass do Dustin Diaz. A partir daí, otimizei o script para chegar ao resultado que gostaria.

  1. function getTextNodeByClassName(searchClass,tag,eventNode) {
  2.  
  3. var els = document.getElementsByTagName(tag);
  4. var pattern = new RegExp("\\b"+searchClass+"\\b");
  5.  
  6. var idLink = 'showHideTextNode';
  7. var messageShow = '[+] Show english content’;
  8. var messageHide = '[-] Hide english content’;
  9.  
  10. var linkTextNode = document.getElementById(idLink);
  11.  
  12. for (i = 0; i < els.length; i++) {
  13. if ( pattern.test(els[i].className) ) {
  14. if (eventNode == 'hide') {
  15. linkTextNode.innerHTML = messageShow;
  16. linkTextNode.className = "link-show";
  17. linkTextNode.onclick = function() {
  18. for (j = 0; j < arrEls.length; j++) {
  19. getTextNodeByClassName('lang-eng',arrEls[j],’show’);
  20. }
  21. };
  22. els[i].style.display = ‘none’;
  23. } else if (eventNode == 'show') {
  24. linkTextNode.innerHTML = messageHide;
  25. linkTextNode.className = "link-hide";
  26. linkTextNode.onclick = function() {
  27. for (j = 0; j < arrEls.length; j++) {
  28. getTextNodeByClassName('lang-eng',arrEls[j],’hide’);
  29. }
  30. };
  31. els[i].style.display = ‘block’;
  32. }
  33. }
  34. }
  35. }

Por fim, inseri uma função para esconder todos os elementos declarados com a classe lang-eng. Esta função é inicializada por um addLoadEvent.

  1. function init_langEngNode() {
  2. if (!document.getElementsByTagName) return
  3. for (j = 0; j < arrEls.length; j++) {
  4. getTextNodeByClassName('lang-eng',arrEls[j],’hide’);
  5. }
  6. }
  7.  
  8. add_event(init_langEngNode);

Como tudo funciona

Pegando todas as tags inseridas como parâmetro e selecionando apenas a classe desejada para estas tags. Numa tag com class="lang-eng alignleft", por exemplo, apenas a lang-left seria selecionada.

  1. function getTextNodeByClassName(searchClass,tag,eventNode) {
  2.  
  3. var els = document.getElementsByTagName(tag);
  4. var pattern = new RegExp("\\b"+searchClass+"\\b");

Eu poderia setar “*” como tag para pegar todas as tags na página (vide linha “var els = document.getElementsByTagName(tag);“), inutilizando a necessidade de criação do Array de elementos, porém esta estrutura tiraria o controle que eu teria sobre os elementos que eu efetivamente gostaria de esconder.

O bom da história é que praticamente toda a aplicabilidade da solução está no script, portanto qualquer alteração futura fica totalmente mais prática. Minhas intenções estavam totalmente voltadas na manipulação do mínimo possível de marcação e trabalhar diretamente no javascript.

Continuando…

Definindo o ID para o link de manipulação e suas mensagens.

  1. var idLink = 'showHideTextNode';
  2. var messageShow = '[+] Show english content’;
  3. var messageHide = '[-] Hide english content’;

Pegando o ID inserido no link da página.

  1. var linkTextNode = document.getElementById(idLink);

Para os elementos encontrados, testar se cada um deles tem a classe escolhida como parâmetro.

  1. for (i = 0; i < els.length; i++) {
  2. if ( pattern.test(els[i].className) ) {

Foram definidos dois parâmetros para manipular as tags: show para mostrar os conteúdos e hide para escondê-los. Uma estrutura de if foi criada para testar em qual status a página está. Caso o evento seja hide o link de manipulação recebe a mensagem [+] Show english content. Caso seja show, recebe a mensagem [-] Hide english content.

Para o evento onclick do link é inserida uma função para voltar à mesma função e mostrar ou esconder o conteúdo. A forma de esconder é simples: o elemento encontrado recebe como atributo display o valor “none” (els[i].style.display = ‘none’;). Para mostrar, o atributo display recebe o valor “block” (els[i].style.display = ‘block’;).

  1. if (eventNode == 'hide') {
  2. linkTextNode.innerHTML = messageShow;
  3. linkTextNode.className = "link-show";
  4. linkTextNode.onclick = function() {
  5. for (j = 0; j < arrEls.length; j++) {
  6. getTextNodeByClassName('lang-eng',arrEls[j],’show’);
  7. }
  8. };
  9. els[i].style.display = ‘none’;
  10. } else if (eventNode == 'show') {
  11. linkTextNode.innerHTML = messageHide;
  12. linkTextNode.className = "link-hide";
  13. linkTextNode.onclick = function() {
  14. for (j = 0; j < arrEls.length; j++) {
  15. getTextNodeByClassName('lang-eng',arrEls[j],’hide’);
  16. }
  17. };
  18. els[i].style.display = ‘block’;
  19. }
  20. }
  21. }
  22. }

O último passo foi estilizar a classe lang-eng para separar as áreas apresentadas (português/ inglês), senão ficaria tudo uma coisa só, visualmente.

Esta solução pode ser utilizada em vários outros contextos. Basta ter criatividade. ;)

Atualização 2006-11-06: Versão 2.0 concluída, ver: Mostrar-esconder conteúdo via DOM V.2

Poste um comentário




Você pode utilizar as seguintes tags para formatação: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Oscomentários

Comentários diversos dos visitantes

Felipe disse:

Gostei do post, foram claros os seus argumentos. Estou fazendo um blog também extremamente clean, somente com recursos necessários. Acho que a grande...

Monica Lage disse:

Ramonzito, Eu concordo em alguns pontos com vc, mas não podemos negar que a Microsoft revolucionou a Web e os computadores. As vezes me pego pen...

RamonPage disse:

Olá nelson. Obrigado pela visita e pelo comentário. A porta está sempre aberta. []'s...

RamonPage disse:

@Sylvestre: Por algum motivo minha mensagem não chegou à vc. Respondi novamente. []'s...

Yogourt disse:

Parabéns, Pagé, pelo site. Está muito bonito!...

Quemsou

Uma prévia de quem é RamonPage

Avatar RamonPageMeu nome é Ramon Bispo. Sou web developer/ designer e natural do Rio de Janeiro, Brasil. Saiba mais sobre mim…