Criando layout tableless (div), com Ajax.
Vamos fazer um site com Ajax, e para quem não souber o que é Ajax, vai um breve comentário.
Ajax significa Asynchronous Javascript And XML. Quer dizer que Ajax nada mais é do que uma capacidade (ferramenta, biblioteca), de fazer com que, em Javascript, eu possa fazer requisições HTTP (e, dependendo do navegador, posso fazer outros tipo de conexões). As requisições que o Ajax faz, podem ser síncronas ou assíncronas. Se for síncrona, o script ficará esperando o retorno da requisição para continuar a executar o seu código. Se for assíncrona, o script enviará a requisição e continuará a sua execução normalmente, e o retorno dessa requisição deverá ser tratado por uma outra função.
O XML nem sempre é usado para trafegar as informações em Ajax, mas como o nome já pegou, então ficou assim mesmo, mas podemos utilizar qualquer tipo de protocolo texto (como JSON), para trafegar as informações via Ajax.
O principal motivo para desenvolver uma página (web site) com Ajax, é faze-la ficar mais interativa com o usuário, mais dinâmica e criativa.
Para saber um pouco mais sobre Ajax, acesse AJAX (programação).
O Código HTML do Layout em Div
Vamos pegar o layout do post Definindo um Layout de Website sem Tabelas (Tableless), e retirar a parte mais a direita dele, para que a parte do meio do layout, contenha somente o menu e o miolo.
O código ficará como abaixo (arquivo index.html):
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-type" content="text/html;charset=ISO-8859-1" />
<title>Exemplo Estrutura de Site Tableless</title>
<link rel="stylesheet" type="text/css" href="estilo.css" />
<script language="javascript" src="script.js"></script>
</head>
<body>
<div id="todo">
<div id="topo">
<div id="logo">Logo</div>
Aqui pode ser uma imagem de background e um texto.
</div>
<div id="meio">
<div id="esquerda">
<div id="menu">
<div><a href="javascript: void(0);" onclick="ajaxHTMLmiolo('miolo', 'principal');">Principal</a></div>
<div><a href="javascript: void(0);" onclick="ajaxHTMLmiolo('miolo', 'empresa');">Empresa</a></div>
<div><a href="javascript: void(0);" onclick="ajaxHTMLmiolo('miolo', 'produtos');">Produtos</a></div>
<div><a href="javascript: void(0);" onclick="ajaxHTMLmiolo('miolo', 'servicos');">Serviços</a></div>
<div><a href="javascript: void(0);" onclick="ajaxHTMLmiolo('miolo', 'contato');">Contato</a></div>
</div>
</div>
<div id="miolo">
<div>Seção 1</div>
<div>Seção 2</div>
<div>Seção 3</div>
</div>
<div style="clear: both;"></div>
</div>
<div id="rodape">
<div id="rodape_direita">
Av. xxx yyy zzz, No 765<br/>
Manaus - AM - CEP: 89000-000<br/>
Email: <a href="mailto:seuemail@seudominio.com.br">seuemail@seudominio.com.br</a>
</div>
</div>
</div>
</body>
</html>
Maiores explicações sobre o layout, pode encontrar no link passado para o post.
As únicas mudanças foram a parte direita do layout que foi deletada, os menus agora são links (tag <a> com atributo onclick para chamada do Javascript), e foi inserida uma linha chamando o script script.js. Esse script contém a programação em Javascript para fazer a requisição em Ajax.
Uma outra mudança foi no arquivo de folhas de estilo estilo.css. Ele está sem os estilos da parte direita do layout e foi adicionado uma classe, para a frase que indica que o Ajax está carregando uma página, no nosso caso, a frase é simplesmente “Carregando…”, mas a classe está vazia, adicione os estilos que achar necessário.
O Código Javascript
O código Javascript precisa fazer tudo que o navegador faz automáticamente quando se coloca um link no web site: enviar a requisição, esperar pela resposta, pegar a resposta quando essa estiver pronta, tratar a resposta e exibir o que for necessário.
O código do arquivo script.js vai abaixo:
function getNewHttpRequest() {
try {
xmlhttp = new XMLHttpRequest();
} catch(ee) {
try {
xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
} catch(e) {
try {
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
} catch(E) {
xmlhttp = false;
}
}
}
return(xmlhttp);
}
oAjax = getNewHttpRequest();
//Fila de conexões
fila = [];
ifila = 0;
// funcao para altear o conteudo do miolo
function ajaxHTMLmiolo(id, conteudo) {
ajaxHTML(id, 'conteudo.php?conteudo='+conteudo);
}
//Executa a próxima conexão da fila
function ajaxRun() {
//Abre a conexão
oAjax.open("GET", fila[ifila][1], true);
//Função para tratamento do retorno
oAjax.onreadystatechange = function() {
if (oAjax.readyState == 4) {
//Mostra o HTML recebido
retorno = unescape(oAjax.responseText.replace(/\+/g, " "));
document.getElementById(fila[ifila][0]).innerHTML = retorno;
//Roda o próximo
ifila++;
if(ifila < fila.length) setTimeout("ajaxRun()", 20);
}
};
//Executa
oAjax.send(null);
}
function ajaxHTML(id, url) {
//Carregando...
document.getElementById(id).innerHTML="<span class='carregando'>"+"Carregando...</span>";
//Adiciona à fila
fila[fila.length] = [id, url];
//Se não há conexões pendentes, executa
if((ifila+1) == fila.length) ajaxRun();
}
Agora vamos as explicações.
Começando pela função getNewHttpRequest, que não recebe parâmetro, e retorna um objeto XMLHTTP. Esse objeto é o responsável pelas requisições que iremos fazer. Os blocos try {…} catch() {…}, tentam pegar o objeto XMLHTTP de várias formas, por causa das várias formas de pegar esse objeto de navegadores diferentes. Se não conseguir nenhuma, retorna false.
Abaixo pego o objeto XMLHTTP e coloco na variável oAjax e logo abaixo defino as minhas variáveis da fila de requisições.
Por que uma fila de requisições?
Tenho uma fila de requisições para organizar as minhas requisições Ajax, pois sem ela, se o usuário clicar em vários links antes de esperar a resposta de uma requisição, ou eu tenho que instanciar vários objetos do Ajax (XMLHTML), ou vai dar um erro no script que executa a requisição, quando uma outra requisição é feita antes de esperar a primeira terminar. A fila resolve esse problema, pois somente uma requisição é feita por vez, e se houver outra requisição na fila, ela é chamada logo após a requisição atual terminar.
A função ajaxHTMLmiolo serve para fazer uma requisição em Ajax que pega o conteúdo do miolo da página, que é o conteúdo da tag div que tem o atributo id igual a miolo, nesse layout é onde o conteúdo do web site será exibido. Essa função recebe dois argumentos, o primeiro é o id do elemento que vai ser exibido o resultado da requisição, o segundo é uma string que é enviada para o servidor para saber qual conteúdo buscar para exibir. Ela chama a função genérica de requisição Ajax, a ajaxHTML, que recebe o id do elemento que vais ser alterado e a URL que vai ser requisitada.
A função ajaxHTML coloca uma requisição na fila de requisições e tenta fazer essa requisição, se a fila estiver vazia, chamando a função ajaxRun, se não estiver vazia, ela não faz nada, pois assim que for a vez da requisição colocada, ela será feita.
A função ajaxRun pega a requisição que está na vez, na fila de requisições, e a executa, pelo método GET. A linha
oAjax.open("GET", fila[ifila][1], true);
diz que é para abrir a conexão com a URL que está na fila, pelo método GET. O último parâmetro quer dizer que essa requisição tem que ser feita pelo modo assíncrono. Se o último parâmetro for false, a requisição seria feita no modo síncrono.
Para saber mais sobre o método GET, acesse Como Funciona os Métodos GET e POST – Diferenças.
Na linha
oAjax.onreadystatechange = function() {
estou informando ao objeto que a função seguinte é a função que eu quero que ele execute quando o estado da minha requisição mudar. Essa função normalmente é chamada de função de callback, ela fica esperando algum evento acontecer para executar, sem interromper a execução do código. Nesse caso, ela espera o evento de alteração de estado da requisição ocorrer para ser chamada, logo, ela provavelmente será chamada mais de uma vez, pois durante uma requisição o estado muda algumas vezes.
Essa função de callback vai testar se o estado atual da requisição é o estado que eu quero, com a linha:
if (oAjax.readyState == 4) {
O estado do objeto Ajax que eu quero é igual a 4, que é o estado onde a resposta foi lida por completo. Para ver uma lista dos estados do objeto Ajax, acesse XMLHttpRequest.
Após a resposta estar pronta, eu a pego e coloco em uma variável, fazendo uma substituição de todos os sinais de “mais” (’+'), por um espaço em branco. Se faz essa substituição, pois a resposta vem codificada como URL, e nessa codificação, os espaços são convertidos em sinais de “mais” (’+'). A linha que faz isso é a linha abaixo:
retorno = unescape(oAjax.responseText.replace(/\+/g, " ")); document.getElementById(fila[ifila][0]).innerHTML = retorno;
A outra linha pega o elemento que tem o atributo id igual ao que foi passado para a requisição e coloca a resposta como conteúdo desse elemento, no caso do elemento em questão (div), faz o conteúdo ser exibido, mas pode ser feito para qualquer tipo de conteúdo, até um campo hidden (escondido) ou para preencher um selectbox.
ifila++;
if(ifila < fila.length) setTimeout("ajaxRun()", 20);
As linhas acima fazem o controle da fila, a primeira incrementa a posição da fila, fazendo a próxima requisição ser lida, se houver. A segunda linha verifica se o tamanho da fila é maior que a posição atual de leitura da fila, se for, é porque ainda existe requisição a ser feita, então ele programa um timer para em 20 milisegundos, para ser executada essa requisição.
Aqui termina a função de callback, ela será executada após o envio da requisição.
A última linha da função ajaxRun
oAjax.send(null);
faz com que a requisição seja feita (enviada). O parâmetro dela, passado como null, indica que não estou enviando nada na requisição, porque já enviei o que eu queria pela URL passada.
O Código PHP
O código em PHP serve para fornecer o conteúdo requisitado pelo Ajax, perceba que a nossa URL da requisição Ajax tem como endereço o arquivo conteudo.php, lá na função ajaxHTMLmiolo, e o código desse arquivo (conteudo.php), vai abaixo:
<?php
$conteudo = $_GET["conteudo"];
if($conteudo == "principal") {
$fileToRead = "conteudo/principal.html";
}
else if($conteudo == "empresa") {
$fileToRead = "conteudo/empresa.html";
}
else if($conteudo == "produtos") {
$fileToRead = "conteudo/produtos.html";
}
else if($conteudo == "servicos") {
$fileToRead = "conteudo/servicos.html";
}
else if($conteudo == "contato") {
$fileToRead = "conteudo/contato.html";
}
$conteudoArquivo = file_get_contents($fileToRead);
print(urlencode($conteudoArquivo));
?>
Ele simplesmente pega o valor do “conteudo”, que foi passado pelo método GET (olha novamente a URL passada na função ajaxHTMLmiolo), e compara com as strings acima. Cada if faz ele colocar na variável $fileToRead um caminho para um arquivo. Na penúltima linha ele joga todo o conteúdo do arquivo para a variável $conteudoArquivo, e na última linha ele codifica para URL e imprime na “tela” com a função print. A impressão na tela, é a resposta que o Ajax pega. QUALQUER coisa que você imprima na tela, vai ser o retorno da sua requisição Ajax, até mesmo se der um erro no script PHP, caso esteja configurado para exibir o erro na tela, o Ajax vai pegar como retorno.
Não vou colocar o conteúdo dos arquivos HTML de resposta, mas você pode ver o exemplo todo rodando em http://www.comocriarsites.com/exemplos/SiteTablelessAjax/. Lá você mesmo pode pegar os arquivos HTML.
