Semana passada, vimos uns conceitos para desmascararmos o tão temido Ajax, e até montamos uma aplicação simples usando a tecnologia.
Porém, aquilo ainda não era o suficiente para uma requisição verdadeiramente útil no nosso dia-a-dia na programação.
Vamos tentar fazer algo um pouco diferente hoje. Mas, antes vamos esclarecer alguns pontos importantes da semana passada:
Como vimos, para abrirmos um documento externo, utilizando o objeto XMLHttp, fazemos assim:
xmlhttp.open(metodo,url,true/false)
onde o primeiro argumento é o método da requisição, o segundo é a url a ser lida/acessada , o terceiro é o modo a se fazer (assíncrono/síncrono).
Os dois primeiros argumentos são de fácil compreensão, já o terceiro, é complicado de se entender a primeira vista.
Imagine o seguinte trecho de código:
xmlhttp.open("get","minhapagina.php",true);
isso irá fazer uma requisição à página chamada minhapagina.php pelo método get de modo assíncrono.
xmlhttp.open("get","minhapagina.php",false);
isso irá fazer a mesma requisição, porém de forma sícrona.
Já discutimos que uma das diferenças entre os dois, é que da primeira maneira a requisição aconteceria em paralelo a outros eventos da página. Da segunda forma, a requisição seria feita, e nenhum outro evento aconteceria enquanto não fosse terminada a requisição (os processos param enquanto a requisição não termina).
Muitas pessoas tratam o método síncrono (false) como o vilão da história, mas ele é útil, e já salvou muitos pescoços por aí (o meu inclusive).
Qual a diferença?
A diferença está na programação...
para chegarmos ao conteúdo do arquivo, seria algo assim, utilizando uma requisição assíncrona (true):
xmlhttp.onreadystatechange = function()
{
if(xmlhttp.readyState==4)
{
alert(xmlhttp.readyState);
}
}
Note que eu fiz executar uma função criada em tempo de execução ( = function()) para cada alteração da propriedade readyState do xmlhttp.
Como essa opção varia de a 0 a 4, o conteúdo da function() executará 4 vezes...Mas, se formos tratar o xmlhttp.responseText neste contexto, teremos um problema de orientação a objetos do JavaScript ... Programável? Programável! ... Necessário de se enfrentar? Nem tanto...
Há duas formas básicas de se contornar isto, umas delas vou explicar agora:
xmlhttp("get","minhapagina.php",false);
Isso mesmo, utilizando false!
Por que? Simples... Como a página pára todos os outros processos para executar apenas essa requisição, não é necessário fazer os testes com a propriedade readyState do objeto xmlhttp, então o retorno responseText já fica disponível naquele ponto do código onde é feita a requisição.
Complicado?
Exemplificando, a diferença seria:
xmlhttp.open("get","minhapagina.php",true);
alert(xmlhttp.responseText);
xmlhttp.send(null);
Não foi necessário criar uma função para isso.
Mas há também o ponto contra a requisição sícrona...
É exatamente ela parar a página para executar, ou seja, se você fizer uma requisição que a resposta seja pouco conteúdo, ela é viável, mas imagine a sua página esperar com que um cadastro de mais de 10.000 registros seja carregado, no ambiente web?
Isso tornaria uma requisição desta forma inviável...
Espero ter deixado clara a diferença entre os métodos...
Agora vamos ir um pouco mais adiante...
Um dos usos mais interessantes do AJAX utilizando XMLHttp, como vimos aqui, é a interação com alguma linguagem server-side (PHP,ASP,ASP NET,etc)...
Fizemos um exemplo com passagens de dados via método post em nosso exemplo anterior. Poderíamos ter usado GET, porém, este método não é muito seguro, nem muito útil quando se quer passar grandes quantidades de dados.
Então, para isso teremos que fazer uma requisição POST, que precisaria de um comando adicional após o nosso xmlhttp.open
*o método get suporta no máximo 255 caracteres, e os parâmetros são passados todos via URL, o que torna manipulá-los ainda mais fácil. Tornando possível quaisquer tentativa de envio de dados maldosos ao servidor.
Então, vamos agora desenvolver outro pequeno exemplo de AJAX, desta vez mais complexo, com o objetivo de ler o conteúdo de um campo de texto da página html, e ao clicar no botão ao lado do campo de texto, executar a função AJAX, que chama a página PHP e esta cria um arquivo de texto (.txt) com o nome digitado no campo de texto.
Para isso, usaremos 2 páginas, uma chamada "lepagina.html", e outra chamada "execpagina.php".
Elas são responsáveis por montar o formulário pedindo a digitação do nome do novo arquivo a ser gerado, e gerar este novo arquivo, respectivamente.
O código da lepagina.html é bastante simples, perto do que já vimos, mas com algumas modificações...
<html>
<head>
<title>Curso de Ajax - parte 2 ... </title>
<script type="text/javascript">
function montaXMLHTTP()
{
try
{
myObj = new XMLHttpRequest()
}
catch(e)
{
myObj = new ActiveXObject("Microsoft.XMLHTTP");
}
return myObj;
}
myObj = new montaXMLHTTP();
function execAjax()
{
myObj.open("post","execpagina.php",true);
myObj.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
myObj.onreadystatechange=function()
{
if(myObj.readyState==4)
{
alert('Alteração efetuada');
}
}
myObj.send("valor="+document.getElementById("arquivo").value);
}
</script>
</head>
<body>
<input type="text" id="arquivo">
<input type="button" id="executa" onclick="execAjax()" value="executar">
</body>
</html>
Um html simples, com um pouco de ajax...
<html>
<head>
<title>Curso de Ajax - parte 2 ... </title>
<script type="text/javascript">
function montaXMLHTTP()
{
try
{
myObj = new XMLHttpRequest()
}
catch(e)
{
myObj = new ActiveXObject("Microsoft.XMLHTTP");
}
return myObj;
}
myObj = new montaXMLHTTP();
Esse trecho começa simples, declarando o <html> e o título (<title>) da página, e depois criamos um objeto xmlhttp (mostrado em mais detalhes na primeira parte do curso). Terminamos criando uma instância (referência alocando espaço necessário na memória) pra esse objeto recém-criado com o código: myObj = new montaXMLHTTP();
Agora algo "novo" até então...
function execAjax()
{
myObj.open("post","execpagina.php",true);
myObj.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
myObj.onreadystatechange=function()
{
if(myObj.readyState==4)
{
alert('Alteração efetuada');
}
}
myObj.send("valor="+document.getElementById("arquivo").value);
}
Estamos criando uma função function execAjax() , igualmente em nosso primeiro exemplo...
myObj.open("post","execpagina.php",true);
temos aqui a chamada para a requisição a um arquivo, no caso o exepagina.php , utilizando o método post.
A linha abaixo é necessária para transferirmos (enviarmos dados para a página requisitada).
myObj.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
Setamos o content-type (tipo de conteúdo, grotescamente falando), para uma forma que os dados cheguem ao destino.
As linhas abaixo também já são conhecidas do primeiro exemplo...
myObj.onreadystatechange=function()
{
if(myObj.readyState==4)
{
alert('Alteração efetuada');
}
}
A cada alteração da propriedade readystate do objeto xmlhttp (referenciado pela variável myObj), ele executa a determinada função (no caso function()).
Quando o readyState chega ao 4 (completada a requisição), damos a saída dizendo que a alteração foi efeutada.
myObj.send("valor="+document.getElementById("arquivo").value);
E esta linha representa um recurso verdadeiramente novo por aqui.
No exemplo anterior fizemos myObj.send(null) e assim ficamos.
Agora, colocamos algo ao invés do null
O método .send serve para enviar dados ao arquivo requisitado, ou seja, podemos passar valores a este arquivo, nesse caso, via método POST (que foi o usado no .open).
Passar variáveis é relativamente simples: usamos o nome da variável, o sinal de igual (=) e o valor que queremos passar, e o & para passarmos mais de uma variável.
Por exemplo, para passarmos duas variáveis, uma chamada animal com o valor camelo, e outra chamada fruta, com o valor banana, faríamos assim:
myObj.send("animal=camelo&fruta=banana");
Note o & para poder passar a segunda variável.
Para passar uma terceira variável, colocaríamos um outro &, logo após a palavra banana, e assim por diante.
Ness trecho usamos o document.getElementById(elemento).value . Isso é JavaScript, fazendo referência a um objeto através da sua propriedade id, e pegando o que há escrito nele (value).
O restante do arquivo é coisa simples,
</head>
<body>
<input type="text" id="arquivo">
<input type="button" id="executa" onclick="execAjax()" value="executar">
</body>
</html>
Fechamos o cabeçalho (</head>), começamos a editar o "corpo" do documento HTML (<body>) e criamos um campo de texto com o atributo id igual a "arquivo" (id este usado como referência no nosso .send) e abaixo um botão que ao clicarmos, executa a função do JavaScript chamada execAjax (onclick="execAjax()"). Função esta que faz todo esse processo de abrir, enviar variáveis, etc ... (Função discutida acima).
Falta agora vermos onde o arquivo é gerado realmente, o arquivo "execpagina.php", acessado através do método .open do nosso objeto xmlhttp.
O código abaixo é um código PHP simples:
<?php
$valor = mysql_escape_string($_POST["valor"]);
fopen($valor,"w");
?>
Sim, essas 4 ridículas linhas lêem os dados enviados e criam um novo arquivo.
Como? PHP!
<?php
"abre" o PHP ... Há pessoas que fazem simplesmente <? , mas isso não é mais recomendado, há servidores que simplesmente não suportam este método.
Rumores dizem que possivelmente nas próximas versões do php, o "short open tags", o nosso <? será totalmente banido.
$valor = mysql_escape_string($_POST["valor"]);
Aqui lemos a variável passada via método post para a página .
$_POST["valor"] contém o valor dessa variável.
Aplicamos a funçao mysql_escape_string para nos previnirmos de sql injection (técnica hacker).
Antes utilizávamos a função addslashes, porém essa função apresenta falhas tidas como de fácil exploração, e hoje em dia é recomendado o uso de mysql_escape_string e mysql_real_escape_string.
A segunda opção não foi utilizada por exige que já exista uma conexão com o banco de dados mysql.
Como nosso exemplo simples não utiliza banco de dados, achei desnecessário criar uma conexão apenas para utilizarmos essa função.
A linha debaixo é a que realmente cria o arquivo:
fopen($valor,"w");
A função fopen é tida para montar um ponteiro (referência) a um arquivo.
Rebede dois argumentos, o primeiro é o arquivo em si, e o segundo é o modo de abertura.
Quando tentamos abrir um arquivo que não existe, em modo de escrita ("w"), o arquivo é criado sem nenhum conteúdo.
É assim que criamos nosso arquivo.
A última linha ?> apenas "fecha" o PHP.
Vale a pena salientar que é necessário rodar isso em algum servidor (local ou remoto) já que utiliza PHP.
* utilizamos a função mysql_escape_string em um script que dificilmente outra pessoa irá executar além de nós mesmos por tratar-se de uma boa prática de programação, portanto é sempre bom utilizar para pegar o costume de fazê-lo.
E foi isso, a segunda parte do nosso "curso de ajax".
Em breve teremos a parte 3...Qualquer erro, eu sinto muito...Eu não revejo os textos, escrevo no próprio post e não releio.