Web Sites com Ajax

JavaScript

Compreendendo a página comportamentos.js

A página comportamentos.js, que abordaremos nesta unidade, é a nossa camada de comportamento e será a responsável por toda interatividade do aplicativo e interpretação da marcação HTML que desenvolvemos nas páginas anteriores. Então, vamos lá!

A página é composta por 16 funções. Veremos cada uma delas para você compreender suas respectivas funcionalidades.

Vejamos a lista com o nome das funções contidas na página:

  1. openAjax()
  2. loadFunctions()
  3. gE()
  4. gEs()
  5. ativarBtnCadastro()
  6. exibirBgBody()
  7. boxCad()
  8. loading()
  9. btnOkBtnCancelar()
  10. focusNome()
  11. validarForm()
  12. validaEmail()
  13. atualizaRelatorio()
  14. ativarBtnEditarBtnExcluir()
  15. removerDivs()
  16. getPageSize()

Repare a primeira função da nossa lista na imagem abaixo:

Função openAjax();

Essa função nomeada como openAjax() é a responsável em instanciar o objeto XMLHttpRequest e essa instância do objeto será atribuída a variável ajax.

Repare que através do try / catch estamos verificando qual o método suportado pelo browser: XMLHttpRequest, presente no Mozila, Firefox, Safari, entre outros; ou XMLHTTP, utilizado no Internet Explorer como um objeto ActiveX.


Observe que nossa marcação HTML está limpa e separada do JavaScript de forma que não temos atribuições de eventos em objetos como o exemplo seguinte:

... onclick="funcaoX('parametroY');" ...

Responsável em chamar as funções JavaScript, precisamos chamar essas funções de outra forma, e uma delas é quando a página é carregada.

Observemos:

Função loadFunctions();

Ao carregar a página - window.onload - será chamada a função loadFunctions, que por sua vez chama outras funções - focusNome(), ativarBtnCadastro(), ativarBtnEditarBtnExcluir().

Você pode se perguntar: se temos dezesseis funções, por quê somente 3 dessas são chamadas? Simples, porque inicialmente ao carregar a página precisamos somente dessas três.

Falaremos sobre cada uma especificamente para uma melhor compreensão.


As funções gE() e gEs() além de facilitar o nosso trabalho, são benéficas para a saúde, ajudando-nos a evitar a LER e a tendinite, acredite.

Observe-as para que eu possa lhe explicar melhor:

Funções gE(); e gEs();

Quando precisamos acessar um objeto através do valor atribuído em seu atributo ID, procedemos assim:

document.getElementById('valorDoAtributoID');

Agora, imagine acessar inúmeros elementos. Imaginou? Então, é cansativo, chato e não há mãos que aguente.

A função gE() foi criada para solucionar este problema, de forma que basta chamá-la assim:

gE('valorDoAtributoID');

O que seria o equivalente ao que fizemos no exemplo anterior.

A função gEs() tem o mesmo próposito, mas, ao invés do método getElementById, ela trabalha com o método getElementsByTagName.


Bom, nossa próxima função - ativarBtnCadastro() já utiliza o Ajax.

Vejamos:

Função ativarBtnCadastro();

Ela inicia verificando se há algum objeto cujo atributo ID tem o valor btnNovoCadastro. Lembra-se dele? É aquele link que dizemos que quando clicarmos nele seria chamado o formulário de cadastro. Então, observe a linha 45 na imagem acima. Estamos dizendo que ao clicar no link - onclick - iremos executar uma função.

Iniciamos tal função chamando outras três funções - exibirBgBody(), boxCad() e openAjax() - essa última foi atribuída a variável que chamamos de ajax. Mais adiante abordaremos as outras duas funções.

Na linha 49 criamos a variável recipiente, a qual terá como valor um objeto cujo ID foi definido como boxCad.

Na linha 50, começamos a maravilha do Ajax, utilizando o método open do objeto XMLHttpRequest. Informamos a esse método que trabalharemos com o método GET de requisição HTTP, que a página formulario.php?ajax=true será requisitado e que trabalharemos de forma assíncrona - true.

O endereço da página foi utilizado desta forma: formulario.php?ajax=true para que a página - formulário.php - saiba que ela está sendo acessada via Ajax.

Na abordagem que realizamos referente a página formulario.php, vimos a importância de se informar a ela que tal acesso ocorrerá via Ajax.

A linha 51 demonstra a utilização do evento onreadystatechange do objeto XMLHttpRequest. Assim, dizemos que ele será igual a uma função.

Na linha 52, verificamos se o estado da propriedade readyState é igual a 1 (um), ou seja, se estamos no estágio de carregamento. Se estivermos, chamamos a função loading() - observe que o valor true foi informado como parâmetro.

Já na linha 55, verificamos se o estágio da requisição está na fase 4, ou seja, completo.

Na linha 56, verificamos se o código númerico do status HTTP retornado pelo servidor é igual a 200, ou seja significa OK, ou melhor dizendo, a página que informamos foi encontrada.

Em seguida, chamamos a função loading(), só que desta vez informando a ela o valor false como parâmetro. Afinal, já passamos do estágio de carregamento.

A linha 58 nos mostra que estamos definindo a string que contém os dados retornados pelo servidor - ajax.responseText - como o HTML interno - innerHTML - da variável recipiente.

Agora que temos o formulário em "nossas mãos", chamamos as funções: btnOkBtnCancelar() e focusNome(), ambas trabalham em conjunto com o formulário (falaremos sobre elas ainda).

Ta vendo só como não fazia sentido chamar todas as funções ao carregar a página? Fique atento aos detalhes.

O método send() do objeto XMLHttpRequest foi utilizado na linha 64 - ajax.send(null). Ele tem a finalidade de enviar a requisição ao servidor web.

Finalizamos a função com o return false - linha 65 - para evitar que o browser execute o link, ou seja, siga para a página atribuída em seu atributo href.


Abordaremos agora a função exibirBgBody(), que tem a finalidade de criar uma tag div e com essa cobrir todo o "viewport" do browser.

Observe-a:

Função exibirBgBody();

Na linha 70 da função exibirBgBody, selecionamos a tag body da página através da função gEs(). Como só temos apenas uma tag body, utilizamos o item(0) para não precisarmos utilizar um loop for, por exemplo.

Criamos a variável sizesPage na linha 71 e, através dela, chamamos a função getPageZise(). Essa função torna um array com a largura e altura da página e da janela.

Na linha 72, criamos uma tag div e já na linha 72 atribuímos a ela o atributo ID com o valor bgBody. Em seguida, definimos o tamanho e a largura (através do style.height e style.width respectivamente) da tag div que criamos. Os valores serão exatamente o tamanho e a largura da página em questão. Para conseguirmosisso, utilizamos o array retornado pela função getPageSize().

Para evitar criarmos duas tags div com o mesmo atribudo ID, verificamos se ela (tag div) não consta na página, linha 76. Em seguinda, utilizamos o insertBefore sobre a variável tagBody para inserirmos a div criada como primeira filha - firstChild - da tag body.


A função boxCad() é semelhante a função exibirBgBody(), ou seja, ela cria uma tag div, define um atributo ID a ela com o valor boxCad e utiliza a função getPageSize() para utilizar-se das medidas da página em questão.

Entretando, ao invés de inserirmos a tag div criada como primeira filha, iremos inserí-la como última filha - lastChild.

Observe a função na imagem de exemplo abaixo:

Função boxCad();


Veremos agora como foi desenvolvido a função loading(), cujo objetivo é criar um efeito de loading na tela.

Vejamos a função abaixo:

Função loading();

A função acima (loading()) recebe um parâmetro que definimos como opt, de option ou opção. Nessa função verificamos qual o parâmetro que foi informado a ela quanda foi chamada. Se o parâmetro informado for true criamos o efeito e se for false o removemos.

Esse efeito nada mais é do que uma imagem do tipo .gif animado que é exibido ou removido da tela.

Na linha 95, criamos a variável refer e atribuímos a ela um objeto cujo ID foi definido como bgBody. Lembra-se dele? Muito bem, isto mesmo.Essa é a tag div que foi criada pela função exibirBgBody().

Vou aproveitar este momento para lhe falar sobre um detalhe importante:

Volte até a imagem acima que nos mostra a função ativarBtnCadatro() e repare que a função loading() - linha 53 - é chamada após a função exibirBgBody() - linha 46.

O que quero dizer com isto é que a função loading() necessita da tag div cujo ID foi definido como bgBody e criada pela função exibirBgBody(). Então, se a função loading() for chamada anteriormente à função exibirBgBody() teríamos um erro porque não consequiríamos localizar na página o objeto que necessitamos - bgBody.

A linha 96 foi utilizada para sabermos o tamanho do objeto referenciado na variável refer. Já a linha 97, para informamos que tal objeto centralizará o que estiver dentro dele.

Em seguida, criamos uma tag img e definimos a ela os atributos src, id e width. Na linha 102 dizemos que ela terá seu margin-top com a metade do tamanho do objeto. Logo após, verificamos se não há presente na página um objeto como o atributo ID igual a loading e, posteriormente, inserimos a imagem como a primeira filha - firstChild - do objeto referenciado - bgBody.


Veja a função btnOkBtnCancelar() na imagem abaixo. Falaremos sobre ela agora.

Função btnOkBtnCancelar()

A função acima será atribuída aos botões de submit - btnOk - e reset - btnCancelar - do formulário. Ao clicarmos no botão de submit executamos uma função, ao clicar no reset executamos outra.

Na linha 115, iniciamos uma função que foi atribuída ao click no botão cujo ID foi definido como btnOk. Criamos a variável validacao e através dela chamamos a função validarForm() para validarmos o formulário. Essa função - validarForm() - retornará true se os dados estiverem corretos ou retornará false se os dados não estiverem corretos. Sendo assim, verificamos na linha 117 se a função retornou true, se este for caso, prosseguimos com a função.

Ao chegarmos na linha 118, percebemos que as coisas estão ficando mais familiares para nós, não é? Isso porque já abordamos tais funcionalidades através da função ativarBtnCadastro().

Porém, se observarmos bem, veremos algo diferente e, essa diferença localiza-se na linha 120. É exatamente nessa linha onde utilizamos um outro método do objeto XMLHttpRequest chamado setRequestHeader, o qual tem o próposito de informar um cabeçalho para a requisição.

O cabeçalho informado foi o Content-Type com o valor application/x-www-form-urlencoded. Uma vez que utilizaremos o método POST de requisição HTTP, como pode ser observado na linha 119, tal cabeçalho se faz necessário ao se trabalhar com esse método - POST.

Quando o código númerico do status HTTP retornado pelo servidor for igual a 200, chamaremos a função atualizaRelatorio(). Sua função é atualizar o relatório com as devidas modificações/inclusões realizadas.

Na linha 128, criamos a variável tipoAcao, que nos dirá se trabalharemos com um processo de inserção ou edição dos dados, para que assim, possamos iniciar a constituição do valor da variável dataPost.

Iremos definir o valor do action (o equivalente ao campo action do formulario) como cadastrar, se o valor da variável tipoAcao for igual a cadastrar. E, tivermos editar como o valor da variável tipoAcao, a definiremos como editar e ao mesmo tempo o valor do ID do contato cadastrado.

É preciso deixar claro que quando trabalhamos com o método POST de requisição HTTP, enviamos os dados em formato de uma "query string" da seguinte forma:

nome=Leandro&obs=&ddd=33&tel=00000000&assim=pordiante

Então, até a linha 143, estamos constituindo o valor da variável dataPost nesse formato.

Observe as imagens seguintes e compreenderá perfeitamente como o valor da variável dataPost é formado.

Exemplo do valor da variável dataPost ao cadastrar

Exemplo do valor da variável dataPost ao editar

Na linha 144, temos o já familiar método send() do objeto XMLHttpRequest. Porém, desta vez ele não terá null como dados e sim a variável dataPost.

Ao clicarmos no botão cujo ID foi atribuído como btnCancelar (sim o botão do tipo reset do formulário) iremos executar uma função. Ela então chamará a função removerDivs() que é utilizada para remover a div - bgBody (que simula o fundo sobre o body) e a div - boxCad (que armazena o formulário).


A função focusNome(), como demonstrado na imagem abaixo, simplesmente concede um foco ao campo nome do formulário ou aborta a função caso tal campo não exista na página - linha 157.

Função focusNome()


A validação dos dados de preenchimento obrigatório do formulário é feita pela função validarForm().

Vejamos:

Função validarForm()

Iniciamos com uma condição - linha 162 - que aborta a função validarForm() se o objeto cujo atributo ID possuir o valor frmCad não presente na página.

Em seguida, criamos as variáveis nome, ddd, telefone e email. Todas terão como valor os respectivos campos do formulário em questão.

Sendo assim, verificaremos se tal campo está vazio ou nulo como exemplificado na imagem acima, linha 167.

Se tal verificação for verdadeira, ou seja, o campo está nulo ou vazio, exibiremos uma mensagem ao usuário através de um "alert box". Assim, colocamos o foco no campo que apresentou o erro e atribuímos um return false, afinal há erro com o campo em questão.

Para validarmos o campo de e-mail, realizamos uma validação mais apurada a fim de garantirmos que o e-mail informado tenha um estrutura válida.

Com essa intenção, criamos a variável verificaEmail e informamos que ela terá como valor a resposta que a função validaEmail() retornará. A função validaEmail() retorna true se o e-mail tiver uma estrutura válida e false se não tiver.

Como podemos observar na linha 183, estamos verificando se o e-mail não tem uma estrutura básica, e se isto ocorrer, alertamos o usuário, colocamos o foco no campo de e-mail e atribuímos um return false.

Se tudo ocorrer bem, ou seja, os dados foram informados como desejávamos, atribuímos um return true.

Lembre-se que a função btnOkBtnCancelar() verifica se a função validarForm() retornou true para prosseguir com o cadastro ou a edição.


Observe essa função abaixo:

Função validaEmail()

Ela retorna true se o e-mail informado pelo usuário tiver uma estrutura válida ou false se não tiver.


A função atualizaRelatorio() a este ponto desta unidade acabou tornando-se íntima nossa. Vejamos:

Função atualizaRelatorio()

Como já a conhecemos, o compreendimento dela será um exercício para você. Calma, basta você observar outras duas funções acima - ativarBtnCadastro() e btnOkbtnCancelar(). Vale ainda ressaltar a linha 206, que chama a função removerDivs() (que conheceremos mais em frente) e a chamada da função ativarBtnEditarBtnExcluir() na linha 208 (que conheceremos agora).


A função ativarBtnEditarBtnExcluir() como o próprio nome já diz, ativa os botões contidos na página que foram desenvolvidos para tais objetivos - editar e excluir - a partir da leitura da marcação HTML da página.

Observe a função:

Função ativarBtnEditarBtnExcluir()

Observe a linha 216 e verá que iniciamos selecionando todos os links contidos na página, ou melhor, todas as tags a, afinal elas foram utilizadas para desempenharem o papel como botão de edição e exclusão dos contatos da nossa agenda. Já na linha 217 realizamos um loop entre todos os links presentes na página.

Na linha 219, atrbuímos à variável atributoRel o valor do atributo rel da tag a. Repara que definimos tal valor como uma string - new String() - para que pudéssemos utilizar o método substring() posteriormente.

As tags a que nos interessam, são aquelas que possuem no atributo rel o valor btnEditar ou btnExcluir, assim, verificaremos se tal valor consta no referido atributo.

Na linha 220, utilizamos o método substring(0,9) pois btnEditar contém 9 caracteres. Então, se os 9 primeiros caracteres do atributo rel forem igual a btnEditar, podemos presseguir com o processo de edição.

Atribuímos uma função quando tal link ou tag receber um click - onclick - e em seguida criamos a variável ID que terá como valor o ID que está contido também no atributo rel da tag a.

Para ficar mais claro, vamos relembrar a estrutura do atributo rel. Vejamos:

rel="btnEditar-10"

Baseado em tal estrutura, utilizarei o "-" para separar os valores e pegar somente o valor do ID que preciso. Para isso, utilizamoso o split('-') que divide uma string em arrays de strings, bastando simplesmente informar um delimitador, em nosso caso o "-". E, como o ID será o segundo do array e esse inicia-se com 0 (zero), utilizamos split('-')[1] para pegar o valor do ID. Observe a linha 222.

Em seguinda, chamamos duas conhecidas funções: exibirBgBody() e boxCad(). Logo após, temos mais códigos conhecidos e íntimos nossos, que abordamos na função ativarBtnCadastro(). A única diferença está presente na linha 227, onde informamos ao método open a URL que será requisitada.

Como se trata de um processo de edição, informamos na URL o seguinte:

formulario.php?ajax=true&editar=true&ID=' + ID

Dessa forma, definimos a variável editar na URL e atribuímos à variável ID, o ID que pegamos no atributo rel do link. Assim, a página formulario.php saberá que se trata de um processo de edição e quais os dados que serão editados.

Agora precisamos desenvolver o processo para exclusão dos arquivos via Ajax. Repare que na linha 245 estamos verificando se o atributo rel contém btnExcluir, assim como fizemos na linha 220. Entretando, ao invés de utilizarmos substring(0,9), utilizamos substring(0,10), pois btnExcluir contém 10 caracteres.

Na linha 248, criamos a variável confirma, que exibirá ao usuário uma mensagem de confirmação de exclusão e retornará true se ele clicar em Ok ou false se clicar em Cancel. Verificamos esse retorno na linha 249 para que possamos prosseguir com o processo somente se o usuário confirmar a exclusão, ou seja, clicar no botão ok.

A partir da linha 250, estamos diante de códigos conhecidos sabemos o que eles fazem e o por que estão ali.

Mais uma vez a diferença encontra-se ao informamos o método openà URL que será requistada.

Como desta vez será um processo de exclusão, temos o seguinte na linha 251.

actions.php?ajax=true&excluir=true&ID=' + ID

Assim, informamos que o processo será de exclusão - excluir=true - e juntamente, o ID do registro na tabela a ser excluído.


Vamos observar a função removerDivs() abaixo:Função removerDivs()

Ela tem a função de remover duas div que criamos: bgBody e boxCad. A primeira que simula o fundo sobre o body e a segunda que é utilizada para colocarmos o formulário dentro dela.

Na linha 271 removemos a div cujo ID foi definido como bgBody. Agora, para removermos a div cujo ID foi definido como boxCad na linha 273, precisamos conferir se tal div realmente existe. Para isso, vamos observar a linha 272.

Mas, por quê isso? Simples, porque no processo de exclusão não chamamos a função boxCad() para que tal div seja criada. Observe a linha 255 da função ativarBtnEditarBtnExcluir() e verá que somente a função exibirBgBody() foi chamada.


Nossa última função a ser abordada, getPageSize(), é uma função desenvolvida pelo web developer Peter-Paul Koch editor do excelente Quirksmode.

Vamos observar a função abaixo e reparar na linha 316.

Função getPageSize()

Essa função nos retorna um array com as seguintes informações: largura da página, tamanho da página, largura da janela e tamanho da janela.

Essas informações são muito utéis em certos casos, a exemplo de como foram utilizadas na função exibirBgBody(), onde precisávamos criar uma div que ocupasse todo o "viewport" do browser.


É isso, esse é o nosso projeto final.

Na próxima unidade faremos algumas considerações.

Até lá!