Ajax Asynchronous JavaScript and Xml Ajax permite construir aplicações Web mais interativas, 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 inativa. Para cada pedido recebido o servidor envia uma nova página html completa e atualizada 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 atualiza 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 atualizadas. 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 interaçã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 efetuado, 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 atualiza 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 atualizaçã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 efetuar o pedido e não fica à espera da resposta (mantendo a página Web ativa). Quando o servidor envia a resposta, código JavaScript atualiza 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 atualizar parte de uma página, tal como mudar imagens, atualizar 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 efetuar pedidos ao servidor usa o objeto Javascript XMLHttpRequest. Mas diferentes browsers têm maneiras diferentes de criar este objeto. Assim vamos necessitar de uma função JavaScript para criar este objeto. Podemos dividir o código JavaScript necessário para uma aplicação Ajax interatuar com o servidor em três funções: 1) criarobjetoxmlhttprequest() 2) efetuarpedido() 3) atualizarpagina() var objxmlhttprequest = null; function criarobjetoxmlhttprequest() { if (window.xmlhttprequest) { objxmlhttprequest = new XMLHttpRequest(); else if (window.activexobject) { objxmlhttprequest = new ActiveXObject("Microsoft.XMLHTTP"); if (objxmlhttprequest == null) alert("erro ao criar o objeto XMLHttpRequest!"); function efetuarpedido() { criarobjetoxmlhttprequest(); var url = "respostaajax.php"; objxmlhttprequest.open("get", url, true); objxmlhttprequest.onreadystatechange = atualizarpagina; objxmlhttprequest.send(null); function atualizarpagina() { if (objxmlhttprequest.readystate == 4 && objxmlhttprequest.status == 200) { var novovalor = objxmlhttprequest.responsetext; document.getelementbyid("id1").childnodes[0].nodevalue= novovalor; A função criarobjetoxmlhttprequest() cria o objeto XMLHttpRequest. Existem diferentes maneiras de o criar dependente do browser. O objeto 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 objeto XMLHttpRequest muda, o browser chama a função callback (neste exemplo atualizarpagina). É 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 efetuado ao servidor: 0 - Ligação não inicializada (Uninitialized) O objeto XMLHttpRequest foi criado, mas não inicializado. O método open() ainda não foi invocado. 1 - Ligação inicializada (Loading) O objeto 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 objeto XMLHttpRequest, mas ainda não terminaram. 4 - Resposta do servidor pronta (Completed) A resposta está disponível na propriedade "responsetext" do objeto 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 objeto 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 objeto XMLHttpRequest. Para atualizar a página Web usamos o DOM (Document Object Model). Se alterarmos uma página Web usando o DOM, o browser atualiza a página imediatamente. DOM Document Object Model (Modelo de Objetos 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. - Atualizaçã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. - Atualizaçã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. <!DOCTYPE html> <html> <head> <title>página de Vendas - sem Ajax</title> <style> td { text-align: center; </style> </head> <body> <form> <div> <table border="1"> <caption>vendas da Empresa A</caption> <th>produtos X vendidos:</th> <td><span id="produtos-vendidos"> <?php $totalvendas = rand(0, 1000); print $totalvendas;?> </span></td> <td colspan="2"> <input type="submit" value="actualizar Vendas" /> </td> </table> </div> </form> </body> </html> Ficheiro vendas.php Sempre que se premir Atualizar 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 atualizar as vendas sem recarregar a página. Ficheiro vendasajax.php: <!DOCTYPE html> <html> <head> <title>página de Vendas - com Ajax</title> <style> td { text-align: center; </style> <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 efetuarpedido() { criarobjectoxmlhttprequest(); var url = "respostaajax.php"; objxmlhttprequest.open("get", url, true); objxmlhttprequest.onreadystatechange = atualizarpagina; objxmlhttprequest.send(null); // alert("enviado o pedido ao servidor para actualizar a pagina!"); function atualizarpagina() { // alert("inicio de actualizar pagina! " + objxmlhttprequest.readystate); if (objxmlhttprequest.readystate == 4 && objxmlhttprequest.status == 200){ var novototal = objxmlhttprequest.responsetext; document.getelementbyid("produtos-vendidos"). childnodes[0].nodevalue = novototal; </script> </head> <body> <form> <div> <table border="1"> <caption>vendas da Empresa A</caption> <th>produtos X vendidos:</th> <td><span id="produtos-vendidos"> <?php $totalvendas = rand(0, 1000); print $totalvendas;?> </span></td> <td colspan="2"> <input type="button" value="atualizar Vendas" onclick="efetuarpedido();" /></td> </table> </div> </form> </body> </html>
<?php $totalvendas = rand(0,1000); print $totalvendas;?> Alterações efetuadas: Ficheiro respostaajax.php 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 efetuarpedido(). As aplicações assíncronas efectuam pedidos usando um objeto javascript e não uma submissão de um formulário. O código JavaScript cria um objeto XMLHtpRequest, abre uma ligação assíncrona ao servidor com o pedido respostaajax.php, atribui à propriedade onreadystatechange a função JavaScript atualizarpagina que contém o código de atualização da página, e envia o pedido ao servidor. O browser coloca a resposta do servidor na propriedade responsetext do objeto XMLHttpRequest. A função JavaScript atualizarpagina lê esta resposta e coloca-a no elemento com o id "produtos-vendidos". O envio dos pedidos ao servidor assim como a receção das respostas do servidor são tratados pelo browser Web e não diretamente 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 pedido é efetuado 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 objeto XMLHttpRequest. Os pedidos efetuados ao servidor podem estar em diferentes estados readystate. De cada vez que o estado readystate muda, a função atribuída à propriedade onreadystatechange do objeto 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 objeto XMLHttpRequest. 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). function submeterpedido() { criarobjetoxmlhttprequest(); var telefone = document.getelementbyid( telefone ).value; var endereco = document.getelementbyid( endereco ).value; var url = "ColocarPedido.aspx"; objxmlhttprequest.open("post", url, true);
objxmlhttprequest.onreadystatechange = atualizarpagina; 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 atualizarpagina() { if (objxmlhttprequest.readystate == 4 && objxmlhttprequest.status == 200) { alert(objxmlhttprequest.responsetext); 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.