AJAX, caracteres especiais e o Internet Explorer

Todo programador de AJAX passa por isso. Os tais caracteres que existem na nossa querida Língua Portuguesa, mas os falantes da Língua Inglesa (azar o deles!) não conhecem. Então você cria o seu objeto AJAX, limpíssimo e escalonável, e chama o arquivo externo:

var ajaxObj = function() {
if (window.ActiveXObject) return new ActiveXObject('Microsoft.XMLHTTP');
else if (window.XMLHttpRequest) return new XMLHttpRequest();
};

function requisicaoAjax(urlArquivoExterno) {
var ajax = ajaxObj();
if (ajax !== null) {
ajax.open('GET', urlArquivoExterno, false);

// Quando o resultado for carregado...
ajax.onreadystatechange = function() {
if (ajax.readyState == 4 && ajax.status == 200) {

// Exibe o conteúdo carregado.
// Esse é o ponto em que você faz alguma coisa_
// com os dados carregados.
alert(ajax.responseText);

}
};

ajax.send(null);

}
}
requisicaoAjax('/meuArquivoExterno.html');

Ajax com jQuery

Ah! você não faz mais assim? Usa jQuery? Desculpa aí:

$.ajax({
type: 'get',
data: 'nome=Usuario&[email protected]',
url: urlArquivoExterno,
success: function(retorno) {

// Exibe o conteúdo carregado.
// Esse é o ponto em que você faz alguma coisa_
// com os dados carregados.
$('#resposta').html(retorno);

}
});

JQuery tem vários métodos para simplificar a chamada de uma requisição ajax. Veja a lista completa de métodos ajax.

Para fazer um campo de busca agora, basta fazer uma função no <input> que você quiser para chamar a página de resultados quando ocorrer uma alteração no campo. Simples? Nada disso. Graças à boa e velha incompatibilidade de navegadores, alguns eventos não acontecem em alguns navegadores, outros são disparados quando você não quer. Veja como eu responderia ao evento change do campo de busca, para retornar o resultado:

var query = '';
var url = 'minhapagina.php';
var div = $('#resultados');

$('input#busca').change(function() {

// Verificando o que foi digitado
// no campo de busca:
var b = $(this).val();

// A chamada só será feita se o conteúdo do campo for editado
if (b != query) {
query = b;
u = url + '?busca=' + b;

$.get(u, function(data) {

// Conteúdo inserido no local reservado
div.html(data);

});

}
});

Problemas com eventos de formulários HTML

Parece ótimo, até testarmos em diferentes navegadores:

Usando o método .preventDefault(), do objeto jQuery, evitamos que o IE faça besteira.

$('#formBusca').submit( function(e){ e.preventDefault(); } );

Mas agora o IE não faz mais a busca. Difícil, né? Sempre ele. É por isso que eu prefiro usar, no lugar do evento change, o evento keyup, que ocorre ao soltarmos uma tecla (qualquer uma). Enquanto não houver uma alteração no campo de busca, nada acontece, evitando chamadas extras desnecessárias, e todos os navegadores vão atualizar o resultado da busca conforme o texto é digitado.

Caracteres com acentuação em chamadas ajax

Mais uma do Internet Explorer (teimoso, hein?). Se você digitar "maçã", ele vai buscar "ma". Se digitar "mão", vai buscar "mo". Todos os navegadores padrão vão fazer a busca direitinho, menos o IE. Caso você tenha erros em outros navegadores, vamos a algumas considerações:

Se você codificou corretamente todos os arquivos, e não tem um erro no seu script, fica a pergunta: por que o amigo Internet Explorer não pode fazer tudo direitinho igual a todo mundo? Ou melhor ainda, se os caracteres não vão na requisição, qual é a mágica que o Opera e o Google Chrome estão fazendo? Acontece que, se você digitar, por exemplo, http://meusite.com/busca.php?q=é maçã na barra de endereço do Opera e pressionar Enter, ele imediatamente converte para http://meusite.com/busca.php?q=%E9%20ma%E7%E3. E, precisando ou não, vai enviar caracteres codificados como URL (URL encode).

Aí está o segredo. Para que o IE também mande a sua string de busca corretamente, basta usar um método javascript que serve para fazer a devida conversão:

$.get(u, encodeURI(q), function(data) {

div.html( data );

});

Perfeito! Agora funciona corretamente e não teremos (tantos) problemas com incompatibilidades de navegadores. Pelo menos não até lançarem o IE 10, em novembro. Comentem.