Quinta-feira, 02 de outubro de 2008 às 10h00

Menos XHTML com JavaScript

Faltam -1 dias! Inscreva-se agora! O maior encontro de profissionais web da américa latina.

Recentemente estou trabalhando no novo layout do Portal do Professor (http://portaldoproferssor.mec.gov.br), no qual projetei o conteúdo separado por caixas que possuem cantos arredondados, sombra, sombra interna, degradê e linhas de borda, como pode ver abaixo:

Com esta combinação deixei o cliente satisfeito com o resultado visual, mas acabei projetando um verdadeiro problema para estruturar o XHTML, pois preciso agora de 6 imagens de fundo para cada caixa e devido ao meu layout ser líquido / elástico, acabei com a seguinte estrutura:

<span class="wrap1´´>
<span class="wrap2´´>
<span class="wrap3´´>
<span class="wrap4´´>
<span class="wrap5´´>
<span class="wrap6´´>
<div class="box">
<h2>Wrap</h2>
<p>
Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Vestibulum tempor. Fusce lacinia. Duis blandit tincidunt lectus. Donec tortor. Nam fringilla justo vitae erat. Vivamus lobortis dui a nisl. Proin justo ante, lacinia non, aliquet in, egestas ac, leo. Sed metus libero, ornare eu, sagittis elementum, vulputate a, erat. Aliquam porttitor.
</p>
</div>
</span>
</span>
</span>
</span>
</span>
</span>

Acabei tendo que escrever um código repetitivo e nada semântico, além de tornar meu código mais difícil de manter, prejudicando assim a escabilidade de um portal que está constantemente recebendo novas implementações.

Para solucionar isto, resolvi escrever um código javascript, que insere tags <span> de forma dinâmica deixando o meu código XHTML apenas com a <div class="box">...</box>, como abaixo:

<div class="box">
<h2>Wrap</h2>
<p>
Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Vestibulum tempor. Fusce lacinia. Duis blandit tincidunt lectus. Donec tortor. Nam fringilla justo vitae erat. Vivamus lobortis dui a nisl. Proin justo ante, lacinia non, aliquet in, egestas ac, leo. Sed metus libero, ornare eu, sagittis elementum, vulputate a, erat. Aliquam porttitor.
</p>
</div>

Para inserir as tags <span> necessárias para inserir as imagens de fundo na caixa, lembrando que cada tag aceita apenas uma imagem de fundo, escrevi o script a seguir:

// Crio um array
var alltags = new Array();
function changeBox() {
// O método getElementsByTagName() retorna um array com todas os elementos <div> que existem no documento e armazena no array alltags.
var alltags=document.getElementsByTagName("div");
// A estrutura de repetição for passa por cada elemento <div> armazenado em alltags.
for (i=0; i<alltags.length; i++) {
// Verifica se o elemento tem a classe box.
if (alltags[i].className==´box´) {
// Armazena na variável element em  cada interação do for o velor armazenado no índice i de alltags
var element = alltags[i];
// Armazena o objeto pai de element na variável content
var content = element.parentNode;
// Cria os elementos XHTML <span>
var wrap1 = document.createElement(´span´);
var wrap2 = document.createElement(´span´);
var wrap3 = document.createElement(´span´);
var wrap4 = document.createElement(´span´);
var wrap5 = document.createElement(´span´);
var wrap6 = document.createElement(´span´);
// Atribui para cada elemento XHTML <span> uma classe
wrap1.setAttribute(´class´, ´wrap1´);
wrap2.setAttribute(´class´, ´wrap2´);
wrap3.setAttribute(´class´, ´wrap3´);
wrap4.setAttribute(´class´, ´wrap4´);
wrap5.setAttribute(´class´, ´wrap5´);
wrap6.setAttribute(´class´, ´wrap6´);
// Insere um elemento filho ao elemento atual, antes de um determinado elemento. O elemento wrap1 é inserido em content antes de element
// Mais informações do método insertBefore no endereço: http://developer.mozilla.org/pt/DOM/element.insertBefore.
content.insertBefore(wrap1, element);
// O elemento wrap1 recebe o novo elemento wrap2. E assim acontece com os demais elementos respectivamente.
// Mais informações do método appendChild no endereço: http://developer.mozilla.org/Pt/DOM/Element.appendChild.
wrap1.appendChild(wrap2);
wrap2.appendChild(wrap3);
wrap3.appendChild(wrap4);
wrap4.appendChild(wrap5);
wrap5.appendChild(wrap6);
// Remove element de content
content.removeChild(element);
// E insere element para wrap6
wrap6.appendChild(element);
}
}
}
// Executa a função
changeBox();

E para finalizar nossas caixas, vamos estilizá-las com CSS. Não irei comentar o CSS, pois acredito que se chegou até aqui buscando solução para um problema semelhante, já domine a linguagem.

Além do CSS que estilizam as classes que atribuímos por JavaScript às tags <span>, escrevi outros estilos para compor a página e representar melhor o exemplo.

*{
padding:0;
margin:0;
font:1em Verdana, Geneva, Arial, Helvetica, sans-serif;
}
body{
background:transparent url(bg_body.png) repeat left top;
font-size:11px;
padding:100px 400px;
}
h2{
font-size:1.5em;
padding-bottom:.5em;
}
p{
color:#666;
}
.box{
padding:25px 30px 30px;
}
.wrap1, .wrap2, .wrap3, .wrap4, .wrap5, .wrap6 {
display:block;
}

.wrap1 {
background:transparent url(bg_cr.png) repeat-y right center;
margin-bottom:1em;
}
.wrap2 {
background:transparent url(bg_cl.png) repeat-y left center;
}
.wrap3 {
background:transparent url(bg_tr.png) no-repeat right top;
}
.wrap4 {
background:transparent url(bg_tl.png) no-repeat left top;
}
.wrap5 {
background:transparent url(bg_br.png) no-repeat right bottom;
}
.wrap6 {
background:transparent url(bg_bl.png) no-repeat left bottom;
}

Espero que visite o Portal do Professor daqui a algum tempo e veja o resultado prático do que estou falando aqui.

Um abraço e até o próximo artigo!

19 comentários

 Fernando Martins
02/10/2008 22h37

Como Tratar Acessibilidade e Adaptação

Muito interessante, mas como seria tratado a acessibilidade e adaptação do site em diversos ambientes.

como exemplo algum navegador como javascript desabilitado.

 Rodrigo da Silva Melo
03/10/2008 01h00

E o CSS?

Fernando,

acho esse cenário menos provável hoje em dia. E como exemplo, talvez mais XHTML menos JavaScript.

Com relação ao artigo, vejo a mesma dificuldade de manutenção, já que parte do "problema" permanece CSS.

Parabéns pelo desenho da caixa, muito bom. Uma dica, eu gosto bastante de bibliotecas js. Neste caso seria perfeito para a manipulacao do DOM, embora eu entenda que intuíto do artigo nao seja mostrar nenhuma biblioteca.

Abcs.

 Carlos Tristacci
03/10/2008 02h59

Muito bom receber críticas construtivas como a sua aqui Rodrigo.
Também adoro bibliotecas, principal a JQuery que provavelmente iremos utilizar no projeto que mencionei.
Mas, discordo de você quando fala de mais XHTML, pois já tivemos bastante HTML quando usávamos tabelas e frames para estruturar nossos layouts.
E sou sincero em dizer que é a primeira vez que achei necessário criar um cenário destes em 5 anos de estrada, mas foi devido ao layout que foi projetado e por estarmos falando de um portal. Onde os custos de forma ampla: Banda, tamanho de arquivo, escalibilidade, manutenção e outros.
A manipulação por DOM fez com que eu diminuísse absurdamente o tamanho dos arquivos e o meu trabalho braçal.
E juntamente com CSS e este simples script me torna possível controlar todo o layout por um arquivo JS e um arquivo CSS.
Sendo que se no futuro ocorra uma nova alteração de layout eu não tenha que refatorar totalmente o meu XHTML, pois ele continua voltado para o seu objetivo: CONTEÚDO. E se eu colocasse as tags HTML ao invés disso, na minha opinião, eu estaria voltando minha marcação XHTML voltada para o LAYOUT.
Bom, para um primeiro artigo sobre JavaScript, fico muito feliz que tenha sido levantadas estas questões, pois elas ajudam a enriquecer o artigo.
Valeu!

 Carlos Tristacci
03/10/2008 02h40

Acessibilidade

Muito bom Fernando ter mencionado da acessibilidade!
Realizo testes de usabilidade/acessibilidade com deficientes visuais há 2 anos e pela experiência que tenho posso afirmar que não irá prejudicar a acessbilidade pois os leitores de tela irão ler o conteúdo e sua marcação HTML. Então quanto mais limpo estiver melhor.
A preocupação que temos que ter com JavaScript e a acessibilidade é principalmente com relação aos eventos como: Onblur e onchange.
Pois uma pessoa cega usa essencialmente o teclado para navegar e por exemplo: Ao interagir com um select (caixa combinada), que tem um evento onchange, esta pessoa não conseguira passar do primeiro item pois ela irá tentar navegar elemento a elemento ou item a item deste select, e assim que selecionar o primeiro item o evento onchange será executado, onde o correto aqui é colocar um botão de submit. Está é uma das principais reclamações depois dos botões sem rótulo ou etiqueta.
No segundo caso, se a pessoa tiver desabilitado o JavaScript as caixas permaneceram na mesma posição, mas sem a estilização que seria renderizada pelas tags que seriam geradas dinamicamente.
Um abraço!

 Igor Escobar
03/10/2008 09h38

Cara...

Não recomendo nem de longe fazer o que você fez ai, Tanto no aspecto SEO, quanto no aspecto interoperabilidade.

O que você fez foi utilizar o DOM contra você mesmo, ao invéz de simplesmente criar na mão, como deve ser, você teve que perder seu tempo criando um código para poder gerar um XHTML equivalente. Facilita de um lado e dificulta e piora muito o outro. Não vale a pena.

Fazer isso que você mostra no tutorial é certamente, andar para trás e ir contra tudo o que nós desenvolvedores estamos lutando por uma web mais semântica e simplificada.

 Carlos Tristacci
03/10/2008 09h46

Tudo vem a somar Igor...
Valeu pelo comentário!

 Dennin Dalke Onório
05/10/2008 23h08

Falou besteira, o artigo que o Carlos fez foi ótimo.
Qual seria a vantagem em criar código repetido, "by hand", gerando um arquivo muito maior, ao invés de se utilizar apenas um script que gera o conteúdo dinamicamente, o resto está tudo correto, se o javascript estiver desabilitado, conteúdo será exibido da mesma forma, quanto a mecanismos de buscas eles irão encontrar exatamente o que devem, somente o conteúdo, e não uma coleção de elementos de layout. Não vale a pena criticar por criticar, ou para se aparecer...

Eu apoio a pratica do Carlos Tristacci. O importante é manter o código o mais semântico possível. E se amanhã mais tarde o portal sofrer atualização e não mais utilizar os warp que ele criou, não será necessário mudar o XHTML, somente desvincular o JavaScript e aplicar o novo CSS.

Parabéns!

Abraço e sucesso!

 Rafael Ritter
03/10/2008 10h33

Tudo depende das características de cada projeto

Acho que uma solução qualquer somente pode ser julgada tendo-se conhecimento de todas as características da demanda, ambiente e exigências do cliente. Entendi a solução descrita e não compreendo de que forma ela possa prejudicar políticas de SEO. Muito pelo contrário! A utilização do javascript para "otimização do layout" vai facilitar a vida de mecanismos de busca que esperam encontrar um código o mais limpo possível. O único cuidado diz respeito à gracefully degradation, ou seja, quando um usuário acessar o site com um navegador que não suporte a solução implementada, ainda assim deve ser capaz de ver o conteúdo, mesmo que através de caixas com cantos retos.

 Rafael Ritter
03/10/2008 10h34

Tudo depende das características de cada projeto

Acho que uma solução qualquer somente pode ser julgada tendo-se conhecimento de todas as características da demanda, ambiente e exigências do cliente. Entendi a solução descrita e não compreendo de que forma ela possa prejudicar políticas de SEO. Muito pelo contrário! A utilização do javascript para "otimização do layout" vai facilitar a vida de mecanismos de busca que esperam encontrar um código o mais limpo possível. O único cuidado diz respeito à gracefully degradation, ou seja, quando um usuário acessar o site com um navegador que não suporte a solução implementada, ainda assim deve ser capaz de ver o conteúdo, mesmo que através de caixas com cantos retos.

 Carlos Tristacci
03/10/2008 11h04

Valeu Rafael!
Finalmente alguém entendeu o objetivo das funcionalidades deste artigo.
Um abraço!

 Marcelo Rodrigues
12/10/2008 22h48

Interessante, mas com cautela!

O artigo é interessante, porém, concordo com o Igor, acho que isso deve ser evitado o máximo possível. Tamanho de código? Não importa o tamanho, isso não afeta a semântica, o que afeta é o modo como foi escrito, se quem vá ler esse código HTML, entenda o que ele quer dizer, isso é semântica. Pedaços de código repetitivos? Não, isso não tem a ver com não ser semântico, tem a ver com conteúdo, se ele requer várias caixas iguais, então que seja gerado pelo servidor, não pelo cliente. Conteúdo PRINCIPAL JAMAIS deve ser manipulado com Javascript, ah não ser que você considere estratégias para que ele seja visto na ausência do Javascript. Por isso, penso que sua solução seria mais elegante gerando esses códigos através de linguagens de servidor (php, asp, python etc), pois não implica em problemas ao usuário caso ele não tenha o javascript habilitado. O que muitos que concordaram com o conteúdo "pensam", pelo que percebi é somente no quesito do trabalho repetitivo. Concordo, é chato mesmo, mas gerar conteúdo com javascript, em minha opinião, é pior para gerenciar. E Rafael, acho que você está equivocado, mas como uma página "gerada" por javascript pode ser otimizada, se o robô de busca não é um browser e não enxerga um conteúdo gerado por javascript? Entende o porque de isso ser prejudicial? O robô espera um conteúdo gerado pelo servidor e não por uma linguagem de "cliente", como o javascript. Agora, como você também colocou, depende do que o cliente espera e do tipo de aplicação, se as caixas forem interativas, com possibilidade de inclusão e exclusão das caixas em tempo real, não vejo problema em usar javascript, mas ainda assim é preciso ter cuidado, o javascript deve apenas solicitar o conteúdo e o servidor é quem deve retornar o código do conteúdo. Além de ser mais elegente gerar isso diretamente no servidor, você tem um nível de reaproveitamento muito maior.

 dieffrei tiepo de quadros
13/10/2008 18h24

Ja utilizei

Ja utilizei e tem alguns bugs no iexplore 6 que não foram corrigidos reference ao setAttribute() e o appendChild();
Por isso é bom resguardar-se desse recurso por enquanto.
Claro que tem algumas gambiarras, para contornar isso.
Mas fica ai o meu aviso ..
att

 Carla Souza
14/10/2008 15h30

A idéia é boa, mas...

Eu já precisei fazer essa "cadeia" de divs por causa de caixas com bordas arredondadas (na verdade, acho pouco somântico ter elementos block dentro de elementos inline. Por isso usei divs ao invés de spans). Achei que o XHTML ficou enorme, feio e realmente chato, embora necessário; e na ocasião sequer me passou pela cabeça essa sua solução.

Ainda que a solução acabe com o código feio no XHTML e o esconda onde não vamos precisar ficar olhando muito, eu vejo um problema que pode crescer junto com o tamanho de suas páginas.

Como o javascript procura pelo seu div com a class box para depois criar os spans, então ele é carregado no cliente depois que o XHTML. Em páginas com muita coisa acontecendo, isso pode causar o estranho efeito da piscada. Pode fazer até o layout dançar, dependendo do caso.

Eu entendo que isso não afeta a acessibilidade e que quem tiver o javascript desabilitado simplesmente não vai ver as bordinhas e tal. Mas também não acho errado ter os montes de divs... até porque, veja bem, se no futuro eles não tiverem utilidade, não vão atrapalhar ninguém ali (talvez fosse melhor colocar os divs dentro do div class box, e não por fora); ou você pode ir retirá-los. No entanto, pra previnir retrabalhos, seu layout atual pode ser prejudicado por um capricho de xhtml... acho que não compensa.

 Leandro Fernandes
16/10/2008 12h02

Isso aí cara, acho que foi o comentário mais maduro até agora, apesar de eu ter gostado bastante da solução pensando na praticidade para desenvolvedor e de consumo de banda.

 Igor Escobar
17/10/2008 08h11

Nao sabem como isso pode piorar o otimização de um site?

Lamentável,
Meus amigos, os spiders, não enxergar o conteudo gerado por javascript, tudo o que vai ser indexado por ele é o que esta em HTML puro e o que esta sendo processado pelo servidor (server-side), o javascript é ignorado.

Se você cria um site inteiro desta forma, o spider não vai enxergar nada mais do que uma página em branco.

Como pode pessoas tão despreparadas falarem com tanta convicção de algo que eles não fazem nem idéia aqui nos comentários.

 Dennin Dalke Onório
17/10/2008 10h17

"Como pode pessoas tão despreparadas falarem com tanta convicção de algo que eles não fazem nem idéia aqui nos comentários."
Igor, parabéns, você expressou exatamente o seu próprio comentário, aposto que nem ao menos leu o artigo direito, condordo com o Rafael, santa ignorância, pra não falar burrice mesmo, lamentável, lamentável mesmo o seu comentário, ninguém falou em construir um site inteiro usando-se javascript, o resto não precisa nem comentar...

 Igor Escobar
17/10/2008 08h15

Aleluia!

@Marcelo Rodrigues
Aleluia alguém que sabe o que faz postou por aqui, lamentável a quantidade de pessoas que apoiam uma maluquice dessas.

Santa ignorância. Sequer analisaram o que ele fez.
os indexadores não necessitam das tags que foram geradas pelo JavaScript. Então como o Igor disse, eles ignoraram o JavaScript.E se for ver a página não ficara em branco.

Parabéns!

Abraço e sucesso!

Cancelar resposta

Qual a sua opinião?

Faça login abaixo ou cadastre-se rapidamente.


Sobre o Autor
Carlos Tristacci é desenvolvedor web do Ministério da Educação, certificado como Adobe Certified Professional Flash Developer e Certified HTML Developer. Graduando em Administração com ênfase em Marketing, trabalha na área de internet desde 2003, na qual destaca-se pelos conhecimentos nas tecnologias Flash, Flex, ActionScript e Padrões de Desenvolvimento Web. Também participa de vários projetos relacionados a E-commerce, Acessibilidade e Java.
3G

2001 - iMasters FFPA Informática Ltda - Todos os direitos reservados.