Chicken possui uma
extensão interessante para desenvolvimento para a Web: o egg
ajax. Essa extensão é, na realidade, um
wrapper para a biblioteca
prototype.
O uso do egg
ajax é bem fácil depois que se entende como ele funciona. Confesso que quebrei um pouco a cabeça para começar a usá-lo, e a dificuldade foi agravada pelo fato de eu não conhecer muito bem a biblioteca
prototype na época.
Para facilitar o entendimento do egg
ajax, vale a pena mencionar um recurso interessante do egg
http: a possibilidade de definição de
recursos (
resources). Com isso, é possível associar uma URL a um procedimento que será executado no servidor. Esta colocação, embora pareça "solta" agora, é necessária para entender como o egg
ajax funciona (espero que ela venha a fazer sentido até o final deste texto...).
Uma das funções mais práticas do egg
ajax é a
remote-link
. Com ela, é possível realizar várias operações no cliente com base no resultado do procedimento executado no servidor. A seguir está um exemplo de aplicação básica de
remote-link
:
(remote-link
"Clique aqui"
(lambda ()
(print "Oi"))
update: "resultado")
remote-link
recebe três argumentos:
- O texto do link
- Uma função sem argumentos a ser executada no servidor
- O tipo de ação a ser executada no cliente e em qual elemento da página aplicar o resultado da função executada no servidor. O tipo de ação a ser executada é determinado pelo parâmetro de palavra-chave escolhido (
update
no exemplo) e o elemento a aplicar o resultado é a string associada ao parâmetro de palavra-chave (resultado
no exemplo).
O exemplo com
remote-link
, então, gera os códigos HTML e Javascript necessários para atualizar o elemento de identificador
resultado
com o texto
Oi
quando o usuário clicar no link
Clique aqui
. O código gerado é mostrado abaixo:
<a href='#' onclick="new Ajax.Updater('resultado', '/9fa328569dc39078f13e29086bbf3b93', { });">Clique aqui</a>O código Javascript gerado corresponde a criação de um objeto
Updater
da bilioteca
prototype, cujos argumentos são o identificador do elemento a ser atualizado no cliente depois da execução do procedimento associado à URL usada como segundo argumento (
/9fa328569dc39078f13e29086bbf3b93
). Essa URL é gerada pelo egg
ajax, usando a funcionalidade de
recursos do egg
http, mencionada no início deste texto. A URL fica associada à função usada como argumento para
remote-link
.
Vamos ver um exemplo prático com o servidor web
Spiffy. São necessários os seguintes
eggs:
Os
eggs podem ser instalados da seguinte forma:
$ chicken-setup spiffy web-scheme ajax spiffy-utils
Todas as dependências serão instaladas automaticamente.
O programa para execução do servidor web está abaixo (
web-server.scm
):
(use spiffy web-scheme web-scheme-handler ajax spiffy-utils)
(spiffy-file-ext-handlers `(("ws" . ,web-scheme-handler)))
(spiffy-tcp-port 8080)
(spiffy-root-path ".")
(spiffy-debug-mode #t)
(start-server)
Para usar o egg
ajax, é necessária a biblioteca
prototype, que acompanha a extensão (o arquivo encontra-se em
CHICKEN_PREFIX/lib/chicken/3/prototype.js
, onde
CHICKEN_PREFIX
é o diretório onde o sistema Chicken foi instalado). Copie o arquivo
prototype.js
para o mesmo diretório onde foi criado o arquivo
web-server.scm
.
O arquivo para gerar a página HTML (index.ws) é mostrado abaixo:
(ws:page
(string-append
(div 'id "resultado")
(remote-link
"Clique aqui"
(lambda ()
(print "Oi"))
update: "resultado"))
additional-headers: (ajax))
Para ver o resultado, basta executar o servidor web:
$ csi -s web-server.scm
e acessar
http://localhost:8080
no seu navegador preferido (algum que tenha suporte a Javascript).
A função
ajax
usada no exemplo gera o código HTML necessário para referenciar a biblioteca
prototype na página.
Obviamente, é possível fazer algo de mais útil com isso. A seguir é mostrado um exemplo mais elaborado (
tamanho.ws
): uma aplicação que mostra em uma caixa do tipo
select
os arquivos no diretório raíz do servidor e exibe o tamanho quando são selecionados.
(use posix)
(ws:page
(string-append
(ws:select
'id "file-box"
'onchange (remote-action
(lambda ()
(let ((file (post-var "file")))
(print "Tamanho de " file " = "
(file-size file) " bytes")))
update: "resultado"
arguments: "'file=' + $F('file-box')")
(string-intersperse
(map (lambda (opt)
(option 'value opt opt))
(glob (make-pathname
(spiffy-root-path) "*")))
""))
(div 'id "resultado"))
additional-headers: (ajax))
O código acima monta uma caixa de opções (
select
de HTML) com os arquivos no diretório raíz do servidor (parâmetro
(spiffy-root-path)
) e usa
remote-action
para registrar a função que é executada no lado do servidor e executá-la quando um arquivo for selecionado na caixa de seleção.
O parâmetro de palavra-chave
arguments
especifica as variáveis a serem passadas através dos métodos GET e POST do HTTP. Se nenhum método for especificado, POST é usado (o parâmetro de palavra-chave
method
permite especificar o método a ser usado). A função
$F
em Javascript, da biblioteca
prototype, retorna o conteúdo do widget cujo identificador é passado como argumento.
Para ver a aplicação em funcionamento, acesse
http://localhost:8080/tamanho.ws
no seu navegador
Mais detalhes sobre o funcionamento do egg
ajax podem ser obtidos na documentação da extensão, em
http://www.call-with-current-continuation.org/eggs/3/ajax.html.