CRUD em AdvPL ASP – Parte 02

Introdução

No post anterior (CRUD em AdvPL ASP – Parte 01), montamos um controle de login, usando um formulário em AdvPL ASP, e uma variável de seção (HTTPSESSION). E, para servir de base para a continuação do CRUD, foram publicados uma sequência de posts para abordar o “básico” do AdvPL ASP:

Agora, vamos começar a montar a interface em HTML e JavaScript para montar as funcionalidades da Agenda via WEB.

Design da Interface

Poderíamos usar algum framework Web, por exemplo o THF – Totvs Html Framework , mas por hora vamos fazer a tela usando o arroz-com-feijão das páginas WEB com AdvPL ASP, e de quebra ver um pouco mais sobre como as coisas funcionam por dentro, e ver algumas alternativas de desenvolvimento. A interface da agenda está sendo desenhada originalmente para ter um layout muito parecido com o layout do programa original, que roda pelo SmartClient.

A ideia é que a interface HTML permita realizar todas as operações a partir da mesma tela, porém cada operação que requer atualização de dados desta tela deve submeter uma requisição via POST para o Web Server, que receberá novamente a tela inteira para executar a ação desejada.

Atualização de Páginas

Nos primórdios da Internet, navegar em qualquer Web Site na Internet construído com HTML, não tinha a possibilidade de alteração ou atualização dinâmica de conteúdo. Imagine um Web Site com um layout de menu lateral, com vários links e opções, uma área de topo ou Header com um logotipo e algumas informações sobre a parte do site que você está navegando, e uma área de conteúdo mostrando duas ou três notícias. Caso você clicasse em um link para ver a próxima página de notícias, a tela inteira é apagada e recarregada, com os mesmos menus laterais, a mesma área de topo, e uma página nova de notícias.

Isso acabava tornando pesada a navegação em alguns Web Sites. Com a possibilidade de criação de páginas de FRAMES em HTML —  acho que a partir do Internet Explorer 4 — você poderia definir um lay-out com frames — por exemplo um superior, um lateral e um central, onde a carga de uma página de notícias apenas recarregava uma página do frame, colocando as notícias desejadas.

Com as melhorias feitas no JavaScript, e sendo possível alterar dinamicamente o conteúdo de um HTML já desenhado na tela do Web Browser, vários Web Sites usavam um frame “escondido” na tela, onde através dele era feita uma requisição de uma nova página. Nesta página, que na verdade não era visível — frame escondido — era carregado um JavaScript retornado pelo Web Server, para atualizar dinamicamente o conteúdo da página sendo mostrada no frame de conteúdo — esse sim visível — sem a necessidade de recarregar (ou fazer REFRESH) da página inteira.

Algum tempo depois, foram descobertas vulnerabilidades nos navegadores Web relacionados ao uso de Frames, que poderiam mascarar um Web Site malicioso que poderia usar o JavaScript para interagir — e roubar dados e credenciais por exemplo — com frames de outros domínios, e a mecânica de atualização dos Frames tornava mais complicado desde o desenvolvimento do site, até a usabilidade do usuário — como usar o botão Voltar do Browse ou mesmo fazer um BookMark.

AJAX – Seus problemas terminaram

Mais melhorias e implementações foram feitas no JavaScript, e surgiu  o AJAX  —  Asynchronous Javascript And XML. NA verdade, este recurso é a união de duas funcionalidades: Primeira, uma função assíncrona do JavaScript foi criada para enviar ou solicitar informações para um Web Server, sem a necessidade de recarga da página atual. E, quando o Web Server retornar os dados solicitados (não necessariamente precisa ser um XML, pode ser usado texto plano, JSON, …), um JavaScript é acionado para processar os dados da requisição, que podem ser usados para atualizar o conteúdo HTML da página sendo atualmente exibida ao usuário.

Vamos pegar por exemplo o FACEBOOK — Uma vez que você  entra no seu “Feed de Notícias”, a URL permanece a mesma, e conforme você vai rolando a tela para baixo, usando a barra de rolagem do lado direito do Browse, ou mesmo o botão “Scroll” presente hoje até nos modelos mais simples de Mouse, novos posts vão sendo trazidos para a sua tela, sem a necessidade de repintar a tela inteira.

É claro que podemos usar AJAX com AdvPL ASP, inclusive vamos abordar este assunto mais para a frente, no decorrer do desenvolvimento do CRUD em AdvPL ASP, por hora estamos entrando neste assunto para fins informativos e didáticos.

Página AdvPL ASP da AGENDA

Sem mais delongas, vamos ver como está a primeira versão — ainda não funcional, mas apresentável — da interface AdvPL ASP da Agenda — futuro arquivo “agenda.aph”

<!DOCTYPE html>
<html>
<head>
<meta charset="ANSI">
<title>Agenda em AdvPL ASP</title>
<style>
.agbutton {
display: inline-block;
text-decoration : none;
width: 120px;
height: 18px;
background: rgb(240, 240, 240);
text-align: center;
color: black;
padding-top: 4px;
}
.agget { 
display: block;
width: 110px;
height: 22px; 
color: black; 
padding-top: 6px; 
text-align: right;
}
.aginput { 
width: 320px;
height: 22px; 
color: black; 
padding-top: 0px; 
padding-right: 10px; 
text-align: left;
}
</style>
</head>

function doLogoff() { 
var f = document.getElementById("F_AGENDA"); 
f.action="/logoff.apw"
f.submit();
};

<body style="font-family:Courier New;font-size: 12px;background-color:rgb(128,128,128);">

<table align="left">
<tr>

<!-- Primeira Tabela - Opções e Imagem 3x4 -->
<td align="left" valign="top">
<table>
<tr><td><a class="agbutton" href="?Op=1">Incluir</a></td></tr>
<tr><td><a class="agbutton" href="?Op=2">Alterar</a></td></tr>
<tr><td><a class="agbutton" href="?Op=3">Excluir</a></td></tr>
<tr><td style="height: 22px;">&nbsp;</td></tr>
<tr><td><a class="agbutton" href="javascript:void(0)" onclick="doLogoff()">Sair</a></td></tr>
<tr><td style="height: 22px;">&nbsp;</td></tr>
<tr><td><img style="width: 120px;height: 160px;" src="./images/Agenda_3x4.png"></td></tr>
</table>
</td>

<!-- Segunda Tabela - Mais Opções -->
<td align="left" valign="top">
<table>
<tr><td><a class="agbutton" href="?Op=4">Primeiro</a></td></tr>
<tr><td><a class="agbutton" href="?Op=5">Anterior</a></td></tr>
<tr><td><a class="agbutton" href="?Op=6">Próximo</a></td></tr>
<tr><td><a class="agbutton" href="?Op=7">Último</a></td></tr>
<tr><td><a class="agbutton" href="?Op=8">Pesquisa</a></td></tr>
<tr><td><a class="agbutton" href="?Op=9">Ordem</a></td></tr>
<tr><td><a class="agbutton" href="?Op=10">Mapa</a></td></tr>
<tr><td><a class="agbutton" href="?Op=11">G-Mail</a></td></tr>
<tr><td><a class="agbutton" href="?Op=12">Foto 3x4</a></td></tr>
</table>
</td>

<!-- Terceira Tabela - Dados do Contato -->
<td align="left" valign="top"> 
<form id="F_AGENDA" action="#" method="post">
<table style="border-spacing: 1px; background: rgb(192,192,192);">
<tr><td colspan="2" style="width: 500px; height: 22px; color: white; padding-top: 4px; background: rgb(0,0,128);">&nbsp;Ordem ...</td></tr>
<tr><td class="agget">ID</td> <td class="aginput"><input id="I_D" type="text" name="ID" disabled size="6" ></td></tr>
<tr><td class="agget">Nome</td> <td class="aginput"><input id="I_NOME" type="text" name="NOME" disabled size="50" ></td></tr>
<tr><td class="agget">Endereço</td> <td class="aginput"><input id="I_ENDER" type="text" name="ENDER" disabled size="50" ></td></tr>
<tr><td class="agget">Complemento</td><td class="aginput"><input id="I_COMPL" type="text" name="COMPL" disabled size="20" ></td></tr>
<tr><td class="agget">Bairro</td> <td class="aginput"><input id="I_BAIRRO" type="text" name="BAIRRO" disabled size="30" ></td></tr>
<tr><td class="agget">Cidade</td> <td class="aginput"><input id="I_CIDADE" type="text" name="CIDADE" disabled size="40" ></td></tr>
<tr><td class="agget">UF</td> <td class="aginput"><input id="I_UF" type="text" name="UF" disabled size="2" ></td></tr>
<tr><td class="agget">CEP</td> <td class="aginput"><input id="I_CEP" type="text" name="CEP" disabled size="9" ></td></tr>
<tr><td class="agget">Fone 1</td> <td class="aginput"><input id="I_FONE1" type="text" name="FONE1" disabled size="20" ></td></tr>
<tr><td class="agget">Fone 2</td> <td class="aginput"><input id="I_FONE2" type="text" name="FONE2" disabled size="20" ></td></tr>
<tr><td class="agget">e-Mail</td> <td class="aginput"><input id="I_EMAIL" type="text" name="EMAIL" disabled size="40" ></td></tr>
<tr>
<td class="agget">&nbsp;</td>
<td>
<a class="agbutton" id="btnConfirm" href="?Op=13">Confirmar</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
<a class="agbutton" id="btnVoltar" href="?Op=14">Voltar</a>
</td>
</tr>
</table>
</form>

</td>
</tr>
</table>

</body>
</html>

Por hora, o resultado da apresentação desta tela no Web Browse pode ser visto abaixo:

Web Agenda 2

Ainda não há conteúdo dinâmico, as ações dos botões ainda estão sendo escritas, e a foto mostrada na tela é o arquivo “Agenda_3x4.png”, que por hora precisa estar dentro de uma pasta chamada “images” a partir da pasta raiz de publicação WEB (No caso do meu ambiente, a pasta images deve estar dentro do Path especificado na seção HTTP).

Pontos de Atenção

  • Por se tratar de uma rotina de consulta dinâmica, não há interesse em manter ou permitir que sejam feitos “BookMarks” das operações da Agenda, mesmo a de consulta. Por isso, boa parte das operações desta rotina vão requisitar o próprio link da agenda.apw passando parâmetros usando POST, e para isso os campos INPUT do formulário. E, inclusive, existe um tipo de campo INPUT que pode ser usado dentro do código HTML, mas que não é mostrado para o usuário, permitindo submeter valores adicionais dentro da requisição POST feita pelo Web Browse, onde podemos por exemplo usar JavaScript para colocar valor nestes campos. Veremos isso em detalhes no decorrer desta sequência de posts.
  • Mesmo que o JavaScript possa nos permitir colocar algumas validações no lado do Web Browse, como não submeter uma página com campos obrigatórios faltando, ou até mesmo implementar algumas verificações de consistência, não devemos confiar cegamente que isto será respeitado. Isto é, como qualquer script retornado ao Web Browse pode e vai ser interpretado pelo mesmo, qualquer um com um pouco de maldade no coração pode abrir uma interface de desenvolvedor no Web Browse, alterar ou desligar dinamicamente uma validação da página em questão, e burlar a validação ou consistência do lado do Client. Logo, sempre critique os dados vindos do Browse, pois eles não necessariamente podem vir da forma que você está esperando. Quer um exemplo simples? Você cria uma página de busca de itens em uma loja virtual, e permite no Browse que o cliente escolha receber os dados em páginas de 10, 20 ou 50 registros, e exige que o usuário informe um termo de busca com pelo menos três letras. Estes parâmetros são enviados junto da requisição de busca, que no servidor monta uma Query no banco, e limita os resultados baseado no número de linhas por página informado. Se esta validação estiver apenas no lado do cliente, um cidadão com más intenções pode burlar esta validação, e submeter uma busca pela letra “A”, estipulando um tamanho de página de  30 mil registros. Pronto, o Web Server vai disparar uma Query contra o banco de dados que vai retornar um volume medonho de registros, e o Web Server vai sofrer pra montar uma página de retorno que pode passar de 1 MB para retornar isso ao Browse.
  • Para evitar dores de cabeça desnecessárias, independente da metodologia ou ferramental aplicado, procure conhecer e seguir o principio “Keep It Simple” — MANTENHA SIMPLES — valorização da simplicidade e descarte de toda a complexidade desnecessária.

Conclusão

Devagar a gente chega lá. Fazer uma tela de login com dois campos é moleza… agora fazer uma tela com atualização dinâmica de um cadastro de 11 campos, 14 opções e uma foto 3×4, vamos por partes.

Referências

 

Uma resposta em “CRUD em AdvPL ASP – Parte 02

  1. Pingback: CRUD em AdvPL ASP – Parte 03 | Tudo em AdvPL

Deixe um comentário