quarta-feira, 20 de fevereiro de 2002

Olá DHTML Behaviors, muito prazer!

Introduzido a partir do IE5.5, e, segundo a própria documentação, "...uma das novidades mais excitantes...", DHTML Behaviors são pequenos códigos associados a elementos do HTML, que estendem sua funcionalidade, implementando recursos não existentes por default.


A Microsoft já implementou alguns behaviors, como o userData que permite persistir dados no client até o limite de 10240kb (ou 10 Megabytes, se preferir) em cenários de intranets, ou, no pior dos casos, 64kb por página para sites restritos, o que, convenhamos, é muito maior que qualquer cookie que conhecemos. Está mais para "torta" que para "biscoito" (ok, piada infame).


Uma forma de implementar novos behaviors é utilizar HTC. HTCs (HTML Components) nos permitem encapsular em um arquivo .htc a lógica necessária para fazermos as manipulações DHTML que nossa aplicação necessita, usando linguagens de scripting bastante conhecidas. Complicado ? Não, não é, e pretendo mostrar neste artigo como podemos montar um pequeno HTC para validarmos dados entrados pelos usuários.


Antes de adentrarmos em código, vamos entender a necessidade de usarmos HTCs:
Você desenvolve uma página, que precisa que fazer uma verificação em um campo, para ver se o que foi digitado é um número maior ou igual que zero e menor ou igual que 100. Um código inicial hipotético seria:


<input id="qtdade" name="qtdade" type="text" onblur="if( isNaN(this.value) || parseInt(this.value,10) < 0 || parseInt(this.value,10) > 100 ) this.value='0'" />


"Viscoso, mas gostoso". Pode não ser o mais belo dos códigos, mas funciona. Depois de um tempo, há a inclusão de outro campo, que precisa ser validado da mesma forma. Sem problemas! Você faria assim:


<script>
function Validar(objeto){
 if( isNaN(objeto.value) || parseInt(objeto.value,10) < 0 || parseInt(objeto.value,10) > 100 ) objeto.value='0';
}
</script>
<input id="qtdade" size="5" maxlength="3" onblur="Validar(this)" />
<input id="outro" type="text" size="5" maxlength="3" onblur="Validar(this)" />


E viva! O código continua funcionando, com a diferença que você modularizou, de certa forma, a funcionalidade da validação. Se eu tiver "n" elementos na mesma página, é só chamar a tal função.


Claro, você entendeu o próximo passo: em uma outra página, a mesma funcionalidade é necessária, mas a faixa de valores permitidos é de 18 a 75 (tipo um campo para a idade). Sem muito tempo, você copia a rotina para a outra página, e adapta-a. E já temos um problema.


Temos um código que não é genérico o suficiente e que precisa ser repetido em diversos lugares, por conta das pequenas peculiaridades. Se houvesse o pedido que letras nunca deveriam ser digitadas (e não excluídas após o campo perder o foco), você teria o trabalho de alterar todas as páginas, prevendo as devidas manipulações anexadas ao evento onkeypress. Putz!


Os DHTML Behaviors, implementados via HTCs, podem resolver este tipo de problema, por conta de suas facilidades:



  • Encapsulamento de código: significa que é possível criarmos pequenos módulos genéricos, que podem ser implementados em qualquer página com pouco/nenhum esforço, bastando fornecer os parâmetros que o código necessita. No caso hipotético acima, quando precisamos mudar uma função, apenas um lugar é alterado e esta mudança reflete nos demais elementos relacionados.

  • Facilidade de uso: Uma vez que é simples declararmos a utilização de um HTC, fica simples para outras pessoas envolvidas na construção de páginas acessar os mesmos recursos, usando apenas uma sintaxe declarativa. Já que o código está encapsulado no HTC, esses desenvolvedores não precisam saber como funciona o tal componente, mas apenas que, dado uma entrada, uma determinada saída é recebida (conceito de 'caixa preta')

  • Separação dos scripts do conteúdo: uma vez que você não precisa colocar código inline (declarado no próprio elemento HTML), é mais simples que qualquer pessoa altere o layout/design da página, sem influenciar muito no comportamento do código. Então a manutenção é mais simples, necessitando de menos tempo para executar eventuais consertos/alterações.

  • Simples de criar, leves na utilização: adivinhe o que é um arquivo HTC: um arquivo texto, onde podemos colocar código JavaScript/VBScript que manipula a nossa página. Só isso. Isso significa que, em uma primeira olhada, você já sabe montar HTCs, só não sabia que sabia :) Na prática, as coisas são um pouco diferentes, pois há alguns conceitos de programação não muito usados e um bocado de testes a fazer. Mas vale a pena. Opcionalmente, se você quiser criar behaviors compilados em VC++, também é possível, com a vantagem adicional de proteger o código fonte do behavior.

Ok, você já viu que pode ser útil, vamos à implementação. Antes de mais nada, associamos uma classe CSS a um documento HTC. A página HTML ficaria parecida com:


<style>
.Validar { behavior: url( validar.htc ) }
</style>
<script>
 function MsgErro(objeto){
 if( confirm( objeto.nErros + " erros já foram cometidos neste campo.\n" +
    "Deseja limpar este contador vergonhoso ?" ) ) objeto.ZerarErros();
 }
</script>
<input id="qtdade" class="Validar" size="5" maxlength="3" min="0" max="100" onTeclaInvalida="MsgErro(this)" />
<input id="idade" class="Validar" size="5" maxlength="3" min="18" max="75" onTeclaInvalida="MsgErro(this)" />


Pronto. O IE já vai entender que o arquivo validar.htc implementa alguma funcionalidade nos elementos que estão associados com a classe Validar. Se quiséssemos colocar um HTC específico a um elemento, poderíamos declará-lo na própria propriedade style. Enfim, é o CSS tal qual conhecemos, sem novidades.


Além disso, estamos implementando código para um evento chamado onTeclaInvalida, que espero que você saiba que não existe. Este evento será implementado pelo nosso HTC. Sem demora, vamos à construção do validar.htc. Abra o notepad e digite:



<METHOD   NAME="ZerarErros" />
<PROPERTY NAME="nErros" GET="nErros" />
<PROPERTY NAME="min" VALUE="0" />
<PROPERTY NAME="max" VALUE="0" />
<EVENT    NAME="onTeclaInvalida" ID="onTeclaInvalida" />
<ATTACH   EVENT="onblur"     HANDLER="ChecarDados" />
<ATTACH   EVENT="onkeypress" HANDLER="KeyPress" />


<SCRIPT LANGUAGE="javascript">
// Aqui vai o código
</SCRIPT>



Para demonstrar algumas das funcionalidades dos HTCs, vamos implementar:



  • A propriedade nErros, que retornará quantos erros de digitação o usuário cometeu.

  • As propriedades min e max, informando a faixa de valores válidos.

  • O método ZerarErros, responsável por zerar este contador

  • O evento TeclaInvalida, que será disparado quando o usuário digitar uma tecla inválida.

  • A captura do evento onBlur do elemento, formatando os números entrados (ex: 00001 -> 1 )

  • A captura do evento onKeyPress, não permitindo a entrada de caracters diferentes de números.

E já está de bom tamanho. Já temos complicações o suficiente. :) Dentro das tags SCRIPTs, vamos começar pela implementação da propriedade nErros. Podemos fazer:


QtdeErros = 0;
function nErros(){
 return( QtdeErros )
}


Apenas retornamos o valor de uma variável. Implementar o método ZerarErros não deve ser, então, tão complicado:


function ZerarErros(){
 QtdeErros = 0;
}


Ta-da! E agora você se pergunta: Cadê as coisas complicadas ? Sinto desapontá-lo, mas não há coisas muito complicadas na codificação de HTCs. :) Implementemos o tratamento para o evento onBlur:


function ChecarDados(){
 // Se for um número e estiver dentro do intervalo, formatá-lo.
 if( !isNaN(element.value) && element.value != "" ){
  min = parseFloat( element.min )
  max = parseFloat( element.max )
  numero = parseFloat( element.value )
  if( numero >= min && numero <= max ) element.value = numero;
  else element.value = "0";
 }
}


Note que aqui acessamos a propriedade value do elemento ao qual o behavior está associado, bem como as propriedades min e max que nós definimos. Da mesma forma, poderíamos acessar *qualquer* propriedade do objeto. Finalmente, o tratamento das teclas digitadas:


function KeyPress(){


 var keyCode=event.keyCode
 var char = String.fromCharCode(keyCode)


 // Verificamos se o usuário entrou com algo diferente de números, ponto ou vírgula.
 // Se sim, ignorar a tecla, incrementar contador e disparar o evento de TeclaInvalida
 if( isNaN( char ) && ".,".indexOf( char ) == -1 ){
  keyCode = 0;
  QtdeErros++;
  onTeclaInvalida.fire()
 }
 // Se foi digitada uma vírgula, trocar por um ponto (facilita operações com o JS)
 if( keyCode == 44 ) keyCode = 46;


 // Se foi digitado um ponto e já tinha um ponto, desconsiderar
 if( element.value.indexOf(".") != -1 && keyCode == 46 ) keyCode = 0;


 // Retornar o código filtrado
 event.keyCode = keyCode
}


Pronto. Salve o arquivo e execute a página, vendo o que implementamos. Note que a mensagem de erro poderia ser implementada dentro do HTC, mas não fizemos para manter a modularidade do código. Desta forma, apenas código genérico fica no HTC, permitindo que ele seja reutilizado em diversos lugares, sem gambiarras.


Algumas possibilidades para desenvolvimento de HTCs:



  • Validação de campos (caracteres válidos, números, datas, cpf, etc)

  • Desenho/manipulação de controles em tela (tabelas com scroll, mouseover/out em imagens,etc)

  • Aprender um pouco mais como programar orientado a eventos (event-driven programming)

Já estou desenvolvendo algumas coisas nesse sentido, e o resultado é bonito de se ver.


Espero que o texto tenha sido esclarecedor. Divirta-se!



Esta matéria foi postada originalmente no ASP4Developers por Rubens N. Farias (site), que na época era "pós-graduado em análise de sistemas orientados a objetos, MCP, MCSD, MCAD, MCSD.NET e consultor em TI, além de idealizador do projeto ASP4Developers. Desenvolve sistemas sob medida, focados na satisfação do usuário, com qualidade e custo realista.". Hoje, vai saber...

0 comentários: