Captura de teclas em Javascript - Parte 1

A sigla Web 2.0 tem sido muito utilizada recentemente. Talvez seja o nome mais marketeiro depois de AJAX. Aliás Web 2.0 depende muito de AJAX. O fato é que softwares Web-based com comportamentos muito semelhantes à aplicações desktop tem pipocado pela internet, e com certeza os exemplos mais impressionantes e eficientes são os produtos lançados pela Google, como o Google Maps, Google Calendar, Google Reader, entre outros. E de fato, o grande barato da Web 2.0 é tentar mudar o paradigma de uso da internet, tornando a experiência do usuário mais rica e interativa (detesto essa expressão “experiência rica”, mas no momento não me veio nada mais apropriado), fazendo com que a web deixe de ser um conjunto de hipertextos, e passe a ser um conjunto de serviços.

Neste esforço de deixar as interfaces web mais interativas, dinâmicas e eficientes, a captura e tratamento de eventos de teclado pode ser uma característica desejável e desejada. A boa notícia é que fazer isso é relativamente simples, usando Javascript. Existem basicamente 3 tipos de eventos de tecla que se pode capturar: keyDown, keyPress e keyUp. Os eventos keyDown e keyUp são disparados respectivamente no momento de descida e subida da tecla, e o evento keyPress é disparado quando a tecla está pressionada. Portanto quando uma tecla é pressionada, os eventos são disparados na ordem keyDown, keyPress e keyUp.

É interessante notar que a forma como os eventos é disparada varia ligeiramente dependendo do S.O: no Linux, os eventos keyDown e keyUp são disparados apenas uma vez por evento de tecla, e keyPress é disparado várias vezes, enquanto a tecla estiver pressionada (não sei bem qual a taxa de disparo, mas é bastante rápida). Já no Windows (tanto no IE quanto no Firefox), apenas o evento onKeyUp é disparado apenas uma vez por evento. Os eventos keyDown e keyPress são disparados sequencialmente enquanto a tecla estiver pressionada (ou seja, caso você mantenha a tecla apertada, o sistema irá lançar a seqüência keyDown-keyPress-keyDown-keyPress….). Não tive a oportunidade de testar no Mac OS, o que é uma folha imperdoável já que eu só uso Mac em casa, mas testarei assim que possível. Esta pequena diferença faz com que a estratégia de captura seja diferente dependo do evento desejado. As seguinte situações me vêem à cabeça:

  1. O sistema deseja capturar apenas um evento por tecla pressionada. No Linux pode se usar onKeyDown ou onKeyUp. No Windows, apenas onKeyUp. Portanto, para que o script seja funcional em todos os sistemas, a melhor escolha é onKeyUp.
  2. O sistema deseja capturar repetidamente uma tecla pressionada, para simular por exemplo o funcionamento de uma tecla pressionada numa caixa de texto (imprime várias vezes o caractere pressionado). Neste caso, a melhor escolha é onKeyPress, que funciona nos dois SOs. Mas é preciso tomar cuidado no caso do Windows: caso o handler de onKeyDown estiver habilitado também, o sistema irá capturar duas vezes o evento, o que pode ser problemático.
  3. O sistema deseja capturar uma vez a descida da tecla, e uma vez a subida. Isso pode ser útil para medir o tempo de pressão da tecla. No caso do Linux, é muito simples: um handler para keyDown e um handler para keyUp, e ambos eventos serão disparados apenas uma vez. No caso do Windows, a estratégia é mais complicada, uma vez que onKeyDown será lançado repetidas vezes. Eu não tenho uma solução em mãos, mas deve ser necessário fazer um controle de qual tecla foi apertada, e não executar caso o evento ja tenha sido processado.
  4. O sistema deseja capturar a descida da tecla uma vez, processar a tecla pressionada várias vezes, e capturar a subida da tecla uma vez. Tanto no caso do Windows quanto do Linux, me parece que a melhor solução é criar um handler para cada evento, mesclando as situações 2 e 3. Em ambos os casos, a ordem de execução será keyDown, keyPress e keyUp. No caso do windows, será necessário utilizar a mesma solução da situação 3 para evitar que keyDown seja processado várias vezes.

Como eu não sei qual o tamanho máximo de um artigo neste blog, vou deixar para o próximo post a descrição de como escrever o código para capturar estes eventos.

Divs e combos no IE

Aposto que muitos desenvolvedores Web já tiveram o seguinte problema com Internet Explorer: criam um DIV (por exemplo, em um menu contextual, ou um tooltip), que aparece bonitinho na tela, mas que para seu desespero fica embaixo de uma caixa de seleção (o famoso combo box). O pior é quando se descobre isso um mês depois, quando um cliente resolve redimensionar a janela, e o combo box em questão vai parar no meio da área visível do DIV.

Quem já teve este problema, sabe que mudar o z-index não adianta nada, porque no IE o combobox fica acima de tudo, não levando em conta o parâmetro de profundidade.

Graças a algumas pesquisas do meu colega Christian, encontramos uma solução para isso: basta criar um IFRAME e colocar exatamente embaixo do DIV, com as mesmas coordenadas e tamanho e com zindex do IFRAME inferior ao do DIV. Por algum motivo que me escapa, o IFRAME encobre o COMBOBOX, e mesmo assim aceita o parâmetro de profundidade, exibindo o DIV de forma correta.

Envio de grandes conjuntos de dados com AJAX

Hoje, totalmente por acaso, descobri alguns macetes para envio e recepção de grandes quantidades de dados usando requisições HTTP assíncronas, como por exemplo textos. Estou trabalhando em um sistema que permite que o usuário cadastre pareceres sobre informações do sistema, e estes pareceres não tem limitação de tamanho.O sistema foi implementado com AJAX, para permitir que os pareceres sejam carregados dinâmicamente, e gravados assincronamente.

O primeiro problema que tive foi que os textos enviados eram sempre truncados em 4096 bytes. A primeira reação foi verificar se estava enviando os dados via POST ou GET: o correto é enviar por POST, uma vez que GET tem tamanho limitado. Os dados realmente estavam sendo enviados por POST, que a priori não tem limitação alguma. Pesquisando um pouco, descobri que precisava definir um header Content-length com o tamanho do conteúdo do texto, antes de enviar a requisição. O comando correto é

requestObject.open('POST', url, true);
requestObject.setRequestHeader('Content-Type',
                             'application/x-www-form-urlencoded');
if (parameters != null)
    requestObject.setRequestHeader("Content-length",
                                   parameters.length);
requestObject.send(parameters);

Bom, eu não sou um expert do protocolo HTTP, mas a minha explicação seria que de fato o método POST aceita uma quantidade ilimitada de dados, mas por default ele define o tamanho máximo como 4096, para evitar erros. Caso o usuário deseje enviar mais, deve informar o tamanho total.

Resolvido este problema, tive um problema semelhante ao ler os dados para exibir na tela. Meu sistema abre uma requisição AJAX, que envia um XML contendo o texto do parecer inserido pelo usuário. Para recuperar o texto, executava o seguinte comando:

var value = decodeURIComponent(
                 root.getElementsByTagName('value')[0].
                                       firstChild.data);

Este código retornava o texto corretamente no IE, mas cortava em 4096 bytes (novamente !) no Firefox. O mais estranho é que tanto no envio quanto na recepção, o XML gerado estava correto. Portanto o problema estava na leitura do CDATA do XML. Fuçando um pouco (desta vez não encontrei nada na internet), descobri que em caso de CDATA com mais de 4096 bytes, o DOM do Firefox considera que a tag value possui mais de um nó filho, cada um com no máximo 4K. Assim, o código correto para obter o texto em ambos os navegadores é

for(var i=0; i i++)
     value += decodeURIComponent(
                     root.getElementsByTagName('value')[0]
                           .childNodes[i].data);

Falando em usabilidade

Aproveitando o tópico anterior sobre usabilidade, deixo aqui uma pergunta, porque perguntar não ofende: quem foi o engenheiro espertão da Microsoft que achou que era uma boa idéia traduzir atalhos do Office ??????? Eu penso absurdos da mãe dele sempre que eu faço Ctrl + S pra salvar um documento no Office aqui do trabalho, que é em português, e me aparece uma palavra sublinhada. Mais legal foi quando abri um Office em alemão e não consegui fazer absolutamente nada.Porque até onde eu sei, atalhos são feitos pra heavy user poder ser mais produtivo no seu trabalho. E me corrijam se eu estiver errado, mas uma vez que você conhece os atalhos, não importa se você sabe a palavra que deu origem à letrinha que vem após o Ctrl, você simplesmente usa !

E para aqueles que disserem que é mais intuitivo o atalho ter alguma coisa a ver com a língua do pacote, pergunto: qual seria a palavra que deu origem ao B, de Ctrl+B, que no Office em português executa a ação Salvar arquivo ?

Construindo interfaces

É notório e sabido que hackers e programadores em geral odeiam pensar em interfaces, e acham isto absolutamente inútil. Afinal, é muito mais divertido manipular as coisas na raça…e de qualquer forma, nenhuma interface é complicado para experts……Apesar de não concordar 100% com isso, assumo que muitas vezes abro mão de interfaces gráficas bonitinhas para mexer em arquivos tenebrosos. Sobretudo quando tenho que configurar uma máquina com Linux.

Mas o fato e que, por sorte, 99.9% das pessoas não são hackers, e nem ao menos tem intimidade com computador [nda: essa porcentagem é completamente fictícia e saiu da minha cabeça, mas serve pra ilustrar o fato que a maioria das pessoas não são hackers] . E ao usar um software, a maioria das pessoas não irão ficar impressionadas se o seu algoritmo é recursivo, roda em O(n), ou usando apenas um loop [nda: se você entendeu o que eu escrevi agora, não tem dúvida: você é geek :-)]. Interface gráfica, para quem desenvolve softwares comerciais desktop, web, para palm, celular e qualquer outro dispositvo gráfico, é crucial. Eu encaro interfaces como encaro engenharia de software: deve ser um porre de se pesquisar e estudar, mas são ferramentas essenciais para qualquer bom programador comercial.

Encontrei hoje um artigo do Joel Spolsky bastante longo (9 capítulos), mas bem interessante e agradável de se ler, sobre princípios básicos que devem ser utilizados para se construir uma boa interface gráfica. É basicamente um resumo de um curso universitário de IHC. Vale a pena dar uma olhada.

/>

Graficos em JSP com Cewolf

Num tópico anterior, eu falei sobre a biblioteca JFreeChart para criação de gráficos, e mencionei uma taglib chamada Cewolf para inserir gráficos gerados pela JFreeChart em páginas JSP. Na época não havia utilizado a taglib em questão..mas nos últimos dias usei bastante, portanto me sinto no dever de relatar a experiência.A biblotece fornece tags que encapsulam o processo de criação de gráficos usando JFreechart. A idéia é boa, porque JFreeChart gera uma grande quantidade de gráficos muito bonitos, e a documentação não está disponível, tornando sua utilização um pouco mais trabalhosa, sobretudo quando os prazos de seu software estão estourando a muito tempo. Para funcionar, é necessário instalar bibliotecas para manipulação de SVG, e XML, além obviamente do próprio JFreechart.

No site, tem um passo a passo bem legal, que permite que em poucos minutos se tenha um demo com gráfico na sua aplicação. A geração de dados é bastante simples, e requer apenas algumas linhas de código para obter os dados e converte-los no formato adequado. A taglib permite também gerar tooltips para os pontos do gráfico, e criar um mapa de links, fazendo com que o gráfico tenha funções de hipertexto, o que pode ser muito útil em alguns casos.

Porém, nem tudo são flores…..

O primeiro problema (que não é realmente um problema, mas sim uma restrição) é que nem todos os tipos de gráficos do JFreeChart estão disponíveis no Cewolf. Até que me provem o contrário, isto é pura preguiça. Mas talvez existam motivos mais nobres. Mas tudo bem, os principais tipos estão contemplados.

O segundo problema, um pouco mais chato, é que a parte de geração dos dados, que deve ser implementada pelo usuário, requer algun conhecimento mínimo do JFreeChart. Portanto, algumas visitas à API da biblioteca são necessárias.

O terceiro (e principal problema) é, pra variar um pouco, documentação. Como todo softwarte livre, ela é problemática. Mas neste caso, tem um agravante: a pouca documentação que existe no site está ERRADA !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
O site contém a API das taglibs, com informações sobre as tags, parâmetros possíveis e valores aceitos para cada parâmetro. Com exceção de alguns parâmetros que se mantém, a impressão que tive é que a documentação está defasada em relação à biblioteca. No meu caso, só não se tornou um pesadelo porque os comentários dentro do descritor da taglib estão corretos, e estes comentários são lidos pelo eclipse e exibidos como documentação, e eu uso eclipse, e assim por diante….

Assim sendo:

Nota final: 10 pela idéia, 6 pela implementação, 0 pra documentação. Média 5 e alguma coisa.

No final das contas, vale a pena dar uma olhada, porque ainda acho que enfiar gráficos dinâmicos a seco deve ser mais trabalhoso.

Pequena biblioteca AJAX

Nas últimas semanas tenho desenvolvido muitas coisas usando a técnica AJAX…digo técnica porque usar a palavra tecnologia neste caso não me parece apropriado. Mas isso é assunto pra outro tópico.Os resultados finais são bem interessantes e satisfatórios: as interfaces geradas com Javascript+XML+requisição assíncrona são bem mais próximas de desktop, leves e dinâmicas, e a comunicaçao entre navegador e servidor é feita de forma muito eficiente e rápida.

Minha única ressalva é que, pra quem usa algum framework como struts como eu estou usando atualmente, o uso de AJAX força a ter que reescrever em javascript muitas das funcionalidades já existentes.

Meu sonho de consumo atualmente seria um bom conjunto de taglibs que gerasse código de requisisição e validação de formulários usando AJAX, deixando o código mais limpo e evitando algumas gambiarras necessárias. Existem algumas libs por aí, mas sinceramente nenhuma delas conseguiu chamar a atenção. Quem sabe um dia não me animo a escrever uma.

Mas enquanto não acho a solução ideal, estou usando uma solução caseira desenvolvida inicialmente por um colega e com algumas extensões minhas: o arquivo ajax.js possui um conjunto de funções que facilitam o uso de AJAX, tanto no acesso aos dados do arquivo XML quanto no acesso e modificação do DOM HTML. Está bem simples e sem nenhuma pretensão de ser uma biblioteca definitiva. Mas pode ser uma mão na roda para quem está começando. Comentários, sugestões e críticas são bem vindos.

Down them All !!!!!!!

O plugin downthemall para Firefox 1.5 é uma mão na roda para aquelas páginas com um monte de links para fotos ou arquivos. Ele simplesmente puxa todos os arquivos desejados de uma vez.

Poder de CSS

Durante muito tempo, desenvolvimento de sites na internet era considerado trabalho de programador. Sim, porque saber “programar” em HTML era uma arte dominada por poucos…….Hoje em dia com o advento de aplicações Web complexas, existe um campo enorma para desenvolvedores mostrarem suas habilidades. Mas definitivamente, programação gráfica para Web agora é coisa levada a sério, e deve ser feita por quem realmente entende disso, ou seja, por designer gráficos.

O site css Zen Garden: The Beauty in CSS Design mostra o que se pode fazer com uma simples página html (aqui) e com um arquivo CSS (aqui). Para mostrar o poder de folhas de estilo, o site oferece a possibilidade de mudar o design da página, mantendo o mesmo conteúdo: selecione um dos estilos listados no menu a direita e veja o resultado. Fenomenal.

Biblioteca de componentes gráficos em Javascript

Com o advento de AJAX, bibliotecas de componentes visuais em Javascript estão pipocando. Uma delas é a RIALTO, acronimo para Rich Internet Application Toolkit. Oferece vários componentes gráficos bem bonitos, utilizando AJAX como forma de carregar dados. Para quem trabalha com Struts (meu caso atualmente), ainda fornece uma taglib para facilitar integração do código. Programadores .NET e PHP, não se desesperem: segundo o site, bibliotecas de integração do RIALTO com essas linguagens estão saindo do forno.

Gráficos em Java

A biblioteca JFreeChart, do projeto JFree.org, cria gráficos de uma qualidade incrível, e permite gerar um número enorme de tipos de gráficos, com vários parâmetros configuráveis, além de permitir a exportação em vários formatos úteis. Outro ponto interessante é que foi desenvolvido uma biblioteca que permite integrar o JFreeChart ao código JSP, para geração de imagens para internet. Mas este ainda não usei. Aconselho seu uso caso precise desenvolver uma aplicação que gere gráficos bonitos.

O único porém é que apesar da bibloteca ser aberta, gratuíta e o código disponível, a documentação oficial é paga. Por isso, para desenvolver sem gastar nada, será necessário passar um tempinho lendo exemplos de códigos e eventualmente alguns fóruns por aí. Mas nada que seja do outro mundo, sobretudo pra quem já está habituado a ter que garimpar informações no mundo open source.

Para onde as pessoas olham quando acessam uma página HTML

Entender o comportamento dos internautas é essencial para o sucesso de uma página na web.

O artigo Eyetrack III: What News Websites Look Like Through Readers’ Eyes da uma
idéia de alguns estudos sobre o comportamento de leitura de pessoas visitando sites de notícias.

Mentes ociosas criam …. GoogleFight !

Escolha duas palavras. Va até o site do GoogleFight e digite as palavras nos campos de texto. Aperte o botão “Make a Fight”. O resultado da luta: ganaha a palavra que aparecer mais vezes no google. Além disso, existe a opção de se rodar “lutas” pré determinadas, como Harry Potter contra o Cálice de Fogo, ou Bush contra Katrina.

A real utilidade disso ? Duvidosa. Mas é inegavel que medir o número de ocorrências de uma palavra no google pode ser uma medida informal de popularidade. E pode ser um bom passatempo, caso todos os outros falhem.

Para iniciantes em AJAX

AJAX é a sigla da moda no mundo de desenvolvimento Web. Se você nunca ouviu falar, e trabalha com tecnologia, aconselho fortemente a leitura mais assídua de sites de notícias…nassas horas um bom RSS ajuda e muito.

O melhor de tudo é que AJAX não é absolutamente nada. Ou melhor: não existe uma tecnologia AJAX, mas sim um conjunto de tecnologias bem conhecidas que foram colocadas juntas sob uma sigla bonitinha, criada pela Adaptative Path.

Resumindo: AJAX = Javascript+CSS+XML+conexão assíncrona no servidor. Este último elemento é de fato o mais importante nessa brincadeira toda: com ele é possível fazer requisições no servidor em background, sem ter que bloquear a interface toda, permitindo que interfaces Web se aproximem muito de interfaces de softwares desktops. Acabou o paradigma do “Clique aqui…espere alguns segundos..a página some..aparece uma nova”.

Mas a verdade é que a parte de conexão assíncrona é banal de se utilizar. Alguns segundos de busca no google, e templates de código (que são todos iguais por sinal) virão aos montes. O problema é o resto..javascript+CSS+mexer no DOM do HTML+mexer no DOM do XML.

Achei 3 referências bem interessantes para aprender sobre isso.

A primeira é um conjunto de tutoriais sobre javascript, HTML DOM e XML DOM bem interessantes e bastante completo, com exemplos e tudo mais, e pode ser encontrado no site da w3school .
A segunda referência se baseia na máxima de Lavoisier “Nada se cria, tudo se transforma”. Em termos de desenvolvimento e programação, ler código alheio e ver como bons programadores programam é no meu ponto de vista a melhor forma de aprender. E muita coisa eu aprendi no site dynamicdrive , que possui uma quantidade enorme de scripts muito interessantes. A última, que pode ser boa fonte de outras referências é o verbete AJAX da Wikipédia.

CSS Hacks

Um grande problema enfrentado por desenvolvedores de interfaces Web é a diferença muitas vezes sutil de interpretação de comandos CSS por parte dos navegadores. Um exemplo simples é a questão do tamanho de um div e de sua borda: um navegador (nunca lembro qual) considera que a borda deve ser considerada dentro do tamanho do DIV, utilizando o espaço interno (portanto, se for estipulado que um div tem tamanho 10px, ele terá 10px não importa o tamanho da borda..) e o outro considera que a borda deve ser adicionada externamente, preservando o espaço interno do DIV (portanto, se o div tiver 10px e a borda 2px, o tamanho total do componente será de 14px…).

Esses detalhes podem ser uma grande fonte de problemas em layouts muito detalhistas. Mas a algum tempo atrás, enfrentando problemas deste tipo, descobri um pequeno hack em CSS muito útil. Este hack se utiliza do fato que o IE, ao contrário do Firefox, é mais flexível na hora de interpretar a folha de estilo.
Assim, é possível definir uma folha de estilo que se adeque aos dois navegadores, sem problemas.

Como funciona ? Simples !

Imagine a seguinte folha de estilo:

.titlediv{
width: 10px;
_width: 12px;
}

O Firefox irá ler o parâmetro width, considerar válido, e definirá a largura do meu div em 10 pixels. Depois lerá _width, não irá reconhecer o parâmetro, e terminará o processamento. O IE também irá ler o parâmetro width, definindo a largura em 10px. Porém, ele irá considerar _width como válido também, apesar do _, e irá sobreescrever o valor. Pronto. Nossa folha de estilo se adaptou ao navegador.

Isso vale para qualquer parâmetro de um CSS..desde que o parâmetro hackeado se encontre logo depois do parâmetro correto.

« Previous PageNext Page »