Ajax Asynchronous JavaScript and Xml Ajax permite construir aplicações Web mais interactivas, responsivas, e fáceis de usar que aplicações Web tradicionais. Numa aplicação Web tradicional quando se prime um botão uma página é carregada. Normalmente, o utilizador preenche informação de um formulário, clica num botão, o browser envia um pedido ao servidor, e enquanto o servidor não responde, a página fica inactiva. Para cada pedido recebido o servidor envia uma nova página html completa e actualizada com novos dados. Quando o servidor responde o browser redesenha completamente a página. Ajax permite criar uma nova geração de aplicações Web, onde JavaScript, HTML dinâmico, e XML tornam a aplicação semelhante a uma aplicação desktop responsiva e dinâmica. Ajax usa um modelo de pedido/resposta diferente para obter aplicações mais rápidas. A página Web efectua o pedido através de uma função JavaScript, em vez de submeter o formulário Web. Código JavaScript faz o pedido ao servidor que responde só com os dados que a página necessita, sem código de anotações ou de apresentação. Quando o browser recebe a resposta do servidor invoca código JavaScript, que actualiza dinamicamente a página Web, alterando apenas o necessário. A maior parte da página não muda, apenas as partes da página que necessitam ser actualizadas. Para o servidor Web nada muda, apenas responde ao pedido. Só que o pedido em vez de ser uma página completa, é apenas dos dados necessários. As aplicações Web Ajax, além de possibilitarem uma interacção com o servidor sem a necessidade do browser ter de carregar e desenhar uma página completa, são assíncronas, porque o código JavaScript efectua um pedido assíncrono ao servidor. Após o pedido ser efectuado, pode-se continuar a trabalhar no formulário Web ao mesmo tempo que o servidor processa o pedido. Quando o servidor envia a resposta, código JavaScript actualiza parte da página sem que o utilizador tenha que estar à espera. O poder das aplicações Ajax reside nos pedidos assíncronos combinados com a actualização de páginas sem necessidade de as recarregar. Código JavaScript de uma Aplicação Ajax Uma aplicação Web Ajax, em vez de submeter um formulário ao servidor, usa código JavaScript para efectuar o pedido e não fica à espera da resposta (mantendo a página Web activa). Quando o servidor envia a resposta, código JavaScript actualiza uma parte da página com os novos valores recebidos em vez de recarregar a página inteira. Deve-se usar Ajax quando se pretende apenas actualizar parte de uma página, tal como mudar imagens, actualizar campos de texto ou responder ao utilizador. Quando se pretende uma mudança significativa da página deve-se permitir que o utilizador submeta o formulário.
Se um browser não permite a execução de código JavaScript não é possível executar uma aplicação Web Ajax. Um utilizador de uma aplicação Web Ajax tem de ter o browser configurado com permissão de JavaScript. Geralmente os browsers, por omissão, estão configurados para permitir execução de código JavaScript. Uma aplicação assíncrona para efectuar pedidos ao servidor usa o objecto Javascript XMLHttpRequest. Mas diferentes browsers têm maneiras diferentes de criar este objecto. Assim vamos necessitar de uma função JavaScript para criar este objecto. Podemos dividir o código JavaScript necessário para uma aplicação Ajax interactuar com o servidor em três funções: 1) criarobjectoxmlhttprequest() 2) efectuarpedido() 3) actualizarpagina() var objxmlhttprequest = null; function criarobjectoxmlhttprequest() { if (window.xmlhttprequest) { objxmlhttprequest = new XMLHttpRequest() else if (window.activexobject) { objxmlhttprequest = new ActiveXObject("Microsoft.XMLHTTP") if (objxmlhttprequest == null) alert("erro ao criar o objecto XMLHttpRequest!"); function efectuarpedido() { criarobjectoxmlhttprequest(); var url = "respostaajax.php"; objxmlhttprequest.open("get", url, true); objxmlhttprequest.onreadystatechange = actualizarpagina; objxmlhttprequest.send(null); function actualizarpagina() { if (objxmlhttprequest.readystate == 4 && objxmlhttprequest.status == 200) { var novovalor = objxmlhttprequest.responsetext; document.getelementbyid("id1").childnodes[0].nodevalue= novovalor; A função criarobjectoxmlhttprequest() cria o objecto XMLHttpRequest. Existem diferentes maneiras de o criar dependente do browser. O objecto XMLHttpRequest possui várias propriedades e funções. open("get", url, true) Esta função inicializa a ligação ao servidor. onreadystatechange Propriedade que permite atribuir uma função JavaScript que vai ser chamada pelo browser sempre que o estado "readystate" muda. Sempre que o estado "readystate" do objecto XMLHttpRequest muda, o browser chama a função callback (neste exemplo actualizarpagina). É necessário colocar esta propriedade antes de chamar send() para que o browser saiba que função chamar quando obtiver a resposta do servidor.
send(null) Esta função envia o pedido ao servidor. null significa que não se envia nenhum dado no pedido. Se necessário, pode-se enviar dados adicionais aos contidos no url. readystate Propriedade que contém o estado do pedido efectuado ao servidor: 0 - Ligação não inicializada (Uninitialized) O objecto XMLHttpRequest foi criado, mas não inicializado. O método open() ainda não foi invocado. 1 - Ligação inicializada (Loading) O objecto XMLHttpRequest sabe como ligar e o que pedir mas ainda não enviou pedido. O método send() ainda não foi invocado. 2 - Resposta em progresso (Loaded) O pedido já foi enviado, o status e cabeçalho da resposta já estão disponíveis, mas a resposta ainda não. 3 - Obtendo a resposta do servidor (Interactive) Os dados estão a ser carregados no objecto XMLHttpRequest, mas ainda não terminaram. 4 - Resposta do servidor pronta (Completed) A resposta está disponível na propriedade "responsetext" do objecto XMLHttpRequest. status Propriedade que informa se o pedido foi executado com sucesso (status = 200). O servidor reporta problemas com o pedido usando um código de status. O código de status indica o que aconteceu durante o pedido. Há uma diferença entre o readystate do pedido e o status do mesmo pedido. O readystate informa o estado de processamento do pedido (inicialização, processamento, completo), enquanto o status informa se o pedido teve sucesso. O browser coloca, quer o readystate, quer o status no objecto XMLHttpRequest. O browser invoca sempre a função callback e reporta o erro se existir, porque para um pedido assíncrono, o callback é a única maneira de podermos escrever código para lidar com a resposta do servidor. Se o readystate é igual a 4 o browser já colocou a resposta do servidor na propriedade responsetext ou responsexml do objecto XMLHttpRequest. Para actualizar a página Web usamos o DOM (Document Object Model). Se alterarmos uma página Web usando o DOM, o browser actualiza a página imediatamente. DOM Document Object Model (Modelo de Objectos do Documento) Muitas vezes os campos de texto são usados para entrar texto. Possuem uma propriedade "value" que permite colocar ou obter o valor do texto directamente. Os elementos span ou div não possuem a propriedade "value", porque à semelhança de muitos outros elementos html não se usam para entrar texto. Ex1. - Actualização do campo de texto com id="id1": var enderecocliente = objxmlhttprequest.responsetext; document.getelementbyid("id1").value = enderecocliente; ou document.getelementbyid("id1"). childnodes[0].nodevalue = enderecocliente;
Ex2. - Actualização do span com id=" id2": var enderecocliente = objxmlhttprequest.responsetext; document.getelementbyid("id2"). childnodes[0].nodevalue = enderecocliente; Formulário Web php sem Ajax Consideremos o seguinte formulário Web que pede ao servidor informação sobre a quantidade de vendas de um dado produto X. O servidor, para simular que acede a uma base de dados, gera aleatoriamente um valor. <?php srand((double)microtime() * 1000000); $totalvendas = rand(0,1000); <html xmlns="http://www.w3.org/1999/xhtml" > <head> <title>página de Vendas - sem Ajax</title> </head> <body> <form> <div> Texto <p /> texto <p /> texto <p /> texto <p /> texto <p /> Texto <p /> texto <p /> texto <p /> texto <p /> texto <p /> Texto <p /> texto <p /> texto <p /> texto <p /> texto <p /> Texto <p /> <table> <caption>vendas da Empresa A</caption> <tr> <th>produtos X vendidos:</th> <td><span id="produtos-vendidos"> <?php print $totalvendas; </span></td> <tr> <td colspan="2"> <input type="submit" value="actualizar Vendas" /> </td> </table> </div> </form> </body> </html> Ficheiro vendas1.php Sempre que se premir Actualizar Vendas toda a página recarrega. Só um número é mudado mas a aplicação redesenha a página inteira. O Servidor recebe o pedido, e envia a quantidade de vendas dentro de uma página HTML. O Browser carrega a página que recebe e mostra-a no ecrã.
Formulário Web php com Ajax Ajax permite actualizar as vendas sem recarregar a página. Ficheiro vendasajax1.php: <?php srand((double)microtime() * 1000000); $totalvendas = rand(0,1000); <html xmlns="http://www.w3.org/1999/xhtml" > <head> <title>página de Vendas - com Ajax</title> <script type="text/javascript"> var objxmlhttprequest = null; function criarobjectoxmlhttprequest() { if (window.xmlhttprequest) { objxmlhttprequest = new XMLHttpRequest() else if (window.activexobject) { objxmlhttprequest = new ActiveXObject("Microsoft.XMLHTTP") if (objxmlhttprequest == null) alert("erro ao criar o objecto XMLHttpRequest!"); function efectuarpedido() { criarobjectoxmlhttprequest(); var url = "respostaajax1.php"; objxmlhttprequest.open("get", url, true); objxmlhttprequest.onreadystatechange = actualizarpagina; objxmlhttprequest.send(null); // alert("enviado o pedido ao servidor para actualizar a pagina!"); function actualizarpagina() { //alert("inicio de actualizar pagina! " + objxmlhttprequest.readystate); if (objxmlhttprequest.readystate == 4) { var novototal = objxmlhttprequest.responsetext; document.getelementbyid("produtos-vendidos").childnodes[0]. nodevalue= novototal; </script> </head> <body> <form> <div> texto<p />texto<p />texto<p />texto<p />texto<p /> texto<p />texto<p />texto<p />texto<p />texto<p /> texto<p />texto<p />texto<p />texto<p />texto<p />texto<p /> <table> <caption>vendas da Empresa A</caption> <tr> <th>produtos X vendidos:</th> <td><span id="produtos-vendidos"> <?php print $totalvendas; </span></td> <tr> <td colspan="2"> <input type="button" value="actualizar Vendas" onclick="efectuarpedido();" /> </td> </table> </div> </form> </body> </html>
<?php srand((double)microtime() * 1000000); $totalvendas = rand(0,1000); print $totalvendas; Ficheiro respostaajax1.php Alterações efectuadas: O botão submit cujo efeito era submeter o formulário foi substituído por um botão javascript em que o evento clique chama a função JavaScript efectuarpedido(). As aplicações assíncronas efectuam pedidos usando um objecto javascript e não uma submissão de um formulário. O código JavaScript cria um objecto XMLHtpRequest, abre uma ligação assíncrona ao servidor com o pedido respostaajax1.php, atribui à propriedade onreadystatechange a função JavaScript actualizarpagina que contém o código de actualização da página, e envia o pedido ao servidor. O browser coloca a resposta do servidor na propriedade responsetext do objecto XMLHttpRequest. A função JavaScript actualizarpágina lê esta resposta e coloca-a no elemento com o id "produtos-vendidos". O envio dos pedidos ao servidor assim como a recepção das respostas do servidor são tratados pelo browser Web e não directamente pelo código JavaScript. Quando o browser obtém a resposta de um pedido assíncrono, invoca código JavaScript e disponibiliza a resposta do servidor. Numa aplicação assíncrona o browser, em vez de efectuar a submissão de um formulário, corre uma função javascript associada a um dado evento. Esta função cria o objecto XMLHttpRequest, configura-o, e diz ao browser para enviar um pedido ao servidor. O pedido é efectuado pelo browser e não directamente pelo código JavaScript. O browser retorna o controlo ao utilizador porque se trata de um pedido assíncrono. Quando o servidor responde, o browser corre a função atribuída à propriedade onreadystatechange do objecto XMLHttpRequest. Os pedidos efectuados ao servidor podem estar em diferentes estados readystate. De cada vez que o estado readystate muda, a função atribuída à propriedade onreadystatechange do objecto XMLHttpRequest é invocada. Quando o readystate é colocado em 4 o servidor já terminou o envio da resposta, e portanto é seguro usar os dados que o Servidor enviou e que estão guardados no objecto XMLHttpRequest.
Colocação de texto: campo de texto versus span No exemplo seguinte (vendasajax2,php) o elemento html span destinado à colocação do valor das vendas foi substituído por um campo de texto (elemento html input type= text ). Os objectos do DOM (Document Object Model) campos de texto e áreas de texto têm a propriedade value, propriedade de leitura e escrita, que permite ler ou escrever um valor nesses objectos.... function actualizarpagina() { if (objxmlhttprequest.readystate == 4 && objxmlhttprequest.status == 200) { var novototal = objxmlhttprequest.responsetext; document.getelementbyid("produtos-vendidos").value= novototal; <table> <caption>vendas da Empresa A</caption> <tr> <th>produtos X vendidos:</th> <td><input id="produtos-vendidos" type="text" value=" <?php print $totalvendas; " /></td> <tr> <td colspan="2"> <input type="button" value="actualizar Vendas" onclick="efectuarpedido();"/> </td> </table>... Parte do Ficheiro vendasajax2.php Nos programas apresentados vendasajax1.php e vendasajax2.php, a primeira vez que se selecciona Actualizar Vendas um novo valor é recebido, mas em seguida o botão Actualizar Vendas recebe sempre o mesmo valor, o que não está correcto. Caching do Internet Explorer O Internet Explorer, tal como o Opera, efectua o cache de imagens e URLs. Depois de visitar uma página com muitas imagens, se se regressa a essa página os gráficos surgem rapidamente. Se se efectua um pedido a um programa servidor, o browser também efectua o cache do resultado. Ao efectuar um pedido com o mesmo URL, sem qualquer dado diferente, em vez de reenviar o pedido, fornece logo o resultado guardado obtido no primeiro pedido. Uma aplicação Ajax executa uma função JavaScript desencadeada pela ocorrência de um evento. A função JavaScript cria um objecto XMLHttpRequest e envia um pedido a um URL. O pedido é enviado ao servidor pelo browser e não directamente pelo código JavaScript.
O servidor envia a resposta ao browser que chama a função callback especificada. Mas, se o browser efectua o cache dos URLs pedidos, guarda o URL e a resposta. Num segundo pedido ao mesmo URL, o browser detecta que já tem uma resposta para esse pedido, e retorna o mesmo resultado. Para ultrapassar o problema do caching, temos de mudar o URL do pedido todas as vezes. Para isso podemos enviar um parâmetro fictício e dar-lhe um valor diferente de cada vez que efectuarmos um pedido. Podemos gerar um número aleatório ou utilizar o tempo corrente em milissegundos. var url = " ------ "; url = url + "?ficticio=" + new Date().getTime(); gettime() retorna o tempo desde 1 de Janeiro de 1970 em milissegundos. A desactivação do caching de páginas só funciona para as páginas que se carregam directamente, quer digitando o URL na barra de endereços, quer clicando num hyperlink. Para os pedidos desencadeados por código javascript o Internet Explorer não oferece possibilidade de desactivação de caching. Mas mesmo que fosse possível desligar o caching, poderia haver sempre utilizadores que não o fariam, pelo que devemos mudar o URL do pedido.... function efectuarpedido() { criarobjectoxmlhttprequest(); var url = "respostaajax1.php"; url = url + "?ficticio=" + new Date().getTime(); objxmlhttprequest.open("get", url, true); objxmlhttprequest.onreadystatechange = actualizarpagina; objxmlhttprequest.send(null);... Parte do Ficheiro vendasajax3.php
POST Pode-se usar o método send() para passar dados ao Servidor, mas para isso é necessário usar o método POST no pedido e especificar o tipo de conteúdo para o pedido. Na versão POST colocam-se no método send() pares nome/valor do mesmo modo que se colocam na versão GET no fim de um URL (querystring). O browser efectua o cache dos pedidos GET, mas não dos pedidos POST. function submeterpedido() { criarobjectoxmlhttprequest(); var telefone = document.getelementbyid( telefone ).value; var endereco = document.getelementbyid( endereco ).value; var url = "ColocarPedido.aspx"; objxmlhttprequest.open("post", url, true); objxmlhttprequest.onreadystatechange = actualizarpagina; objxmlhttprequest.setrequestheader( Content-Type, application/x-www-form-urlencoded ); objxmlhttprequest.send( telefone= + escape(telefone) + &endereco= + escape(endereco)); Num pedido GET os dados fazem parte do URL pedido, por isso são texto. Mas num pedido POST pode-se enviar uma imagem, ou XML, ou texto. Por isso é necessário informar o servidor do tipo de conteúdo, para ele poder descodificar. objxmlhttprequest.setrequestheader( Content-Type, application/x-www-form-urlencoded ); diz ao servidor que os dados estão codificados como se fossem provenientes de um pedido GET, isto é, enviados sob a forma nome=valor.
XML Cliente recebe XML No caso de o servidor necessitar de enviar uma tabela de valores, poderia enviar uma string com os valores separados por ponto e vírgula ( ; ), ou ou por vírgula, e no cliente separar as substrings. Mas é preferível enviar um documento XML. <?xml version= 1.0 encoding= utf-8 <vendas> <artigo-1>189</artigo-1> <artigo-2>241</artigo-2> <artigo-3>456</artigo-3> </vendas> function actualizarpagina() { if (objxmlhttprequest.readystate == 4 && objxmlhttprequest.status == 200) { var respostatexto = objxmlhttprequest.responsetext; alert(respostatexto); var docxml = objxmlhttprequest.responsexml; var vendas1 = docxml.getelementbytagname("artigo-1"); document.getelementbyid( "produtos-vendidos").childnodes[0].nodevalue= vendas1; else alert( Erro! status de XMLHttpRequest = + objxmlhttprequest.status); Cliente envia XML Para enviar XML, tem que ser através de POST. objxmlhttprequest.setrequestheader( Content-Type, text/xml ); Informa o servidor que o tipo de conteúdo da mensagem é XML no formato texto.