Ajax: Requisições HEAD

Postado por Plinio Cruz em 9 de maio de 2009 na categoria AJAX, Programação | Seja o primeiro a comentar

É nóis di novo, apresentando mais um daqueles recursos que você vai achar extremamente interessante, mas não vai achar uso nenhum para ele. Falo das requisições to tipo HEAD em Ajax. Elas tem utilidade sim, mas você vai ter que por a cabeça pra pensar pra conseguir achar alguma.

O que é uma requisição HEAD?

Em uma requisição do tipo HEAD, oição do tipo HEAD, o servidor apenas retorna as linhas de cabeçaletorna as linhas de cabeçalho (os headers) de um arquivo qualquer. Isso quer dizer que podemos descobso quer dizer que podemos descobrir o Content-Type, ou Last-Modified de um arquivo sem precisar receber todo ele.

Qual é a utilidade disso tudo? Não muita, concordo. Mas pense. Temos um arquivo extremamente grande para ser retornado. Devemos atualizar ele a um certo tempo, mas não precisamos disso se sua última modificação foi antes da primeira requisição. Fazemos uma requisição HEAD, descobrimos isso, e retornamos tudo aquilo apenas se precisarmos. Redundante, pouco prático, mas ainda assim é útil.

Fazendo a tal requisição

Para fazermos a “tal requisição”, precisamos de um objeto XMLHttpRequest já setado. Mas antes de colocar a mão na massa, veja o que pode ser o cabeçalho de um arquivo:

HTTP/1.1 200 OK
Server: Microsoft-IIS/4.0
Cache-Control: max-age=172800
Expires: Sat, 06 Apr 2002 11:34:01 GMT
Date: Thu, 04 Apr 2002 11:34:01 GMT
Content-Type: text/html
Accept-Ranges: bytes
Last-Modified: Thu, 14 Mar 2002 12:06:30 GMT
ETag: "0a7ccac50cbc11:1aad"
Content-Length: 52282

Veja bem: você conhece (e talvez usou, em Ajax mesmo) alguns desses headers. Até creio que seja possível retorna-los mesmo em uma requisição GET ou POST, mas não vem ao caso.

Para retornarmos um header individual, utilizamos o método getResponseHeader(strName), e para retornarmos todos os headers podemos usar getAllResponseHeaders(). Um exemplo mais prático:

// Eis o mistério resolvido
xmlhttp.open("HEAD", "http://qualquer.lugar.com", false);
// Usei uma requisição síncrona, pra não precisar tratar dos readyStates
xmlhttp.send("");
alert(xmlhttp.getAllResponseHeaders());

Facinho, não? Eu disse, o difícil é achar utilidade, mas se você tem uma mente engenhosa ou estilo dominador-global-ou-genérico-maluco, você vai achar…

Julio Greff – Programador e Desenvolvedor de Web

Formulários com XAJAX

Postado por Plinio Cruz em 20 de março de 2009 na categoria AJAX, PHP, Programação | Seja o primeiro a comentar

Olá Pessoal. Obrigado pelos comentários e pelos e-mails recebidos nas últimas semanas. Neste artigo iremos estudar como enviar as informações de vários campos em nosso formulário, para nossa função PHP, sem que haja um submit.

No artigo anteior vimos podemos fazer isso utilizando-se comando em javascript que pegam o conteúdo(value) do campo e passa para função, mas temos que concordar que se nosso formulário tiver uma quantidade grande de campos isso fica inviável, já que a quantidade de parametros na chamada da função xajax_() irá ficar enorme. O XAJAX então tem uma função para contornar isso: xajax.getFormValues(‘formID’).

Esta função pega todos os campos com seus valores atuais e retorna um array com essas informações. Após isso é só tratar esse array e extrair as informações que são de nosso interesse. Vamos ao exemplo.

Interface do formulário form.php
 

form.php

<?php
require “./library/xajax/xajax_core/xajax.inc.php”;
require “./library/validacoes.php”;
?>
<head>
<meta http-equiv=”Content-Type” content=”text/html; charset=iso-8859-1″ />
<title>FORMULÁRIOS COM XAJAX – PARTE 2</title>
<?php ajax->printJavascript(‘./library/xajax/’); ?>
</head>
<body>
    <form id=”form” name=”form” method=”post” action=”">
       <table width=”300″ border=”0″ align=”center” cellpadding=”1″ cellspacing=”1″>
          <tr>
             <td colspan=”2″><p>FORMULÁRIOS COM XAJAX – PARTE 2</p>
                 <p>Validado o formulário </p></td>
          </tr>
          <tr>
             <td width=”73″>nbsp;</td>
             <td width=”220″><label id=”resultado”></label></td>
          </tr>
          <tr>
              <td align=”right”>Nome:</td>
              <td><input name=”nome” type=”text” id=”nome” size=”25″ maxlength=”50″ /></td>
          </tr>
          <tr>
               <td align=”right”>Sexo:</td>
               <td><input name=”sexo” type=”radio” value=”Masculino”>
                   Masculino
                   <input name=”sexo” type=”radio” value=”Feminino”>
                   Feminino </td>
          </tr>
          <tr>
                <td align=”right”>E-Mail:</td>
                <td><input name=”email” type=”text” id=”email” size=”25″ maxlength=”75″ /></td>
          </tr>
          <tr>
                <td align=”right”>Telefone:</td>
                <td><input name=”telefone” type=”text” id=”telefone” size=”25″ maxlength=”75″ /></td>
          </tr>
          <tr>
                <td>nbsp;</td>
                <td><input name=”btn” type=”button” value=”Enviar Dados”=”xajax_enviarDados(xajax.getFormValues(‘form’));”/></td>
          </tr>
       </table>
</form>
</body>
</html>


Nesse formulário com o name = “form”, nós temos 4 campos, com os respectivos name’s:

-> nome

-> email
-> sexo

-> telefone
Linha 42

-> Essa é a linha na qual tem a chamada da função xajax_enviarDados(xajax.getFormValues(‘form’));, onde a função xajax.getFormValues(‘form’) irá pegar todos os campos e valores e retornar esse array de informações para uma variável que está lá na nossa função em PHP, que veremos a seguir.

validacoes.php

<?php
ajax = new xajax();

// Registra as funções no javascript
ajax->registerFunction(“enviarDados”);

// FUNÇÕES JAVASCRIPT REGISTRADAS PELO XAJAX

function enviarDados(formData){

// Instancia o objeto XAJAX response com
// codificação padrão ISO-8859-1
objResponse = new xajaxResponse(‘ISO-8859-1′);

// Inicializa a variável de resultado
res = “”;

// Cria uma variável para cada campo
// com o nome do ID do campo, ex.: nome, email
foreach(formData as chave => valor){
chave = valor;
}

// Verifica os campos e atribui strings a res
if(nome == false)
res .= “Preencha o campo nome<br />\n”;
if(sexo == false)
res .= “Selecione um sexo<br />\n”;
if(email == false)
res .= “Preencha o campo e-mail<br />\n”;
if(telefone == false)
res .= “Preencha o campo telefone<br />\n”;

// Verifica res
if(empty(res))
res = “<font color=green>Formulário preenchido com sucesso!</font>”;
else
res = “<font color=red>”.res.”</font>”;

// Atribui a variável res ao label resultado
objResponse->assign(‘resultado’, ‘innerHTML’, res);

// Retorna a resposta de XML gerada pelo
// objeto do xajaxResponse
return objResponse;
}

// Manda o ajax processar os pedidos acima
ajax->processRequest();
?>

Linhas 2 e 5

-> Instânciamos o objeto do XAJAX e registramos a função enviarDados no XAJAX;

Linha 11

-> Declaramos a função enviarDados, e no parametro a variável formData quer irá receber o array com todos os campos e informações do formulário;

Linha 15

-> Instancia o objeto XAJAX response com codificação padrão ISO-8859-1;

Linhas 19 a 21

-> Com um foreach() nós percorremos o array formData e criamos as variáveis de cada campo do formulário, com nomes iguais ao dos campos. Conseguimos isso utilizando o recurso de “”, mais conhecido como variável da variável.

-> formData['nome'] = “André Luiz”;

-> Olhem isso! ‘nome’ é uma chave (índice) da variável formData, e ‘André Luiz’ um valor dentro da chave (índice) ‘nome’.

-> Então isso: chave = valor;, seria o mesmo que: nome = ‘André Luiz’; Todos concordam? Se não concorda, leia tudo de novo! Isso é feito para todos os campos do formulário.

Linhas 24 a 40

-> Nestas linhas fazemos somente a verificação se os campos estão vázios e montamos na variável res a mensagem de resposta;

Linha 43

-> Atribuimos a variável res ao label resultado;

Linhas 47 a 52

-> Finalizamos o código com as respostas processadas.

Espero que tenha esclarecido algumas dúvidas. Para baixar o código desse artigo clique aqui. Nos próximos artigos iremos tratar mais funções de resposta, como o assign.

Um abraço!
 

André Rodrigues

Analista desenvolvedor de sites e sistemas web com o Grupo Host-Up.com

 

Ilustrações retiradas do artigo original do site www.imasters.com.br

Gerenciador de Arquivos com Ajax e ASP.Net

Postado por Plinio Cruz em 10 de outubro de 2007 na categoria AJAX, ASP, Programação | Seja o primeiro a comentar

Olá pessoal! Primeiramente gostaria de agradecer o grande retorno por parte dos leitores de meu último artigo, que tem enviado sugestões e até implementado mais o código. É realmente gratificante saber que meus textos estão ajudando.

Hoje irei abordar algo menos comum, mas que considero bem interessante. Iremos começar a desenvolver um Gerenciador de Arquivos em ASP.net utilizando o Magic Ajax. Este é um artigo um pouco mais avançado, e destina-se à quem tenha um mínimo conhecimento em .Net e Orientação a Objetos.

Para quem ainda não conhece o MagicAjax, ele é um framework open-source quem visa facilitar a implementação de AJAX nas aplicações ASP.net. Em junho eu escrevi um artigo aqui no iMasters falando sobre ele. Clique aqui para ler este artigo.

. Antes de mais nada, visite o link e veja o exemplo on-line:
. Ou baixe o código fonte do artigo:

Iremos utilizar um controle DataList para exibir os dados na página. Isso irá facilitar muito nossa vida.
Então vamos começar.

01. Adicionando o MagicAjax

Faça o download do MagicAjax e copie a dll para a pasta Bin do novo site. Em seguida, crie um arquivo Web.Config (ou altere o atual) com as seguintes tags:

<?xml version="1.0"?>
<configuration>
<system.web>
<customErrors mode="Off"/>
<compilation debug="false"/>
<httpModules>
<add name="MagicAjax" type="MagicAjax.MagicAjaxModule, MagicAjax"/>
</httpModules>
</system.web>
</configuration>

Isto é necessário para utilizar o MagicAjax em nossas páginas.

02. Classes do gerenciador de arquivos

Para facilitar as coisas, nossa aplicação será Orientado à Objetos.

Criaremos uma classe chamada Arquivo que irá conter os dados de cada arquivo ou pasta que será mostrada.

Iremos também criar uma classe chamada Gerenciador que será responsável por obter uma lista com os arquivos e subdiretórios de uma determinada pasta. Estas duas classes estarão no arquivo Arquivo.vb.

02.1. A Classe Arquivo

Crie um arquivo chamado Arquivo.vb e adicione o código abaixo. Essa classe contém 7 propriedades essenciais que serão utilizadas no decorrer do artigo. Apesar do nome da classe ser “Arquivo”, ela recebe tanto arquivos quanto diretórios. Para diferenciar, temos a propriedade Tipo.

Essa classe também tem uma função que diz qual será o ícone do arquivo. Coloquei os arquivos mais básicos. Você provavelmente vai querer adicionar ícones para outros tipos de arquivos, e verá que é bem fácil.

Public Class Arquivo 
Private _Nome As String
Private _Caminho As String
Private _Tamanho As String
Private _Icone As String
Private _DataCriacao As Date
Private _DataAlteracao As Date
Private _Tipo As TipoArquivo
'Nome do arquivo. Ex.: imagem.jpg
Public Property Nome() As String
Get
Return _Nome
End Get
Set(ByVal value As String)
_Nome = value
End Set
End Property
'Caminho completo do arquivo. Ex.: c:\inetpub\walteram\imagem.jpg
Public Property Caminho() As String
Get
Return _Caminho
End Get
Set(ByVal value As String)
_Caminho = value
End Set
End Property
'Tamanho do arquivo em kBytes
Public Property Tamanho() As String
Get
Return _Tamanho
End Get
Set(ByVal value As String)
If IsNumeric(value) Then
'Aqui convertemos para KB.
'Você poderia dar um tratamento mais detalhado para mostrar MB, KB, GB, etc,
'de acordo com cada situação.
_Tamanho = Math.Ceiling(CInt(value) / 1024).ToString & " KB"
Else
_Tamanho = value
End If
End Set
End Property
'Ícone do arquivo
Public Property Icone() As String
Get
Return _Icone
End Get
Set(ByVal value As String)
_Icone = AcharIcone(value)
End Set
End Property
'Data da criação do arquivo
Public Property DataCriacao() As Date
Get
Return _DataCriacao
End Get
Set(ByVal value As Date)
_DataCriacao = value
End Set
End Property
'Data da última alteração do arquivo
Public Property DataAlteracao() As Date
Get
Return _DataAlteracao
End Get
Set(ByVal value As Date)
_DataAlteracao = value
End Set
End Property
'Tipo. Pode ser pasta ou arquivo
Public Property Tipo() As TipoArquivo
Get
Return _Tipo
End Get
Set(ByVal value As TipoArquivo)
_Tipo = value
End Set
End Property
'Retorna o caminho do ícone de acordo com a extensão
Private Shared Function AcharIcone(ByVal Extensao As String) As String
Select Case Extensao
Case ".gif", ".peg", ".jpe", ".jpg", ".png"
Return "images/IconesArquivos/imagem.gif"
Case ".txt"
Return "images/IconesArquivos/texto.gif"
Case ".htm", ".xml", ".xsl", ".css", ".html", ".config"
Return "images/IconesArquivos/html.gif"
Case ".mp3", ".wav", ".wma", ".au", ".mid", ".ram", ".rm", ".snd", ".asf"
Return "images/IconesArquivos/audio.gif"
Case ".zip", "tar", ".gz", ".rar", ".cab", ".tgz"
Return "images/IconesArquivos/zip.gif"
Case ".asp", ".wsh", ".js", ".vbs", ".aspx", ".cs", ".vb"
Return "images/IconesArquivos/script.gif"
Case "pasta"
Return "images/IconesArquivos/pasta.gif"
Case Else
Return "images/IconesArquivos/generico.gif"
End Select
End Function
Public Enum TipoArquivo
Arquivo
Diretorio
End Enum
End Class

02.2. A Classe Gerenciador

No mesmo arquivo, adicione o código abaixo. Esta é a classe Gerenciador. Esta classe tem dois métodos compartilhados.

A função Obter recebe o nome de uma pasta e retorna uma lista de seus arquivos e subpastas. Note que essa lista não é um simples Array. Trata-se de uma Lista do tipo arquivo, uma Collection (coleção).
Coleções são parecidos com arrays. A diferença é que as coleções possui funcionalidades muito úteis, e são ótimas para trabalhar com dados complexos. Uma coleção pode ser uma Lista (List), uma Pilha (Stack), uma Fila (Queue), etc. Neste caso, utilizamos uma Lista.

Quando a função Obter é chamada, criamos uma nova lista de subdiretórios e arquivos de uma determinada pasta. Utilizamos o namespace System.IO do .Net, que fornece operações no sistema de arquivos.

A classe também possui um procedimento chamado Ordenar. Esse método recebe uma lista de arquivos e ordena por uma determinada propriedade. Assim, podemos ordenar a lista de arquivos por Nome do arquivo, Tamanho, Data de Criação, etc.

Public Class Gerenciador
Public Shared Function Obter(ByVal Pasta As String, ByVal Ordem As String) As _ Collections.Generic.List(Of Arquivo)
'Aqui iremos criar uma Collection, baseada na classe Arquivo
Obter = New Collections.Generic.List(Of Arquivo)
'Busca todos os diretórios
Dim Item As Arquivo
For Each strPasta As String In IO.Directory.GetDirectories(Pasta)
Dim _Pasta As New IO.DirectoryInfo(strPasta)
Item = New Arquivo
Item.Caminho = _Pasta.FullName.Replace(Pasta, "")
Item.Nome = _Pasta.Name
Item.Tamanho = "-"
Item.Icone = "pasta"
Item.DataCriacao = _Pasta.CreationTime
Item.DataAlteracao = _Pasta.LastWriteTime
Item.Tipo = Arquivo.TipoArquivo.Diretorio
Obter.Add(Item)
Next
If Ordem <> "Nome" Then Ordenar(Obter, Ordem, 0)
'Busca todos os arquivos
Dim QuantPastas As Integer = Obter.Count
For Each strArquivo As String In IO.Directory.GetFiles(Pasta)
Dim _Arq As New IO.FileInfo(strArquivo)
Item = New Arquivo
Item.Caminho = _Arq.FullName.Replace(Pasta, "")
Item.Nome = _Arq.Name
Item.Tamanho = _Arq.Length.ToString
Item.Icone = _Arq.Extension
Item.DataCriacao = _Arq.CreationTime
Item.DataAlteracao = _Arq.LastWriteTime
Item.Tipo = Arquivo.TipoArquivo.Arquivo
Obter.Add(Item)
Next
If Ordem <> "Nome" Then Ordenar(Obter, Ordem, QuantPastas)
Return Obter 
End Function
'Permite ordenar uma lista de arquivos por alguma propriedade
Private Shared Sub Ordenar(ByRef Lista As Generic.List(Of Arquivo), ByVal Coluna _ 
As String, ByVal Inicio As Integer)
Dim menor As Integer, aux As Arquivo
For i As Integer = Inicio To Lista.Count - 2
menor = i
For j As Integer = i + 1 To Lista.Count - 1
If CallByName(Lista(j), Coluna, CallType.Get) < _
CallByName(Lista(menor), Coluna, CallType.Get) Then
menor = j
End If
Next
If menor <> i Then
aux = Lista(i)
Lista(i) = Lista(menor)
Lista(menor) = aux
End If
Next
End Sub
End Class

Agora a base de nossa aplicação está pronta. O próximo passo é criar a página que irá consumir estas classes.

03. Exibindo os dados

Crie um arquivo chamado Default.aspx e adicione a marcação abaixo.

<html>
<head><title>Gerenciador de Arquivos</title></head>
<body>
<form id="form1" runat="server"> 
<ajax:AjaxPanel ID="AjaxPanel1" runat="server">
<asp:HiddenField ID="PastaAtual" runat="server" />
<asp:HiddenField ID="OrdemAtual" runat="server" />
<asp:DataList ID="dlArquivos" runat="server" Width="550" OnItemCommand="dlArquivos_ItemCommand">
<HeaderTemplate>
<tr>
<td width="8%"></td>
<td width="4%"><asp:CheckBox id="chkTODOS" runat="server"/></td>
<td width="4%">
<asp:ImageButton ImageUrl="images/Icones/subir.gif" ID="cmdSubir" runat="server" 
OnClick="cmdSubir_Click" /></td>
<td width="28%">
<asp:LinkButton ID="ordem1" runat="server" OnClick="Ordenar" Text="Nome" 
CommandName="Nome"/></td>
<td width="8%">
<asp:LinkButton ID="ordem2" runat="server" OnClick="Ordenar" Text="Tamanho" 
CommandName="tamanho" /></td>
<td width="25%">
<asp:LinkButton ID="ordem3" runat="server" OnClick="Ordenar" Text="Criação" 
CommandName="DataCriacao" /> </td>
<td width="25%">
<asp:LinkButton ID="ordem4" runat="server" OnClick="Ordenar" Text="Alteração" 
CommandName="DataAlteracao" /></td> 
</tr> 
</HeaderTemplate> 
<EditItemTemplate> 
<asp:HiddenField ID="caminho" runat="server" 
Value="<%#DirectCast(Container.DataItem, Arquivo).Caminho%>" />
<asp:HiddenField ID="tipo" runat="server" 
Value="<%#DirectCast(Container.DataItem, Arquivo).Tipo%>" />
<tr> 
<td>
<asp:ImageButton CommandName="renomear" id="Renomear" 
ImageUrl="images/Icones/renomear.gif" runat="server" ToolTip="Renomear"/>
<asp:ImageButton CommandName="excluir" id="Excluir" ImageUrl="images/Icones/excluir.gif" 
runat="server" ToolTip="Excluir" OnClientClick="javascript:return confirm('Tem certeza que deseja excluir?')"/> </td> 
<td>
<asp:CheckBox ID="chkArquivo" runat="server"/></td>
<td>
<img src="<%#DirectCast(Container.DataItem,arquivo).Icone%>" /></td>
<td>
<asp:TextBox ID="txtNome" runat="server" 
Text="<%#DirectCast(Container.DataItem, Arquivo).Nome%>" CssClass="input" Width="100px" /> 
<asp:ImageButton ID="cmdOk" runat="server" CommandName="Atualizar" Text="Ok" 
ImageUrl="images/Icones/ok.gif" ToolTip="Ok"/>
<asp:ImageButton ID="cmdCancelar" runat="server" CommandName="Cancelar" Text="Cancelar" 
ImageUrl="images/Icones/cancelar.gif" ToolTip="Cancelar"/>
</td>
<td class="Padd"><%#DirectCast(Container.DataItem, Arquivo).Tamanho%></td> 
<td><%#DirectCast(Container.DataItem, Arquivo).DataCriacao%></td> 
<td><%#DirectCast(Container.DataItem, Arquivo).DataAlteracao%></td> 
</tr>
</EditItemTemplate> 
<ItemTemplate> 
<asp:HiddenField ID="caminho" runat="server" 
Value="<%#DirectCast(Container.DataItem, Arquivo).Caminho%>" />
<asp:HiddenField ID="tipo" runat="server" 
Value="<%#DirectCast(Container.DataItem, Arquivo).Tipo%>" />
<tr> 
<td>
<asp:ImageButton CommandName="renomear" id="Renomear" ImageUrl="images/Icones/renomear.gif" runat="server" ToolTip="Renomear"/>
<asp:ImageButton CommandName="excluir" id="Excluir" ImageUrl="images/Icones/excluir.gif" runat="server" ToolTip="Excluir" OnClientClick="javascript:return confirm('Tem certeza que deseja excluir?')"/>
</td> 
<td><asp:CheckBox onClick="desmarcar_chkTodos(this.checked)" ID="chkArquivo" runat="server"/></td>
<td><img src="<%#DirectCast(Container.DataItem,arquivo).Icone%>" /></td>
<td>
<asp:LinkButton CommandName="Abrir" ID="Abrir" runat="server" Text="<%#DirectCast(Container.DataItem, Arquivo).Nome%>"/>
</td>
<td><%#DirectCast(Container.DataItem, Arquivo).Tamanho%></td> 
<td><%#DirectCast(Container.DataItem, Arquivo).DataCriacao%></td> 
<td><%#DirectCast(Container.DataItem, Arquivo).DataAlteracao%></td> 
</tr> 
</ItemTemplate> 
</asp:DataList> 
</ajax:AjaxPanel>
</form>
</body>
</html>

A primeira vista, você deve ter um susto com tanto código, e tão embolado. Mas é bem simples.
Na página, temos um AjaxPanel, e dentro dele um DataList. Simples. Tudo que estiver dentro do AjaxPanel (que é um web control do MagicAjax) irá agir de forma assíncrona.

O código acima está sem estilos. No download você encontrará a página já formatada.

Cada linha do Datalist irá ter dois campos ocultos, com o nome do ítem (nome.txt) e seu tipo (arquivo|pasta).

O Datalist tem 3 seções que você deve dar atenção:

01. Header (Cabeçalho): É onde estão os links de ordenação e um botão para subir um nível nas pastas. Ele tem também um checkbox para selecionar todos.

02. EditItemTemplate: Esta seção é mostrada quando clicamos para renomear algum arquivo ou pasta.

03. ItemTemplate: Esta é a seção mais importante do datalist. É onde irão aparecer os arquivos e pastas.

A função DirectCast tem o mesmo efeito da função CType, mas faz uma conversão direta para a classe Arquivo, sendo por isso muito mais rápida.

04. Populando o Datalist

Iremos agora fazer a ligação dos dados com o datalist. Para isso, adicione o código abaixo no topo da página Default.aspx. Pra facilitar sua vida o código está bastante comentado.

<%@ Page Language="VB" ResponseEncoding="ISO-8859-1" culture="pt-BR"%>
<%@ Assembly Src="Arquivo.vb" %>
<%@ Import Namespace="Arquivo" %>
<%@ Register Assembly="MagicAjax" Namespace="MagicAjax.UI.Controls" TagPrefix="ajax" %>
<script runat="server">
 
'Aqui iremos definir à partir de qual pasta o usuário tem acesso
'Neste caso, eu usei uma pasta sugestivamente chamada 'Aquivos que o usuário pode mexer'
Private PastaBase As String = "Aquivos que o usuário pode mexer"
 
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs)
'Quando a página é carregada pela
'primeira vez abre na pasta base
If Not Page.IsPostBack Then 
Bind(PastaBase, "Nome")
End If 
End Sub
 
Protected Sub Ordenar(ByVal sender As Object, ByVal e As System.EventArgs)
'Quando o usuário clica em algum link de ordenação
Bind(PastaAtual.Value, DirectCast(sender, LinkButton).CommandName)
End Sub
 
Protected Sub cmdSubir_Click(ByVal sender As Object, ByVal e As _ System.Web.UI.ImageClickEventArgs)
'Sobe um nível Bind(IO.Directory.GetParent(Server.MapPath(PastaAtual.Value)).FullName.Replace(Server.MapPath(".") & "\", "").Replace(Server.MapPath("."), ""), OrdemAtual.Value)
End Sub 
Protected Sub Bind(ByVal Pasta As String, ByVal Ordem As String)
'Esta rotina fará a ligação dos dados do Repeater. 
'Aqui certificamos que um usuário esperto não tentará ir para um diretório 
'acima da pasta base
If Not Server.MapPath(Pasta).Contains(PastaBase) Then Pasta = PastaBase
PastaAtual.Value = Pasta
OrdemAtual.Value = Ordem
Try
dlArquivos.DataSource = Gerenciador.Obter(Server.MapPath(Pasta), Ordem)
Catch
dlArquivos.DataSource = Gerenciador.Obter(Server.MapPath(PastaBase), Ordem)
End Try
dlArquivos.DataBind()
End Sub
Protected Sub dlArquivos_ItemCommand(ByVal source As Object, ByVal e As _ System.Web.UI.WebControls.DataListCommandEventArgs) 
If e.Item.ItemType = ListItemType.Item Or _ 
e.Item.ItemType = ListItemType.AlternatingItem Or _ 
e.Item.ItemType = ListItemType.EditItem Then
'Ocorre quando o usuário clica nos botões Abrir, Renomear, Excluir, Ok ou Cancelar
Dim Caminho As String = DirectCast(e.Item.FindControl("caminho"), HiddenField).Value
Dim Tipo As Arquivo.TipoArquivo = CDbl(DirectCast(e.Item.FindControl("tipo"), _
HiddenField).Value) 
Select Case e.CommandName.ToLower
Case "abrir"
If Tipo = TipoArquivo.Diretorio Then
Bind(PastaAtual.Value & "\" & Caminho, OrdemAtual.Value)
Else
Response.Redirect("download.aspx?arquivo=" & _
Server.MapPath(PastaAtual.Value & "\" & Caminho).Replace("\", "\\"))
End If
Case "renomear"
dlArquivos.EditItemIndex = e.Item.ItemIndex
Bind(PastaAtual.Value, OrdemAtual.Value) 
Case "excluir"
If Tipo = TipoArquivo.Diretorio Then
IO.Directory.Delete(Server.MapPath(PastaAtual.Value & "\" & Caminho))
Else
IO.File.Delete(Server.MapPath(PastaAtual.Value & "\" & Caminho))
End If
Bind(PastaAtual.Value, OrdemAtual.Value)
Case "atualizar" 'ok 
Try 
If DirectCast(e.Item.FindControl("txtNome"), TextBox).Text.Trim <> "" And Server.MapPath(PastaAtual.Value & "\" & DirectCast(e.Item.FindControl("txtNome"), TextBox).Text) <> Server.MapPath(PastaAtual.Value & "\" & Caminho) Then
If Not IO.Directory.Exists(Server.MapPath(PastaAtual.Value & "\" & DirectCast(e.Item.FindControl("txtNome"), TextBox).Text)) And Not IO.File.Exists(Server.MapPath(PastaAtual.Value & "\" & DirectCast(e.Item.FindControl("txtNome"), TextBox).Text)) Then
If Tipo = TipoArquivo.Diretorio Then
IO.Directory.Move(Server.MapPath(PastaAtual.Value & "\" & Caminho), Server.MapPath(PastaAtual.Value & "\" & DirectCast(e.Item.FindControl("txtNome"), TextBox).Text))
Else
IO.File.Move(Server.MapPath(PastaAtual.Value & "\" & Caminho), Server.MapPath(PastaAtual.Value & "\" & DirectCast(e.Item.FindControl("txtNome"), TextBox).Text))
End If
dlArquivos.EditItemIndex = -1
Bind(PastaAtual.Value, OrdemAtual.Value)
Else
MagicAjax.AjaxCallHelper.WriteAlert("Já existe um arquivo ou pasta com esse nome!")
End If
Else
MagicAjax.AjaxCallHelper.WriteAlert("Digite o novo nome!")
End If
Catch ex As Exception 
MagicAjax.AjaxCallHelper.WriteAlert("Nome de arquivo inválido!" & Chr(13) & "Um nome de arquivo não pode conter nenhum dos caracteres: \ / : * ? "" < > |")
End Try
Case "cancelar"
dlArquivos.EditItemIndex = -1
Bind(PastaAtual.Value, OrdemAtual.Value)
End Select
End If
End Sub
</script>

A função mais importante desse código todo é a função Bind que faz a ligação dos dados com o DataList.

Ligamos o DataList à função Obter, explicada anteriormente. Ou seja, ligamos ele a uma Lista do tipo Arquivo. Novidade?

Você já deve estar acostumado a ligar um datalist à um DataSet, ou a um DataReader. Na verdade, o Datalist, assim como o Datagrid ou o Repeater, permite ser ligado à praticamente qualquer coisa.
Para os programadores de ASP convencional, isso tudo deve estar parecendo loucura. Poucas linguagem para Web oferecem essa flexibilidade, e uma quantidade tão grande e tão controles. Aliás, tudo nesse artigo é novo em .Net!

No código acima também já está o código para abrir, renomear e excluir itens, e para ordenar o Datalist. Por isso é tão grande.

Quando você clica para renomear um ítem, a linha tranforma-se numa EditItemTemplate, onde você poderá alterar o nome do arquivo ou pasta.

Quando você clica para abrir uma pasta, ou subir um nível, a função Bind é chamada novamente para aquela pasta. Quando você clica no linka para abrir um arquivo, é redirecionado para a página Download.aspx, que força o download do arquivo.

05. Forçando o Download de arquivos

Para finalizar, crie uma página chamada Download.aspx e adicione o código abaixo. Esta página será responsável por forçar o download de um arquivo:

<%@ Page language="VB" %>
<script language="VB" runat="server">
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs)
'Força o download do arquivo. 
'Talvez você tenha que configurar a pasta, definindo acesso 
'ao usuário 'ASPNET' para poder acessar o arquivo quando estiver testando em localhost.
Try
If _ Request.QueryString("arquivo").ToString.ToLower.Contains(Server.MapPath("Aquivos que o usuário pode mexer").ToString.ToLower) Then
Dim fs As IO.FileStream
fs = IO.File.Open(Request.QueryString("arquivo"), IO.FileMode.Open)
Dim bytBytes(fs.Length) As Byte
fs.Read(bytBytes, 0, fs.Length)
fs.Close()
Response.AddHeader("Content-disposition", "attachment; filename=" & _ IO.Path.GetFileName(Request.QueryString("arquivo")))
Response.ContentType = "application/octet-stream"
Response.BinaryWrite(bytBytes)
Response.End()
End If
Catch 
End Try
End Sub
</script>

No próximo artigo, você verá como apagar mais de um arquivo, mover, copiar, criar pastas e fazer upload. Enquanto isso, não deixe de implementar esse aí.

Bem pessoal, é isso.

O Código parece complicado, mas é bem simples. Não hesite em mandar e-mail para mim se tiver alguma dúvida. Infelizmente nem sempre dá responder na mesma hora, ou no mesmo dia, mas prometo ajudar. Continuem colaborando, enviando críticas, dúvidas e sugestões.

Um abraço.

 

 

Walter Amorim
Visite o site do colunista: http://www.walteram.com.br

AJAX com ASP.Net – Criando uma aplicação em poucos minutos

Postado por Plinio Cruz em na categoria AJAX, ASP, Programação, Tutorial | Seja o primeiro a comentar

Olá pessoal! Neste artigo iremos abordar de forma prática um assunto muito na moda. Trata-se do AJAX. O AJAX (Asynchronous Javascript and XML) é uma metodologia antiga para acesso assíncrono a páginas Web. Ele já vem sendo utilizado arduamente há anos por programadores ASP, PHP e etc, utilizando uma mistura de JavaScript e XML.

Tentarei mostrar como ASP.Net simplifica (e muito) a implementação de AJAX em suas páginas.

Simplificando, as linguagens de programação Web (como ASP, PHP e até mesmo ASP.net) são processadas no servidor. Isso significa que cada vez que o usuário clica em um botão, a página é enviada de volta ao servidor, e recarregada. A utilização do AJAX permite que esse processamento seja assíncrono, evitando que a página seja recarregada, dando ao usuário uma sensação muito mais confortável. É uma ferramenta maravilhosa, quando bem utilizada.

O exemplo mais bem sucedido que conheço da utilização de AJAX é o Gmail. Quando você navega pelo Gmail, as páginas não são diretamente carregadas. Ao invés disso, é mostrada uma mensagem na lateral superior direita, informando que a página está sendo carregada e enquanto isso podemos continuar a usá-la.

Vamos criar uma aplicação bem simples, para inclusão, exclusão e acesso à dados de uma Lista Telefônica, com nome, cidade, e-mail e telefone. Um exemplo simples, pra que você entenda o funcionamento do Ajax.

Antes de começar, veja aqui o exemplo rodando e baixe aqui o código completo.

Irei utilizar a biblioteca MagicAjax, que, na minha opinião, é a mais fácil de usar, e é OpenSource. Você pode baixá-la em http://www.magicajax.net. Usarei o Visual Web Developer 2005 (.Net 2.0), mas nada impede que você codifique manualmente.

1 – Configurando o MagicAjax em nossa aplicação

Pois bem. Baixe o MagicAjax e copie para a pasta de sua aplicação as pastas “bin” e “core”. Na pasta bin está o arquivo MagicAjax.dll, a biblioteca que usaremos para construir nossa aplicação, e na pasta core estão os scripts usados pelo MagicAjax.

Primeiramente, temos que definir em nossa aplicação que iremos utilizar a biblioteca do MagicAjax. Isso é feito através de algumas linhas de código no Web.config.

Então, crie um arquivo chamado Web.config e neste arquivo, digite o código abaixo:

<?xml version="1.0"?>
<configuration>
       <configSections>
             <section name="magicAjax" type="MagicAjax.Configuration.MagicAjaxSectionHandler, MagicAjax"/>
       </configSections>
       <magicAjax scriptPath="~/Core/Script" outputCompareMode="HashCode" tracing="false">
             <pageStore mode="NoStore" unloadStoredPage="false" cacheTimeout="5" maxConcurrentPages="5" maxPagesLimitAlert="false"/>
       </magicAjax>
       <system.web>
             <httpModules><add name="MagicAjax" type="MagicAjax.MagicAjaxModule, MagicAjax"/>
             </httpModules>
             <customErrors mode="Off"></customErrors></system.web></configuration>

2 – Criando o arquivo de dados

Agora, crie o arquivo XML/XSD que irá conter nossos dados, chamado “dados.xml”. Iremos usar os dados provenientes desse arquivo. Nada impede que você use um banco de dados. No arquivo dados.xml, copie o texto abaixo:

<?xml version="1.0" standalone="yes"?>
<Content xmlns="http://tempuri.org/Content.xsd">
  <xs:schema id="Content" targetNamespace="http://tempuri.org/Content.xsd" xmlns:mstns="http://tempuri.org/Content.xsd" xmlns="http://tempuri.org/Content.xsd" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" attributeFormDefault="qualified" elementFormDefault="qualified">
    <xs:element name="Content" msdata:IsDataSet="true" msdata:Locale="en-US">
      <xs:complexType>
        <xs:choice minOccurs="0" maxOccurs="unbounded">
          <xs:element name="Lista">
            <xs:complexType>
              <xs:sequence>
                <xs:element name="ID" msdata:ReadOnly="true" msdata:AutoIncrement="true" type="xs:short" />
                <xs:element name="nome" type="xs:string" minOccurs="0" default=""/>
                <xs:element name="cidade" type="xs:string" minOccurs="0" default=""/>
                <xs:element name="email" type="xs:string" minOccurs="0" default=""/>
                <xs:element name="telefone" type="xs:string" minOccurs="0" default=""/>                
              </xs:sequence>
            </xs:complexType>
          </xs:element>
        </xs:choice>
      </xs:complexType>
    </xs:element>
  </xs:schema>
  <Lista>
    <ID>1</ID>
    <nome>Walter V. S. de Amorim</nome>
    <cidade>Barra Mansa/RJ</cidade>
    <email>nao.faca.spam@walteram.com.br</email>
    <telefone>(24)9999-0000</telefone>
  </Lista>
  <Lista>
    <ID>2</ID>
    <nome>Fulano</nome>
    <cidade>Volta Redonda/RJ</cidade>
    <email>teste@teste.com</email>
    <telefone>(21)9990-0123</telefone>
  </Lista>   
</Content>

Os detalhes do arquivo XML não são importantes. São apenas os dados usados por nossa aplicação.

3 – Exibindo os dados

Agora crie um arquivo chamado “default.aspx”. Essa página irá exibir os dados provenientes do arquivo XML criado, através de um DataGrid, e nos permitirá filtrar os itens.

No arquivo, copie o código abaixo:

<%@ Page Language="VB" %>
<%@ Import Namespace="System.Data" %>
<%@ Register Assembly="MagicAjax" Namespace="MagicAjax.UI.Controls" TagPrefix="ajax" %>
<script runat="server">
    Private Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Load
        If Not Page.IsPostBack Then CarregarDados()
    End Sub
 
    Private Sub CarregarDados()
        'Cria um dataset, e lê os dados do arquivo dados.xml.
        'Você poderia também carregar de um banco de dados, da 
        'mesma forma como está acostumado.
        Dim ds As New DataSet
        ds.ReadXml(Server.MapPath("dados.xml"), XmlReadMode.ReadSchema)        
        'Filtra os dados, se houver algum texto no campo de filtro.
        ds.Tables(0).DefaultView.Ro                         
wFilter = "nome like '%" & txtFiltrar.Text & "%' or cidade like '%" & txtFiltrar.Text & "%'"
        dg.DataSource = ds.Tables(0)
        dg.DataBind()        
    End Sub
 
    Private Sub dg_Command(ByVal sender As System.Object, ByVal e As System.Web.UI.WebControls.DataGridCommandEventArgs)
        If e.CommandName.ToLower = "excluir" Then
            'Rotina responsável por excluir um ítem        
            'Pega o código do ítem
            Dim IDItem As Long = e.Item.Cells(0).Text.ToString
            'Cria um dataset, lê os dados e acha o ítem a apagar
            Dim ds As New DataSet
            ds.ReadXml(Server.MapPath("dados.xml"), XmlReadMode.ReadSchema)
            ds.Tables(0).DefaultView.RowFilter = "ID=" & IDItem
            'Se achar o ítem, apaga
            If ds.Tables(0).DefaultView.Count > 0 Then ds.Tables(0).DefaultView.Delete(0)
            'Salva o dataset no arquivo
            ds.WriteXml(Server.MapPath("dados.xml"), XmlWriteMode.WriteSchema)
            'Carrega os dados
            CarregarDados()
        ElseIf e.CommandName.ToLower = "detalhes" Then
            'Abre os detalhes do ítem escolhido
            Dim IDItem As Long = e.Item.Cells(0).Text.ToString
            MagicAjax.AjaxCallHelper.Redirect("editar.aspx?id=" & IDItem)
        End If
    End Sub
 
    Protected Sub CapturarTecla_KeyUp(ByVal sender As Object, ByVal e As MagicAjax.UI.Controls.KeyEventArgs)
        'Toda vez que uma tecla for pressionada, em qualquer controle
        'dentro deste container, este evento será carregado.
        CarregarDados()
    End Sub
</script>
 
<html>
<head runat="server"><title>Mostrando os Dados</title>
</head>
<body>
    <form id="form1" runat="server">
        <ajax:AjaxPanel ID="AjaxPanel1" runat="server">
            <!--Tudo que estiver dentro do controle AjaxPanel
                irá funcionar com os recursos do MagicAjax.-->
            <ajax:KeyClientEventWrapper ID="CapturarTecla" runat="server" OnKeyUp="CapturarTecla_KeyUp">
                <!--Dentro do AjaxPanel temos um KeyClientEventWrapper 
                    que irá capturar todas as teclas digitadas.-->
                Filtrar:
                <asp:TextBox ID="txtFiltrar" runat="server"></asp:TextBox>
            </ajax:KeyClientEventWrapper>
            <!--Dentro do AjaxPanel temos também um DataGrid, que irá exibir os dados -->
            <asp:DataGrid ID="dg" runat="server" Width="520px" AutoGenerateColumns="False" OnItemCommand="dg_Command">
                <Columns>
                    <asp:BoundColumn DataField="Id" HeaderText="Cód." />
                    <asp:BoundColumn DataField="nome" HeaderText="Nome" />
                    <asp:BoundColumn DataField="cidade" HeaderText="Cidade" />                    
                    <asp:ButtonColumn ButtonType="LinkButton" Text="Ver + " CommandName="Detalhes" />
                    <asp:ButtonColumn ButtonType="LinkButton" Text="Excluir" CommandName="Excluir" />
                </Columns>
            </asp:DataGrid>
            <br />
     <a href="adicionar.aspx">
         Para Adicionar um ítem, clique aqui.
     </a>
        </ajax:AjaxPanel>        
    </form></body></html>

Salve a página e execute-a. Você verá o seguinte:

Imagem

Tente digitar algum texto no campo “Filtrar”. Você verá que os dados serão filtrados sem recarregar a página.

Observe também que quando você faz o filtro, ou exclui um item, aparece um pequeno quadro com o texto “Loading”, no canto superior direito, bem parecido com o que acontece com o Gmail:

Imagem

Mais à frente, você verá como alterar o texto “Loading”.

O código da página, como você pode ver, não tem nada de incrível, à não ser por dois pequenos trechos. O primeiro, no início da página, é:

<%@ Register Assembly="MagicAjax" Namespace="MagicAjax.UI.Controls" TagPrefix="AJAX" %>

Nesta linha registramos os controles do MagicAjax. Assim podemos usar todos os recursos dessa biblioteca.

Um outro trecho importante:

<AJAX:AjaxPanel ID="AjaxPanel1" runat="server">
  <AJAX:KeyClientEventWrapper ID="CapturarTecla" runat="server" OnKeyUp="CapturarTecla_KeyUp">
Filtrar: <asp:TextBox ID="txtFiltrar" runat="server"></asp:TextBox>
  </AJAX:KeyClientEventWrapper>
  <asp:DataGrid ID="dg" runat="server" Width="520px" AutoGenerateColumns="False" OnItemCommand= "dg_Command">
       ... 
  </asp:DataGrid>
</AJAX:AjaxPanel>

Neste trecho, utilizamos o AjaxPanel para controlar os eventos de nossa aplicação. Tudo que estiver dentro desse controle irá atuar sobre as regras do MagicAjax. E tudo que estiver fora do AjaxPanel, irá atuar da forma normal.

Dentro desse controle está o KeyClientEventWrapper. Este outro controle, que também vêm com a biblioteca MagicAjax, é responsável por capturar as teclas digitadas. Dentro dele temos um TextBox comum. Quando uma tecla é digitada neste TextBox, o KeyClientEventWrapper chama a função CapturarTecla_KeyUp, que carrega os dados novamente.

Dentro do AjaxPanel está também o DataGrid, que exibe os dados e permite-nos excluir um item. O DataGrid tem ainda um link para editar os dados. Essa será a próxima etapa.

Em nosso caso, usamos os controles AjaxPanel e KeyClientEventWrapper. Sugiro que você consulte a documentação do MagicAjax (disponível no download) que contém uma explicação geral de cada controle disponível na biblioteca.

Você pode ver que é bem simples implementar o AJAX em suas páginas. Tudo que tem que fazer é colocar seus controles dentro da tag AjaxPanel.

4 – Alterando os Dados da Lista Telefônica

A próxima etapa em nosso exemplo é criar a página que irá nos possibilitar a edição dos dados. Nesta, como você verá, não há nada de extraordinário.

Crie uma página chamada “editar.aspx”, e nela cole o código abaixo.

<%@ Page Language="VB" Debug="true" %>
<%@ Import Namespace="System.Data" %>
<%@ Register Assembly="MagicAjax" Namespace="MagicAjax.UI.Controls" TagPrefix="ajax" %>
<script runat="server">
    Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs)
        'Carrega os dados do arquivo
        If Not Page.IsPostBack Then
            'Cria um dataset, e lê os dados do arquivo dados.xml.
            Dim Codigo As Long = Request.QueryString("id")
            Dim ds As New DataSet, dr As DataRow
            ds.ReadXml(Server.MapPath("dados.xml"), XmlReadMode.ReadSchema)
            'Filtra os dados
            ds.Tables(0).DefaultView.RowFilter = "id =" & Codigo.ToString
            'Se achar o item, coloca nos textboxes
            If ds.Tables(0).DefaultView.Count > 0 Then
                dr = ds.Tables(0).DefaultView.ToTable.Rows(0)
                lblCodigo.Text = dr.Item("id")
                txtNome.Text = dr.Item("nome")
                txtCidade.Text = dr.Item("cidade")
                txtEmail.Text = dr.Item("email")
                txtTelefone.Text = dr.Item("telefone")
            End If
        End If
    End Sub
 
    Protected Sub cmdSalvar_Click(ByVal sender As Object, ByVal e As System.EventArgs)
        'Salva os dados no arquivo
        Dim Codigo As Long = Request.QueryString("id")
        Dim ds As New DataSet
        ds.ReadXml(Server.MapPath("dados.xml"), XmlReadMode.ReadSchema)
        For i As Integer = 0 To ds.Tables(0).Rows.Count - 1
            If ds.Tables(0).Rows(i).Item("id") = Codigo Then
                ds.Tables(0).Rows(i).Item("nome") = txtNome.Text.ToString
                ds.Tables(0).Rows(i).Item("cidade") = txtCidade.Text.ToString
                ds.Tables(0).Rows(i).Item("email") = txtEmail.Text.ToString
                ds.Tables(0).Rows(i).Item("telefone") = txtTelefone.Text.ToString
                ds.WriteXml(Server.MapPath("dados.xml"), XmlWriteMode.WriteSchema)
                Exit For
            End If
        Next
        'Redireciona para a página de exibição.
        'Note que usamos a função redirect própria do MagicAjax.
        'Você pode usar o habitual Response.Redirect
        MagicAjax.AjaxCallHelper.Redirect("default.aspx")
    End Sub
    Protected Sub cmdCancelar_Click(ByVal sender As Object, ByVal e As System.EventArgs)
        'Ao cancelar, simplesmente redireciona para a página de exibição.
        MagicAjax.AjaxCallHelper.Redirect("default.aspx")
    End Sub
</script>
<html>
<head runat="server"><title>Editando os Dados</title></head>
<body>
    <form id="form1" runat="server">
        <table>
            <tr>
                <td>Código:</td>
                <td><asp:Label ID="lblCodigo" runat="server"></asp:Label></td>
            </tr>
            <tr><td>Nome:</td>
                <td><asp:TextBox ID="txtNome" runat="server" Width="245px" /></td>
            </tr>
            <tr><td>Cidade:</td>
                <td><asp:TextBox ID="txtCidade" runat="server" /></td>
            </tr>
            <tr><td>E-mail:</td>
                <td><asp:TextBox ID="txtEmail" runat="server" /></td>
            </tr>
            <tr><td>Telefone:</td>
                <td><asp:TextBox ID="txtTelefone" runat="server" Width="80px" /></td>
            </tr>
            <tr><td></td>
                <td>
                    <ajax:AjaxPanel ID="AjaxPanel1" runat="server">
                        <asp:Button ID="cmdSalvar" runat="server" OnClick="cmdSalvar_Click" Text="Salvar" />
                        <asp:Button ID="cmdCancelar" runat="server" Text="Cancelar" OnClick="cmdCancelar_Click" />
                    </ajax:AjaxPanel>                                            
                </td>                    
            </tr>
        </table>
    </form></body></html>

Novamente, utilizamos o AjaxPanel. Mas, desta vez, apenas nos botões Salvar e Cancelar.

Você deve ter notado que utilizamos a função MagicAjax.AjaxCallHelper.Redirect. Esta função atua de forma quase que idêntica ao Response.Redirect, mas utiliza Ajax. A biblioteca MagicAjax possui diversas funções interessantes, como essa.

5 – Adicionando Dados à Lista

A última etapa em nossa pequena aplicação é criar a página onde poderemos adicionar dados.
Então, crie uma página chamada “adicionar.aspx” e cole o código abaixo:

<%@ Page Language="VB" Debug="true" %>
<%@ Import Namespace="System.Data" %>
<%@ Register Assembly="MagicAjax" Namespace="MagicAjax.UI.Controls" TagPrefix="ajax" %>
<script runat="server">
    Protected Sub cmdSalvar_Click(ByVal sender As Object, ByVal e As System.EventArgs)
        'Salva os dados no arquivo
        Dim ds As New DataSet, dr As DataRow
        ds.ReadXml(Server.MapPath("dados.xml"), XmlReadMode.ReadSchema)
        dr = ds.Tables(0).NewRow
        dr.Item("nome") = txtNome.Text.ToString
        dr.Item("cidade") = txtCidade.Text.ToString
        dr.Item("email") = txtEmail.Text.ToString
        dr.Item("telefone") = txtTelefone.Text.ToString
        ds.Tables(0).Rows.Add(dr)
        ds.WriteXml(Server.MapPath("dados.xml"), XmlWriteMode.WriteSchema)
        'Redireciona para a página de exibição.
        'Note que usamos a função redirect própria do MagicAjax.
        'Você pode usar o habitual Response.Redirect
        MagicAjax.AjaxCallHelper.Redirect("default.aspx")
    End Sub
    Protected Sub cmdCancelar_Click(ByVal sender As Object, ByVal e As System.EventArgs)
        'Ao cancelar, simplesmente redireciona para a página de exibição.
        MagicAjax.AjaxCallHelper.Redirect("default.aspx")
    End Sub
</script>
<html>
<head runat="server">
    <title>Adicionando Dados</title>
</head>
<body>
    <form id="form1" runat="server">
        <table>
            <tr><td>Nome:</td>
                <td><asp:TextBox ID="txtNome" runat="server" Width="245px" /></td>
            </tr>
            <tr><td>Cidade:</td>
                <td><asp:TextBox ID="txtCidade" runat="server" /></td>
            </tr>
            <tr><td>E-mail:</td>
                <td><asp:TextBox ID="txtEmail" runat="server" /></td>
            </tr>
            <tr><td>Telefone:</td>
                <td><asp:TextBox ID="txtTelefone" runat="server" Width="80px" /></td>
            </tr>
            <tr>
                <td></td>
                <td>
                    <ajax:AjaxPanel ID="AjaxPanel1" runat="server">
                        <asp:Button ID="cmdSalvar" runat="server" OnClick="cmdSalvar_Click" Text="Salvar" />
                        <asp:Button ID="cmdCancelar" runat="server" Text="Cancelar" OnClick="cmdCancelar_Click" />
                    </ajax:AjaxPanel>                                            
                </td>                    
            </tr>
        </table>
    </form>
</body>
</html>

6 – Alterando o texto “Loading”

Conforme prometi, irei mostrar como alterar o texto “Loading”. Pois bem. Abra o arquivo “AjaxCallObject.js” (dentro da pasta core/script). Lá no final do arquivo (+- linha 1051), você verá o código:

function CreateWaitElement() {
var elem = document.getElementById('__AjaxCall_Wait');
if (!elem) {
elem = document.createElement("div");
elem.id = '__AjaxCall_Wait';
elem.style.position = 'absolute';
elem.style.height = 17;
elem.style.paddingLeft = "3px";
elem.style.paddingRight = "3px";
elem.style.fontSize = "11px";
elem.style.fontFamily = 'Arial, Verdana, Tahoma';
elem.style.border = "#000000 1px solid";
elem.style.backgroundColor = "DimGray";
elem.style.color = "#ffffff";
elem.innerHTML = 'Loading ...'; 
elem.style.visibility = 'hidden';
document.body.insertBefore(elem, document.body.firstChild);
}
waitElement = elem;
}
// end wait element

Altere o texto (por exemplo, para ‘Aguarde…’). Você pode também definir a cor de fundo, altura, borda, e etc.
Quando terminar, salve o arquivo e execute novamente. Pronto:

Imagem

7 – Concluindo

É isso aí. Agora você está pronto pra começar a desenvolver suas próprias aplicações em Ajax.
Como você viu, tudo que tem de fazer é definir o Web.Config, registrar o MagicAjax no topo das páginas que for usar, e colocar os seus controles dentro do AjaxPanel. Simples, não?!

Nos próximos artigos irei me aprofundar mais nesse assunto tão importante. E por hoje é só. Não deixe de baixar o exemplo e brincar um pouco. E em caso de dúvidas, mande um e-mail.

Um Abraço!

Walter Amorim

Ajax com a Mootools

Postado por Plinio Cruz em 2 de outubro de 2007 na categoria AJAX, Programação | Seja o primeiro a comentar

 

Sempre gostei de escrever minhas próprias funções para meus scripts, e nunca havia usado uma biblioteca JavaScript (não que eu não tenha tentado). Elas nunca se adaptavam ao que eu queria. Até o lançamento da Mootools 1.11, o qual ouvi falarem muito bem. Resolvi testar.

Motools é uma biblioteca JavaScript orientada a objetos, muito modular, compacta e, na minha opinião, muito simples de usar (não tanto quanto a jQuery, foi por isso que gostei). Nesse post vou explicar como fazer as requisições assíncronas, vulgo Ajax.

Fazendo o Download

Vá em http://mootools.net, e faça o download da biblioteca. Escolha os módulos que achar necessário para usos futuros, mas inclua os seguintes: Core, Function, Array, String, Element e Ajax (sério?). Também escolha a compressão que quiser.

Feito isso, crie uma nova página, e inclua o script.

Uma Requisição Simples

Vamos fazer uma simples requisição, sem retorno algum, bastando informar ao servidor que alguma coisa aconteceu. A base para o uso de Ajax é a classe Ajax (isso mesmo, é assim que os construtores são chamados aqui, por serem baseados em um construtor Class, da própria biblioteca). Ela cria a requisição, mas não a executa. Essa parte fica a cargo do método request. Vamos ao código:

var options = { "method": "get" };
var ajaxReq = new Ajax("http://localhost/informa_servidor", options).request();

A classe possui apenas dois parâmetros que podem ser passados: url (String) e options (Object). Vamos ver todas mais adiante. Setei apenas "method", pois o método padrão na biblioteca é POST. Um bug que encontrei: se você definer o método como “GET” em vez de “get”, a biblioteca tratará como sendo POST. Ou seja, use sempre letras minúsculas.

Atualizando um Objeto

Mais uma grande facilidade da Mootools (não que as outras também não tenham): não precisamos, necessariamente, criar uma função para ser executada quando a requisição for completada, podemos apenas definir um objeto a ser atualizado. Isso pode ser feito através da opção update (String ou Object). Mais um código:

var options = { "method": "get", "update": "elementoPraAtualizar" };
var ajaxReq = new Ajax("http://localhost/retorna_resposta", options);

Essa seria uma maneira de retornar uma resposta “estática” do servidor, já que não enviamos nenhum dado junto com a requisição. Aí entra a opção data (String, nesse caso), que levará a query string juntamente com a requisição, assim: “parametro=valor&outro=valor”.

A opção data, além de uma query string, pode ser um objeto ou um elemento <form>. A biblioteca se encarrega de transforma-los em query string, seja para envio pelo método GET ou POST. Legal, né? Outro exemplo:

var queryString = { "id": userId, "action": "getName" };
var options = { "method": "get", "update": "algumElemento", "data": queryString };
var ajaxReq = new Ajax("http://localhost/envia_query_string", options);

Função onComplete

Muitas vezes não se torna necessário tratar a resposta da requisição, bastando passa-la diretamente para um elemento. A diferença é quando os dados devem ser analisados, testados, interpretados ou qualquer coisa do gênero, ou seja, precisamos de uma função pra ser executada no final da requisição. A Mootools também permite isso através da opção onComplete. Aí fica a nosso cargo implementar toda a complexidade necessária na função. Código de novo:

var options = { "method": "get", "onComplete": onComplete };
var ajaxReq = new Ajax("http://localhost/requer_tratamento", options);
var onComplete = function(text) {
  var returnText = text.treatRequest();
  $("placeholder").empty().setHTML(returnText);
  applicationStatus = 0;
}

Como podemos ver, temos todo o controle de volta quando precisamos. Seria melhor ainda se pudéssemos ter controle sobre o XML que é enviado… Que bom, pois podemos ter controle sobre ele. Para a função do onComplete, são passados dois parâmetros: o texto e o XML. Muito bom, não?

Enviando um Formulário

Essa também é ótima. Podemos enviar um formulário inteiro com apenas um comando, que é uma extensão da classe Element disponibilizada pelo módulo Ajax. Através da função $, obtemos o formulário, e pelo método send enviamos a requisição via POST.

var formReq = $("meuForm").send();

O método send possui apenas o parâmetro options, sem URL (ela é retirada do action do formulário). As opções podem ser as mesmas de Ajax.request.

Interpretando Scripts

Todo mundo sabe que às vezes é necessário interpretar toda ou uma parte da requisição, enviada como JavaScript. A Mootools disponibiliza mais duas opções para esses casos: evalScripts e evalResponse (ambos Boolean).

Através de evalScripts, a biblioteca interpreta todos os scripts da requisição que estiverem entre as tags <script>. Caso o header recebido seja “text/javascript” ou “text/ecmascript”, toda a requisição é interpretada.

Já a opção evalResponse é mais generalista. Mesmo que seu header seja “text/html”, “text/xml” ou qualquer outra coisa, toda a requisição será interpretada. Não interessa o tipo de conteúdo. Parece ambíguo, mas as duas opções têm seu uso real.

Lembrando: as duas opções interpretam os scripts no escopo global.

Tá certo que esse módulo tem seus defeitos. Aquele bug do “GET” que eu falei acima, a falta de um controle sobre os stateChanges, que foi retirado nessa versão, enfim. Mas isso não torna a biblioteca menos útil.

E vou ficando por aqui. Até!

Julio Greff

Programador e Desenvolvedor de Web

Switch to our mobile site