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.
<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.
- 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.
function getTextNodeByClassName(searchClass,tag,eventNode) {var els = document.getElementsByTagName(tag);var pattern = new RegExp("\\b"+searchClass+"\\b");var idLink = 'showHideTextNode';var messageShow = '[+] Show english content’;var messageHide = '[-] Hide english content’;var linkTextNode = document.getElementById(idLink);for (i = 0; i < els.length; i++) {if ( pattern.test(els[i].className) ) {if (eventNode == 'hide') {linkTextNode.innerHTML = messageShow;linkTextNode.className = "link-show";linkTextNode.onclick = function() {for (j = 0; j < arrEls.length; j++) {getTextNodeByClassName('lang-eng',arrEls[j],’show’);}};els[i].style.display = ‘none’;} else if (eventNode == 'show') {linkTextNode.innerHTML = messageHide;linkTextNode.className = "link-hide";linkTextNode.onclick = function() {for (j = 0; j < arrEls.length; j++) {getTextNodeByClassName('lang-eng',arrEls[j],’hide’);}};els[i].style.display = ‘block’;}}}}
Por fim, inseri uma função para esconder todos os elementos declarados com a classe lang-eng. Esta função é inicializada por um addLoadEvent.
- function init_langEngNode() {
if (!document.getElementsByTagName) returnfor (j = 0; j < arrEls.length; j++) {getTextNodeByClassName('lang-eng',arrEls[j],’hide’);}- }
- 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.
function getTextNodeByClassName(searchClass,tag,eventNode) {var els = document.getElementsByTagName(tag);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.
var idLink = 'showHideTextNode';var messageShow = '[+] Show english content’;var messageHide = '[-] Hide english content’;
Pegando o ID inserido no link da página.
var linkTextNode = document.getElementById(idLink);
Para os elementos encontrados, testar se cada um deles tem a classe escolhida como parâmetro.
for (i = 0; i < els.length; i++) {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’;).
if (eventNode == 'hide') {linkTextNode.innerHTML = messageShow;linkTextNode.className = "link-show";linkTextNode.onclick = function() {for (j = 0; j < arrEls.length; j++) {getTextNodeByClassName('lang-eng',arrEls[j],’show’);}};els[i].style.display = ‘none’;} else if (eventNode == 'show') {linkTextNode.innerHTML = messageHide;linkTextNode.className = "link-hide";linkTextNode.onclick = function() {for (j = 0; j < arrEls.length; j++) {getTextNodeByClassName('lang-eng',arrEls[j],’hide’);}};els[i].style.display = ‘block’;}}}}
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
