Parece óbvio, não? Mas infelizmente não é tão óbvio quanto parece. Muitos sites por aí estão regredindo vários passos na escala evolutiva da web e criando formulários que só submetem com um clique do mouse em um botão ou um ENTER quando o mesmo botão tem o foco.
Esse tipo de problema é devido, praticamente sempre, ao desejo de fazer alguma coisa “legal” com o formulário, sempre usando JavaScript e AJAX.
E a solução é tão simples: coloque um botão de submissão comum em seus formulários.
Exemplos comuns desse tipo de formulário são campos de busca e formulários onde você deve entrar apenas seu email, por exemplo, para se inscrever em algum tipo de serviço.
Nesse tipo de formulário, o comportamento padrão do usuário é digitar e apertar ENTER. Veja como é fácil fazer isso funcionar:
<input type="text" name="email" size="50">
<input type=”submit” value=”Enviar”>
Simples assim. A não ser que o campo onde os dados devem ser digitados seja uma TEXTAREA, um ENTER dentro do campo de texto vai submeter o formulário, enviar os dados para o servidor e, com sorte, trazer uma resposta para o usuário.
Se você quiser fazer algo bonito, com AJAX e tudo mais, faça em outra camada. Na camada de comportamento. Já falei sobre isso aqui em alguns posts então não vale a pena gastar espaço falando de novo.
A moral da história é: não torne o que é simples complicado. Até porque acaba sendo mais complicado pra você também.
- Pesquisa de Preços: Notebook Positivo, Computador, TV LCD, Notebook HP, Notebook Barato, TV 32, Celular
Em alguns casos precisamos usar alguns elementos HTML que só têm função quando há suporte a javascript, nas página que estamos desenvolvendo.
Nesse caso, o mais sensato a se fazer é criar esses elementos via JavaScript. Dessa forma eles só estarão disponíveis para o usuário caso o browser que ele estiver usando tenha suporte a javascript, ficando fora do caminho caso contrário. Assim, não criamos expectativas frustradas no usuário e temos uma página cujas funcionalidades são coerentes com o ambiente onde ela está sendo exibida.
Criar elementos via javascript não é nenhum bicho de sete cabeças. Há duas maneiras interessantes (e algumas outras não interessantes) de se fazer isso:
- Adicionando conteúdo ao innerHTML do elemento em questão
- Criando um objeto DOM e inserindo dentro da página via DOM API
A primeira é mais fácil e, segundo alguns testes (cujos links não tenho agora, mas vou procurar), mais rápido que o segundo. Porém não faz parte de nenhum padrão DOM e pode causar problemas em alguns casos raros, como por exemplo se você estiver usando XHTML e enviando ao browser como uma aplicação de XML. Como ninguém em sã consciência, que esteja pretendendo fazer um site com o máximo de compatibilidade faria isso, não precisa se preocupar.
A segunda segue padrões mais rígidos e vai funcionar sempre que houver um suporte decente ao DOM. Grosso modo, é menos compatível que a primeira, e devemos sempre testar a presença dos métodos necessários a sua execução antes de criar os elementos.
Vamos então aos códigos:
Usaremos o seguinte exemplo: Imagine que você tenha em sua página um botão cuja função é esconder ou mostrar um determinado conteúdo. Digamos que esta funcionalidade esteja implementada apenas por meio de JavaScript. Você não vai querer que os usuários que não tenham suporte a javascript vejam o botão e sintam-se frustrados ao clicar e nada acontecer, vai?
Portanto é importante que esse botão seja criado via JavaScript.
Criando elementos via innerHTML
innerHTML é uma propriedade que permite ler ou modificar o conteúdo HTML de um elemento HTML. Exemplo:
<p>Site do <a href=http://w3.org/>W3C</a></p>
No caso acima, o innerHTML do elemento P é “Site do <a href=http://w3.org/>W3C</a>“. Entendeu? Simples, não é?
No nosso exemplo, precisamos criar algo do tipo:
<button type="button" id="toggle">Esconder/Mostrar</button>
E depois adicionar a esse botão, via JavaScript, a funcionalidade desejada.
Antes de criar o elemento precisamos definir onde o elemento deve ser colocado. Ou seja, precisamos decidir qual será o elemento “pai” deste nosso botão.
Digamos que você tenha um DIV e que este DIV tenha o ID “conteudo”. Dentro deste DIV está o conteúdo que deve ser exibido ou escondido, dependendo do caso. O botão entraria, então, ao fim deste DIV.
Este é o código HTML do DIV conteudo:
<div id="conteudo">
<div class=”texto”>
<p>Aqui entra o texto.</p>
<p>Poderíamos ter um DIV apenas, mas optei por usar dois para facilitar o exemplo.</p>
</div> <!– /texto –>
</div> <!– /conteudo –>
Vamos lá. O primeiro passo é acessar o DIV pelo JavaScript:
var conteudo = document.getElementById('conteudo');
Jogamos uma referência ao elemento cujo ID é conteúdo para uma variável criativamente nomeada “conteudo”. Isso significa que tudo que fizermos com esta variável será aplicado de fato ao elemento referenciado.
O passo seguinte é criar o código do nosso elemento. Vamos colocá-lo em uma variável também:
var button = '<button type="button" id="toggle">Esconder/Mostrar</button>';
A variável button é uma string que contém o código do nosso botão. Agora basta colocar esse código dentro do DIV conteudo:
conteudo.innerHTML += button;
O operador += tem o efeito de adição. No caso acima é o mesmo que conteudo.innerHTML = conteudo.innerHTML + button.
Agora só falta adicionar a função javascript desejada, o que faremos ao fim do texto.
Criando elementos via DOM API
Criar elementos via DOM API não é tão simples quanto via innerHTML. Primeiro precisamos criar o elemento, depois adicionar suas propriedades e atributos e, por fim, adicioná-lo ao conteúdo da página. Acompanhe comigo.
Criando o elemento:
var button = document.createElement('button');
A linha acima cria o elemento e associa este elemento à variável button. Note que, embora tenha sido criado, o elemento ainda não está visível no documento. Continuemos.
Precisamos, agora, adicionar os atributos TYPE e ID ao botão:
button.setAttribute('type', 'button');
button.setAttribute(’id’, ‘toggle’);
Agora vamos adicionar o texto “Esconder/Mostrar” ao botão. Primeiro precisamos criar este texto no documento em uma variável e depois adicioná-lo ao botão. Assim:
var btntext = document.createTextNode('Esconder/Mostrar');
button.appendChild(btntext);
Como no outro exemplo, precisamos criar uma variável que referencie o elemento “pai”, ou seja, o DIV conteudo:
var conteudo = document.getElementById('conteudo');
E, por fim, adicionar o botão ao elemento pai:
conteudo.appendChild(button);
Ou seja, adicionamos um “filho” ao “pai” conteudo. O filho é o nosso famoso botão.
Claro que podemos adicionar elementos em outros lugares além do fim de um outro elemento, mas isso é um pouco mais avançado e fica para um outro post.
Adicionando funcionalidade ao elemento
O elemento que criamos é, até então, inútil. Vamos adicionar funcionalidade a ele. Para isso vamos usar a seguinte função:
function toggle(el) {
if ( el.style.display != ‘none’ ) {
el.style.display = ‘none’;
}
else {
el.style.display = ”;
}
}
Esta função pega uma referência a um elemento como parâmetro e exibe ou esconde este elemento, dependendo do seu estado atual.
Antes de aplicar a função, vamos criar uma variável que referencie o conteúdo que será escondido ou exibido que é, no nosso caso, o DIV cuja classe é “texto” e que está dentro do DIV conteudo:
var texto = conteudo.getElementsByTagName('div')[0];
A função getElementsByTagName vai pegar todos os elementos dentro de “conteudo” que sejam definidos pela tag <div>. Essa função retorna um Array, que terá tantas posições quantos elementos existam. O [0] significa que queremos a primeira posição que, no nosso caso, é a única. (Preciso explicar melhor Arrays e getElementsByTagName. Mais uma promessa…)
Primeiro vamos adicionar esta função ao evento onclick — que é executado quando o elemento é clicado com o mouse — do botão:
button.onclick = function(){ toggle(texto); }
Depois, vamos adicioná-la ao evento onkeypress — que é executado quando o usuário digita alguma tecla enquanto tem o elemento em foco –, checando antes se a tecla pressionada foi ENTER:
button.onkeypress = function(e){
var keynum;
if(window.event) // para o IE
keynum = window.event.keyCode;
else if(e.keyCode) // Netscape/Firefox/Opera
keynum = e.keyCode;
if (keynum == 13) {
toggle(texto);
}
}
E assim temos o nosso elemento criado e funcionando.
Fazer um texto deste tamanho sobre o assunto pode fazer com que pareça mais difícil do que é, por isso veja os exemplos abaixo, com os códigos consolidados, para entender melhor como funciona e ver que não é nenhum bicho de sete cabeças:
- Pesquisa de Preços: Smartphone, Computador Positivo, Notebook Rosa, TV LCD, Notebook, Celular Motorola
Podemos fazer maravilhas com JavaScript e, com a popularização das chamadas HTTP via JavaScript (mais conhecidas como AJAX) e posteriormente do que chamam de web 2.0, essa linguagem de scripts, tão mal falada e quase esquecida em um passado não muito distante, voltou à tona e é usada, hoje, por 9,9 entre 10 desenvolvedores web.
O problema é que, na maioria dos casos, os desenvolvedores não se limitam a usar o JavaScript onde ele é realmente necessário e traz realmente algum ganho de produtividade e usabilidade para o usuário, e acabam abusando da linguagem e, pior ainda, fazendo com que funcionalidades e conteúdo estejam acessíveis apenas quando houver suporte a JavaScript.
A idéia desse texto não é falar mal do JavaScript e sim mostrar a vocês como fazer com que ele não fique no caminho do usuário, ou seja, fazer com que o que funciona com JavaScript também funcione sem JavaScript.
Na verdade, é o contrário, a idéia é usar sempre o conceito de progressive enhancement (explico melhor em outro post, se vocês acharem necessário), que é, basicamente, o uso racional e correto do desenvolvimento em camadas. Algo tão simples quanto começar do começo, dar um passo de cada vez para chegar a um resultado satisfatório.
Tenha em mente que, por mais que existam poucos usuários que navegam sem JavaScript, um desses usuários pode ser um grande cliente em potencial navegando de um PDA ou o Google.
Enfim, vamos ao que interessa. Comecemos pelo exemplo mais simples.
Não existe protocolo javascript, portanto não é certo usar javascript:
Isso mesmo. Atire a primeira pedra aquele que nunca fez isso:
<a href="javascript:fazAlgumaCoisa();">Clique aqui para fazer alguma coisa</a>
O atributo HREF do elemento A (o popular anchor, ou link para os íntimos) foi feito especificamente para definir uma URI. Uma URI é composta por algumas partes e a primeira delas é o protocolo (na verdade, um esquema, mas vamos chamar de protocolo porque é o nome mais comum. Prometo explicar isso melhor outro dia também), que deve ser algo como http:, ftp:, mailto:, etc e tal. javascript: não faz parte dessa lista. Não é um esquema, não é um protocolo. Não use sob hipótese alguma.
Outra coisa importante é: só use links se realmente tiver algum lugar para apontar usando HREF. Se o propósito é totalmente outro, use outro elemento. Veremos isso mais a frente no texto.
Tá bom, eu não uso, mas como eu faço então, tio?
Há varias maneiras. Algumas melhores, outras piores. Vejamos:
<a href=http://meusite.com/teste.html onclick="fazAlgumaCoisa();return false;">Link de teste</a>
O que estamos fazendo na linha acima é um link para uma URL que existe e, caso haja suporte a JavaScript, ao ser clicado, esse link vai executar a função fazAlgumaCoisa(), definida em algum outro lugar.
Notem o return false depois da chamada da função. Ele serve para que o clique seja cancelado após executar a função. Se esquecer dele, o usuário será levado à URL em questão depois de executar a tal função e, em geral, não é isso que você quer, não é?
Mas esse modo tem alguns problemas:
- Não separa o comportamento do conteúdo. Ou seja, você está misturando as camadas, o que não é bom por diversos motivos.
- Só funciona para o evento de clique do mouse. Usuários que sigam o link via teclado não vão ter a funcionalidade do script, o que pode ser o efeito desejado, mas, em geral, não é.
Como resolver isso então?
Separando o JavaScript do HTML. Para isso, você precisa definir algo para identificar esse link em específico e poder acessá-lo pelo JavaScript. Vamos usar um ID para o nosso exemplo:
<a href=http://meusite.com/teste.html id="linkteste">Link de teste</a>
Um link simples. Vamos agora adicionar a funcionalidade em um JavaScript externo:
function powerLinks(){
var link = document.getElementById(’linkteste’);
link.onclick = function(){
fazAlgumaCoisa();
return false;
}
}
window.onload = powerLinks;
Ou seja, redefinimos o evento onclick do link e adicionamos o nosso código nele. Simples, não? A última linha faz com que a função seja executada ao carregar a página (existem formas melhores de fazer isso, mais uma promessa para um outro post. Me cobrem, por favor).
Mas ainda temos o problema do mouse. Precisamos fazer com que o script funcione também para quem está navegando via teclado.
Fazemos isso usando o evento onkeypress, que é ativado quando o usuário aperta alguma tecla, e checando se a tecla pressionada foi o ENTER. Veja como:
function powerLinks(){
//aqui entra o codigo anterior do script
link.onkeypress = function(e){
var keynum;
if(window.event) // para o IE
keynum = window.event.keyCode;
else if(e.keyCode) // Netscape/Firefox/Opera
keynum = e.keyCode;
if (keynum == 13) {
fazAlgumaCoisa();
return false;
}
}
}
Como vocês podem perceber, o IE trata o evento onkeypress um pouquinho diferente dos outros browsers, mas nada ultra complicado. 13 é o número de tecla correspondente ao ENTER. Ou seja, quando o usuário pressionar ENTER, o script será executado.
E quando não houver URL pra usar no HREF?
Bem, nesse caso então você não tem um link e, claro, não deve usar o elemento A. Use qualquer outra coisa e, via CSS, faça com que essa coisa se pareça com um link e, de preferência, crie essa coisa com JavaScript, para que aqueles que não têm suporte a JavaScript nem vejam a tal coisa.
Infelizmente, não é qualquer elemento que pode receber o foco via teclado, portanto se a sua idéia é que esse elemento seja acessível via teclado, não há outro jeito senão usar um A. Porém, como esse A será criado na página via JavaScript, ele não vai incomodar ninguém que não tenha suporte a scripts. Exemplo:
function criaPseudoLink(){
var paiPseudoLink = document.getElementById(’pai’) //o elemento que conterá o pseudo link
paiPseudoLink.innerHTML += ‘<a href=”#” id=”linkteste”>Faz Alguma coisa</a>’;
}
Ou seja, o conteúdo do elemento “pai” do pseudo link , cujo ID é “pai” será acrescido do HTML correspondente ao A. O resto é igualzinho ao que foi descrito anteriormente.
Por hoje é só. Ficou claro? Alguma dúvida? Esqueci de algo? Falei alguma besteira? A caixa de comentários é toda de vocês.
Para não deixar o post ainda mais longo, vou abordar outros tipos de abusos de JavaScript em outro post. E, como já disse, me cobrem, por favor.
- Pesquisa de Preços: TV 29, Notebook Acer, Monitor LCD 17, Notebook Celeron, Mochila Notebook
Depois de um longo inverno, estou pretendendo voltar a escrever por aqui. Como o meu blog principal, Bruno Torres ponto net vem mudando de foco com o tempo (e acredito que vá mudar muito ainda, de acordo com as mudanças na minha vida, tanto pessoal quanto profissional) acho que esse aqui é o espaço ideal para voltar a escrever textos sobre desenvolvimento web.
O meu maior problema em voltar a escrever aqui é que acho que esse nome “O básico da web” tem me feito sentir um pouco engessado sobre os temas que devo abordar.
Além disso, comecei a fazer posts em série, no estilo curso de html, e isso acabou não me agradando, e a vontade de continuar escrevendo foi diminuindo.
Porém, este blog tem hoje incríveis 900 assinantes, o que é muito para um blog tão pequeno, com tão pouco conteúdo. Imagino que boa parte desses assinantes (ou seja, vocês, que estão lendo isso agora) vieram do outro blog e isso me faz pensar mais duas vezes antes de escrever. E aí acabo não escrevendo.
A minha idéia com esse post é tentar entender o que vocês esperam encontrar por aqui. Eu acho que devo abandonar esse esquema de posts sequenciais sobre um mesmo tema e escrever sobre o que me der na telha, ou o que estiver em foco ou, melhor ainda, o que vocês quiserem.
Sendo assim, peço àqueles que estiverem afim de ajudar, que usem o formulário de contato, ou me escrevam um email diretamente, ou façam comentários, sugerindo temas, me ajudando a definir qual o futuro do conteúdo desse espaço.
E então. Alguém afim de ajudar? Não precisa fazer trackback nem pingback (aliás, se não souberem o que é isso, me avisem ;)). Só quero idéias e sugestões para fazer desse espaço um lugar melhor para aqueles que querem aprender mais sobre a web.
Conto com vocês!
- Pesquisa de Preços: Notebook 17, Notebook Toshiba, Conversor para TV Digital, Computador Positivo, Celular V3, Jogos para PC