Como assim? Mas eu digito uma letra e aparece uma janelinha me dando sugestões em tempo de digitação!
Pois é, o Google Suggest utiliza sim requisições assíncronas mas não podemos chamar de Ajax.
O famoso Ajax ficou conhecido devido ao uso do objeto XMLHttpRequest e o nosso amigo Google não utiliza este objeto para fazer suas requisições assíncronas, ele utiliza simplesmente o fato de chamar scripts externos.

Essa é uma técnica antiga muito utilizada quando o XMLHttpRequest não era tão famoso, o pessoal já se virava com seus scripts dinâmicos e iframes.

Como funciona internamente o Google Suggest?

Na primeira letra digitada ele faz a criação dinâmica de uma tag <script> já setando seu atributo src para http://clients1.google.com.br/complete/search?hl=pt-BR&q= sendo que o parâmetro q equivale ao valor do campo de busca.

Então por exemplo, vou buscar sobre “futebol”, assim que digito a letra “f”, ele faz todo esse processo apontando para http://clients1.google.com.br/complete/search?hl=pt-BR&q=f 

Na segunda letra digitada, visto que a tag <script> já foi criada anteriormente ele simplesmente muda o atributo src agora apontando para a nova url http://clients1.google.com.br/complete/search?hl=pt-BR&q=fu

Mas como através dessa requisição aparece a lista de sugestões ?

A resposta dessa requisição é simplesmente texto puro, mas por ser chamada na tag <script> ela acaba sendo reconhecida como JavaScript e sendo executada por quem a chamou, em nosso caso a página inicial do Google.
O retorno da requisição é simplesmente isso (Um exemplo para a busca da palavra fut):

window.google.ac.h(["fut",[["futebol ao vivo","5.880.000 resultados","0"],
["futebol","39.800.000 resultados","1"]

Somente essa linha de código é responsável por popular a lista de sugestões.

Segue abaixo uma screenshot no momento da “popularização” de dados:

Google Suggest internamente

Por que a Google não utilizou o XMLHttpRequest? Isso foi uma boa solução?

Não é interessante para o Google Suggest controlar o retorno da requisição, saber readyState, status, nada disso é interessante visto que uma requisição é feita a cada letra digitada, então cada requisição sobrescreve a outra.

Não estamos preocupados se a requisição foi feita corretamente, ele simplesmente faz a requisição e se concluir OK, se não der tempo de completar (Isso é bem provável pois se outra letra foi digitada uma nova requisição foi feita), então ele esquece a chamada anterior e vai para a próxima, assim até o usuário “descansar” o dedo e dar tempo para a requisição ser concluída, logo depois a conclusão será mostrado para o usuário os resultados de sua busca.

Outro ponto interessante é a compatibilidade entre browsers. Navegadores muito antigos não têm suporte a XMLHttpRequest e atuais como o IE podem desabilitar essa opção, então na minha opinião foi uma ótima sacada sendo que é garantido que rodará em praticamente qualquer navegador.

Anúncios

Ainda vejo muitos desenvolvedores tentando fazer duas requisições Ajax ao mesmo tempo e sofrendo muito com os problemas que isso pode causar. Lembrando que ao fazer a segunda requisição (junto com a primeira) você está simplesmente anulando a anterior. Outra opção é a criação de diversas instâncias de XMLHttpRequest, mas também não é viável devido a incompatibilidade e sobrecarregamento do browser.

Recentemente desenvolvi uma classe Ajax que suporta múltiplas requisições utilizando o conceito de fila e venho aqui compartilhar com vocês.
É uma classe simples responsável por encapsular toda a complexidade do Ajax (não que Ajax seja difícil, pelo contrário Ajax é muito fácil desde que seja utilizado corretamente).
Utilizando o padrão Singleton (lembrando que esse padrão não é 100% seguro em JavaScript) criamos uma única instância do objeto XMLHttpRequest para ser usado em todas as requisições.

Código de classe:
Clique aqui para ver

Modo de usar:

1 Ajax.doPost(teste.php, “param=1&param=2”, function()
2 {
3     if (Ajax.getInstance().readyState == 4)
4     {
5         if (Ajax.getInstance().status == 200)
6         {
7             alert(Ajax.getInstance().responseText);
8          }
9          Ajax.next();
10    }
11 });

Código de exemplo:
Clique aqui para ver

Basta chamar o método Ajax.doPost() para executar uma nova requisição sem se importar se a requisição anterior foi concluída ou não, pois o próximo doPost() somente será executado se a requisição anterior foi concluída.

Um dos grandes problemas que costumo ver no MySQL é o seguinte: “Quero inserir um registro em uma tabela, recuperar o ID que foi gerado pelo AUTO_INCREMENT e inserir registros em outras tabelas.”
Vejo por aí muitas soluções,  algumas interessantes e outras grandes gambiarras.
Esqueça MAX() +1 , ORDER BY chave DESC LIMIT 1, SHOW TABLE STATUS, entre outros…

Segue abaixo uma das melhores formas para se fazer isso:

1 INSERT INTO tabela (chave_primaria, coluna1, coluna2) VALUES (null, aaa, bbb);
2 SELECT LAST_INSERT_ID() INTO @ID;
3 INSERT INTO outratabela (chave_estrangeira, coluna3, coluna4) VALUES (@id, xxx, yyy);
4 INSERT INTO outratabela (chave_estrangeira, coluna3, coluna4) VALUES (@id, www, zzz);
5 INSERT INTO outratabela (chave_estrangeira, coluna3, coluna4) VALUES (@id, uuu, iiii);

Desta forma você tem 100% de eficiência na recuperação do ID, não tendo problemas em capturar um ID recém-inserido por outro usuário. Com LAST_INSERT_ID() você estará recuperando sempre o último ID gerado pela SUA SESSÃO.

Se você estiver usando INNODB engine, ainda pode trabalhar com transações adicionando os comandos START TRANSACTION e COMMIT para ter total integridade dos dados.

[UPDATE]
Este artigo mostra a forma de recuperar um ID recém-gerado através do próprio MySQL, através de comandos SQL.
Muitas pessoas estão perguntando nos comentários sobre como fazer isso em PHP. Segue a dica do leitor Isaque Victor para a utilização da função mysql_insert_id().

Obs: Apesar da função LAST_INSERT_ID() do MySQL e a função mysql_insert_id() do PHP funcionarem de forma parecida, existem algumas situações que podem retornar valores diferentes. Para saber mais: http://dev.mysql.com/doc/refman/5.1/en/mysql-insert-id.html
[/UPDATE]

O Log4J

Com a famosa biblioteca Log4J é possível gerar diversos níveis de erro que vão desde simples informações de debug até erros de nível crítico. É possível também indicar como esses erros serão apresentados, você tem a opção de mostrá-los no console, armazená-los em arquivos ou até mesmo serem enviados por email.

Em alguns casos essa opção de envio por email é muito importante, principalmente quando é usada para informar ao programador ou administrador do sistema os erros mais críticos que ocorrem ocasionalmente com o usuário final.

O Problema

A classe SMTPAppender que é responsável por enviar email no Log4J (apesar de usar internamente as classes da Mail API javax.mail) não dá suporte a envio de emails autenticados, sendo que a maioria dos servidores obriga você a enviar um email utilizando um username e senha existente.

A Solução

A solução é a boa prática da linguagem Orientada a Objeto, isto é, reuso de classes e aprimoramento.
Criando uma nova classe herdada de  SMTPAppender você pode sobrescrever o método activeOptions() para então fornecer o suporte ao envio autenticado.

Segue abaixo um modelo criado por Chris Butler que encontrei em um fórum americano.

Clique aqui e veja o código da classe

Seguindo este modelo é necessário incluir/alterar seu arquivo log4j.properties para as seguintes configurações:

log4j.appender.email=org.apache.log4j.net.AuthSMTPAppender
log4j.appender.email.SMTPHost=<smtp.somedomain.com>
log4j.appender.email.user=<your username>
log4j.appender.email.password=<your password>

Lembrando que para quem utilizar configurações em xml (log4j.xml) os parâmetros a serem alterados e adicionados serão os mesmos, só fazendo a diferença que lá são escritos em tags, por exemplo:

<param name="user" value="danilo" />

Você já precisou enviar dados em um formulário com codificação diferente da sua página?
Como assim? Inicialmente é meio confuso, mas às vezes acontece.
Por exemplo:

No documento principal que está localizado meu <form>, utilizo o conjunto de caracteres UTF-8 (definido na meta tag)
Na página que irá processar o formulário utilizo o conjunto de caracteres iso-8859-1.

Geralmente isso acontece quando você apenas tem o poder de enviar dados, sendo que a ação do formulário é processada por outro site/servidor.

O atributo accept-charset especifica uma lista de conjuntos de caracteres para a entrada de dados que serão aceitas pelo servidor neste formulário.

Então com isso, resolvemos nosso problema.
Um pequeno exemplo:

form.php

1 <html>
2 <head>
3 <meta http-equiv=”Content-Type” content=”text/html; charset=UTF-8″ />
4 </head>
5
6 <body>
7
8 <form action=”post.php” method=”post” accept-charset=”iso-8859-1″>
9 <input type=”text” name=”nome” value=”Avião faz vôo hoje às 9:30″ />
10 <input type=”submit” value=”Enviar”>
11 </form>
12
13 </body>
14 </html>

post.php

1 <html>
2  <head>
3 <meta http-equiv=”Content-Type” content=”text/html; charset=iso-8859-1″ />
4 </head>
5
6 <body>
7

8  <?php
echo $_POST[nome];
 10 ?>
11
12 </body>
13 </html>

Neste exemplo teremos como resposta o texto exatamente na mesma forma que foi escrito, sem nenhum erro de acentuação. Experimente remover o atributo accept-charset e veja o que acontece.

ou também conhecida como “‘Permission denied to set property XULElement.selectedIndex”…

Alguém já sofreu com este problema? Eu já 😀
Esse erro do FireFox ocorre quando você tenta dar foco à um campo que possui auto-completar. Isso é muito estranho pois é um ato extremamente normal, essa “exceção” só ocorre em alguns campos e não pode ser capturada via try/catch.

Pesquisando, percebi que realmente se tratava de um bug, ele já foi postado no fórum de bugs da mozilla e já deram como resolvido, estranho pois utilizo a última versão do FF e continuo com esse erro, será mesmo que foi corrigido?

Enfim, como sempre há soluções para contornar o erro… Basta desativar o autocompletar do browser ou do campo específico utilizando o atributo autocomplete=”off”. Exemplo:

1 <input type=”text” name=”campo” autocomplete=”off” />

Infelizmente essa propriedade não é validada pela W3C, então os desenvolvedores costumam setar essa propriedade através de JavaScript.

1 objeto.setAttribute(autocomplete, off);

HTML: Imagem embutida

outubro 21, 2008

No HTML é possível embutir imagens diretamente pelo código fonte, assim como o Outlook faz para os anexos (imagens) no corpo do email.
Isso não será uma requisição HTTP para o caminho da imagem e sim seu código binário codificado na base64, quer dizer que você pode inserir o código em qualquer página, sem precisar do arquivo físico da imagem.
Essa pode ser considerada uma técnica de otimização, pois a imagem é carregada diretamente com o código fonte HTML, sem requisições externas.

Mas como nem tudo é perfeito, possui algumas restrições: Alguns desenvolvedores não recomendam a utilização de imagens muito grandes para não afetar o desempenho, apesar de rodar perfeitamente. Outra restrição é não funcionar no Internet Explorer (versões 6, 7 até o momento).

[UPDATE]O Internet Explorer 8 já suporta imagens embutidas[/UPDATE]

“Sintaxe” do código: <img src=”data:[mime-type];base64,[imagem-codificada]”>
É necessário inserir a palavra data, o mime-type da imagem, o tipo de codificação e o código binário da imagem codificado na base64. 

Clique aqui e veja o exemplo do código

Caso queira abrir a imagem no Internet Explorer também, a primeira solução que pensei foi forçar o carregamento via JavaScript, isto é, carregar da forma normal (requisitando a URL da imagem). Como já estamos utilizando o atributo SRC, podemos substituir o SRC via JavaScript. O comentário condicional indica que o bloco abaixo só será executado em versões anteriores do Internet Explorer 8.

1 <!–[if lt IE 8]>
2 <script type=”text/javascript”>
3 document.getElementById(‘idImagem’).src = ‘pasta/imagem.jpg’;
4 </script>
5 <![endif]–>

Se alguém tiver uma solução melhor para o IE, por favor postar.