DESENVOLVIMENTO DE APLICAÇÕES WEB UTILIZANDO A

Transcrição

DESENVOLVIMENTO DE APLICAÇÕES WEB UTILIZANDO A
Paulo de Rezende Pinatti
0650410
DESENVOLVIMENTO DE APLICAÇÕES WEB UTILIZANDO
A ABORDAGEM AJAX
Jaguariúna
2007
Paulo de Rezende Pinatti
0650410
DESENVOLVIMENTO DE APLICAÇÕES WEB UTILIZANDO
A ABORDAGEM AJAX
Monografia apresentada à disciplina
Trabalho de Graduação III, do curso de
Ciência da Computação da Faculdade de
Jaguariúna, sob a orientação do Prof.
Peter Jandl Jr, como exigência parcial
para a conclusão do curso.
Jaguariúna
2007
PINATTI, Paulo de Rezende. Desenvolvimento de Aplicações Web Utilizando a
Abordagem Ajax. Monografia defendida e aprovada na FAJ em 10 de dezembro de
2007 pela banca examinadora constituída pelos professores:
__________________________________________
Prof. Peter Jandl Jr.
FAJ
__________________________________________
Prof. José Arnaldo Geraldini Nunes
FAJ
__________________________________________
Prof. Valdecir de Oliveira Pereira
POLICAMP
DEDICATÓRIA
Dedico esse trabalho à minha família, na qual incluo
minha noiva, pela dedicação com que fui educado e
pela maravilhosa oportunidade de partilhar sua
convivência, fatos que propiciaram me tornar a
pessoa que sou hoje. Espero durante a minha vida
ser capaz de retribuir a tudo que aprendi e ainda hoje
aprendo com eles e que contribui para a minha
formação como ser humano.
PINATTI, Paulo de Rezende. Desenvolvimento de Aplicações Web Utilizando a
Abordagem Ajax. 2007. Monografia (Bacharelado em Ciência da Computação) – Curso de
Ciência da Computação da Faculdade de Jaguariúna, Jaguariúna.
RESUMO
Desde o início da utilização da Internet para fins comerciais cresce a cada dia a quantidade
de recursos e serviços disponibilizados através da rede. As aplicações web são as
responsáveis por grande parte desses serviços, e seu modelo tradicional de funcionamento
não é capaz de atender à crescente demanda por aplicações mais funcionais e interativas,
que possam prover uma experiência de uso mais agradável ao usuário e suportar
funcionalidades que se tornam cada vez mais complexas. A utilização de um conjunto de
determinadas tecnologias com a finalidade de atender tais necessidades designa o termo
conhecido como Ajax, ou Asynchronous JavaScript + XML, estabelecendo uma nova
maneira de se desenvolver aplicações web.
O presente trabalho tem por objetivo analisar a utilização do modelo Ajax como solução a
ser adotada no desenvolvimento de aplicações web que sobreponham o modelo tradicional,
propiciando uma rica experiência de uso ao usuário. Para isso é inicialmente realizada uma
análise comparativa entre os modelos tradicional e Ajax, seguida de uma abordagem das
tecnologias empregadas como HTML, CSS, XML, DOM e JavaScript. Também é feita a
implementação de um protótipo utilizando a técnica, seguida de uma análise de seus
resultados.
Ao final do estudo são apresentadas as conclusões que consideram a abordagem Ajax
capaz de atender o objetivo especificado, as alternativas para a solução de algumas
desvantagens encontradas na adoção da técnica e também seu contexto de utilização.
Palavras-chave: Aplicações web, experiência de uso, Ajax, JavaScript.
ABSTRACT
Since the beginning of the Internet use for commercial purposes, the quantity of resources
and services offered through the network grows each day. Web applications are responsible
for a huge part of these services, and its traditional working model is not capable of satisfying
the increasing demand for more functional and interactive applications that can provide a
more pleasant use experience to the user and support functionalities that become more and
more complex. The utilization of a certain group of technologies with the purpose of
satisfying the mentioned needs designates the term known as Ajax, or Asynchronous
JavaScript + XML, establishing a new way to develop web applications.
The objective of this work is to analyze the use of the Ajax model as a solution to be adopted
for the development of web applications that overlap the traditional model, offering to the
user a rich use experience. In order to do so, at the beginning of this work it is done a
comparative analysis between the traditional and Ajax models, followed by an approach of
the technologies used such as HTML, CSS, XML, DOM and JavaScript. Also, a prototype
has been implemented employing the technique, followed by an analysis of its results.
At the end of this work, conclusions that consider the Ajax approach capable of
accomplishing the specified objective are presented, as well as alternatives for solutioning
some disadvantages found when adopting the technique and also its utilization scope.
Keywords: Web applications, use experience, Ajax, JavaScript.
6
SUMÁRIO
LISTA DE SIGLAS .......................................................................................................... 7
LISTA DE FIGURAS ....................................................................................................... 8
LISTA DE CÓDIGOS E TABELAS .................................................................................. 9
1. INTRODUÇÃO ............................................................................................................ 10
1.1 Objetivo ..................................................................................................................... 12
1.2 Estrutura do trabalho ................................................................................................ 12
2. MODELOS TRADICIONAL E AJAX DE APLICAÇÕES WEB .................................... 14
2.1 Modelo tradicional de aplicações web ...................................................................... 17
2.2 Modelo Ajax de aplicações web ............................................................................... 18
2.3 Tecnologias .............................................................................................................. 20
3. HTML/XHTML E CSS ................................................................................................. 23
3.1 O que são HTML/XHTML ......................................................................................... 24
3.2 Web Standards ......................................................................................................... 28
3.3 Cascading Style Sheets (CSS) ................................................................................. 30
4. JAVASCRIPT .............................................................................................................. 34
4.1 Sintaxe ...................................................................................................................... 35
4.2 Browser Object Model .............................................................................................. 39
4.3 Eventos ..................................................................................................................... 45
4.4 O objeto XMLHttpRequest ........................................................................................ 53
5. DOCUMENT OBJECT MODEL E XML ...................................................................... 59
5.1 Documento XML ...................................................................................................... 59
5.2 Funcionamento do DOM .......................................................................................... 64
5.3 DOM e XML na abordagem Ajax ............................................................................. 76
6. PROTÓTIPO .............................................................................................................. 82
6.1 Funcionamento e estrutura ...................................................................................... 83
6.2 Recursos .................................................................................................................. 86
6.3 Resultados ............................................................................................................... 92
7. CONCLUSÕES .......................................................................................................... 93
7.1 Frameworks ............................................................................................................. 95
7.2 Considerações finais ................................................................................................ 96
8. REFERÊNCIAS BIBLIOGRÁFICAS ........................................................................... 98
7
Lista de Siglas
Ajax -
Asynchronous JavaScript + XML
API -
Application Programming Interface
ARPAnet -
Advanced Reserch Projects Agency Network of the Departament of
Defense
ASP -
Active Server Pages
BOM -
Browser Object Model
CERN -
Conseil Européen pour la Recherche Nucléaire
CGI -
Common Gateway Interface
CSS -
Cascading Style Sheets
DOM -
Document Object Model
DTD -
Document Type Definition
ECMA -
European Computer Manufacturers Association
GPL -
General Public License
GWT -
Google Web Toolkit
HTML -
HyperText Markup Language
HTTP -
HyperText Transfer Protocol
IE -
Internet Explorer
ISO/IEC -
International Organization for Standardization and International
Electrotechnical Commission
JSON -
JavaScript Object Notation
JSP -
Java Server Pages
MIME -
Multipurpose Internet Mail Extension
PDA -
Personal Digital Assistant
PHP -
PHP: Hypertext Preprocessor
SAX -
Simple API for XML
SGML -
Standard Generalized Markup Language
URL -
Unique Resource Locator
UTF-8 -
Unicode Transformation Format-8
XHR -
XMLHttpRequest
XHTML -
Extensible HyperText Markup Language
XML -
Extensible Markup Language
XSLT -
Extensible Stylesheet Language Transformations
W3C -
World Wide Web Consortium
8
Lista de Figuras
FIGURA 1 – Exemplo de transação HTTP .................................................................... 15
FIGURA 2 – Transação HTTP com processamento do lado servidor ........................... 16
FIGURA 3 – Servidor envia ao cliente documento HTML contendo JavaScript ............ 16
FIGURA 4 – Modelo de funcionamento de uma aplicação web atual ............................ 17
FIGURA 5 – Modelo tradicional e modelo Ajax de aplicação web ................................. 19
FIGURA 6 – Relacionamento entre as tecnologias empregadas em Ajax ..................... 21
FIGURA 7 – Hierarquia de objetos no BOM ................................................................... 39
FIGURA 8 – Janelas de diálogo confirm(), prompt() e alert() ......................................... 42
FIGURA 9 – Modelo event bubbling de fluxo de evento ................................................. 48
FIGURA 10 – Modelo DOM de fluxo de evento .............................................................. 48
FIGURA 11 – Conteúdo do arquivo mensagem.txt exibido na tela ................................ 57
FIGURA 12 – Árvore de nós representando documento XML ....................................... 66
FIGURA 13 – Relação entre as principais propriedades da interface Node ................... 68
FIGURA 14 – Aplicação realizando requisição XML ....................................................... 81
FIGURA 15 – Interface do protótipo Ajax ........................................................................ 83
FIGURA 16 – Protótipo exibindo aviso de resposta em andamento ............................... 86
FIGURA 17 – Registro habilitado para edição ................................................................ 87
FIGURA 18 – Usuário cadastrando novo registro ........................................................... 88
FIGURA 19 – Links para navegação das páginas .......................................................... 88
FIGURA 20 – Registro sendo editado após busca através da aba "Procurar" ................ 89
FIGURA 21 – Aplicação usando tema azul e exibindo a aba "Configurações" ............... 90
9
Lista de Códigos e Tabelas
CÓDIGO 1 – Estrutura básica de um documento XHTML .............................................. 25
CÓDIGO 2 – Estrutura básica de um documento HTML ................................................ 27
TABELA 1 – Elementos e sua abordagem correspondente ........................................... 29
CÓDIGO 3 – Inserção de folha de estilo em documento HTML ..................................... 32
CÓDIGO 4 – Exemplo de utilização da regra @import .................................................. 32
CÓDIGO 5 – Bloco de código em JavaScript ................................................................. 36
CÓDIGO 6 – Estruturas if-else e for em JavaScript ....................................................... 36
CÓDIGO 7 – Criação e utilização de um objeto Array .................................................... 38
CÓDIGO 8 – Documento HTML usando framesets ........................................................ 40
CÓDIGO 9 – Uso do método window.open() .................................................................. 41
CÓDIGO 10 – Utilização das janelas de diálogo alert(), confirm() e prompt() ................ 42
CÓDIGO 11 – Emprego do objeto navigator para detecção do navegador em uso ....... 44
CÓDIGO 12 – Documento HTML .................................................................................... 47
CÓDIGO 13 – Atribuição de event handlers a objeto no código JavaScript ................... 49
CÓDIGO 14 – Atribuição de event handlers no Internet Explorer ................................... 49
CÓDIGO 15 – Atribuição de event handlers de acordo com o DOM .............................. 50
CÓDIGO 16 – Técnica para detecção do objeto event ................................................... 51
CÓDIGO 17 – Criação de um objeto XMLHttpRequest .................................................. 54
CÓDIGO 18 – Utilização do objeto XMLHttpRequest ..................................................... 57
CÓDIGO 19 – Documento XML representado acervo de biblioteca ............................... 60
TABELA 2 – Entidades de caractere usadas em documentos XML ............................... 62
CÓDIGO 20 – Exemplo do emprego de uma entidade de caractere .............................. 62
TABELA 3 – Suporte ao DOM pelos principais navegadores ......................................... 65
CÓDIGO 21 – Documento XML ...................................................................................... 65
CÓDIGO 22 – Tabela HTML ........................................................................................... 74
CÓDIGO 23 – Criação de tabela através do DOM HTML .............................................. 74
CÓDIGO 24 – Acesso a folha de estilo CSS através do DOM ....................................... 75
CÓDIGO 25 – Criação de documento XML em JavaScript ............................................ 77
CÓDIGO 26 – Aplicação para cadastro de nome e e-mail ............................................. 80
CÓDIGO 27 – Criação dos pares nome/valor e envio de requisição .............................. 85
CÓDIGO 28 – Documento XML contendo resposta do servidor .................................... 85
CÓDIGO 29 – Implementação da navegação pelo teclado ............................................ 87
CÓDIGO 30 – Função que implementa o recurso de mudança de tema ....................... 91
CÓDIGO 31 – Técnica para evitar armazenamento de resposta para GET .................. 91
10
1. INTRODUÇÃO
Desde o início do uso dos computadores as pessoas têm aprendido a utilizá-los de
maneira a compensar a falta de capacidade destes em entender os seres humanos. A
situação ideal seria aquela em que bastaria dizer qual tarefa deve ser realizada para que o
computador respondesse ao comando. A tecnologia, com o passar do tempo, tem evoluído
sua capacidade de ser amigável ao usuário, porém ainda existe um longo caminho a ser
percorrido e até que se alcance a situação ideal em que as pessoas se comuniquem com
computadores como se comunicam entre si, elas precisam aprender como dizer ao
computador o que querem que seja feito.
Em meio a esse processo de interação homem-máquina a interface que o software
provê exerce papel fundamental. O nível de satisfação do usuário está diretamente ligado à
qualidade da interface de utilização do software. A indústria do software aprendeu muito
neste sentido e percebeu, de acordo com Darie et al. (2006, p. 7), que “... o equivalente a
um motor potente em um carro esporte vermelho é a usabilidade e acessibilidade para o
software.”. Ícones, janelas, botões e menus corroboram essa constatação, já que se
encontram na grande maioria dos softwares existentes no mercado direcionados ao usuário
comum. Uma vez que a lucratividade dos negócios está normalmente ligada ao nível de
satisfação dos clientes, tem-se buscado proporcionar ao usuário uma experiência de
utilização cada vez melhor.
Segundo Darie et al. (2006, p. 8), o termo usabilidade de software é definido como “...
a arte de atender às necessidades dos usuários com relação à interface, entendendo a
natureza de seu trabalho e desenvolvendo software de maneira adequada.”. Técnicas de
usabilidade são historicamente utilizadas em aplicações desktop, por estas possuírem as
ferramentas necessárias para tal. Aplicações desktop possuem interatividade e usabilidade
muito melhores que aplicações web, basta utilizar um simples processador de texto ou uma
planilha de cálculo para notar a quantidade de interações que ocorrem entre o usuário e a
aplicação. Essa diferença se deve ao fato das aplicações web terem sido concebidas
originalmente para transmitir apenas textos e imagens, não funcionalidades complexas.
Além disso, aplicações web possuem problemas relativos à padronização, pois é necessário
testá-las em dois ou três navegadores diferentes para se ter certeza de que vão funcionar
corretamente. Porém, ainda assim cresce cada vez mais a utilização da web para fornecer
serviços e recursos. O motivo desse crescimento são as vantagens tecnológicas que as
aplicações web apresentam em relação às aplicações desktop:
11
− São disponibilizadas de maneira fácil e com baixo custo: um computador com
navegador web e acesso à Internet ou Intranet é o suficiente para que o usuário
possa utilizar uma aplicação web;
− São atualizadas de maneira fácil e com baixo custo: a partir do momento em que é
realizada a atualização do software localizado no servidor todos os usuários
automaticamente têm acesso à nova versão;
− Possuem
requisitos flexíveis de utilização: uma aplicação
corretamente
desenvolvida pode ser utilizada através de qualquer navegador web moderno,
independentemente da plataforma empregada pelo usuário;
− Facilitam o armazenamento de informações de maneira centralizada: quando vários
locais necessitam acessar as mesmas informações, armazená-las em um mesmo
local é mais simples do que manter bases de dados em diferentes locais,
minimizando problemas com sincronização de informações e diminuindo riscos de
segurança.
Apesar das vantagens citadas terem conferido às aplicações web grande
popularidade, seu modelo de funcionamento apresenta-se como uma barreira à questão da
usabilidade e satisfação do usuário. Gehtland (2006, p. 6) define a que se propunha a web
inicialmente: “A web teve início mais como um repositório de documentos. [...] Seu propósito
era compartilhamento de documentos e informações, sem nenhum senso significativo de
interatividade.”. Asleson e Schutta (2006, p. 3) também comentam: “... cientistas usavam a
Internet para trocar documentos de pesquisa, e universidades colocavam online informações
de aulas. O mercado ainda não tinha descoberto o que fazer com esse novo 'canal'.”. Hoje,
praticamente todo o mercado encontra-se na web e, além dos recursos e serviços
disponibilizados tornarem-se cada vez mais complexos, fornecer ao usuário uma
experiência de utilização agradável e satisfatória é fator primordial. Faz-se necessário
romper a limitação do modelo tradicional das aplicações web e aproximá-las das aplicações
desktop. Vários esforços têm sido realizados com esse objetivo e no ano de 2005 Jesse
James Garret, através de seu ensaio “Ajax: A New Approach to Web Applications” (Ajax:
Uma Nova Abordagem para as Aplicações Web), criou o termo Ajax (Asynchronous
JavaScript + XML) definindo-o como uma maneira de se desenvolver aplicações web mais
interativas, utilizando um determinado conjunto de tecnologias. A abordagem Ajax elimina a
necessidade de recarregamento e bloqueio da aplicação sempre que requisições são feitas
ao servidor (modelo síncrono) passando a enviar as requisições em segundo plano e
atualizando apenas o que é necessário, sem bloquear a aplicação (modelo assíncrono). A
proposta é sobrepor o modelo tradicional, adicionando interatividade e usabilidade às
aplicações web, tornando seu funcionamento semelhante ao das aplicações desktop. A
técnica tem sido adotada em vários sites na web, dentre os quais pode-se destacar o Gmail,
12
Google Suggest e Google Maps da Google e o mecanismo de busca A9 (www.a9.com) da
Amazon, exemplos de grandes empresas que adotaram o método para melhorar a
experiência de uso do usuário.
1.1 Objetivo
Disponibilizar recursos e interatividade através da web sempre foi uma tarefa difícil,
devido ao seu modelo de funcionamento. Tecnologias como Flash e Java Applets surgiram
com o intuito de atender tais demandas, porém apresentam certas desvantagens
(necessidade de instalação de plug-in ou máquina virtual, maior consumo de banda,
requisitos maiores de hardware) que restringem seu uso.
O objetivo do presente trabalho é realizar um estudo da empregabilidade da técnica
Ajax como opção a ser adotada no desenvolvimento de aplicações web que apresentem
melhores recursos de usabilidade, sobrepondo as limitações do modelo tradicional com a
finalidade de proporcionar ao usuário uma melhor experiência de utilização. Para isso, serão
analisadas as tecnologias que compõem esse método, seu modo de funcionamento,
vantagens e desvantagens, além da implementação de protótipo utilizando a técnica em
questão. Ao final do estudo serão apresentadas as conclusões relativas à viabilidade do
método para a finalidade proposta e possíveis observações adicionais acerca de pontos
fortes e desvantagens.
1.2 Estrutura do trabalho
No capítulo 2 será realizado um estudo comparativo entre os modelos tradicional e o
modelo Ajax de aplicações web. Características e modo de funcionamento serão analisados.
Os capítulos 3, 4 e 5 terão como conteúdo um estudo das tecnologias que compõem a
técnica Ajax. Inicialmente, no capítulo 3 serão abordadas as linguagens HyperText Markup
Language/Extensible HyperText Markup Language (HTML/XHTML), utilizadas para definir o
conteúdo e estrutura do documento web e Cascading Style Sheets (CSS), empregada para
formatação visual. No capítulo 4 será abordado o JavaScript, utilizado para a programação
dos eventos e fluxo da aplicação e o objeto XMLHttpRequest pertencente a esta linguagem,
responsável pela tarefa de realizar a comunicação assíncrona com o servidor. Além destes,
serão analisados no capítulo 5 o DOM (Document Object Model), que especifica uma
interface com o conteúdo, a estrutura e o estilo do documento e o Extensible Markup
Language (XML), utilizado como formato de dados para a troca de dados entre cliente e
servidor.
13
No capítulo 6 será apresentado um protótipo desenvolvido utilizando a metodologia
proposta, e a implementação será analisada para verificar a capacidade da técnica em
atender o objetivo determinado.
Ao final do estudo, no capítulo 7, serão feitas as conclusões acerca do tema, através
das constatações encontradas nos capítulos anteriores.
14
2. MODELOS TRADICIONAL E AJAX DE APLICAÇÕES WEB
A Internet não foi sempre como é conhecida hoje. Várias mudanças ocorreram ao
longo do tempo. No início, todas as páginas web eram estáticas. Usuários solicitavam um
recurso e o servidor o retornava. Para a grande maioria dos sites web, isso era o suficiente as páginas web não eram nada mais que cópias eletrônicas de textos. Com o tempo, a
quantidade de pessoas conectadas à rede foi aumentando e junto com ela a demanda por
experiências de utilização mais dinâmicas. Para compreender o modelo de funcionamento
das aplicações web é preciso primeiramente analisar as tecnologias e abordagens
desenvolvidas que fazem a web funcionar da maneira que é conhecida atualmente.
Conforme explicam Darie et al. (2006) em 1991 foi criado o HyperText Transfer
Protocol (HTTP), protocolo utilizado para transmitir dados pela Internet. Através deste
protocolo são transmitidos páginas web, imagens e arquivos. HTTP não é o único protocolo
existente na Internet para transmissão de dados, sua importância reside no fato de ser
utilizado para a transmissão de conteúdo web. Quando é digitado no navegador um
endereço, ou Unique Resource Locator (URL), como por exemplo www.google.com.br,
automaticamente é inserido na frente deste o "http://", assumindo que será utilizado tal
protocolo para acessar a página. O HTTP funciona dividido em duas partes: uma requisição
e uma resposta. Quando uma URL é digitada no navegador (conhecido como cliente web),
este envia uma requisição contendo o endereço digitado e algumas informações a respeito
dele próprio. O servidor web recebe a requisição e envia uma resposta, contendo
informações sobre a requisição e os dados existentes naquele endereço (caso exista). Após
receber a resposta o navegador a interpreta, exibindo a página web.
O tipo de documento padrão da web é o HyperText Markup Language (HTML), uma
linguagem compreendida, processada e exibida pelos navegadores. Sua finalidade é
descrever o formato e conteúdo do documento, que é composto basicamente de texto
estático e imagens. O navegador, ao receber a resposta de um determinado endereço,
processa esse documento HTML e o exibe. É importante salientar que o HTML não foi
concebido para disponibilizar aplicações web complexas com conteúdo interativo. Quando
se deseja acessar outro documento HTML, é necessário realizar novamente o processo de
carregamento de toda a página, enviando a requisição e processando a resposta do
servidor. A figura 1 mostra o funcionamento de uma transação quando o usuário acessa
uma página web utilizando o protocolo HTTP:
15
FIGURA 1 – Exemplo de transação HTTP.
A dupla HTTP/HTML é a base do funcionamento da web como a conhecemos hoje, e
é clara a limitação que essa combinação apresenta em relação ao que pode ser feito permite aos usuários apenas acessar conteúdo estático (documentos HTML) através da
web. Para suprir essa falta de funcionalidades, várias tecnologias têm sido desenvolvidas.
Ainda que as requisições web continuem funcionando através do protocolo HTTP, duas
alternativas se apresentam: pode-se criar os dados dinamicamente no servidor web, além
de ser possível também que esses dados contenham mais do que apenas HTML, permitindo
ao cliente executar outras funcionalidades ao invés de apenas exibir páginas estáticas.
As tecnologias que fazem uso dessas alternativas e permitem a web funcionar de
maneira melhorada são divididas em duas categorias:
− Tecnologias server-side (ou lado-servidor): são aquelas que habilitam o servidor a
utilizar lógica para construir páginas web dinamicamente;
− Tecnologias client-side (ou lado-cliente): permitem ao cliente web realizar mais
tarefas ao invés de apenas exibir documentos estáticos.
As tecnologias server-side habilitam o servidor web a realizar outras tarefas, além de
simplesmente retornar ao cliente um documento HTML solicitado, como por exemplo
cálculos complexos, programação orientada a objeto e integração com bancos de dados.
Alguns exemplos dessas tecnologias são CGI (Common Gateway Interface), PHP (PHP:
Hypertext Preprocessor), ASP (Active Server Pages), e JSP (Java Server Pages). Darie et
al. (2006) definem o processamento lado-servidor como sendo o motor que causou a
revolução da web, e a razão pela qual esta é tão útil atualmente. É importante ressaltar que,
independentemente do processamento realizado pelo servidor, a resposta é enviada em um
formato que o cliente entenda, ou seja, normalmente HTML, que possui muitas limitações
como mencionado anteriormente. A figura 2 mostra o funcionamento de uma transação em
que ocorre processamento do servidor para enviar a resposta ao cliente:
16
FIGURA 2 – Transação HTTP com processamento do lado servidor.
As tecnologias client-side ou lado-cliente têm a finalidade de solucionar a questão dos
documentos de funcionalidade limitada enviados pelo servidor web. Pode-se citar como
exemplo o Macromedia Flash, que necessita de um plug-in instalado no navegador, e os
Java Applets, que utilizam uma máquina virtual pré-instalada. Ambas são tecnologias
bastante populares, mas que normalmente são utilizadas apenas em determinados
contextos por apresentarem certas desvantagens, como a necessidade de instalação de
softwares adicionais ou maior consumo de recursos do sistema. Além destas, existe a
linguagem JavaScript, principal tecnologia client-side. Quando um cliente solicita uma
página web, o servidor envia o documento HTML contendo código JavaScript embutido, que
é interpretado e processado nativamente pelos navegadores modernos, adicionando
grandes funcionalidades às páginas web, como por exemplo verificações de formulários com
avisos para evitar erros de digitação e a necessidade de reiniciar o processo de
preenchimento. A figura 3 exibe o funcionamento de uma transação em que o servidor
realiza o processamento e envia ao cliente um documento HTML contendo JavaScript:
FIGURA 3 – Servidor envia ao cliente documento HTML contendo JavaScript.
O par HTTP/HTML, juntamente com as tecnologias server-side e client-side definem o
modelo atual de funcionamento das aplicações web.
17
2.1 Modelo tradicional de aplicações web
A partir da análise feita, é possível definir uma seqüência de passos que caracterizam
o modelo de funcionamento das aplicações web:
1. o usuário digita o endereço (ou URL) na barra de endereços do navegador;
2. o navegador (ou cliente web) envia uma requisição HTTP ao servidor, contendo o
endereço digitado e informações referentes ao próprio cliente web;
3. o servidor cria a resposta, esta contendo informações da requisição e dados
(podendo ou não para isso realizar algum tipo de processamento com tecnologia
server-side), e envia a resposta HTTP com o documento HTML (provavelmente
contendo código JavaScript embutido) para o cliente;
4. o cliente recebe a resposta e processa o documento recebido, exibindo os dados
contidos nas instruções HTML e adicionando as funcionalidades de acordo com o
código JavaScript;
5. o usuário realiza uma ação que necessita de dados do servidor, e o processo se
reinicia a partir do passo 2.
A figura 4 exemplifica o funcionamento das aplicações web atuais:
FIGURA 4 – Modelo de funcionamento de uma aplicação web atual.
Das primeiras páginas web que exibiam praticamente apenas textos até o modelo
atual, muitas mudanças aconteceram. O servidor pode gerar os dados dinamicamente,
comunicar-se com bancos de dados, além do cliente ser capaz de processar outras
funcionalidades ao invés de simplesmente exibir conteúdo HTML. Porém uma característica
permanece inalterada: o paradigma requisição/resposta. De acordo com Darie et al. (2006),
cada vez que o cliente precisa de novos dados do servidor uma nova requisição HTTP
precisa ser feita para recarregar a página, congelando a atividade do usuário. Ou seja,
sempre que o usuário executa alguma ação em que é preciso recuperar novos dados do
servidor, mesmo sendo uma ação simples, é necessário submeter uma requisição e a
aplicação fica bloqueada até que uma resposta seja recebida e processada, ocorrendo
18
então uma atualização completa da página. Durante este processo o usuário não tem
alternativa a não ser esperar, e esperar sempre que uma interação ocorre, diminuindo muito
o nível de usabilidade da aplicação. Tal característica é um fator limitador à qualidade da
experiência de utilização do usuário. Como será visto a seguir, o modelo Ajax busca
solucionar a limitação relacionada a esse paradigma.
2.2 Modelo Ajax de aplicações web
Ajax não é uma nova tecnologia, mas sim uma técnica para desenvolvimento de
aplicações web. Isso significa que neste novo modelo de funcionamento não há a adoção de
novas tecnologias, mas na verdade a utilização de um novo conceito. Zakas et al. (2006, p.
11) definem: "Ao invés do modelo tradicional de aplicações web no qual o próprio navegador
é responsável por iniciar as requisições para e processar as respostas do servidor web, o
modelo Ajax provê uma camada intermediária - chamada por Garret de motor Ajax - para
controlar essa comunicação.". Garret (2005) explica o funcionamento do motor Ajax: "Ao
invés de carregar uma página web no começo da sessão, o navegador carrega um motor
Ajax [...] esse motor é responsável tanto por desenhar a interface que o usuário vê, quanto
realizar a comunicação com o servidor representando o usuário.".
Neste modelo, o servidor - que tradicionalmente envia ao cliente documentos HTML passa a enviar dados que o motor Ajax pode utilizar, podendo ser texto puro, código XML,
HTML, ou outro formato de dados necessário. O importante neste caso é que o motor Ajax
seja capaz de interpretar e processar as informações. Por sua vez, o motor Ajax ao receber
a resposta do servidor, processa e realiza alterações na interface do usuário1 de acordo com
os dados recebidos. Devido ao fato do processo envolver transferência de uma quantidade
menor de informações do que em uma aplicação web tradicional (não é necessário
recarregar uma página inteira) as atualizações na interface do usuário são mais rápidas, e
este é capaz de fazer seu trabalho de maneira mais ágil. A figura 5 mostra a comparação
entre a estrutura dos modelos tradicional e Ajax:
1
Normalmente utilizando o DOM para acessar os elementos da interface, como será visto mais adiante.
19
FIGURA 5 – Modelo tradicional e modelo Ajax de aplicação web.
O funcionamento de uma aplicação Ajax segue a seguinte seqüência de passos:
1. o usuário digita o endereço (ou URL) na barra de endereços do navegador;
2. o navegador (ou cliente web) envia uma requisição HTTP ao servidor, contendo o
endereço digitado e informações referentes ao próprio cliente web;
3. o servidor cria a resposta, esta contendo informações da requisição e dados
(podendo ou não para isso realizar algum tipo de processamento com tecnologia
server-side), e envia a resposta HTTP com o documento HTML contendo o motor
Ajax embutido, codificado em JavaScript;
4. o cliente recebe a resposta e processa o documento recebido, exibindo os dados
contidos nas instruções HTML e habilitando o motor Ajax;
5. o usuário realiza uma ação que é recebida pelo motor Ajax. Se não há necessidade
de buscar dados no servidor, o motor faz as alterações necessárias na interface em
resposta à ação disparada. Caso contrário é feita uma requisição em segundo
plano ao servidor, sem bloquear a utilização da aplicação pelo usuário;
6. o servidor responde à requisição, enviando os dados (normalmente em XML)
necessários ao processamento do motor Ajax;
7. O motor realiza as atualizações na interface do usuário, de acordo com os dados
recebidos na resposta.
Analisando a seqüência de passos nota-se as vantagens desse modelo de
funcionamento: é possível comunicar-se com o servidor de maneira assíncrona, de forma
que enquanto o motor Ajax faz a requisição ao servidor, o usuário possa interagir com a
aplicação, sem precisar aguardar pelo processamento da resposta. Elimina-se o problema
20
presente no modelo clássico no qual o fluxo de trabalho do usuário é interrompido sempre
que este realiza uma ação, obrigando-o a aguardar o desbloqueio da aplicação enquanto a
resposta do servidor não é processada. Em certos casos, o próprio motor Ajax pode
responder à ação do usuário, sem a necessidade de realizar uma requisição ao servidor1.
Tal característica, aliada ao fato das respostas do servidor possuírem apenas os dados
necessários ao processamento do motor Ajax ao invés de uma página inteira a ser
processada pelo navegador, tornam também as aplicações muito mais ágeis.
Ajax faz uso de uma técnica conhecida como remote scripting, que permite ao cliente
realizar requisições ao servidor de forma assíncrona, ou seja, o cliente pode trocar
informações com o servidor sem a necessidade de bloquear a utilização da aplicação pelo
usuário durante o processo. Apesar do termo Ajax ser recente, remote scripting não é. Uma
das mais conhecidas, a técnica hidden IFRAME (IFRAME escondido) implementa remote
scripting e já existe há vários anos. Tal técnica consiste em utilizar uma tag IFRAME
invisível ao usuário em um documento HTML, através da qual é feita a troca de dados com o
servidor. Apesar da tag não ser destinada para esse fim e tratar-se na verdade de uma
adaptação, sua adoção é comum. Além do remote scripting, as tecnologias associadas ao
termo Ajax também não são recentes. Na realidade, a tecnologia mais recente - o objeto
XMLHttpRequest (XHR), responsável justamente pela comunicação assíncrona com o
servidor - existe desde a versão 5 do navegador Internet Explorer (IE), lançado em março de
1999. O fato recente neste cenário é o nível de suporte dos navegadores em relação ao
objeto XHR. Segundo Asleson e Schutta (2006, p. 13), “Originalmente, o objeto XHR era
suportado apenas pelo Internet Explorer (portanto limitando o seu uso), porém começando
com Mozilla 1.0 e Safari 1.2 o suporte difundiu-se.”. Neste ponto, com a proliferação de
aplicações como Google Maps, Google Suggest, Gmail, Flickr, Netflix e A9, XHR torna-se
padrão de fato e a metodologia Ajax popularizou-se.
2.3 Tecnologias
As principais tecnologias que compõem o modelo Ajax são as seguintes:
– HTML/XHTML: definição e estruturação do conteúdo a ser exibido ao usuário;
− CSS: definição de estilos visuais, a serem utilizados para formatar a exibição do
conteúdo HTML/XHTML;
− JavaScript: linguagem de programação que fornece acesso às funcionalidades do
navegador, é utilizada para codificar a aplicação Ajax;
1
Isso já ocorre com as aplicações web tradicionais, porém usualmente de maneira superficial, como verificações
de preenchimento de formulários. Com Ajax, essa possibilidade é mais explorada.
21
− XMLHttpRequest: objeto JavaScript usado para a troca de dados entre o cliente e o
servidor, realizando a comunicação em segundo plano;
− DOM: interface contendo os elementos da página web que podem ser manipulados
através de JavaScript, permitindo à aplicação Ajax alterar a interface do usuário,
redesenhando partes da página;
− XML: formato de representação de dados utilizado para a troca de informações
entre cliente e servidor.
Através da estrutura exibida na figura 6 é possível observar a relação entre as
tecnologias dentro deste modelo:
FIGURA 6 – Relacionamento entre as tecnologias empregadas em Ajax.
Outras tecnologias também podem ser utilizadas em implementações Ajax, como
Extensible Stylesheet Language Transformations (XSLT), cuja função é transformar um
documento XML em outro diferente (dentro da abordagem Ajax, normalmente um
documento XHTML). Além disso, a utilização de XML como formato para a troca de dados
entre cliente e servidor não é obrigatória, pois pode-se utilizar qualquer formato baseado em
22
texto, sendo possível encontrar casos em que é usado JavaScript Object Notation (JSON)
ou mesmo HTML. Porém, tais implementações não fazem parte do padrão adotado e
normalmente são usadas em determinados contextos, de maneira que estão fora de escopo
e não serão abordadas neste estudo.
Pode-se notar que as tecnologias empregadas no modelo tradicional continuam
presentes no modelo Ajax: a comunicação entre cliente e servidor ainda é feita através do
protocolo HTTP; HTML continua sendo utilizado para exibir as informações ao usuário; o
servidor continua gerando conteúdo dinamicamente através das tecnologias server-side e
JavaScript continua sendo utilizado do lado cliente. A diferença está na abordagem: o
servidor passa a entregar dados, e não documentos HTML completos; JavaScript passa a
ser utilizado para criar o motor Ajax, que por sua vez assume as funções de requisitar
informações ao servidor e desenhar a interface exibida ao usuário. Esse é um ponto forte da
técnica Ajax: mantém as características das aplicações web que as tornaram populares,
além de não ser necessário aos programadores aprenderem uma nova tecnologia serverside, pois Ajax pode interagir com qualquer uma delas.
Nos próximos capítulos, será feita uma análise das tecnologias citadas que fazem
parte da metodologia de desenvolvimento Ajax.
23
3. HTML/XHTML E CSS
O início da Internet ocorreu no final dos anos sessenta com o intuito de se criar uma
robusta rede de computadores, capaz de lidar com a perda de vários pontos, mantendo a
comunicação entre os restantes. Os fundos para criação de tal rede vieram do
Departamento de Defesa americano, que tinha um grande interesse em construir uma rede
de informação que pudessem suportar um ataque nuclear.
Kennedy e Musciano (2006) explicam que a rede resultante foi um grande sucesso
técnico, porém era limitada em tamanho e escopo. Em sua maior parte, apenas instituições
de defesa e instituições acadêmicas podiam obter acesso ao que na época era conhecida
como Advanced Reserch Projects Agency Network of the Departament of Defense
(ARPAnet). No início dos anos 90, empresas e indivíduos, ávidos por aproveitar a facilidade
e o poder das comunicações digitais globais, pressionaram as maiores redes de
computadores, principalmente as de Internet baseada em fundos do governo americano,
para que liberassem seus sistemas para um tráfego praticamente irrestrito.
A maior parte das informações disponíveis na rede eram simples textos sobre
assuntos acadêmicos. A Internet era muito desorganizada e, fora do meio governamental e
acadêmico, poucas pessoas tinham o conhecimento ou interesse para aprender como usar
os misteriosos softwares ou para gastar seu tempo pesquisando minuciosamente através de
documentos procurando os de seu interesse. No mesmo período em que a Internet foi
aberta para o mercado tal situação mudou, quando cientistas do Conseil Européen pour la
Recherche Nucléaire (CERN, ou Organização Européia para a Pesquisa Nuclear) lançaram
uma linguagem de criação de apresentações e um sistema de distribuição que eles haviam
construído para criação e compartilhamento, através da Internet, de documentos eletrônicos
integrados com capacidades multimídia. De acordo Kennedy e Musciano (2006) dessa
maneira nasceram o HTML, o software navegador, e a web. Os autores não precisariam
mais distribuir seus trabalhos em coleções fragmentadas de imagens, sons e texto. O HTML
unificou esses elementos. Além disso, a web permitiu a ligação de hipertexto, através da
qual documentos referenciavam automaticamente outros documentos localizados em
qualquer lugar do mundo, gerando uma mídia totalmente nova, de troca de informações e
comércio em âmbito global.
24
3.1 O que são HTML e XHTML
HTML e XHTML definem a sintaxe e localização de instruções especiais que não são
exibidas pelo navegador, mas o dizem como exibir o conteúdo do documento, sendo este
conteúdo texto, imagens, e outras mídias suportadas. Eles também tornam um documento
interativo através de ligações de hipertexto especiais (hyperlinks), que conectam o
documento a outros em qualquer lugar, assim como também a recursos da Internet.
HTML é baseado na metalinguagem Standard Generalized Markup Language (SGML),
e sua versão atual, HTML 4.01, não é conforme com o formato XML. A evolução do HTML é
o XHTML, uma linguagem conforme com XML que procura suportar o conjunto de
características do HTML 4.01, atendendo às regras mais rígidas do XML. Mesmo que
XHTML tenha as características do HTML, ambas as linguagens possuem certas diferenças,
que serão abordadas em um segundo momento.
Segundo Griffiths (2007) HTML/XHTML possui uma sintaxe direta, sendo seu
conteúdo estruturado em elementos que, de acordo com Haine (2006), contêm normalmente
uma tag de abertura, atributos opcionais, conteúdo, e uma tag de fechamento. Uma tag é
indicada pelo sinal de menor (<) e o sinal de maior (>), como pode ser visto no seguinte
exemplo:
<a href="http://www.google.com.br">Busca do Google</a>
Sendo:
– “<a href=”http://www.google.com.br“>”: é a tag de abertura, que define o início do
elemento;
– “</a>”: tag de fechamento, indica o final do elemento;
– “href”: atributo do elemento;
– “http://www.google.com.br”: valor do atributo;
– “Busca do Google”: conteúdo do elemento;
– “<a href=”http://www.google.com.br“>Busca do Google</a>”: o elemento completo.
Nem todos os elementos possuem uma tag de fechamento, como por exemplo <br>,
<meta> e <img>. Conhecidas como self-closing tags (tags de autofechamento), seu
conteúdo e formatação são gerenciados através dos valores de seus atributos. Esse tipo de
elemento denota uma das diferenças entre HTML e XHTML: enquanto que em HTML são
escritos simplesmente como <br> ou <meta>, em XHTML deve-se adicionar uma barra, na
forma <br /> e <meta />. Neste ponto, cabe descrever as principais características que
diferenciam XHTML do HTML, de acordo com Haine (2006):
– As tags <html>, <head> e <body> são mandatórias em XHTML.
25
– A tag <html> deve ter um atributo “xmlns” com o valor de “http://www.w3.org/1999/
xhtml”.
– Todos os elementos precisam ser fechados. Uma tag de abertura precisa ter outra
igual de fechamento ou, no caso de uma tag self-closing, ter uma barra, como já
dito anteriormente.
– Todas as tags devem ser escritas em letras minúsculas.
– Todos os valores de atributos devem ser referenciados utilizando aspas simples ou
duplas. Ou seja, class=page está incorreto, enquanto que class=’page’ ou
class=”page” estão corretos.
– Todos os atributos devem possuir valores. Alguns atributos, em HTML, podem ser
escritos em uma forma curta, como em <option selected>data</option>. Porém em
XHTML deve-se escrever <option selected=”selected”>data</option>.
– O símbolo & deve ser codificado. Deve-se escrever &amp; ao invés de
simplesmente &.
Tais pontos mostram a natureza mais exigente do documento XHTML em relação ao
HTML, para atender aos padrões XML. Existem outras características que diferenciam
ambos, porém não serão abordadas por estarem fora do escopo deste trabalho. Foram
apresentadas as principais diferenças para que seja levado em consideração o fato de que
mesmo sendo HTML e XHTML muito semelhantes, o desenvolvedor deve estar atento às
diferenças ao fazer sua escolha. Além disso, é importante salientar que ambas podem ser
utilizadas no modelo Ajax indistintamente.
A estrutura básica de um documento XHTML segundo Haine (2006) é a exibida no
código 1:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>O título</title>
</head>
<body>
<p>O conteúdo</p>
</body>
</html>
CÓDIGO 1 – Estrutura básica de um documento XHTML.
As duas primeiras linhas do documento contêm uma declaração de doctype. Essa
declaração provê uma indicação de qual Document Type Definition (DTD) será utilizado.
Como explicam Asleson e Schutta (2006) a maioria dos navegadores funciona possuindo
26
dois modos de renderização: strict ou standards mode e quirks mode. Navegadores web
usam strict mode quando o doctype indica que a página web é escrita para seguir uma
determinada recomendação World Wide Web Consortium (W3C1) como HTML 4.01 ou
XHTML 1.0, e usam quirks mode quando um doctype não está disponível ou quando a
página contém conflitos com o doctype especificado. De acordo com a W3C (2007B), isso
significa que diferentes regras são aplicadas para a apresentação do documento, estando o
standards mode em conformidade com os padrões W3C e o quirks mode baseado em
comportamento não-padrão, de navegadores antigos. Ainda de acordo com York (2005),
quirks mode existe como uma maneira de se prover retro-compatibilidade com várias
páginas web que foram criadas antes que os padrões W3C fossem implementados e
passassem a ser amplamente utilizados, ou para aquelas as quais o autor ainda não tem
conhecimento dos padrões. A declaração de doctype não segue nenhuma das regras de
sintaxe para criação de tags HTML, devendo ser escrita exatamente como exibida. Além do
XHTML 1.0 Strict exibido no código, existem doctypes XHTML 1.0 Transitional e Frameset,
HTML 4.01 Strict, HTML 4.01 Transitional e HTML 4.01 Frameset, além de outras versões
de HTML2. Basicamente, os doctypes Transitional possuem tags e atributos que foram
desaprovados no doctype Strict (são doctypes de transição, como o próprio nome diz),
enquanto que os doctypes Frameset são adotados em páginas que utilizam frames.
A questão relativa à utilização de doctypes é importante na criação de aplicações Ajax,
pois o desenvolvedor que utiliza os padrões W3C não só evita inconsistências na
interpretação de código CSS e torna suas aplicações acessíveis por todos os navegadores
web modernos, como também facilita seu trabalho ao garantir que o navegador possa criar
uma representação acurada do DOM a partir do código HTML. Segundo Asleson e Schutta
(2006), o navegador pode não ser capaz de criar uma representação correta do DOM se a
página foi mal escrita, forçando o navegador a renderizá-la utilizando quirks mode. Uma
representação incorreta do DOM pode tornar difícil o acesso e a modificação do mesmo por
meio do JavaScript (DOM e Javascript serão abordados mais adiante neste estudo),
principalmente de uma maneira compatível com navegadores diferentes.
Em seguida à declaração de doctype, na terceira linha, encontra-se uma tag de
abertura <html> com um atributo xmlns. Esse atributo é usado para declarar um XML
namespace, que descreve qual linguagem de marcação está sendo utilizada. O valor
inserido é http://www.w3.org/1999/xhtml e deve estar presente em qualquer documento
XHTML. Após o elemento <html> aberto existe, na quarta linha, o elemento <head> do
documento, que contém um elemento <title> (na quinta linha) e pode conter também os
elementos <style>, <script>, <meta>, e <link>. Apenas o elemento <title> é obrigatório,
1
2
Para uma abordagem mais detalhada sobre a W3C consulte o item 3.2 Web Standards.
Uma relação com os DTDs disponíveis pode ser encontrada em http://www.w3.org/QA/2002/04/valid-dtd-list.
27
sendo seu conteúdo exibido na barra de título do navegador. Segundo Griffiths (2007),
<style> é usado para definir código CSS específico da página, e <script> para também
definir scripts específicos, como JavaScript. O elemento <link> define uma ligação com um
recurso externo, como um arquivo CSS, ou um ícone.
Analisando novamente a estrutura do documento XHTML, seguindo a tag de
fechamento do elemento <head>, na sexta linha, há a tag de abertura do elemento <body>,
na linha seguinte. Essa tag contém os parágrafos, listas, imagens e outros conteúdos, como
pode ser observado o elemento de parágrafo (tag <p>) localizado na oitava linha do código.
Em seguida à tag de fechamento de <body> está a tag de fechamento do elemento <html>,
na décima e última linha, encerrando o documento.
Alguns documentos XHTML podem também apresentar uma declaração XML no
seguinte formato:
<?xml version="1.0" encoding="iso-8859-1"?>
Essa linha é inserida antes da declaração de doctype, e seu objetivo é declarar que o
documento em questão é um documento XML, sua versão, e o character set (conjunto de
caracteres) em que o documento foi codificado. De acordo com Haine (2006) tal declaração
é opcional, e utilizá-la pode causar efeitos adversos, sendo o pior deles fazer o navegador
Internet Explorer passar a funcionar em quirks mode - qualquer coisa que apareça antes da
declaração de doctype, exceto espaço em branco, gera esse efeito. Assim, o autor sugere
que essa linha não seja inserida.
A definição do character set de um documento é um ponto relevante, pois permite que
este seja exibido corretamente (evitando a exibição de caracteres incorretos). Segundo
Jacobs (2006), pode-se definir o character set de várias maneiras, como uma declaração
XML (como visto acima) ou utilizando uma tag <meta> dentro da seção <head>, na forma:
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> para especificar o
charset UTF-8, por exemplo. Porém, a maneira mais confiável de se definir o character set
de um documento XHTML é fazê-lo através do cabeçalho HTTP que o servidor envia ao
cliente, podendo ser realizado através da utilização de alguma tecnologia server-side ou
mesmo configurando o servidor web adequadamente.
A estrutura básica de um documento HTML segue o mesmo modelo do XHTML, com
poucas diferenças como pode ser visto no código 2:
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<title>O título</title>
<p>O conteúdo</p>
CÓDIGO 2 – Estrutura básica de um documento HTML.
28
Os elementos <html>, <head> e <body> não são obrigatórios em HTML, mas deve-se
estar atento para o fato de que mesmo não tendo sido explicitamente criados, tais
elementos existirão no DOM. Além disso, caso seja especificado algum elemento
pertencente a <head> como <link> ou <meta>, ele deve aparecer antes de qualquer
marcação pertencente ao elemento <body>, caso contrário a marcação será considerada
inválida.
3.2 Web Standards
De acordo com a definição de Griffiths (2007) web standards (ou padrões web) são
regras universais que determinam como algo deve ser usado, independentemente de
qualquer outra coisa (como um navegador específico, por exemplo). A utilização de web
standards ajuda a garantir a compatibilidade universal e a acessibilidade.
Esses padrões são criações da W3C, uma entidade independente que conta com
empresas como Google, Intel, AOL, Apple, várias universidades, Sony, Microsoft, e muitos
outros. A W3C (2007A) é um consórcio internacional cujo objetivo é, de acordo com a
definição encontrada em seu próprio site “Levar a World Wide Web a atingir todo seu
potencial através do desenvolvimento de protocolos e diretrizes que assegurem o
crescimento da web em longo prazo”. A entidade busca atingir seus objetivos com a criação
de padrões web e diretrizes, divulgando as chamadas Recomendações W3C. Além do
próprio HTML/XHTML, a W3C é responsável por padronizar uma grande gama de
tecnologias relacionadas à web como XML, CSS, HTTP e DOM, por exemplo.
Os padrões HTML são baseados em semântica. Isso consiste em um processo de
utilização de tags para aplicar significado, como em "esse pedaço de texto é um parágrafo"
ou "o HTML neste elemento faz uma tabela". Tal processo é parte de uma importante
definição: HTML deve ser utilizado para conteúdo, enquanto CSS deve ser usado para
apresentação.
A filosofia central dos web standards é "separação de conteúdo e apresentação".
Griffiths (2007, p. XIX) afirma que: "Se você aplicar essa regra ao construir páginas web
então você já está na metade do caminho em direção à realização dos web standards e dos
benefícios que eles trazem". Isso significa que HTML é para uma coisa e CSS é para outra.
A tabela 1 exemplifica alguns elementos e sua abordagem correspondente:
29
TABELA 1 – Elementos e sua abordagem correspondente.
Os benefícios mais importantes da utilização dos web standards são:
– Compatibilidade entre navegadores: um problema comum no processo de criação
web foi a "necessidade" de desenvolver uma página para um navegador e outra
página para outro. Mesmo hoje, alguns sites são feitos para funcionar apenas no
Microsoft Internet Explorer, excluindo uma pequena, mas significante, percentagem
de usuários. Porém, com exceção de algumas pequenas discrepâncias, seguir os
web standards garantirá que as páginas funcionem em qualquer lugar;
– Compatibilidade à frente: graças à crescente predisposição à compatibilidade,
páginas web funcionarão mais como desejado em navegadores futuros do que se
dependessem dos elementos proprietários não padronizados dos navegadores
atuais;
– Controle centralizado da apresentação: seguir web standards e utilizar CSS permite
que um único ou múltiplos arquivos globais apliquem apresentação a todas as
páginas web de um site. Separando dessa forma a apresentação do HTML tornamse muito mais fáceis e rápidas alterações de apresentação de todo um site,
resultando em um design mais consistente;
– Páginas mais leves: páginas mais leves significam diminuição de consumo de
banda (reduzindo custos de hospedagem) e tempo de carregamento da página
(melhora a usabilidade);
– Acessibilidade: uma grande proporção de problemas de acessibilidade da web são
problemas técnicos e podem ser resolvidos fazendo uso de bons padrões de HTML
e CSS.
Dois benefícios destacam-se entre os demais: as páginas mais leves, que provêm
maior usabilidade, e a acessibilidade melhorada através do HTML e CSS. Ambas são as
finalidades ao se desenvolver aplicações Ajax, o que demonstra uma grande contribuição
dos web standards a esta abordagem.
30
Um princípio fundamental por trás dos web standards é que eles são independentes
de navegador. Não deve ser necessário criar código específico para navegadores - se os
navegadores seguirem os padrões W3C uma página deve ser o suficiente. Porém, no
mundo real, os navegadores não são perfeitos. De acordo com Griffiths (2007) isso não
significa que os padrões web são inúteis em termos práticos. A maioria dos navegadores
populares modernos suporta a vasta maioria dos padrões web. Porém, de longe o
navegador mais popular é o Internet Explorer para Windows, que possui deficiências em
relação aos padrões web. Navegadores mais modernos, como Firefox e Safari, são
tecnicamente superiores, mas infelizmente para o desenvolvedor poucos são os usuários
que usam outra coisa além do navegador pré-instalado em sua máquina. Isso significa
predominantemente Windows e Internet Explorer. Em termos gerais, não há absolutamente
um motivo prático para não adotar os web standards - todos os navegadores modernos são
mais que capazes de lidar com eles. O ponto a ser considerado é que ao trabalhar em um
mundo multi-navegador, sempre é possível encontrar discrepâncias entre eles. Desde que
sejam realizados testes em vários navegadores para garantir o funcionamento da página,
questões de compatibilidade não devem causar muitos problemas.
3.3 Cascading Style Sheets (CSS)
Cascading Style Sheets (Folhas de Estilo em Cascata) é uma linguagem cujo objetivo
é simplificar o processo de tornar as páginas web apresentáveis. De maneira simples, CSS
lida com a parte de look and feel (ou aparência) de uma página web. Quando combinado
com uma linguagem estrutural de marcação como HTML, XHTML ou XML, CSS provê aos
navegadores as informações que os permitem apresentar todos os aspectos visuais de um
documento web. Cascading Style Sheets aplica bordas, espaços entre parágrafos,
cabeçalhos ou imagens, controle de tipos ou cores de fontes, cores de segundo plano e
imagens, efeitos textuais como textos sublinhados ou sobre-tachados, disposição de
camadas, posicionamento, e outros efeitos de apresentação. CSS controla os aspectos de
apresentação do desenho de uma página web, ao passo que HTML, XHTML ou XML
controlam sua estrutura.
Griffiths (2007) explica que, embora intrinsicamente ligado com o HTML na formação
da página web, CSS possui uma sintaxe completamente diferente, que consiste em uma
coleção de regras que são feitas de seletores, propriedades, e valores. Uma típica regra
CSS é a seguinte:
h1 { font-size: 2pt; }
31
Na qual:
– "h1" é o seletor, que define em qual parte do HTML o CSS se aplica;
– "font-size" é a propriedade, que define qual aspecto de apresentação específico do
elemento alvo será ajustado;
– "2pt" é um valor, que define qual o ajuste da propriedade;
– "font-size: 2pt;" é conhecido como declaração;
– "h1 { font-size: 2pt; }" todos juntos são definidos como sendo uma regra.
Seletores especificam a quais elementos HTML as declarações de estilo devem ser
aplicadas. Existem três principais tipos de seletores: seletores HTML, seletores
identificadores, e seletores de classe.
Seletores HTML simplesmente especificam um elemento HTML ao qual as
declarações devem ser aplicadas. A declaração "h2 { color: red; }" faz com que todos os
elementos h2 sejam vermelhos.
Seletores identificadores anexam estilos ao elemento HTML com o id correspondente.
Se existe o código HTML <h3 id="carro">Carro</h3>, para aplicar um estilo apenas para
esse elemento, deve-se fazer (destaque para o caractere # no início do seletor):
#carro { color: red; }
Seletores de classe anexam estilos para elementos HTML que sejam da classe
correspondente. Por exemplo, se existe o HTML <h3 class="veiculo">Carro</h3> e desejase aplicar estilos a esse elemento e a todos os outros da classe veiculo, a regra deve ser
(destaque para o ponto no início do seletor):
.veiculo { color: red; }
Pode-se também anexar mais de uma classe a um elemento HTML, separando-as por
espaço, como em <h3 class="veiculo utilitario">Carro</h3>. Neste caso, as duas regras
seguintes seriam aplicadas:
.veiculo { color: red; }
.utilitario { font-style: italic; }
Também é possível ser mais específico sobre quais elementos uma classe se aplica,
colocando o seletor dessa classe logo após outro seletor. Para associar estilos a um
elemento h2 com a classe "veiculo", por exemplo, utiliza-se o seletor h2.veiculo. Pode-se
então utilizar o seletor p.veiculo para aplicar estilos específicos aos elementos p com a
classe "veiculo", e assim por diante. Ainda é possível aplicar um mesmo bloco de
declaração a mais de um seletor, basta separá-los por vírgula, como em:
h2, #carro, .veiculo { color: red; }
32
Para que o CSS possa ser utilizado, ele deve ser anexado a um documento. Segundo
York (2005) o CSS é bastante flexível com relação à maneira pela qual isso pode ser feito.
Primeiramente, é possível realizar essa tarefa incluindo folhas de estilo embutidas: neste
caso utiliza-se a tag <style> para inserir folhas de estilo embutidas diretamente no
documento, como pode ser visto no código 3:
<style type='text/css'>
<!-body, td {
color: blue;
}
-->
</style>
CÓDIGO 3 – Inserção de folha de estilo em documento HTML.
O objetivo das linhas de comentário <!-- e --> é fazer com que navegadores antigos
que não suportam CSS ignorem o texto entre elas, permitindo que o CSS fique escondido
desses navegadores. Para que a tag <style> esteja de acordo com a sintaxe XHTML, é
necessário o atributo type, cuja finalidade é dizer ao navegador qual é o tipo da sintaxe que
se segue.
O método recomendado de inclusão de CSS em um documento é fazendo uma
ligação a folhas de estilo externas. A recomendação W3C permite que folhas de estilo
externas sejam incluídas no documento através do uso do elemento <link> ou a partir de
uma folha de estilo no próprio documento utilizando a regra @import. Um elemento <link>
tem o seguinte formato:
<link rel="stylesheet" href="caminho/para/css_doc.css" type="text/css" />
O atributo rel define a relação entre o documento externo e o documento solicitante.
Neste caso, a relação é que o documento externo é uma folha de estilo para o documento
solicitante. O atributo href é a referência de hyperlink, o caminho de onde o documento
externo se encontra. Por fim, o atributo type define o tipo Multipurpose Internet Mail
Extension (MIME1) do arquivo externo.
A outra maneira de realizar uma ligação a uma folha de estilo externa é através da
regra @import, de acordo com o código 4:
<style type="text/css">
@import url(caminho/para/css_doc.css);
</style>
CÓDIGO 4 – Exemplo de utilização da regra @import.
1
"Um MIME type diz ao navegador qual é o tipo de mídia de um arquivo e assim o que fazer com ele." Griffiths
(2007, p. 11).
33
Este método é bastante direto, colocando em frente à regra @import o url(), e entre os
parênteses deste o caminho de onde o arquivo com as folhas de estilo se encontra.
Ainda é possível aplicar CSS inline, utilizando o atributo style diretamente no
documento HTML, como em <p style="color: red;">Não coma laranjas.</p>. Griffiths (2007)
explica que essa maneira de se aplicar CSS é geralmente desencorajada e que ela perde
muitos dos grandes benefícios pelos quais CSS é famoso - especialmente a separação
entre apresentação e estrutura e a habilidade de realizar alterações globais a partir de uma
única fonte.
A utilização de Cascading Style Sheets pode reduzir a quantidade de banda
necessária para transmitir um site do servidor para o navegador. De acordo com York
(2005), CSS apresenta as seguintes vantagens:
– A apresentação de um website inteiro pode ser centralizada em um ou poucos
documentos, permitindo que sua aparência seja atualizada rapidamente;
– Usuários de um website podem criar suas próprias folhas de estilo, uma
característica que torna os websites mais acessíveis. Por exemplo, um usuário
pode criar uma folha de estilo de alto contraste que torne o conteúdo mais fácil de
ser lido;
– Navegadores estão começando a suportar múltiplas folhas de estilo, característica
que permite a exibição de mais de uma aparência do website ao mesmo tempo. O
usuário pode simplesmente selecionar a aparência que mais lhe agrade;
– Folhas de estilo permitem que o conteúdo seja otimizado para mais de um tipo de
dispositivo. Utilizando o mesmo documento HTML, diferentes versões de um
website podem ser apresentadas por exemplo para dispositivos como Personal
Digital Assistants (PDAs) e telefones celulares;
– O download é muito mais rápido porque documentos web usando CSS ocupam
menos espaço em disco e consomem menos banda.
As vantagens citadas demonstram claramente a contribuição que os Cascading Style
Sheets dão à usabilidade de uma aplicação web e conseqüentemente à abordagem Ajax.
Uma característica importante do Ajax em relação ao CSS é que as regras das folhas de
estilo (e por extensão a aparência do documento) podem ser alteradas dinamicamente,
tornando a usabilidade das aplicações web ainda maior. Essas alterações dinâmicas são
feitas utilizando código JavaScript que é incorporado ao documento HTML. A linguagem
JavaScript é a tecnologia a ser abordada no capítulo seguinte.
34
4. JAVASCRIPT
JavaScript foi desenvolvido como uma linguagem de scripting leve e de propósito
geral, adequada para o uso em diferentes contextos. Inicialmente nomeada LiveScript,
segundo Goodman (2001) a linguagem servia para dois propósitos. Um desses propósitos
era uma linguagem que administradores de servidores web pudessem usar para gerenciar o
servidor e conectar suas páginas com outros serviços, como banco de dados em backend.
No lado cliente - em documentos HTML - autores poderiam empregar scripts escritos nessa
nova linguagem para melhorar páginas web de diferentes maneiras. Por exemplo, um autor
poderia usar LiveScript para ter certeza que a informação inserida pelo usuário em um
formulário está correta. Ao invés de forçar o servidor ou o banco de dados a fazer a
validação (necessitando de trocas de informações entre o navegador cliente e o servidor), o
computador do usuário realizaria o trabalho.
Em 1995, a linguagem foi renomeada para JavaScript e lançada junto com o
navegador Netscape Navigator 2.0. Ao contrário do que se possa pensar, JavaScript não
tem relação com a linguagem Java, tendo recebido esse nome apenas por questões de
marketing.
Como explica Zakas (2005, p. 2), devido à necessidade de padronização, em 1997 o
JavaScript 1.1 foi submetido como proposta ao European Computer Manufacturers
Association (ECMA). "O comitê técnico 39 foi designado para 'padronizar a sintaxe e
semântica de uma linguagem de scripting de propósito geral, multiplataforma e neutra de
fornecedor' (http://www.ecma-international.org/memento/TC39.htm).". Foi então criado o
padrão ECMA-262, definindo uma nova linguagem de scripting chamada ECMAScript. No
ano
seguinte,
a
International
Organization
for
Standardization
and
International
Electrotechnical Commission (ISO/IEC) também adotou ECMAScript como um padrão.
Desde então, navegadores web têm procurado utilizar ECMAScript como uma base para
suas implementações de JavaScript.
Embora ECMAScript seja um importante padrão, não é a única parte do JavaScript.
Uma completa implementação de JavaScript é composta por três partes distintas: o núcleo
(ECMAScript), o Document Object Model (DOM), e o Browser Object Model (BOM).
ECMAScript não está preso a nenhum navegador em particular. Um navegador web é
considerado um ambiente hospedeiro para o ECMAScript, existindo inúmeros outros
ambientes (como por exemplo o Macromedia ActionScript, utilizado no Flash). De maneira
simplificada ECMAScript é uma descrição, definindo todas as propriedades, métodos,
sintaxe e objetos de uma linguagem de scripting. Outras linguagens implementam o
ECMAScript, como faz o JavaScript, utilizando-o como um ponto de partida de
35
funcionalidades. Cada navegador possui sua própria implementação da interface do
ECMAScript, que é então extendida para conter o DOM e o BOM.
O Document Object Model (DOM) é uma Application Programming Interface (API) para
manipulação de HTML e XML. O DOM mapeia toda a página como um documento formado
por uma hierarquia de nós. Através da criação de uma árvore para representar um
documento, o DOM permite aos desenvolvedores um nível sem precedentes de controle
sobre o conteúdo e a estrutura desse documento. Nós podem ser facilmente removidos,
adicionados ou substituídos utilizando a API do DOM. Por sua importância e pelo fato de ser
uma interface independente de linguagem de programação, o DOM será abordado
separadamente no capítulo 5.
A terceira parte do JavaScript, o Browser Object Model (BOM), permite o acesso e a
manipulação da janela do navegador. Utilizando o BOM, desenvolvedores podem mover a
janela, mudar o texto da barra de status, e realizar outras ações que não têm diretamente
relação com o conteúdo da página. O que torna o BOM único, e freqüentemente
problemático, é que ele é a única parte da implementação do JavaScript que não possui
padronização. Por esse motivo, cada navegador possui sua própria implementação. Existem
alguns padrões de fato, como a existência de um objeto window e um objeto navigator, mas
cada navegador define suas próprias propriedades e métodos para esses e outros objetos.
4.1 Sintaxe
A sintaxe do JavaScript empresta alguns elementos de linguagens como Java, C e
Perl. Os conceitos básicos da linguagem, segundo Zakas (2005), são os seguintes:
– Tudo é sensível à caixa (case-sensitive): variáveis, nomes de funções, operadores
e todo o restante são case-sensitive (sensíveis ao tamanho da letra), ou seja, uma
variável chamada test é diferente de uma outra chamada Test.
– Variáveis são de tipo dinâmico: diferentemente de Java e C, não é definido um tipo
específico às variáveis em JavaScript. Ao invés disso, cada variável é definida
usando o operador var e pode ser inicializada com qualquer valor. Isso permite que
seja alterado o tipo de dado que uma variável contém a qualquer momento (embora
isso deva ser evitado). Por exemplo:
var color = "azul";
var num = 25;
var visible = true;
– Ponto-e-vírgula no final da linha é opcional: Java, C e Perl requerem que toda linha
termine com um ponto-e-vírgula para estar sintaticamente correta. JavaScript
36
permite ao desenvolvedor decidir se usa ou não um ponto-e-vírgula no final da
linha.
– Comentários são iguais a Java, C e Perl: JavaScript emprestou seus comentários
dessas linguagens. Existem dois tipos de comentários: linha única e multilinha.
Comentários de linha única
começam com duas barras (//), enquanto que
comentários multilinha começam com uma barra e um asterisco (/*) e terminam
com um asterisco seguido de uma barra (*/), da seguinte forma:
// este é um comentário de linha única
/* este é um comentário
multilinha */
– Colchetes indicam blocos de código: outro conceito emprestado do Java é o bloco
de código. Blocos de código são usados para indicar uma série de expressões que
devem ser executadas em seqüência e são indicados através do envolvimento das
expressões entre um colchete de abertura ({) e um colchete de fechamento (}),
como no código 5:
if (test1 == "azul") {
test1 = "vermelho";
alert(test1);
}
CÓDIGO 5 – Bloco de código em JavaScript.
A construção de expressões e estruturas de controle em JavaScript é bastante
semelhante às linguagens C, C++ e Java. As estruturas if-else, while, e for por exemplo
apresentam bastante similaridade, como mostrado no código 6:
// estrutura if-else
if (i > 25) {
alert("Maior que 25.");
} else if (i < 0) {
alert("Menor que 0.");
} else {
alert("Entre 0 e 25, inclusive.");
}
// estrutura for
var iNum = 0;
for (var i=1; i < 10; i++) {
if (i % 5 == 0) {
break;
}
iNum++;
}
alert(iNum);
// exibe 4
CÓDIGO 6 – Estruturas if-else e for em JavaScript.
37
De acordo com Zakas (2005) os valores que as variáveis recebem podem ser divididos
em dois grupos: valores primitivos (primitive values) ou valores referência (reference values).
Valores primitivos são dados simples que são armazenados na pilha (stack), o que significa
que são mantidos na localização diretamente acessada pela variável. Por outro lado, os
valores referência são objetos armazenados na memória heap, o que quer dizer que o valor
mantido no local acessado pela variável é um ponteiro para a localização em memória onde
o objeto se encontra armazenado.
Um valor é considerado primitivo quando faz parte de um dos conjuntos de valores
definidos para cada um dos cinco tipos primitivos existentes em ECMAScript, que são:
– Tipo Undefined: possui apenas um valor, undefined. Quando uma variável é
declarada mas não é inicializada, ela recebe o valor undefined por padrão.
– Tipo Null: também possui apenas um valor, null. Na verdade o valor undefined é um
derivativo do valor null e ECMAScript os define como iguais, portanto a expressão
"if (null == undefined)" é considerada verdadeira. Isso não quer dizer que ambos
possuem o mesmo significado, pois enquanto undefined é utilizado para variáveis
declaradas mas não inicializadas, null é o valor utilizado para representar um objeto
que não existe. O fato de Null ser um tipo primitivo e apontar para um objeto é
devido a um erro na implementação do JavaScript original que acabou sendo
incorporado ao ECMAScript. Portanto, quando se espera que uma função ou
método1 retorne um objeto, é retornado null quando o objeto não é encontrado.
– Tipo Boolean: possui dois valores, true e false. Mesmo que false não seja igual a 0,
0 é convertido para false quando necessário, sendo seguro utilizá-lo em uma
declaração booleana.
– Tipo Number: pode representar valores inteiros de 32 bits e ponto flutuante de 64
bits. Para se declarar em uma variável um valor em ponto flutuante deve-se
adicionar um ponto e um dígito após o ponto (1.0 ao invés de 1, por exemplo). Os
valores limite suportados pelo tipo Number podem ser obtidos através de
Number.MAX_VALUE (valor máximo) e Number.MIN_VALUE (valor mínimo).
– Tipo String: pode armazenar zero ou mais caracteres Unicode, representados por
números inteiros de 16 bits.
Diferentemente dos valores primitivos, os valores referência lidam com objetos.
Conforme define ECMA (1999) no padrão ECMA-262, um objeto é "uma coleção não
ordenada de propriedades, cada qual contendo um valor primitivo, objeto, ou função", o que
significa em outras palavras que um objeto é um vetor de valores sem ordenamento. Cada
objeto é, ainda de acordo com o ECMA-262, determinado por uma definição de objeto
1
ECMA-262 define que "uma função armazenada como propriedade de um objeto é chamada de método".
38
(object definition), que estabelece a interface do objeto (suas propriedades e métodos) e seu
funcionamento interno (o código que faz o objeto funcionar). As objects definitions são
semelhantes em funcionalidade às classes das linguagens orientadas a objeto. A maneira
como os objetos são criados (ou instanciados) também é semelhante à das linguagens
orientadas a objeto C++ e Java: utiliza-se a palavra-chave new seguida pelo nome do
objeto. O código 7 mostra a criação do objeto Array e a utilização da propriedade length e do
método toString:
var array_cores = new Array(); // cria objeto Array
array_cores[0] = "azul";
array_cores[1] = "laranja";
array_cores[2] = "verde";
alert(array_cores.length); // exibe 3
alert(array_cores.toString()); // exibe "azul,laranja,verde"
CÓDIGO 7 – Criação e utilização de um objeto Array.
Os objetos em ECMAScript podem ser de três tipos:
– Objetos nativos (Native objects): são aqueles disponíveis em uma implementação
ECMAScript que independem do ambiente hospedeiro. Ou seja, são os objetos
definidos pelo padrão ECMA-262. Exemplos são os objetos Array, Date, Function, e
Error.
– Objetos embutidos (Built-in objects): trata-se de qualquer objeto disponível na
implementação ECMAScript que, além de independente do ambiente hospedeiro,
está presente no início da execução de um programa ECMAScript. Isso significa
que não é necessário criá-lo (ou instanciá-lo) explicitamente pelo desenvolvedor,
pois ele já se encontra criado. Os dois únicos objetos embutidos definidos pelo
ECMA-262 são Global e Math. Por definição, todo objeto embutido também é um
objeto nativo.
– Objetos do hospedeiro (Host objects): é definido pelo ECMA-262 como sendo
qualquer objeto fornecido pelo ambiente hospedeiro, com o propósito de
complementar o ambiente de execução do ECMAScript. Todo objeto que não é
nativo é um objeto do hospedeiro. Portanto, os objetos do BOM e do DOM são
considerados objetos deste tipo, já que são providos pelo ambiente hospedeiro
(navegador web).
Os conceitos relativos à definição e funcionamento dos objetos em JavaScript são
particularmente importantes, pois os host objects são essenciais ao funcionamento da
técnica Ajax. São os objetos do DOM e do BOM que permitem a atualização dinâmica da
interface do usuário e é através do objeto XMLHttpRequest que é realizada a comunicação
39
assíncrona para troca de dados entre cliente e servidor. Dado sua importância, tais objetos
serão abordados em maior detalhe mais adiante.
4.2 Browser Object Model
Segundo Zakas, (2005) o BOM é constituído por uma série de objetos que interagem
com a janela do navegador, independentemente do conteúdo. Tais objetos relacionam-se
entre si de acordo com a hierarquia exibida na figura 7:
FIGURA 7 – Hierarquia de objetos no BOM.
Através da hierarquia pode-se notar que o objeto window é o ponto central do BOM.
Ele representa toda a janela do navegador, mas não necessariamente o conteúdo que a
janela contém. Isso significa que o objeto pode ser utilizado para, por exemplo, mover,
redimensionar, ou de alguma maneira alterar o comportamento do navegador que ele
representa.
Se uma página utiliza framesets, cada frame é representado pelo seu próprio objeto
window e armazenado na coleção de frames. Dentro dessa coleção, os objetos window são
indexados (da esquerda para a direita, de cima para baixo), tanto por número, quanto por
nome do frame. Considerando o seguinte documento HTML do código 8:
40
<html>
<head>
<title>Exemplo de página com framesets</title>
</head>
<frameset rows="70,*">
<frame src="frame.htm" name="Frame_cima" />
<frameset cols="50%,50%">
<frame src="outroframe.htm" name="Frame_esq" />
<frame src="outroframe2.htm" name="Frame_dir" />
</frameset>
</frameset>
</html>
CÓDIGO 8 – Documento HTML usando framesets.
O código HTML acima cria um frame no alto da página e dois frames lado a lado
abaixo. Neste caso, os frames podem ser referenciados da seguinte maneira:
– Frame no alto da página: window.frames[0] ou window.frames["Frame_cima"];
– Frame abaixo à esquerda: window.frames[1] ou window.frames["Frame_esq"];
– Frame abaixo à direita: window.frames[2] ou window.frames["Frame_dir"].
Pelo fato do objeto window ser o ponto principal do BOM, ele apresenta a
característica de não ser necessário referenciá-lo diretamente. Isso significa que é possível
reescrever window.frames[0] como frames[0], ou ainda window.frames["Frame_cima"] como
frames["Frame_cima"].
Como mencionado anteriormente, através do objeto window é possível mover ou
redimensionar a janela do navegador. Existem quatro métodos disponíveis para realizar
essa tarefa:
– moveBy(x, y): move a janela do navegador x pixels horizontalmente e y pixels
verticalmente, relativamente à posição atual. Pode-se utilizar números negativos em
x para mover a janela para esquerda e em y para mover para cima.
– moveTo(x, y): move a janela do navegador de maneira que o canto superior
esquerdo fique localizado na posição (x, y) da tela do usuário. Pode-se utilizar
números negativos, porém isso faz com que parte da janela fique fora da tela.
– resizeBy(w, h): redimensiona a largura (width) da janela em w pixels e a altura
(height) em h pixels, relativamente ao tamanho atual. Pode-se utilizar números
negativos em w para diminuir a largura e em h para diminuir a altura.
– resizeTo(w, h): redimensiona a janela do navegador para w pixels de largura e h
pixels de altura. Não é possível utilizar números negativos.
Para realizar as operações de movimentação e redimensionamento de janelas, por
vezes se faz necessário acessar as informações relativas ao posicionamento e tamanho
atual da janela. O BOM, como já citado, não possui um padrão definido a ser seguido e
41
nesse ponto é possível notar a falta de padronização entre os navegadores. Para determinar
a posição da janela, o navegador Internet Explorer provê as propriedades window.screenLeft
e window.screenTop, enquanto que Mozilla, Opera e Safari disponibilizam window.screenX
e window.screenY. Determinar o tamanho da janela do navegador no Internet Explorer não é
possível, apenas é permitido determinar o tamanho do viewport, que é a área na qual a
página
HTML
é
exibida,
através
das
propriedades
document.body.offsetWidth
e
document.body.offsetHeight. Os outros três navegadores apresentam as propriedades
window.innerWidth e window.innerHeight para determinação do tamanho do viewport, além
de window.outerWidth e window.outerHeight para o tamanho real da janela do navegador.
O objeto window também permite que novas janelas do navegador sejam abertas
através do método window.open(). Usualmente, o método é utilizado com três argumentos:
a URL da página a ser carregada na nova janela, o nome da janela e uma string de atributos
separados por vírgula. Caso o método seja chamado com o nome de um frame existente
como segundo argumento, a URL é então carregada neste frame. O código 9 a seguir abre
uma nova janela com altura de 150 e largura de 300 pixels (height=150, width=300),
localizada na posição (10, 10) da tela (top=10, left=10) e podendo ser redimensionada
(resizable=yes):
/* abre uma nova janela com o nome de janela_2 e carrega
a página do Gmail */
window.open("http://www.gmail.com/","janela_2","height=150,width=300,top=10,left
=10,resizable=yes");
CÓDIGO 9 – Uso do método window.open().
Além de abrir novas janelas, também é possível utilizar três tipos de janelas de
diálogo:
– window.alert(): esse método recebe um argumento, que é o texto a ser exibido para
o usuário. Quando alert() é chamado, o navegador cria uma caixa de mensagem do
sistema e exibe o texto definido juntamente com o botão "OK". Freqüentemente
alert() é utilizado para avisar o usuário quando este submeteu dados inválidos em
um formulário.
– window.confirm(): é parecido com o diálogo de alerta, a principal diferença é a
exibição de um botão de "Cancelar" além do botão de "OK", o que permite ao
usuário indicar se uma determinada ação deve ser realizada. Para determinar qual
botão o usuário pressionou, confirm() retorna true se "OK" foi selecionado e false
caso "Cancelar" tenha sido selecionado.
– window.prompt(): exibe uma caixa de diálogo que permite a entrada de dados pelo
usuário. Juntamente com os botões de "OK" e "Cancelar" é exibida uma caixa de
42
texto na qual solicita-se que o usuário entre alguma informação. O método prompt()
recebe dois argumentos: o texto a ser exibido ao usuário e um valor padrão para a
caixa de texto (podendo ser um valor vazio).
O código 10 mostra a utilização das três janelas de diálogo em uma função que exibe
uma mensagem de boas vindas ao usuário. As janelas do exemplo podem ser visualizadas
na figura 8:
// caso o usuário clique em "Cancelar" a mensagem não é exibida.
function mostra_msg() {
var resp = confirm("Deseja visualizar a mensagem de boas vindas?");
if(resp == true) {
var nome = prompt("Informe seu nome:", "Nome");
if(nome == null) {
alert("Ação cancelada.");
}
else {
alert("Olá "+nome+"! Bem vindo ao sistema!");
}
}
else {
alert("Mensagem cancelada.");
}
}
CÓDIGO 10 – Utilização das janelas de diálogo alert(), confirm() e prompt().
FIGURA 8 – Janelas de diálogo confirm(), prompt() e alert().
43
O BOM disponibiliza mais uma série de funcionalidades, além das já citadas, através
dos seguintes métodos e objetos:
– Método window.setTimeout(): permite que um determinado código seja executado
após um número de milisegundos especificado. Por exemplo, para exibir um aviso
ao usuário dentro de cinco segundos utiliza-se: setTimeout("alert('Aviso! Verifique
seu e-mail!')",5000).
– Método window.setInterval(): semelhante ao setTimeout(), com a diferença que o
código passado como argumento é executado repetidamente no intervalo
especificado. Para repetir o aviso do código anterior de um em um segundo, podese utilizar setInterval("alert('Aviso! Verifique seu e-mail!')", 1000).
– Objeto window.history: através do objeto history é possível acessar o histórico de
uma janela do navegador. Por razões de segurança não há uma maneira de saber
quais foram as URLs visitadas, apenas é possível navegar pelo histórico. Para isso,
utiliza-se o método go() passando o número de páginas à frente ou para trás (neste
caso usando um número negativo). Por exemplo, para voltar duas páginas no
histórico, utiliza-se o código window.history.go(-2). Também existem, além de go(),
os métodos history.back() (voltar uma página) e history.forward() (avançar uma
página).
– Objeto location: representa a URL carregada na janela do navegador e possui
várias propriedades representando segmentos da URL como location.host,
(representa o nome do servidor, como em www.google.com) e location.pathname,
(representa a parte da URL depois do nome do servidor). A propriedade
location.href é a mais utilizada, pois representa a URL atualmente carregada na
página e alterando seu valor é possível navegar para outra página. Por exemplo,
location.href
=
"http://www.mozilla.org"
envia
o
navegador
ao
endereço
especificado. Também é possível recarregar a página atual através do método
location.reload(). O objeto location é uma propriedade tanto de window
(window.location)
quanto
de
document
(window.document.location
ou
document.location), sendo o mesmo objeto nos dois casos e podendo portanto ser
usado das duas formas indistintamente.
– Objeto window.screen: disponibiliza informações sobre a tela do usuário. Como
costuma ocorrer, cada navegador possui propriedades específicas para o objeto,
mas existem entre os navegadores as propriedades comuns screen.availHeight
(altura da tela disponível para a janela em pixels, levando em consideração
elementos da interface do usuário, como por exemplo a barra de tarefas no sistema
operacional
Windows),
screen.availWidth
(largura
da
tela
disponível),
screen.colorDepth (número de bits para representação de cores), screen.height
44
(altura total da tela) e screen.width (largura total da tela). As propriedades
availHeight e availWidth são particularmente úteis quando se deseja exibir uma
janela em tela cheia, por exemplo.
Outro objeto do BOM, o window.navigator, fornece várias informações sobre o
navegador web, sendo bastante útil na determinação de qual navegador está sendo
utilizado. Várias técnicas de detecção de navegador e sistema operacional fazem uso desse
objeto com a finalidade de determinar se o navegador é capaz de executar a aplicação web.
O código 11 exibe sua utilização:
if(navigator.userAgent.indexOf("Opera") > -1)
alert("Você está utilizando o navegador Opera.");
else if(navigator.userAgent.indexOf("MSIE") > -1)
alert("Você está utilizando o navegador Internet Explorer.");
else if(navigator.userAgent.indexOf("Firefox") > -1)
alert("Você está utilizando o navegador Firefox.");
else
alert("Não foi possível detectar o seu navegador.");
CÓDIGO 11 – Emprego do objeto navigator para detecção do navegador em uso.
Segundo Zakas (2005) além dessa técnica de detecção, conhecida como detecção
pela string do user-agent (sendo user-agent o navegador), existe a técnica de detecção por
objeto/funcionalidade, que busca determinar se um dado objeto ou método está disponível
antes de usá-lo. A maioria dos desenvolvedores JavaScript aponta essa última como mais
apropriada por tornar o código imune a mudanças que possam dificultar a determinação do
navegador em uso.
A correta determinação das funcionalidades do navegador é ponto importante na
utilização da abordagem Ajax, pois certas funcionalidades estão disponíveis de forma
diferente entre os navegadores ou, em versões mais antigas, não estão disponíveis.
Realizar uma correta detecção permite que a aplicação funcione livre de erros e, nos casos
em que o navegador é antigo, que o usuário seja corretamente informado da situação,
economizando esforços tanto do desenvolvedor quanto do usuário da aplicação.
O último objeto pertencente ao BOM é o window.document, que apresenta a
característica única de pertencer tanto ao BOM quanto ao DOM2. Da perspectiva do BOM, o
objeto window.document constitui-se de uma série de coleções que acessam várias partes
do documento, além de propriedades que fornecem informações sobre a página em si. As
coleções e propriedades principais são:
2
A forma como o objeto document relaciona-se com o DOM é abordada no capítulo 5.
45
– document.anchors: coleção de todas as âncoras da página (representadas por <a
name="nome_da_ancora"></a>);
– document.forms: coleção que contempla todos os formulários da página;
– document.images: coleção referenciando todas as imagens da página;
– document.links: coleção contendo todos os links da página (representados por <a
href="pagina.htm"></a>);
– document.title: propriedade que contém o texto da tag <title> (título da página);
– document.referrer: propriedade contendo a URL da posição imediatamente anterior
no histórico do navegador;
– document.URL: propriedade contendo a URL da página atual.
De maneira similar à coleção window.frames, cada uma das coleções do objeto
document são indexadas tanto por número quanto por nome, o que significa que é possível
acessar um elemento usando document.images[0] ou document.images["nome_imagem"]. O
objeto document também possui dois métodos bastante utilizados: document.write() e
document.writeln(). Ambos aceitam um argumento, que é a string a ser escrita no
documento, sendo a única diferença a adição de uma quebra de linha ao final da string em
writeln(). Os métodos inserem a string de texto no documento no ponto onde foram
executados, e o navegador a trata como se fosse parte do HTML normal da página. A string
deve ser inserida antes do fim do carregamento do documento, caso contrário todo o
documento será substituído pela string de texto passada ao método.
O estudo do Browser Object Model permite notar sua contribuição ao desenvolvimento
Ajax, pois ele disponibiliza uma série de funcionalidades que provêm interatividade às
aplicações web. O ponto a ser ressaltado é relativo à falta de padronização entre os
diferentes navegadores na utilização do BOM: o desenvolvedor Ajax deve estar atento para
garantir a compatibilidade entre navegadores através de técnicas de identificação do useragent, como a demonstrada utilizando o objeto navigator, ou através da detecção das
funcionalidades disponíveis, procurando definir previamente se um dado objeto, método ou
propriedade está presente antes de utilizá-lo.
4.2 Eventos
Conforme explica Zakas (2005) a interação entre o código JavaScript e o documento
HTML é gerenciada através de eventos, que ocorrem quando o usuário ou o navegador
manipulam a página de alguma maneira. Vários tipos de operações são considerados
eventos, como quando a página é carregada ou quando um usuário realiza um clique no
mouse. Através dos eventos é possível codificar respostas fazendo com que botões fechem
46
janelas, mensagens sejam exibidas ao usuário e dados sejam validados. Em suma, o
mecanismo de eventos permite que a página interaja com o usuário e o navegador,
respondendo às ações que estes realizam.
Os eventos fazem parte do Document Object Model, porém seu completo
desenvolvimento pelo DOM ocorreu apenas em 2004. Portanto, à época da criação do
modelo de eventos nos navegadores, não haviam padrões a serem usados como referência
pelos desenvolvedores, levando Internet Explorer e Netscape a criarem seus próprios
modelos de eventos. Quando a Netscape liberou seu código fonte para a comunidade de
código aberto (Open Source) sob o nome Mozilla, os desenvolvedores-chave procuraram
aderir aos padrões e os navegadores Opera e Safari também adotaram o padrão do DOM,
deixando o Internet Explorer como o único dos principais navegadores sem o suporte
apropriado ao modelo de eventos do DOM. No restante da abordagem dos eventos em
JavaScript, serão vistas as diferenças entre os dois modelos de eventos.
Os eventos que ocorrem no navegador podem ser separados em quatro grupos,
dependendo do objeto que disparou o evento e do que causou a ocorrência deste. O DOM
define os seguintes grupos de eventos:
– Eventos de mouse: ocorrem quando o usuário utiliza o mouse para realizar uma
ação. Os eventos podem ser click (clique do botão esquerdo), dblclick (duplo clique
do botão esquerdo), mousedown (qualquer botão é pressionado), mouseout (cursor
move-se para fora do foco do elemento), mouseover (cursos move-se para dentro
do foco do elemento), mouseup (qualquer botão deixa de ser pressionado) e
mousemove (qualquer movimentação do cursor é realizada sobre o elemento).
– Eventos de teclado: ocorrem quando o usuário realiza uma digitação no teclado,
podendo ser keydown (tecla é pressionada), keypress (tecla é pressionada, mas
neste caso o retorno é um caractere para teclas de caractere e teclas como Shift e
Alt são ignoradas) e keyup (tecla deixa de ser pressionada).
– Eventos HTML: são disparados quando certas mudanças ocorrem na janela do
navegador ou em uma interação específica entre cliente e servidor. Este tipo de
evento possui uma série de possibilidades:
1. load: elemento termina de ser carregado;
2. unload: elemento termina de ser descarregado;
3. abort: processo de download é interrompido e o elemento não foi carregado;
4. error: para o objeto window é disparado quando ocorre um erro de JavaScript
e para elemento quando este não pode ser carregado;
5. select: usuário seleciona um ou mais caracteres em uma caixa de texto
(<input> ou <textarea>);
6. submit: botão Submit de um <form> é pressionado;
47
7. reset: botão Reset de um <form> é pressionado;
8. resize: ocorre quando uma janela ou frame é redimensionado;
9. scroll: é disparado quando o usuário rola a barra de rolagem de um elemento;
10. focus: elemento recebe o foco (através de clique ou interação);
11. blur: disparado no momento em que o elemento perde o foco.
– Eventos de mutação (Mutation events): disparados quando acontecem mudanças
na estrutura DOM da página. Este tipo de evento ainda não foi implementado nos
navegadores, apesar de fazer parte da especificação DOM. Dois exemplos
especificados pelo DOM para esse tipo de evento são DOMNodeInserted (nó é
inserido como filho de outro nó) e DOMNodeRemoved (nó é removido como filho de
outro nó).
Quando um botão recebe um clique em uma página, na verdade não só ele está
recebendo o clique, mas também o elemento que o contém (uma tabela, por exemplo) e a
página como um todo. Logicamente cada um dos elementos deve responder ao evento em
uma ordem específica. O fluxo de eventos (ou a ordem em que cada elemento responde) é
diferente entre o modelo Internet Explorer e o modelo DOM. No caso do IE, foi desenvolvido
um fluxo de eventos conhecido como event bubbling. Ele consiste em disparar o evento
seqüencialmente a partir do alvo mais específico para o menos específico (o objeto
document, que é a raiz da árvore do DOM). Por exemplo, no caso da página do código 12,
a ordem de ocorrência do evento seria: div, body, html e document (nas versões anteriores
ao IE 6.0 o elemento html não recebe o evento, passando direto de body para document).
<html>
<head>
<title>Exemplo</title>
</head>
<body>
<div onclick="funcao()">Clique aqui</div>
</body>
</html>
CÓDIGO 12 – Documento HTML.
48
FIGURA 9 – Modelo event bubbling de fluxo de evento.
No DOM, o fluxo de evento, além de suportar o event bubbling, suporta o event
capturing, um modelo de fluxo de evento que era utilizado pelo navegador Netscape 4.0. Ele
consiste exatamente no oposto do bubbling: dispara o evento do elemento menos específico
(objeto document) para o mais específico. No DOM, o capturing ocorre primeiro e em
seguida ocorre o bubbling, ambos passando por todos os elementos, começando a partir e
terminando no objeto document (a maioria dos navegadores que seguem o DOM utiliza o
objeto window como referência no lugar de document). O fluxo de evento do código 12 em
um navegador que segue o DOM é o exibido na figura 10:
FIGURA 10 – Modelo DOM de fluxo de evento.
49
Eventos são ações realizadas pelo usuário ou pelo próprio navegador. Para responder
a um evento uma função é chamada, a qual se dá o nome de event handler (ou manipulador
de evento). Uma função que responde a um evento click (clique do mouse) é considerada a
manipuladora do evento onclick. Tradicionalmente, event handlers são designados de duas
maneiras: no código JavaScript ou no documento HTML.
Para designar um manipulador de evento no JavaScript, deve-se definir uma
referência ao objeto ao qual o manipulador será designado e então atribuir uma função à
propriedade event handler correspondente ao evento em questão, conforme pode ser visto
no código 13:
var div_1 = document.getElementById("div_1");
div_1.onclick = function () {
alert("Clique recebido");
};
CÓDIGO 13 – Atribuição de event handlers a objeto no código JavaScript.
No caso do HTML, basta adicionar à tag HTML o atributo referente ao manipulador de
evento, inserindo como valor deste o código JavaScript desejado, da seguinte maneira:
<div id="div_1" onclick="alert('Clique recebido')"></div>
Ambos os métodos funcionam nos navegadores modernos, mas métodos adicionais
permitem que mais de um manipulador seja designado por evento. Novamente, Internet
Explorer possui um método e o DOM possui outro.
No IE, todo elemento possui dois métodos: attachEvent() e detachEvent(). O primeiro
é utilizado para anexar um manipulador a um evento e o segundo é usado para remover um
manipulador de evento. Ambos recebem dois argumentos: o nome do evento ao qual o
manipulador será designado (ondoubleclick, por exemplo) e uma função. No caso de
attachEvent() a função é adicionada como um manipulador de evento; no caso de
detachEvent() este procura pela função na lista de manipuladores e a remove.
var recebe_click1 = function () {
alert("Clique recebido");
};
var recebe_click2 = function () {
alert("Clique recebido novamente");
};
var div_1 = document.getElementById("div_1");
div_1.attachEvent("onclick", recebe_click1);
div_1.attachEvent("onclick", recebe_click2);
CÓDIGO 14 – Atribuição de event handlers no Internet Explorer.
50
Como mencionado, o método pode ser utilizado para adicionar mais de um
manipulador de evento. O código 14 faz com que dois alertas sejam exibidos quando o
elemento <div> é clicado. Primeiramente o “Clique recebido”, seguido pelo “Clique recebido
novamente”. Os manipuladores de evento são sempre executados na ordem em que foram
adicionados.
No caso do DOM, a tarefa de adicionar e remover manipuladores de evento é feita
pelos métodos addEventListener() e removeEventListener(). Diferentemente do IE, eles
recebem três argumentos: o nome do evento, a função a ser designada, e se o manipulador
deve ser usado na fase de bubbling ou de capturing. Para capturing o parâmetro deve ser
true, para bubbling, false. Da mesma maneira que o IE, pode-se adicionar mais de um
manipulador para o evento:
var recebe_click1 = function () {
alert("Clique recebido");
};
var recebe_click2 = function () {
alert("Clique recebido novamente");
};
var div_1 = document.getElementById("div_1");
div_1.addEventListener("click", recebe_click1, false);
div_1.addEventListener("click", recebe_click2, false);
CÓDIGO 15 – Atribuição de event handlers de acordo com o DOM.
O código 15 produz o mesmo resultado que o exibido no código 14, apenas com a
diferença relativa à utilização do método DOM addEventListener() ao invés de attachEvent()
do IE. Deve-se notar que se o manipulador de evento é adicionado para uma determinada
fase (capturing ou bubbling), é preciso especificar esta mesma fase ao removê-lo com
removeEventListener(), caso contrário a função não será removida.
Um ponto importante sobre manipuladores de evento no DOM é que se a maneira
tradicional, que consiste em designar uma função diretamente à propriedade event handler
do objeto, é utilizada, o manipulador de evento é adicionado para a fase de bubbling. Assim,
as duas linhas de código a seguir possuem o mesmo efeito:
div_1.onclick = recebe_click1; // maneira tradicional
div_1.addEventListener("click", recebe_click1, false); // método DOM
Se as duas linhas fossem inseridas em um código e o segundo argumento de
addEventListener fosse recebe_click2() ao invés de recebe_click1(), seriam adicionados
dois manipuladores de evento (recebe_click1 e recebe_click2), ambos para a fase de
bubbling. É importante lembrar que a maneira tradicional não permite que mais de um
manipulador seja associado ao objeto, de forma que caso a segunda linha fosse substituída
51
pelo código “div_1.onclick = recebe_click2;”, o manipulador deixaria de ser a função
recebe_click1() e passaria a ser recebe_click2().
Definida a função (ou funções) responsável por processar o evento, se faz necessário
que ela tenha acesso a informações relativas ao evento ocorrido. Zakas (2005) explica que
para isso criou-se um objeto evento (event object) contendo informações específicas sobre o
evento que acabou de ocorrer, tais como:
– O objeto que causou o evento;
– Informações sobre o mouse no momento do evento;
– Informações sobre o teclado no momento do evento.
Os objetos evento são criados quando este ocorre e se são acessíveis pelos
manipuladores do evento. Depois que todos os manipuladores foram executados, o objeto
evento é destruído. Como esperado, o Internet Explorer e o DOM implementam o objeto
evento de maneiras diferentes.
No Internet Explorer, o objeto evento é uma propriedade do objeto window. Isso
significa que um manipulador de evento deve acessar o objeto através de “window.event”.
Mesmo sendo uma propriedade de window, o objeto window.event é acessível apenas
quando um evento ocorre. Depois que todos os manipuladores são executados, esse objeto
é destruído. O padrão DOM, por sua vez, determina que o objeto evento deve ser passado
como único argumento ao manipulador de evento. Goodman (2001) ensina uma maneira de
implementar uma detecção do objeto event de forma independente do navegador utilizado:
function executa_acao(evt) {
evt = (evt) ? evt : (window.event) ? window.event : "";
if (evt) {
// processa ação
}
}
CÓDIGO 16 – Técnica para detecção do objeto event.
Se o objeto evento é passado como parâmetro da função (modelo DOM), este
continua disponível como evt; caso contrário a função verifica se o objeto window.event está
disponível (modelo IE) e o atribui a evt; por fim, se ainda assim não há um objeto evento
disponível, a variável evt se torna vazia, e o processamento da função só continua se evt
possuir um objeto evento.
Acessar as propriedades e métodos do objeto event pode ser uma tarefa mais difícil
do que detectá-lo, devido às variações nos nomes das propriedades e métodos entre os
modelos. Ainda assim, eles apresentam propriedades semelhantes, sendo as principais as
seguintes:
52
– Tipo do evento: para saber qual o tipo do evento ocorrido, utiliza-se a propriedade
type (evt.type), que retorna um valor contendo o nome do evento (como “click”,
“mouseover” ou “doubleclick”, por exemplo).
– Código da tecla: em um evento keydown ou keyup, é possível saber o código da
tecla que foi pressionada através da propriedade keyCode (evt.keyCode). No caso
da tecla Enter o código é 13, a barra de espaço é 32 e a tecla Backspace é 8.
– Coordenadas do mouse na área do cliente: durante eventos do mouse, é possível
acessar a localização do cursor do mouse em relação à parte da janela que exibe a
página web (chamada de área do cliente), através das propriedades clientX
(evt.clientX, coordenada do eixo x) e clientY (evt.clientY, coordenada do eixo y). As
coordenadas dizem o quão longe em pixels o cursor do mouse está do início da
área do cliente;
– Coordenadas do mouse na tela: de maneira análoga às propriedades clientX e
clientY, é possível em eventos do mouse acessar a localização do cursor em
relação à tela do computador através das propriedades screenX (evt.screenX) e
screenY (evt.screenY).
Com relação às diferenças entre Internet Explorer e DOM, as principais propriedades e
métodos são:
– Alvo do evento: o objeto que é o centro de um evento é chamado de alvo. Supondo
que seja atribuído um manipulador para o evento onclick ao elemento <div>, no
momento em que o evento click é disparado o elemento <div> é considerado o alvo.
No Internet Explorer, a propriedade que contém o alvo é srcElement
(evt.srcElement), enquanto que no DOM o nome da propriedade é target
(evt.target).
– Bloquear o comportamento padrão do evento: para impedir que ocorra o
comportamento padrão de um evento no IE, deve-se atribuir o valor false à
propriedade returnValue (“evt.returnValue = false;”). No DOM, utiliza-se o método
preventDefault() (“evt.preventDefault();”). Bloquear o comportamento padrão do
evento pode ser útil quando se deseja, por exemplo, rejeitar um determinado
caractere que é digitado em uma caixa de texto, ou impedir o uso pelo usuário do
menu de contexto que aparece quando este realiza um clique sobre a página com o
botão direito do mouse.
– Código do caractere: em eventos do tipo keypress é possível saber o valor Unicode
da tecla pressionada caso esta represente um caractere. No IE, esse valor é
acessível através da propriedade keyCode (evt.keyCode) vista anteriormente
53
enquanto que no DOM keyCode é 0, e o valor Unicode é disponibilizado pela
propriedade charCode (evt.charCode).
– Parar a propagação do evento: para impedir a propagação (bubbling) do evento no
Internet Explorer, deve-se atribuir o valor true à propriedade cancelBubble
(“evt.cancelBubble = true;”). No DOM, isto é feito através da chamada ao método
stopPropagation() (“evt.stopPropagation();”). Parar a propagação do evento faz com
que os manipuladores (event handlers) de outros objetos no fluxo do evento não
sejam executados.
Zakas (2005) define os eventos como um dos conceitos mais importantes em
JavaScript, sendo a principal maneira de anexar JavaScript a uma interface web. Os
eventos capturam praticamente qualquer ação que o usuário realiza enquanto está
interagindo com a interface, conferindo ao desenvolvedor grande flexibilidade no
desenvolvimento de aplicações web.
4.4 O objeto XMLHttpRequest
Conforme explicam Crane et al. (2006) o objeto XMLHttpRequest é uma extensão nãopadrão suportada pela maioria dos navegadores web. Ele dinamiza o trabalho de realizar
chamadas assíncronas consideravelmente, pois é concebido explicitamente para buscar
dados em segundo plano. De acordo com Jacobs (2006) o objeto XHR se encontra no
coração da abordagem Ajax, permitindo a páginas web requisitar dados de um servidor
utilizando código do lado cliente.
O XMLHttpRequest originou-se como um componente ActiveX específico da Microsoft,
disponibilizado como um objeto JavaScript no navegador Internet Explorer. Outros
navegadores então o implementaram como um objeto nativo, e atualmente os principais
navegadores (Firefox, Safari, Opera, Konqueror e IE) implementam o comportamento do
objeto de maneira similar.
Para que o XHR possa ser utilizado para enviar requisições e processar respostas,
Asleson e Schutta (2006) esclarecem que primeiramente é necessário instanciá-lo. Visto
que não se trata de um padrão W3C e que o Internet Explorer implementa o
XMLHttpRequest como um objeto ActiveX, enquanto que os demais como um objeto
JavaScript nativo3, o código JavaScript precisa conter a lógica necessária para poder criar o
objeto tanto utilizando a técnica ActiveX quanto JavaScript. O seguinte código, extraído de
3
No Internet Explorer 7 o objeto pode ser utilizado tanto de maneira nativa quanto através do ActiveX.
54
Jacobs (2006, p. 268), exemplifica como instanciar o objeto independentemente do
navegador utilizado:
var xmlhttp = false;
if (window.XMLHttpRequest) {
// navegadores Mozilla, Opera ou Safari
xmlhttp = new XMLHttpRequest();
}
else if (window.ActiveXObject) {
// navegador Internet Explorer
try {
xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
} catch(e) {
try {
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
} catch(e) {
xmlhttp = false;
}
}
}
CÓDIGO 17 – Criação de um objeto XMLHttpRequest.
O motivo de se tentar instanciar duas vezes o objeto ActiveX em um bloco try-catch é
devido ao fato da biblioteca MSXML (que contém o objeto XHR) possuir várias versões
diferentes. Uma maneira de utilizar sempre a versão mais recente disponível é criar um
vetor contendo todas as versões conhecidas e através de um laço for tentar instanciar o
objeto para cada elemento do vetor (a partir da versão mais recente) até que a operação
seja bem sucedida.
De acordo com Darie et al. (2006) o objeto XHR possui os seguintes métodos e
propriedades:
– abort(): interrompe a requisição atual;
– getAllResponseHeaders(): retorna uma string com todos os cabeçalhos da resposta
HTTP;
– getResponseHeader(“nome_cabeçalho”): retorna uma string contendo um único
cabeçalho de resposta;
– open(“metodo”, “URL”, indicador_assinc, “nome_usuario”, “senha”): inicializa os
parâmetros da requisição;
– send("conteúdo"): realiza a requisição HTTP;
– setRequestHeader(“nome”, “valor”): define um par nome/valor para o cabeçalho da
requisição;
– onreadystatechange: define a função que manipula as mudanças de estado da
requisição;
55
– readyState: retorna o status atual da requisição. Jacobs (2006) define os seguintes
valores possíveis:
0: Requisição ainda não foi inicializada. Ocorre antes da chamada ao método
open();
1: Requisição inicializada mas não enviada. Ocorre antes da chamada ao
método send();
2: Requisição enviada e sendo processada;
3: Requisição send processada mas ainda não terminada;
4: A resposta está completa.
– responseText: retorna uma string contendo a resposta do servidor;
– responseXML: retorna a resposta do servidor no formato de um documento XML;
– status: retorna o código de status HTTP da resposta do servidor;
– statusText: retorna a mensagem relativa ao status da resposta.
O próximo passo depois de criado o objeto é definir, através da propriedade
onreadystatechange, a função a ser executada cada vez que o status da requisição
(propriedade readyState) muda. Em seguida, deve-se utilizar o método open() para
inicializar a requisição, configurando as opções da conexão. O primeiro parâmetro de open()
especifica o método usado para enviar dados ao servidor, usualmente GET ou POST. O
segundo parâmetro é a URL, que especifica para onde será feita a requisição (caso seja
especificado um recurso não disponível via HTTP, o primeiro parâmetro é ignorado). O
terceiro parâmetro especifica se a requisição deve ser feita de maneira assíncrona; true
significa que o processamento continua depois que o método send() retorna, sem aguardar
por uma resposta deste, enquanto que false faz com que seja aguardada uma resposta
antes de continuar o processamento, paralisando a funcionalidade da página web. Portanto,
deve-se utilizar o valor true para habilitar o processamento assíncrono e processar a
resposta do servidor a partir da manipulação do evento onreadystatechange.
Ao utilizar-se GET, os parâmetros são enviados através da query string da URL, como
em http://algumhost.com/teste.php?param_1=cliente&param_2=20 (essa requisição envia
param_1 com o valor cliente e o param_2 com o valor 20). Com GET, os parâmetros são
enviados na chamada ao método open():
xmlhttp.open("GET",
"http://algumhost.com/teste.php?param_1=cliente&param_2=20", true);
xmlhttp.send(null);
Quando POST é utilizado, os parâmetros são enviados através do método send(), no
momento em que este dispara a requisição:
56
xmlhttp.open("POST", "http://algumhost.com/teste.php", true);
xmlhttp.send("param_1=cliente&param_2=20");
Asleson e Schutta (2006) explicam que POST deve ser usado quando a requisição
gerar alguma mudança de estado (alteração de um banco de dados no servidor, por
exemplo), e GET quando o intuito é buscar dados do servidor. Também existe entre os dois
métodos uma diferença na quantidade de dados que pode ser enviada: no caso do GET,
muitos navegadores e servidores limitam o tamanho da URL usada para enviar dados ao
servidor, o que não ocorre com POST.
Feita a requisição, a resposta do servidor pode ser processada uma vez que a
propriedade readyState possua o valor 4. Se o código de status da resposta for 200, a
requisição foi processada com sucesso (outros valores como 404 ou 500 indicam erro) e o
conteúdo pode ser acessado através da propriedade responseText, ou como um documento
XML através de responseXML.
É importante lembrar que por questões de segurança, não é possível requisitar
conteúdo de um dominío diferente daquele onde se encontra o script que originou a
chamada ao objeto. Jacobs (2006) define essa característica como caixa de areia do Ajax
(Ajax sandbox). No código 18 é exibido todo o fluxo de funcionamento do objeto
XMLHttpRequest. Neste exemplo, quando o usuário pressiona o botão “Ver mensagem” é
feita uma requisição HTTP ao servidor para acessar o arquivo texto mensagem.txt e exibir
seu conteúdo na tela. A figura 11 exibe a mensagem com o conteúdo recebido.
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<title>Exemplo de uso - objeto XMLHttpRequest</title>
<script type="text/javascript">
var xmlhttp = null;
// função para instanciar o objeto
function CriaObjetoXHR() {
if (window.XMLHttpRequest) {
// navegadores Mozilla, Opera ou Safari
xmlhttp = new XMLHttpRequest();
}
else if (window.ActiveXObject) {
// navegador Internet Explorer
var XmlHttpVersions = new Array('MSXML2.XMLHTTP.6.0',
'MSXML2.XMLHTTP.5.0',
'MSXML2.XMLHTTP.4.0',
'MSXML2.XMLHTTP.3.0',
'MSXML2.XMLHTTP',
'Microsoft.XMLHTTP');
// loop for para procurar instanciar a versão mais recente do objeto
for(var i=0; i < XmlHttpVersions.length && !xmlhttp; i++)
{
try {
57
xmlhttp = new ActiveXObject(XmlHttpVersions[i]);
} catch(e) {
xmlhttp = null;
}
}
}
}
// funcao responsavel por realizar a requisicao ao servidor
function RealizaRequisicao() {
CriaObjetoXHR();
if(!xmlhttp) {
alert ("Nao foi possivel realizar a operacao.");
return;
}
xmlhttp.onreadystatechange = ProcessaResposta;
xmlhttp.open("GET", "http://localhost/mensagem.txt", true);
xmlhttp.send(null);
}
// funcao que processa a resposta do servidor, exibindo o conteudo do arquivo
function ProcessaResposta() {
if(xmlhttp.readyState == 4) {
if(xmlhttp.status == 200) {
var conteudo = xmlhttp.responseText;
alert(conteudo);
} else {
alert("Ocorreu um erro no processamento da resposta.");
}
}
}
</script>
</head>
<body>
<div style="text-align:center">
<input value="Ver mensagem" type="button" onclick="RealizaRequisicao()">
</div>
</body>
</html>
CÓDIGO 18 – Utilização do objeto XMLHttpRequest.
FIGURA 11 – Conteúdo do arquivo mensagem.txt exibido na tela.
58
Apesar do objeto XMLHttpRequest possuir amplo suporte por parte dos navegadores,
não se trata de um padrão W3C como já mencionado anteriormente. A especificação W3C
que trata dessa funcionalidade é o DOM Level 3 Load and Save Specification, que ainda
não foi implementado por nenhum navegador. De acordo com Asleson e Schutta (2006)
essa especificação foi criada com o objetivo de ser uma maneira de alterar o conteúdo do
documento DOM usando conteúdo XML. Ambas as tecnologias são os assuntos a serem
abordados no próximo capítulo.
59
5. DOCUMENT OBJECT MODEL E XML
Segundo a definição de Asleson e Schutta (2006) o DOM é uma especificação da
W3C para uma maneira de se acessar e modificar o conteúdo e estrutura de um documento
de maneira independente de plataforma e linguagem de programação utilizada. Trata-se,
como explica Jacobs (2006), de uma application programming interface (API) para XML cujo
objetivo é permitir a uma aplicação manipular um documento XML, ler dados, adicionar
novos nós e editar o conteúdo existente. Pelo fato de estar diretamente relacionado ao XML
antes de abordar os conceitos relativos ao DOM é necessário primeiramente compreender a
estrutura do documento XML.
5.1 Documento XML
O Extensible Markup Language (XML) surgiu em 1998 e é baseado no SGML, uma
linguagem cujo propósito é definir a sintaxe de linguagens de marcação para representar
dados usando tags. Jacobs (2006) diz que o ponto mais importante sobre o XML é que não
se trata de uma linguagem em si. Na verdade, trata-se de uma metalinguagem usada para
construir outras linguagens e vocabulários. Um exemplo de linguagem XML é o XHTML, que
possui um grupo padrão de tags que devem ser usadas de uma maneira específica. XML é
uma recomendação W3C e é uma poderosa abordagem para o gerenciamento de
informações. Através de documentos XML é possível compartilhar dados. A W3C definiu
uma série de objetivos para o XML, dentre os quais pode-se destacar:
– Deve ser fácil escrever programas que processam documentos XML;
– Documentos XML devem ser legíveis para humanos e razoavelmente claros;
– Documentos XML devem ser fáceis de criar.
É possível notar que a W3C deu ao XML dois alvos: humanos e processadores XML.
Um processador XML ou analisador (parser) é um pacote de software que processa um
documento XML. Processadores identificam o conteúdo de um documento XML, lêem,
escrevem, mudam o documento ou criam um novo do início. O objetivo é abrir o mercado
para os processadores XML fazendo com que sejam simples de serem desenvolvidos.
Regras de construção estritas significam que menos processamento é necessário. Além
disso, mantendo os documentos legíveis por humanos permite-se que os dados sejam
acessados sem grande dificuldade, facilitando a construção e a depuração (debug) de
aplicações. Um efeito colateral é que documentos XML podem ser extensos e descrever
dados usando XML pode ser um processo mais longo do que seria utilizando outros
métodos.
60
A sintaxe do XML baseia-se no uso de tags para marcação de texto. O uso de tags já
foi visto na abordagem da linguagem XHTML, a diferença é que no XHTML as tags
possuem um significado pré definido (<p> é um parágrafo, por exemplo), enquanto que no
XML é possível construir tags próprias. Uma grande vantagem do XML é que as tags podem
descrevem seu conteúdo (como em <cor>Azul</cor>). Os documentos XML possuem certos
critérios para serem corretamente formados:
– As linguagens XML são sensíveis à caixa (case sensitive), ou seja, a tag <nome> é
diferente de <Nome> ou <NOME>.
– Os nomes em XML não podem começar com número: deve ser uma letra ou
sublinhado (underscore). Os caracteres restantes podem ser qualquer um, com
exceção do espaço.
– Todas as tags precisam ter uma tag de fechamento equivalente, e caso não exista
conteúdo entre duas tags de abertura e fechamento pode-se utilizar uma única tag
com uma barra ao final de seu nome (<livro/>, por exemplo).
– Atributos sempre devem possuir aspas envolvendo seus valores, podendo ser tanto
aspas simples quanto duplas. Exemplo: <livro isbn=”1020304050”>.
<?xml version="1.0" encoding="UTF-8"?>
<!-- Este documento XML contém os livros do acervo de uma biblioteca -->
<acervo>
<livro isbn="1010101010">
<titulo>Dom Casmurro</titulo>
<autor>Machado de Assis</autor>
<anoPublicacao>1900</anoPublicacao>
</livro>
<livro isbn="2020202020">
<titulo>O Ateneu</titulo>
<autor>Raul Pompéia</autor>
<anoPublicacao>1888</anoPublicacao>
</livro>
<livro isbn="3030303030">
<titulo>O Cortiço</titulo>
<autor>Aluízio Azevedo</autor>
<anoPublicacao>1890</anoPublicacao>
</livro>
</acervo>
CÓDIGO 19 – Documento XML representado acervo de biblioteca.
Todo documento XML é dividido em duas partes: o prolog e o elemento raiz (também
chamado de document element). O prolog aparece no topo do documento XML. No código
19, o prolog contém uma declaração XML que define para o documento a versão 1.0 e a
codificação UTF-8. Embora seja opcional, é sempre uma boa idéia incluir a declaração XML
para informar que o documento apresenta conteúdo XML, além de também prover a
61
processadores informações adicionais como o tipo de codificação de caractere (neste caso
UTF-8). A declaração XML sempre deve aparecer na primeira linha do documento.
O prolog também pode conter instruções de processamento, cuja finalidade é passar
informações para aplicações que estejam processando o documento XML. O processador
XML não processa essa instrução, ao invés disso ele apenas repassa para a aplicação, sem
alterações. Um uso comum de instruções de processamento é o seguinte:
<?xml-stylesheet type="text/css" href="folha_de_estilo.css"?>
Essa instrução especifica a folha de estilo folha_de_estilo.css a ser aplicada ao
documento XML.
Comentários, da mesma forma que HTML/XHTML, começam com <!-- e terminam com
--> e podem ser inseridos em praticamente qualquer lugar do documento. Apenas não
podem ser inseridos dentro de nomes de tag. O código 19 contém um comentário no prolog
do documento.
O prolog também pode conter DTDs e esquemas XML, que provêm regras sobre quais
elementos e atributos podem aparecer dentro do documento XML. Em outras palavras, eles
especificam quais elementos e atributos são válidos e quais são necessários ou opcionais.
Uma referência externa a um DTD poderia ser inserida no documento do código 19 da
seguinte forma:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE acervo SYSTEM "biblioteca.dtd">
<!-- Este documento XML contém os livros do acervo de uma biblioteca -->
A segunda parte do documento XML, o elemento raiz, é onde são armazenados os
dados do documento. Ele contém todos os outros elementos, atributos, textos e CDATA
(tipo de seção a ser vista adiante), além de poder também incluir entidades e comentários.
Um elemento é o conjunto da tag de abertura e de fechamento, além do conteúdo
entre eles. O conteúdo pode ser texto e elementos filhos. A tag de abertura do elemento
também pode conter atributos, e comentários podem ser inseridos dentro de elementos.
Ainda utilizando como referência o documento do código 19:
<livro isbn="1010101010">
<titulo>Dom Casmurro</titulo>
<autor>Machado de Assis</autor>
<anoPublicacao>1900</anoPublicacao>
</livro>
A tag de abertura <livro> contém um atributo isbn e inclui três outros elementos:
<titulo>, <autor> e <anoPublicacao>. Cada um desses elementos contêm texto.
62
Atributos são uma outra maneira de prover informação em documentos XML. Através
de sua inserção na tag de abertura de um elemento, eles normalmente provêm informações
adicionais sobre o elemento que modificam. Não há limite ao número de atributos que
podem aparecer em um elemento. Eles consistem de pares de nome/valor, com o valor
envolvido por aspas duplas ou simples. Dois usos comuns de atributos são transmitir
informações de formatação e indicar o uso de um formato específico ou codificação. Por
exemplo, poderia-se transmitir uma data como:
<data formato="ddmmyyyy">20102007</data>
Todo texto em um documento XML está contido dentro de tags de abertura e de
fechamento e, a não ser que seja marcado como CDATA, será tratado como se fosse XML e
processado dessa maneira. Isso significa que um sinal de maior será tratado como se fosse
parte de uma tag XML. Se for necessário utilizar caracteres reservados no texto, é
necessário reescrevê-los como entidades de caractere (character entities). As entidades de
caractere são símbolos que representam um único caractere. Os caracteres considerados
reservados e suas entidades correspondentes são descritos na tabela 2, e o código 20
apresenta um exemplo de sua utilização:
Caractere
Entidade
&
&amp;
'
&apos;
>
&gt;
<
&lt;
"
&quot;
TABELA 2 – Entidades de caractere usadas em documentos XML.
<!-- A tag abaixo invalida o documento pois contém um caracter reservado no texto -->
<expressao_invalida>30 < 45</expressao_invalida>
<!-- A tag a seguir é válida, utiliza uma entidade de caractere -->
<expressao_valida>30 &lt; 45</expressao_valida>
CÓDIGO 20 – Exemplo do emprego de uma entidade de caractere.
Também é possível incluir outros caracteres como entidades de caractere usando
números Unicode ou hexadecimais. Por exemplo, é possível codificar o símbolo de copyright
© como &#169; ou &#xA9;. O número entre &# e o ponto-e-vírgula é o código Unicode do
caractere a ser exibido. Se o código for em hexadecimal, então ele é prefixado com o
caractere x.
63
Além da utilização de entidades de caractere, também é possível inserir caracteres
reservados no texto usando CDATA. Seções CDATA permitem que blocos de texto sejam
marcados para que não sejam processados como XML:
<questao><!CDATA[Demonstre porque 5 < 10]]</questao>
A seção CDATA inicia com <!CDATA[ e termina com ]], e os dados ficam contidos
entre o colchete de abertura e o de fechamento. Seções CDATA são úteis para inserir
código embutido, como JavaScript, e para adicionar conteúdo que não requer
processamento. Por exemplo, uma aplicação que lê dados de um banco de dados e os
marca em XML poderia inserir todo o conteúdo em seções CDATA para evitar a
necessidade de processar caracteres reservados explicitamente.
De acordo com Jacobs (2006) a recomendação XML assume que um documento XML
deve ser processado de uma maneira particular: um processador XML deve passar o
conteúdo e a estrutura do documento XML para uma aplicação. A biblioteca MSXML da
Microsoft, por exemplo, disponibiliza juntamente com o objeto XMLHttpRequest visto
anteriormente, um parser XML.
Existem dois tipos de processamento XML: baseado em evento (event-based) e
baseado em árvore (tree-based). Os analisadores (parsers) baseados em evento são
conhecidos como analisadores Simple API for XML (SAX). Zakas (2005) explica como
funcionam os analisadores SAX: eles começam a partir do início do documento e analisam o
código navegando através dele de maneira direta, disparando eventos sempre que
encontram uma tag de abertura, uma tag de fechamento, atributo, texto, ou outra sintaxe
XML. O desenvolvedor então define o que fazer quando cada um desses eventos ocorre.
Analisadores SAX são leves e rápidos porque apenas analisam o texto e continuam seu
caminho em direção ao final do documento. Sua principal desvantagem é que não é
possível parar, voltar, ou acessar partes específicas da estrutura XML sem iniciar
novamente a partir do início do documento. Esse tipo de analisador funciona bem com
linguagens que possuem boas propriedades de manipulação de eventos. SAX, por exemplo,
é bastante utilizado com Java, mas é menos adequado para as linguagens de scripting
freqüentemente utilizadas na web.
Os analisadores baseados em árvore, por sua vez, são conhecidos como analisadores
DOM. O DOM é uma API baseada em árvore para XML. Seu foco principal não é apenas
analisar código XML, mas representar esse código usando uma série de objetos interligados
que podem ser modificados e acessados diretamente sem a necessidade de re-analisar o
código. Usando o DOM, o código é analisado uma vez para criar uma árvore modelo, e
então o código original não é mais necessário. Embora o DOM seja mais lento que o SAX e
64
requeira mais sobrecarga porque cria muitos objetos, ele é, devido a sua facilidade de uso, o
método preferido para JavaScript e navegadores web.
5.2 Funcionamento do DOM
A definição exata da W3C para o DOM é:
O Document Object Model é uma interface neutra de plataforma e linguagem que permitirá
a programas e scripts dinamicamente acessar e atualizar o conteúdo, estrutura, e estilo de
documentos. O documento pode ser adicionalmente processado, e os resultados desse
processamento podem ser incorporados de volta à página atual. (W3C apud Asleson e
Schutta, 2006 p. 43).
A recomendação da W3C para o DOM prevê três níveis de suporte, numerados de 1 a
3, respectivamente. Quanto maior o nível DOM, mais recursos suportados. Zakas (2005)
define os níveis: o DOM Level 1 consiste de duas partes: o núcleo do DOM, que provê uma
maneira de mapear a estrutura de um documento baseado em XML, e o DOM HTML, que
estende o núcleo do DOM adicionando objetos e métodos específicos do HTML. O DOM
Level 2 adicionou suporte a eventos do mouse e da interface do usuário e métodos para
realizar iterações em um documento DOM, suporte a CSS através de interfaces de objetos e
suporte a XML namespaces1. O DOM Level 3 introduziu métodos para salvar e carregar
documentos de maneira uniforme (através do já citado DOM Level 3 Load and Save
Specification) bem como métodos para validar um documento. Este nível também estende o
núcleo do DOM para suportar todo o XML 1.0, incluindo XML Infoset, XPath e XML Base.
Por parte dos navegadores web, o que apresenta o melhor nível de suporte ao DOM é o
Mozilla, enquanto que o Internet Explorer é o que apresenta o menor nível. A tabela 3
contém o suporte ao DOM por parte dos principais navegadores:
1
XML namespaces provêm uma maneira de classificar nomes de elementos e atributos usados em documentos
XML. Um namespace identifica nomes de maneira única evitando ambigüidade.
65
Navegador
Conformidade com o DOM
Netscape Navigator 1.0 - 4.x
-
Netscape 6.0+ (Mozilla 0.6.0+)
Nível 1, Nível 2, Nível 3 (parcial)
Internet Explorer 2.0 - 4.x
-
Internet Explorer 5.0
Nível 1 (mínimo)
Internet Explorer 5.5+
Nível 1 (quase completo)
Opera 1.0 - 6.0
-
Opera 7.0+
Nível 1 (quase completo), Nível 2 (parcial)
Safari 1.0+ / Konqueror ~2.0+
Nível 1
TABELA 3 – Suporte ao DOM pelos principais navegadores.
Um ponto importante destacado por Asleson e Schutta (2006) é que o DOM pode ser
facilmente confudido com JavaScript. O DOM é uma API que provê uma representação
estrutural do documento e define como o documento é acessado, enquanto que JavaScript
é uma linguagem usada para acessar e manipular o DOM. Sem o DOM, JavaScript não teria
qualquer noção de páginas web e os elementos que compõem as páginas. Cada elemento
em um documento é parte do DOM, que torna as propriedades e métodos dos elementos
disponíveis ao JavaScript.
Como já mencionado, o DOM é uma API baseada em árvore (tree-based). Isso
significa que ele representa o documento XML como uma árvore (ou hierarquia) de nós.
Considerando o documento XML do código 21, sua correspondente árvore de nós
representada pelo DOM é a exibida pela figura 12:
<?xml version="1.0"?>
<alunos>
<!-- Único aluno -->
<aluno>
<nome>João Silva</nome>
<idade>15</idade>
<comentarios><![CDATA[
Aluno aplicado em sala.
]]></comentarios>
</aluno>
</alunos>
CÓDIGO 21 – Documento XML.
66
FIGURA 12 – Árvore de nós representando documento XML.
Na figura 12, cada retângulo representa um nó na árvore do documento DOM, com o
texto em negrito indicando o tipo do nó e o texto comum indicando o conteúdo do nó. O nó
de comentário e o nó <aluno> são considerados nós filhos de <alunos>, pois aparecem
imediatamente abaixo dele. Portanto, <alunos> é considerado nó pai de ambos os nós
<aluno> e de comentário. Similarmente, <nome>, <idade>, e <comentarios> são todos
considerados nós filhos de <aluno> e também considerados irmãos (siblings) um do outro,
pois estão no mesmo nível na árvore DOM e possuem o mesmo nó pai. O nó document é
considerado o ancestral de todos os nós do documento.
Zakas (2005) relaciona os tipos de nó definidos pelo DOM:
– Document: o nó de mais alto nível ao qual todos os outros nós estão anexados;
– DocumentType: a representação em objeto de uma referência DTD; não pode
conter nós filhos;
– DocumentFragment: pode ser usado da mesma maneira que Document para
manter outros nós;
– Element: representa o conteúdo das tags de abertura e de fechamento, como em
<tag></tag>. É o único tipo de nó que pode conter atributos bem como nós filhos;
– Attr: representa um par nome-valor de atributo. Esse tipo de nó não pode ter nós
filhos;
– Text: representa o texto contido entre uma tag de abertura e uma de fechamento ou
dentro de uma seção CDATA. Não pode conter nós filhos;
– CDATASection: a representação em objeto de <![CDATA[ ]]>. Esse tipo de nó só
pode conter nós texto como nós filhos;
67
– Entity: representa uma definição de entidade em um DTD. Não pode conter nós
filhos;
– EntityReference: representa uma entidade de referência (ou entidade de caractere),
como &quot;. Este tipo de nó não pode ter nós filhos;
– ProcessingInstruction: representa uma instrução de processamento. Não pode
conter nós filhos;
– Comment: representa um comentário. Não pode conter nós filhos;
– Notation: representa notação definida em um DTD. Raramente utilizado.
Além dos tipos de nó listados, o DOM também define várias interfaces. As principais
são Document, Node, NodeList e NamedNodeMap. A interface Document representa o
documento inteiro e é a raiz da árvore deste. Essa interface contém métodos para a criação
de novos objetos que podem ser usados para adicionar novos elementos, nós de texto, e
atributos usando código. A interface contém os seguintes membros:
– documentElement: provê acesso direto ao elemento raiz do documento XML. Em
um documento XHTML, este é o elemento <html>;
– getElementsByTagName(nome_tag):
este método retorna uma coleção de
elementos do tipo NodeList com todos os elementos chamados nome_tag;
– createElement(nome_da_tag): método utilizado para criar um elemento do tipo
Element. O método cria um elemento com o nome de tag especificado:
oDocument.createElement("nome_tag");
Quando esse método cria um novo elemento, este ainda não possui uma posição
na árvore do documento. Ainda é necessário adicioná-lo, usando o método
appendChild():
oDocument.documentElement.appendChild(Document.createElement("nome_tag"));
– createTextNode(valor): cria nós de texto contendo “valor”, passado como
argumento. Isso é equivalente a adicionar texto dentro de um elemento. O código
abaixo cria um elemento <nome>João</nome>:
oElement = oDocument.createElement("nome");
oElement.appendChild(oDocument.createTextNode("João"));
oDocument.documentElement.appendChild(oElement);
– createAttribute(nome_atr): pode-se utilizar esse método para criar objetos do tipo
Attr (atributo). O valor de um atributo aparece em um nó de texto dentro deste
atributo, então é possível utilizar uma abordagem similar à usada para adicionar um
valor para um Element. É possível também utilizar a propriedade value para definir
o valor do nó texto em um atributo:
68
oAttribute = oDocument.createAttribute("ID");
oAttribute.value = "4";
oNamedNodeMap = oDocument.documentElement.attributes;
oNamedNodeMap.setNamedItem(oAttribute);
Este código cria um atributo com o valor 4, e então o insere na coleção de atributos
de um elemento através da chamada ao método setNamedItem() de um
NamedNodeMap, que será abordado mais adiante.
Document possui também os métodos para criar os demais tipos de nó:
– createCDATASection();
– createComment();
– createDocumentFragment();
– createEntityReference();
– createProcessingInstruction().
A interface Node representa um único nó na árvore do documento. É o bloco de
construção fundamental na representação de dados XML. Ela define uma série de
propriedades e métodos que todos os tipos de nós contêm. A figura 13, baseada em Jacobs
(2006, p. 231), demonstra a relação entre as principais propriedades da interface:
FIGURA 13 – Relação entre as principais propriedades da interface Node.
– attributes: essa propriedade retorna um NamedNodeMap que contém todos os
atributos de um nó Element. Para outros tipos de nó, essa propriedade retorna null;
69
– parentNode: propriedade que retorna o pai do nó corrente. Nós sem pais retornam
null. O código a seguir procura o pai do primeiro elemento <titulo>:
oDocument.getElementsByTagName('titulo')[0].parentNode;
– childNodes: retorna um NodeList que contém todos os nós filhos do nó selecionado.
Os tipos de nó de podem conter filhos são Attr, Document, DocumentFragment,
Element, Entity e EntityReference. Um texto dentro de um atributo é considerado
um nó filho deste atributo;
– firstChild e lastChild: a propriedade firstChild retorna o primeiro nó (tipo Node) da
coleção childNodes do nó corrente enquanto que lastChild retorna o último:
oNode = oDocument.documentElement.firstChild;
– previousSibling e nextSibling: essas propriedades retornam respectivamente o nó
anterior e o próximo nó que compartilham o mesmo pai que o nó corrente;
– nodeName: propriedade que retorna uma string contendo o nome do nó corrente;
– nodeValue: retorna o conteúdo do nó corrente. Para um elemento é null, mas para
um atributo ou um nó texto, a propriedade retorna o valor do atributo ou o conteúdo
do texto. O exemplo a seguir busca o texto contido no primeiro elemento <titulo>:
oDocument.getElementsByTagName('titulo')[0].firstChild.nodeValue;
– nodeType: essa propriedade fornece informação sobre o tipo do nó corrente. Cada
nó tem um valor inteiro mapeado que vai de 1 a 12. Esses valores podem ser
acessados
também
através
de
constantes
Node,
como
por
exemplo
Node.ELEMENT_NODE (valor 1) ou Node.TEXT_NODE (valor 3);
– hasChildNodes(): esse método retorna um valor booleano indicando se o nó
corrente possui nós filhos;
– appendChild(novo_filho): adiciona um novo filho ao fim da lista de nós filhos do nó
corrente. É preciso criar o nó antes de adicioná-lo:
oNewNode = oDocument.createElement("titulo");
oDocument.documentElement.appendChild(oNewNode);
– cloneNode(profundidade): esse método clona o nó existente, copiando todos os
seus atributos e valores. Possui o parâmetro boleano profundidade que determina
se a clonagem deve ser recursiva;
– insertBefore(novo_filho, filho_ref): insere um novo nó filho antes de um nó filho
existente. Se filho_ref é null, o nó filho é inserido como o último. Se o nó novo já
existe na árvore, o método o remove de sua posição original:
70
var oOldNode = oDocument.getElementsByTagName('titulo')[0];
oNewNode = oDocument.createElement('titulo');
oDocument.documentElement.insertBefore(oNewNode, oOldNode);
–
removeChild(filho): método que remove o parâmetro “filho” da coleção childNodes do
nó corrente. Retorna uma refêrencia ao nó removido;
–
replaceChild(novo_filho, filho_antigo): esse método substitui um nó filho do nó
corrente por um novo filho. O método retorna o nó substituído. O código a seguir cria
um novo nó e usa replaceChild para substituir o último elemento filho:
oNewNode = oDocument.createElement('titulo');
oRootNode = oDocument.documentElement;
oOldNode = oRootNode.replaceChild(oRootNode.lastChild, oNewNode);
É possível notar que as interfaces Document e Node permitem que nós sejam criados,
adicionados,
removidos
ou
substituídos.
Essas
funcionalidades
tornam
o
DOM
verdadeiramente dinâmico.
A interface NodeList lida com coleções ordenadas de nós. Cada nó na coleção é
indexado, iniciando em 0. Como visto anteriormente, a propriedade childNodes retorna um
NodeList. Essa interface possui a propriedade length, que indica o tamanho do NodeList, e o
método item(indice), o qual recebe como argumento um índice e retorna o nó
correspondente no NodeList. O exemplo abaixo usa um loop for para realizar uma iteração
através da coleção childNodes de documentElement e exibe um alerta mostrando o nome
de cada nó da coleção:
for(var i=0; i < oDocument.documentElement.childNodes.length; i++) {
alert(oDocument.documentElement.childNodes.item(i).nodeName);
}
A última interface, NamedNodeMap, representa uma coleção de nós que podem ser
acessados por nome ou índice. A coleção não é mantida em nenhuma ordem particular, e é
possível usar a interface para adicionar e remover nós da coleção. NamedNodeMap pode
ser retornado para coleções do tipo Entity ou Notation, mas é comumente associado à
coleção de atributos de um nó. A propriedade attributes de um nó do tipo Element é um
NamedNodeMap. A interface apresenta os mesmos membros item() e length de NodeList,
além dos seguintes:
– getNamedItem(nome_no): busca um nó por nome usando como parâmetro de
busca nome_no;
– removeNamedItem(nome_no): esse método usa o argumento nome_no para
determinar o nó a ser removido;
– setNamedItem(novo_no): recebe um Node como parâmetro e o adiciona à coleção:
71
var idAttr = oDocument.documentElement.firstChild.attributes.removeNamedItem("id");
oDocument.documentElement.lastChild.attributes.setNamedItem(idAttr);
O código anterior remove o atributo id do primeiro filho e o adiciona à coleção
attributes do último elemento filho.
Quando usado para representar atributos, cada nó de um NamedNodeMap é um nó do
tipo Attr, o qual sua propriedade nodeName contém o nome do atributo e nodeValue o seu
valor. O atributo id do exemplo anterior pode ter seu valor alterado através da atribuição de
um novo valor à propriedade nodeValue:
oDocument.documentElement.lastChild.getNamedItem("id").nodeValue = "novoid";
Nós Attr também possuem uma propriedade value que é exatamente igual a
nodeValue, bem como uma propriedade name igual a nodeName.
De acordo com Zakas (2005) existem três métodos adicionais que auxiliam na
designação de atributos:
– getAttribute(nome): é o mesmo que attributes.getNamedItem(nome).nodeValue;
– setAttribute(nome, novo_valor): equivalente a
attributes.getNamedItem(nome).nodeValue = novo_valor;
– removeAttribute(nome): equivalente a attributes.removeNamedItem(nome).
Esses métodos facilitam a manipulação de atributos, pois escondem os nós Attr e
permitem que o código se torne menor.
Junto com o desenvolvimento do DOM XML, a W3C ao mesmo tempo desenvolveu
um DOM mais específico ao XHTML (e HTML). Esse DOM define um HTMLDocument e
HTMLElement como base da implementação e, com exceção de um pequeno grupo de
elementos, cada elemento HTML é representado pelo seu próprio tipo HTMLElement
(HTMLDivElement, por exemplo, representa <div>). É através desse DOM que a
manipulação da página web pode ser realizada com JavaScript, permitindo a alteração da
interface do usuário na abordagem Ajax.
A criação do DOM HTML foi possível pois qualquer linguagem baseada em XML,
como XHTML, pode utilizar o núcleo do DOM por se tratar tecnicamente de XML. As
propriedades e métodos do núcleo do DOM (core DOM) são genéricas, feitas para funcionar
com qualquer documento XML em qualquer situação. O HTMLDocument, que é a
representação do Document do DOM XML e considerado a raiz da árvore do documento, é
representado em JavaScript pelo objeto document1.
1
Como visto no capítulo 4, o objeto document também é considerado parte do BOM.
72
O DOM HTML apresenta propriedades e métodos adicionais específicos do HTML que
tornam certas manipulações do DOM mais fáceis. Ele define, por exemplo, dois métodos
para acessar nós de forma específica:
– getElementsById(valor_id): esse método retorna um elemento com o atributo id
contendo um valor específico. Em HTML, o atributo id é único: não podem haver
dois elementos compartilhando o mesmo id. Este é sem dúvida o método mais
rápido de se acessar um único nó específico na árvore do documento. Supondo o
seguinte código HTML:
<div id="div_1">Conteúdo do div</div>
O elemento pode ser acessado da seguinte forma:
var oDiv1 = document.getElementById("div_1");
– getElementsByName(nome): busca todos os elementos que possuem o atributo
nome com o valor especificado. Considerando o seguinte trecho HTML:
<p>Qual sua fruta preferida?</p>
<input type="radio" name="radFruta" value="banana" />Banana <br/>
<input type="radio" name="radFruta" value="pera" />Pêra <br/>
<input type="radio" name="radFruta" value="laranja" />Laranja <br/>
Todos os botões radio possuem o mesmo atributo name, pois deseja-se apenas um
valor para esse campo. Para acessar esses elementos, pode-se utilizar o código:
var oRadios = document.getElementsByName("radFruta");
alert(oRadios[0].getAttribute("value")); // exibe banana
alert(oRadios[1].getAttribute("value")); // exibe pera
O DOM HTML também permite que atributos sejam acessados como propriedades.
Eles são adicionados aos elementos como propriedades, facilitando seu acesso. Supondo,
por exemplo, o elemento:
<img src="imagem.png" border="0" />
Para acessar e alterar os atributos src e border usando o núcleo do DOM, é
necessário utilizar os métodos getAttribute() e setAttribute(), como visto anteriormente:
alert(oImg.getAttribute("src"));
alert(oImg.getAttribute("border"));
oImg.setAttribute("src", "imagem_2.png");
oImg.setAttribute("border", "1");
73
Porém, através do DOM HTML é possível acessar e alterar esses valores usando
propriedades com o mesmo nome:
alert(oImg.src);
alert(oImg.border);
oImg.src = "imagem_2.png";
oImg.border = "1";
A única exceção em que o nome do atributo não é o mesmo que o nome da
propriedade é o atributo class, que especifica uma classe CSS a ser aplicada ao elemento.
Isso ocorre porque class é uma palavra reservada em ECMAScript e não pode ser usada
como nome de variável, propriedade ou função em JavaScript. Neste caso, o nome da
propriedade é className.
Utilizar propriedades para manipular atributos ao invés de usar getAttribute() e
setAttribute() não traz vantagens reais, além do fato de diminuir o tamanho do código e
torná-lo mais fácil de ser lido. Zakas (2005) ressalta que o navegador Internet Explorer tem
problemas com o método setAttribute(): quando ele é usado, as mudanças nem sempre são
refletidas corretamente, sendo melhor usar os atributos na forma de propriedades.
O DOM HTML também apresenta recursos específicos para facilitar a tarefa de
criação de tabelas, através da adição de uma série de propriedades e métodos aos
elementos <table>, <tbody> e <tr>. Para o elemento <table>, os principais são:
– tBodies: coleção de elementos <tbody>;
– tFoot: aponta para o elemento <tfoot>, caso exista;
– tHead: aponta para o elemento <thead>, caso exista;
– rows: coleção de todas as linhas (rows) da tabela;
– createTHead(): método que cria um elemento <thead> e o posiciona na tabela;
– createTFoot(): cria um elemento <tfoot> e o posiciona na tabela;
– deleteTHead(): remove o elemento <thead>;
– deleteTFoot(): remove o elemento <tfoot>;
– deleteRow(posição): remove a linha na posição especificada;
– insertRow(posição): insere uma linha na coleção rows na posição especificada.
Para o elemento <tbody> são adicionados os seguintes:
– rows: coleção de linhas no elemento <tbody>;
– deleteRow(posição): remove uma linha na posição especificada;
– insertRow(posição): insere uma linha na coleção rows na posição especificada.
Ao elemento <tr> são adicionados:
– cells: coleção de células (cells) no elemento <tr>;
74
– deleteCell(posição): remove a célula na posição especificada;
– insertCell(posição): insere uma célula na coleção cells na posição especificada;
<table border="1" width="100%"> <tbody>
<tr>
<td>Célula 1,1</td>
<td>Célula 2,1</td>
</tr>
<tr>
<td>Célula 1,2</td>
<td>Célula 2,2</td>
</tr>
</tbody>
</table>
CÓDIGO 22 – Tabela HTML.
A implementação para a criação da tabela do código 22 utilizando os métodos
específicos pode ser visto no código 23:
// criar tabela
var oTable = document.createElement("table");
oTable.setAttribute("border", "1");
oTable.setAttribute("width", "100%");
//criar o tbody
var oTBody = document.createElement("tbody");
oTable.appendChild(oTBody);
//criar primeira linha
oTBody.insertRow(0);
oTBody.rows[0].insertCell(0);
oTBody.rows[0].cells[0].appendChild(document.createTextNode("Célula
oTBody.rows[0].insertCell(1);
oTBody.rows[0].cells[1].appendChild(document.createTextNode("Célula
//criar segunda linha
oTBody.insertRow(1);
oTBody.rows[1].insertCell(0);
oTBody.rows[1].cells[0].appendChild(document.createTextNode("Célula
oTBody.rows[1].insertCell(1);
oTBody.rows[1].cells[1].appendChild(document.createTextNode("Célula
//adicionar a tabela ao corpo do documento
document.body.appendChild(oTable);
1,1"));
2,1"));
1,2"));
2,2"));
CÓDIGO 23 – Criação de tabela através do DOM HTML.
A criação dos elementos <table> e <tbody> utilizou os métodos já conhecidos do
núcleo do DOM, mas para a criação das duas linhas foram utilizados os métodos e
propriedades específicos do DOM HTML para tabelas. Eles permitem que o código se torne
mais lógico e legível, apesar de serem tecnicamente equivalentes aos métodos do núcleo do
DOM.
75
Outro recurso bastante importante do DOM é o acesso ao estilo CSS dos elementos e
às folhas de estilo CSS da página web, que permitem a mudança nos aspectos de
apresentação dos elementos de forma dinâmica através de código JavaScript, sendo um
recurso bastante empregado na técnica Ajax. O seguinte exemplo demonstra o acesso ao
estilo CSS de um elemento:
var oDiv = document.getElementById("div_1");
oDiv.style.border = "1px solid black";
oDiv.style.backgroundColor = "green";
Através do objeto style, é definido ao elemento <div> uma borda (style.border) de 1
pixel (1px), estilo sólido (solid) e de cor preta (black), além da cor de fundo
(style.backgroundColor) verde (green).
Supondo que as regras CSS anteriores tivessem sido definidas em uma folha de estilo
como da forma a seguir:
.div_1 {
border: 1px solid black;
background-color: green;
}
Seria possível acessá-las utilizando o código 24:
<html>
<head>
<title>Acesso a folhas de estilo</title>
<style type="text/css">
.div_1 {
border: 1px solid black;
background-color: green;
}
</style>
<script language="javascript">
function pegaCorFundo() {
var folhaEstilo = document.styleSheets[0].rules; // DOM
if(!folhaEstilo) {
folhaEstilo = document.styleSheets[0].cssRules; // Internet Explorer
}
alert(folhaEstilo[0].style.backgroundColor);
alert(folhaEstilo[0].style.border);
}
</script>
</head>
<body>
<div class="div_1"></div>
<input type="button" value="Pegar cor de fundo" onclick="pegaCorFundo()">
</body>
</html>
CÓDIGO 24 – Acesso a folha de estilo CSS através do DOM.
76
No código 24, o usuário ao clicar no botão “Pegar cor de fundo” verá um aviso com o
texto “green” (verde), que é a cor de fundo definida para a classe div_1. Para acessar esse
valor, primeiramente é estabelecida uma referência à folha de estilo da página
(document.styleSheets[0]) através da coleção document.styleSheets. Para acessar as
regras individuais na folha de estilo especificada, existe uma diferença entre os
navegadores: o DOM define para cada folha de estilo uma coleção chamada cssRules que
contém todas as regras CSS da folha de estilo, enquanto que o IE define a mesma coleção,
porém com o nome de rules. Cada uma das regras possui uma propriedade style, que é a
mesma encontrada em elementos, como visto anteriormente. Portanto, para obter uma
referência
à
regra
style.backgroundColor,
individual
que
por
background-color
sua
vez
através
pode
ser
de
style
referenciado
utiliza-se
como
document.styleSheets[0].cssRules[0].style.backgroundColor no caso do método para
navegadores DOM ou document.styleSheets[0].rules[0].style.backgroundColor para Internet
Explorer.
O DOM ainda possui outros recursos, como os ranges que podem ser usados para
selecionar uma seção de um documento independentemente de limites de nó, além de
NodeIterator e TreeWalker (ambos partes do DOM Level 2, não suportados pelo navegador
IE), que auxiliam tarefa de navegar através dos nós da árvore DOM. Os navegadores ainda
disponibilizam também algumas extensões ao DOM não padronizadas, como as
propriedades innerText, que permite acessar ou inserir texto entre uma tag de abertura e
fechamento, e innerHTML, cuja função é a mesma porém permite a inserção de código
HTML.
No próximo item, serão vistos exemplos de utilização do DOM e XML dentro da
abordagem Ajax.
5.3 DOM e XML na abordagem Ajax
De acordo com Jacobs (2006) é possível que código do lado cliente utilize documentos
XML como fonte de dados que podem ser trabalhados com JavaScript para gerar conteúdo
HTML dinamicamente. Isso permite que a página web seja atualizada sem a necessidade de
recarregá-la. A abordagem Ajax faz uso dessa possibilidade, empregando para isso o DOM
e o XML. A função do XML é servir como formato para a representação de dados, enquanto
que o DOM permite através de sua API o processamento do documento XML e a
atualização do conteúdo HTML da página web de maneira dinâmica através do JavaScript.
Na técnica Ajax, o XML pode ser empregado tanto nas requisições do cliente ao
servidor quanto nas respostas deste ao cliente. McLaughlin (2006) porém sugere que na
77
maioria das vezes XML não deve ser usado em requisições do cliente ao servidor, pois a
construção de uma requisição em XML não é tão simples quanto utilizar o tradicional texto
plano e pares de nome/valor. Clientes podem enviar requisições com múltiplos valores
usando pares de nome/valor facilmente, bastando adicionar o caractere & entre os
sucessivos pares, como em cargo=gerente&salario=1500. Quando pares nome/valor são
enviados, o navegador web que envia a requisição e a plataforma que hospeda o programa
servidor cooperam para transformar esses pares em dados com os quais o programa pode
trabalhar facilmente. Praticamente todas as tecnologias do lado servidor (server side) como
PHP e Java servlets possuem vários métodos para acesso aos dados baseados em
nome/valor, sendo portanto uma tarefa trivial. Além disso, XML não traz vantagens em
relação ao texto plano, já que não há quase nada que possa ser enviando usando XML que
não possa ser enviado utilizando texto com pares de nome/valor.
Em relação às respostas retornadas ao cliente, McLaughlin (2006) explica que a
recíproca não é verdadeira. O cliente não possui uma maneira fácil e padronizada de
processar vários pares de nome/valor, mas possui para o XML através do uso do DOM para
processar um documento XML recebido como resposta do servidor.
Embora não seja indicado na maioria das vezes, pode ser necessário enviar XML para
o servidor nos casos em que este apenas aceita requisições neste formato. Nessa situação,
é necessário criar um novo documento XML no cliente para envio ao servidor. Da mesma
forma que ocorre com o objeto XMLHttpRequest, existem duas maneiras: uma de acordo
com o DOM e a outra encontrada no navegador Internet Explorer, como visto no código 25.
var oXmlDoc = null;
// cria documento XML em navegadores DOM
if(document.implementation && document.implementation.createDocument) {
oXmlDoc = document.implementation.createDocument("", "", null);
}
// cria documento no navegador Internet Explorer
else if (window.ActiveXObject) {
oXmlDoc = new ActiveXObject("Microsoft.XMLDOM");
}
else {
alert("Não foi possível criar documento XML.");
}
CÓDIGO 25 – Criação de documento XML em JavaScript.
De maneira análoga ao objeto XMLHttpRequest, pode-se procurar instanciar a versão
mais recente do objeto documento DOM no Internet Explorer utilizando um loop for e um
vetor contendo todas as versões conhecidas. Uma vez criado, é possível adicionar conteúdo
ao documento utilizando os métodos já vistos do núcleo DOM, ou mesmo carregando um
arquivo XML através do método load(“nome_arquivo.xml”). O código 26 mostra uma
78
aplicação que envia uma requisição XML ao servidor para realizar um cadastro. Este então
retorna ao cliente um documento XML contendo o código de resposta para a requisição:
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<title>Exemplo de requisição XML</title>
<style type="text/css">
#divStatus {
background-color: yellow; display: block;
width: 220px; margin-top: 10px;
}
</style>
<script type="text/javascript">
function cadastraUsuario() {
var iNome = document.getElementById("inputNome").value;
var iEmail = document.getElementById("inputEmail").value;
if(iNome == "" || iEmail == "") {
alert("Dados incompletos."); return;
}
// criar documento XML
var docXml = criaDocumentoXML();
var xmlRaiz = docXml.createElement("requisicao");
var xmlNome = docXml.createElement("nome");
var xmlEmail = docXml.createElement("email");
xmlNome.appendChild(docXml.createTextNode(iNome));
xmlEmail.appendChild(docXml.createTextNode(iEmail));
xmlRaiz.appendChild(xmlNome);
xmlRaiz.appendChild(xmlEmail);
docXml.appendChild(xmlRaiz);
// converter documento para string
var xmlString = "";
if(window.XMLSerializer) {
//conversão em navegadores DOM
var serializer = new XMLSerializer();
xmlString = serializer.serializeToString(docXml,"text/xml");
}
else if(window.ActiveXObject) {
// conversão no navegador Internet Explorer
xmlString = docXml.xml;
}
else {
alert("Não foi possível realizar operação."); return;
}
realizaRequisicao(xmlString);
}
function criaDocumentoXML() {
var oXmlDoc = null;
// cria documento XML em navegadores DOM
if(document.implementation && document.implementation.createDocument) {
oXmlDoc = document.implementation.createDocument("", "", null);
}
// cria documento no navegador Internet Explorer
else if (window.ActiveXObject) {
oXmlDoc = new ActiveXObject("Microsoft.XmlDOM");
}
79
else {
alert("Não foi possível criar documento XML.");
}
return oXmlDoc;
}
function criaObjetoXHR() {
xmlhttp = null;
if (window.XMLHttpRequest) {
// navegadores Mozilla, Opera ou Safari
xmlhttp = new XMLHttpRequest();
}
else if (window.ActiveXObject) {
// navegador Internet Explorer
var XmlHttpVersions = new Array('MSXML2.XMLHTTP.6.0',
'MSXML2.XMLHTTP.5.0',
'MSXML2.XMLHTTP.4.0',
'MSXML2.XMLHTTP.3.0',
'MSXML2.XMLHTTP',
'Microsoft.XMLHTTP');
for(var i=0; i < XmlHttpVersions.length && !xmlhttp; i++)
{
try {
xmlhttp = new ActiveXObject(XmlHttpVersions[i]);
} catch(e) {
xmlhttp = null;
}
}
}
}
function realizaRequisicao(dados) {
criaObjetoXHR();
if(!xmlhttp) {
alert ("Não foi possível realizar a operação.");
return;
}
xmlhttp.onreadystatechange = processaResposta;
xmlhttp.open("POST", "http://localhost/processa.php", true);
xmlhttp.send(dados);
}
function processaResposta() {
if(xmlhttp.readyState == 4) {
var oDivStatus = document.getElementById("divStatus");
if(xmlhttp.status == 200) {
try {
var resposta = xmlhttp.responseXML;
var statusResposta =
resposta.getElementsByTagName("status")[0].firstChild;
switch(statusResposta.nodeValue) {
case "20": oDivStatus.firstChild.nodeValue = "Cadastro realizado.";
break;
case "10": oDivStatus.firstChild.nodeValue = "E-mail já existe.";
break;
default: oDivStatus.firstChild.nodeValue = "Erro desconhecido.";
}
80
} catch(e) {
document.body.removeChild(oDivStatus);
alert("Ocorreu um erro no processamento da resposta.");
}
} else {
document.body.removeChild(oDivStatus);
alert("Ocorreu um erro no envio da requisição.");
}
setTimeout("document.body.removeChild(document.getElementById('divStatus'))",
3000);
}
else {
var msgStatus = "Carregando ... status: "+xmlhttp.readyState;
if(!document.getElementById("divStatus")) {
var oDivStatus = document.createElement("div");
oDivStatus.setAttribute("id","divStatus");
oDivStatus.appendChild(document.createTextNode(msgStatus));
document.body.appendChild(oDivStatus);
}
else {
document.getElementById("divStatus").firstChild.nodeValue = msgStatus;
}
}
}
// adiciona manipulador do evento onclick
window.onload = function() {
document.getElementById("inputButton").onclick = cadastraUsuario;
}
</script>
</head>
<body>
<div>
Nome: <input id="inputNome" type="text" value="">
E-mail: <input id="inputEmail" type="text" value="">
<input id="inputButton" type="button" value="Cadastrar">
</div>
</body>
</html>
CÓDIGO 26 – Aplicação para cadastro de nome e e-mail.
No código 26, primeiramente o usuário digita seu nome e e-mail e pressiona o botão
“Cadastrar”. Em seguida, de acordo com o manipulador onclick definido para este botão
(definido através de window.onload), a função cadastraUsuario() é disparada, que por sua
vez verifica se os valores dos campos Nome e E-mail não são vazios (utilizando o método
getElementById() do DOM HTML), e então aciona a função criaDocumentoXML(). Essa
função cria um novo documento XML de acordo com o navegador em uso e retorna o objeto
à função cadastraUsuario(). Esta usa os métodos do núcleo DOM para criar os nós
(métodos createElement(), createTextNode() e appendChild()) e os anexa ao documento
criado. O objeto é então convertido em texto (string) para que possa ser enviado na
requisição ao servidor. Para essa operação também é necessário realizar uma verificação
de objeto/funcionalidade, pois o navegador Internet Explorer executa a operação de maneira
diferente dos navegadores DOM. Feita a conversão, a função realizaRequisicao() é
acionada, recebendo como argumento a string do documento XML. Esta função cria o objeto
81
XMLHttpRequest através de criaObjetoXHR() (como já visto anteriormente no código 18 do
capítulo 4) e faz uma requisição POST ao endereço http://localhost/processa.php, enviando
o documento XML através do método send(). Quando send() é disparado, a função
processaResposta(), definida como manipuladora do evento onreadystatechange, passa a
atuar, e enquanto a requisição está sendo processada (enquanto readyState é diferente de
4), ela exibe na interface do usuário uma mensagem informando que a ação está em curso
e qual é seu status atual. Isso é feito criando-se um elemento <div> e o adicionando à
página (document.body.appendChild()). A função setAttribute() também é usada para
designar um atributo id ao elemento, de maneira que ele possa incorporar as regras de
estilo CSS definidas para este id e também para que possa ser localizado posteriormente
pelo método getElementById(). No momento em que o processamento termina (readyState
igual a 4), verifica-se o status HTTP da requisição (200 significa requisição bem sucedida) e
então a resposta, que também é um documento XML, é processada. Esse documento
contém uma tag <status> que contém o código de status da operação. Através do método
do núcleo DOM getElementsByTagName(), o valor dessa tag é acessado e uma mensagem
é exibida ao usuário (utilizando o <div> previamente criado) de acordo com o número de
status encontrado (bloco switch-case). O documento XML de resposta é processado dentro
de um bloco try-catch porque caso haja algum erro no XML enviado pelo servidor, uma
exceção é disparada e o erro é tratado exibindo uma mensagem de aviso ao usuário. Por
fim, utiliza-se o método do BOM do JavaScript setTimeout() para que a mensagem exibida
ao usuário (elemento <div>) seja removida da página em três segundos. É importante
lembrar que todas as operações são feitas de forma assíncrona, ou seja, em nenhum
momento a página fica bloqueada para uso pelo usuário. A figura 14 exibe a aplicação
sendo utilizada no momento em que a requisição está em andamento.
FIGURA 14 – Aplicação realizando requisição XML.
Embora seja um exemplo simples, a aplicação mostra os conceitos e a integração das
várias tecnologias que compõem a abordagem Ajax.
82
6. PROTÓTIPO
A utilização de grades de dados em páginas web sempre foi uma tarefa difícil de ser
realizada devido a sua natureza tradicionalmente estática, sendo uma área em que
aplicações web sempre apresentaram desvantagens em relação às aplicações desktop. A
necessidade de um completo recarregamento da página ao atualizar células de um registro
ou mudar a página da grade compromete a usabilidade da aplicação e inviabiliza seu uso
para esse tipo de tarefa.
Como já visto nesse estudo, a abordagem Ajax se propõe a tornar as aplicações web
dinâmicas e interativas, através da troca de dados com o servidor de forma assíncrona e da
atualização dinâmica da interface do usuário. Grades de dados apresentam uma demanda
inerente por interatividade e usabilidade e necessitam de atualização dinâmica da interface,
justamente os requisitos aos quais Ajax procura atender. Dessa maneira, isso torna uma
aplicação web que disponibilize uma grade de dados utilizando Ajax um excelente exemplo
de aplicação da abordagem e uma boa maneira de avaliar sua aplicabilidade para o fim a
que se propõe.
O protótipo desenvolvido, portanto, faz uso de uma grade de dados na forma de um
cadastro de clientes. A implementação buscou atender aos seguintes requisitos:
– o usuário deve ser capaz de interagir com a grade atualizando qualquer campo de
um registro de maneira dinâmica, sem a necessidade de recarregar a página;
– deve ser possível adicionar um novo registro, e para tanto a aplicação deve
gerenciar a atualização da interface para disponibilizar os novos campos para
inserção do cadastro e em seguida incorporar o novo registro aos demais já
existentes;
– o usuário deve ser capaz de navegar entre os registros utilizando as setas para
cima e para baixo, como o faria em uma grade de uma aplicação desktop;
– é necessária que a edição de um registro possa ser cancelada a qualquer momento
através da tecla ESC ou de um clique do mouse fora da área de edição, retornando
os dados alterados mas não salvos aos seus valores originais;
– deve ser possível realizar uma busca por nome de cliente, e o resultado levar o
usuário automaticamente aonde o registro se encontra na grade;
– a aplicação deve permitir ao usuário personalizar configurações, sendo possível
definir quantos registros serão exibidos por página e a aparência (look and feel) da
interface.
83
Os requisitos descritos buscam aproximar as funcionalidades do protótipo às de uma
aplicação desktop, procurando avaliar a efetividade da técnica Ajax. A interface
disponibilizada pelo protótipo é a exibida na figura 15:
FIGURA 15 – Interface do protótipo Ajax.
6.1 Funcionamento e estrutura
A aplicação é composta por um conjunto de arquivos, com finalidades específicas e
estruturados da seguinte maneira:
– ajax/index.html: ponto de partida da aplicação, trata-se de uma página HTML
contendo a estrutura do documento a ser exibido ao usuário. Ao término do
carregamento do arquivo, a função JavaScript iniciar(), embutida no elemento body
como manipuladora do evento onload, é disparada e dá início ao funcionamento do
motor Ajax.
84
– ajax/proto.js: arquivo principal da aplicação, contém toda a lógica JavaScript
responsável pelo funcionamento do protótipo. No momento que a função iniciar() é
disparada, todos os manipuladores de evento são adicionados aos elementos do
documento HTML e conforme o usuário dispara um determinado evento, uma
função correspondente contida nesse arquivo é chamada para responder à ação
realizada.
– ajax/css/base.css: arquivo contendo as regras CSS que definem a aparência básica
da interface. Conforme determinam os web standards, todas as definições de
apresentação (CSS) encontram-se separadas das definições de estrutura (HTML).
– ajax/css/seta.png: imagem contendo uma seta utilizada para indicar o registro sobre
o qual o mouse se encontra.
– ajax/css/temas/padrao.css: regras CSS que definem a aparência do tema Padrão.
– ajax/css/temas/azul.css: regras CSS que definem a aparência do tema Azul.
– ajax/css/temas/vermelho.css: regras CSS que definem a aparência do tema
Vermelho.
– cgi-bin/servidor.cgi: aplicação C++ que atua como um CGI responsável por
responder às requisições da aplicação Ajax, retornando as respostas no formato de
um documento XML a ser processado pelo cliente;
– cgi-bin/banco.dat: arquivo utilizado pela aplicação CGI que representa o banco de
dados contendo os registros dos clientes.
No momento em que o documento HTML termina de ser carregado e a função iniciar()
é executada, começa a funcionar o motor Ajax. O protótipo funciona baseado nesse motor
que, de acordo com as ações que o usuário realiza, dispara um evento JavaScript que por
sua vez executa a função definida como manipuladora do evento. Esse manipulador realiza,
quando necessário, uma requisição ao servidor (aplicação CGI), processa a resposta deste
e atualiza a interface da página de maneira a responder à ação do usuário. O processo de
definição das funções manipuladoras é feito de maneira análoga ao trecho a seguir, o qual
associa a função irPrimeiraPag() ao elemento oLinkNavPri, elemento este que representa o
link "<< Primeira" usado para mover-se até a primeira página da grade.
oLinkNavPri.onclick = function() { irPrimeiraPag(); };
As requisições feitas ao servidor são enviadas no formato de pares nome/valor e as
respostas são recebidas na forma de um documento XML, seguindo as definições vistas no
item 5.3 do capítulo 5. O trecho do código 27, extraído do arquivo proto.js, mostra como os
dados da requisição são criados para solicitar o envio dos registros dos clientes:
85
function irPrimeiraPag() {
Sessao.registroAtual = 0;
var dadosReq = "ACAO=BUSCARCLIENTES&REGISTROATUAL=1&QTDREG=" +
Config.registrosPagina;
Sessao.xmlhttpAux.funcaoAcao = atualizarTabela;
realizaRequisicao(dadosReq, Config.appServidor);
}
CÓDIGO 27 – Criação dos pares nome/valor e envio de requisição.
O código é referente à função responsável por buscar os registros pertencentes à
primeira página da grade de dados. A requisição é composta da ação a ser realizada
(ACAO=BUSCARCLIENTES), o registro inicial (REGISTROATUAL=1) e o registro final
(QTDREG=Config.registrosPagina), sendo Config.registrosPagina a variável que define a
quantidade de registros que são exibidos por página.
A aplicação CGI do lado servidor, ao receber a requisição, acessa a base de dados e
cria o documento XML de resposta, que é posteriormente processado pelo cliente através
do DOM parser. O documento XML de resposta apresenta a seguinte estrutura:
<?xml version='1.0' encoding='UTF-8'?>
<resposta>
<total>15</total>
<cadastro>
<cliente>
<id>10</id>
<nome>João da Silva</nome>
<endereco>Rua do Cacique, 10</endereco>
<telefone>3867-5119</telefone>
<ativo>0</ativo>
</cliente>
</cadastro>
</resposta>
CÓDIGO 28 – Documento XML contendo resposta do servidor.
A função responsável pela comunicação com o servidor é realizaRequisicao(), que
define os parâmetros da requisição e a executa através do método send() do objeto
XMLHttpRequest. Recebida a resposta, é necessário processar o documento XML recebido
e atualizar a interface do usuário. No caso do código 27, a função responsável por essa
tarefa é atualizarTabela(), definida através da propriedade funcaoAcao. Essa função recebe
a estrutura DOM contendo o XML da resposta e a utiliza para atualizar a interface do
usuário, redesenhando a grade com os novos dados recebidos. Todas as ações do motor
Ajax que envolvem comunicação com o servidor seguem o fluxo descrito, com variações nas
funções a serem utilizadas e dados a serem enviados na requisição. De maneira geral,
86
depois que o usuário dispara o evento, o motor Ajax é acionado, executando a função
associada ao elemento e ao evento em questão, realizando quando necessário uma
requisição ao servidor através do objeto XMLHttpRequest do JavaScript e atualizando a
interface da aplicação através da alteração do DOM da página, respondendo à ação do
usuário.
É importante lembrar que a comunicação feita com o servidor é feita de forma
assíncrona, não havendo bloqueio no uso da aplicação por parte do usuário. Para que o
usuário esteja ciente de que a comunicação está em andamento, o protótipo sempre exibe
uma mensagem de "Processando ..." que é removida ao término do processamento, como
uma maneira de informar ao usuário que a resposta à sua ação está em andamento. A
mensagem pode ser vista através da figura 16.
FIGURA 16 – Protótipo exibindo aviso de resposta em andamento.
6.2 Recursos
Um dos recursos que a aplicação disponibiliza ao usuário é a capacidade de editar
registros e adicionar novos. O acesso à edição de um registro é feito clicando-se sobre um
de seus campos. Nesse momento, os campos do registro tornam-se editáveis e a opção de
salvar surge ao final da linha. O usuário pode editar os valores e submeter os dados
clicando em "Salvar", ou cancelar a edição tanto pressionando a tecla ESC quanto mudando
o foco para qualquer outro elemento da página (clicando em outro registro, por exemplo). A
figura 17 exibe um campo habilitado para edição:
87
FIGURA 17 – Registro habilitado para edição.
O usuário pode inclusive navegar entre os registros utilizando o teclado através das
teclas para cima e para baixo, como faria em uma tabela de uma aplicação desktop. Isso é
possível graças ao evento onkeydown, que captura a tecla pressionada e associa a ela um
código (keyCode), como visto no capítulo 4. O trecho do código 29, extraído de uma
declaração switch-case, demonstra como é implementado o recurso:
// seta para cima
case 38:
{
if(!alvoTr.previousSibling) { return; }
novoAlvo = alvoTr.previousSibling.firstChild;
cancelarEdicao(e);
var eNovo = new Object();
eNovo.target = novoAlvo;
novoAlvo.onclick(eNovo);
break;
}
CÓDIGO 29 – Implementação da navegação pelo teclado.
A função do código basicamente é identificar a tecla pressionada (38, número
correspondente à seta para cima), definir o registro imediatamente acima como o novo alvo,
cancelar a edição do registro atual e acionar a edição do outro registro.
A adição de um novo cadastro é disponibilizada pelo botão "Cadastrar Novo". No
momento em que o usuário o pressiona, a aplicação desloca-se para a última página da
grade e insere uma nova linha em branco, para que o usuário entre com os novos dados. De
maneira análoga à edição de um cadastro já existente, o usuário pode cancelar a operação
através da tecla ESC ou mudando o foco da linha para outro elemento. Neste caso, a nova
linha é automaticamente removida. Se o usuário selecionar "Salvar", a aplicação verifica se
os valores são válidos (campos em branco não são permitidos) e envia o novo registro ao
servidor, exibindo em seguida na tela uma mensagem informando ao usuário que a
88
operação foi bem sucedida. A figura 18 exibe a aplicação no momento do cadastro de um
novo cliente, após o usuário tentar submeter valores em branco.
FIGURA 18 – Usuário cadastrando novo registro.
Sempre que necessário, avisos iguais ao ilustrado na figura 18 são exibidos ao usuário
para informá-lo de que este está realizando uma ação inválida ou retornar uma mensagem
de sucesso ou falha, em resposta a alguma operação. Os avisos são exibidos e removidos
dentro de um determinado intervalo, recurso implementado através da utilização do método
JavaScript setTimeout, que permite o agendamento de um código a ser executado depois
de um intervalo definido, e da regra CSS visibility, que permite alterar a visibilidade de um
dado elemento do documento.
Na parte superior da grade de dados são exibidas informações referentes ao total de
clientes cadastrados (canto superior esquerdo), página atual, número de páginas e registros
em exibição (canto superior direito). Para navegação entre as páginas, existem na parte
inferior direita da grade os links "<<Primeira" (muda para a primeira página), "< Anterior"
(página anterior), "Próxima >" (próxima página) e "Última >>" (última página). Tais links são
atualizados dinamicamente conforme a página em que o usuário se encontra, de maneira
que caso o usuário esteja na primeira página os links "< Anterior" e "<< Primeira" estarão
desabilitados. Esse comportamento pode ser visto através da figura 19:
FIGURA 19 – Links para navegação das páginas.
89
Para auxiliar no processo de edição da grade, o protótipo disponibiliza outros recursos
através das abas localizadas na parte inferior da tela. O conteúdo de cada uma das abas é
exibido dinamicamente, conforme o usuário seleciona a aba desejada. Quando a aplicação
é iniciada a aba que surge por padrão é "Procurar". Sua função é auxiliar o usuário no
processo de busca de um determinado registro, permitindo a este realizar uma procura
através do nome do cliente. O usuário digita o nome desejado e a aplicação retorna os
resultados da busca. Se nenhum nome for encontrado, a aplicação exibe o aviso
correspondente na parte superior da tela, de maneira semelhante ao visto na figura 18.
Caso registros sejam encontrados, uma tabela com os registros correspondentes é exibida,
e no momento em que o usuário pressiona o botão do mouse sobre o registro desejado a
aplicação automaticamente muda a grade para a página correspondente e aciona o registro
para edição. Essa operação pode ser vista na figura 20.
FIGURA 20 – Registro sendo editado após busca através da Aba "Procurar".
Depois de terminada a procura, o usuário pode fechar a tabela com os resultados com
um clique em "Fechar", localizado no canto superior direito desta.
90
A segunda aba, "Configurações", disponibiliza três opções ao usuário. A primeira é a
possibilidade de determinar a quantidade de registros a serem exibidos por página, num
intervalo de 5 a 15. Conforme o usuário altera o número, a aplicação automaticamente
atualiza a grade, alterando a quantidade de registros sendo exibidos para o número
selecionado e recalculando o número total de páginas.
A segunda opção da aba permite ao usuário selecionar o tema de sua preferência a
ser adotado para a interface da aplicação. Alterar o tema faz com que a aparência (look and
feel) da aplicação mude, utilizando por exemplo novas cores e fonte de letra. A figura 21
exibe as opções da aba "Configurações", com a grade configurada para exibir 6 registros
por página e a interface utilizando o tema alternativo azul.
FIGURA 21 – Aplicação usando tema azul e exibindo a aba "Configurações".
A implementação do recurso de seleção de tema consiste em remover do DOM da
página o elemento <link> referente ao arquivo CSS que contém o tema atual, e adicionar um
novo <link> apontando para o arquivo CSS do novo tema. A implementação pode ser vista
no código 30:
91
function mudarTema(nomeTema) {
var oLink = document.createElement("link");
oLink.href = "css/temas/" + nomeTema;
oLink.type = "text/css";
oLink.rel = "stylesheet";
var oHead = document.getElementsByTagName("head")[0];
oHead.removeChild(oHead.getElementsByTagName("link")[1]);
oHead.appendChild(oLink);
}
CÓDIGO 30 – Função que implementa o recurso de mudança de tema.
A última opção da aba permite ao usuário selecionar qual método HTML (GET ou
POST) deseja utilizar na comunicação da aplicação com o servidor. No momento em que o
usuário seleciona um método diferente, a aplicação automaticamente envia uma requisição
ao servidor solicitando dados e muda a grade para a primeira página, como uma maneira de
se testar o funcionamento do método selecionado. Caso o método não esteja funcional (por
restrição do servidor de páginas, por exemplo), um aviso é exibido ao usuário informando-o
da falha na comunicação, podendo o usuário retornar ao método anterior. No caso do
método GET, é necessário evitar o armazenamento da resposta em cache por parte do
navegador. Para tanto é adicionado ao final da string que contém os dados a serem
enviados a data atual, de maneira que a URL sempre será diferente e o navegador nunca
armazenará em cache a resposta. A implementação dessa funcionalidade pode ser vista no
código 31:
var dataAtual = new Date();
var stringData = dataAtual.getFullYear() + "" + dataAtual.getMonth() + "" +
dataAtual.getDate() + "" + dataAtual.getDay() + "" +
dataAtual.getHours() + "" + dataAtual.getSeconds() + "" +
dataAtual.getMilliseconds();
Sessao.xmlhttp.open("GET",url+"?"+encodeURIComponent(dados)+
"&CONTROLE="+stringData);
Sessao.xmlhttp.send(null);
CÓDIGO 31 – Técnica para evitar armazenamento de resposta para GET.
A última aba, "Sobre", não disponibiliza recursos adicionais, sendo apenas de caráter
informativo. Ao ser selecionada ela exibe o nome do protótipo e o autor.
92
6.3 Resultados
Como resultado da implementação do protótipo é possível notar a proximidade que
este apresenta em relação às aplicações desktop. A possibilidade de navegar entre os
registros através do teclado e recursos como a edição e criação de registros sem a
necessidade de recarregamento, deslocamento entre as páginas da grade sem bloqueio da
aplicação, e a possibilidade do usuário selecionar um tema para aparência da interface são
recursos encontrados apenas em programas desktop, como planilhas de cálculo por
exemplo.
O processo de desenvolvimento do protótipo tornou possível perceber de maneira
efetiva como as tecnologias empregadas se relacionam. A utilização de JavaScript na
codificação da lógica da aplicação, juntamente com a manipulação da API DOM para a
alteração da estrutura da página são os elementos fundamentais no funcionamento da
aplicação. O uso de documentos XML na recepção de dados do servidor mostrou ser uma
maneira eficaz e simples de manipulador dados, pois é um formato de fácil manuseio e
através do DOM parser é possível manipular o documento da mesma maneira que se
manipula os elementos da página web, visto que se trata da mesma API.
O emprego do objeto XMLHttpRequest na comunicação com o servidor permite um
eficiente controle sobre a operação, sendo possível identificar erros de comunicação e de
resposta, além da possibilidade de informar ao usuário que a operação está em andamento,
sempre de forma assíncrona sem comprometimento da usabilidade da aplicação por parte
do usuário. O par HTML/CSS possibilita uma separação clara entre estrutura e
apresentação, o que facilita o trabalho do desenvolvedor, e CSS em particular fornece um
alto nível de controle sobre a aparência dos elementos tornando possível a alteração da
aparência de toda a estrutura da página com um clique do mouse, como mostrado no
funcionamento do protótipo.
Em contrapartida, devido ao nível de controle e recursos que esse conjunto de
tecnologias disponibiliza ao programador, as aplicações web feitas em Ajax apresentam
uma codificação mais complexa do que as aplicações tradicionais, chegando a um nível de
dificuldade próximo ao de aplicações desktop. Além disso, existe a questão da
compatibilidade entre navegadores, que torna o esforço de se criar uma aplicação ainda
maior, pois em determinados momentos é necessário criar código duplicado para a mesma
funcionalidade, um para cada tipo de navegador.
Após o estudo do modelo de funcionamento do Ajax, de suas tecnologias e em vista
dos resultados provenientes da implementação do protótipo, no capítulo a seguir são
definidas as conclusões sobre a utilização da técnica no desenvolvimento de aplicações
web.
93
7. CONCLUSÕES
No início deste estudo foi abordada a questão relativa à demanda que os usuários
apresentam por interfaces que facilitem o uso do software, permitindo a eles comunicar o
que deve ser feito de maneira eficiente e ágil. Em meio a este contexto surgem os conceitos
de usabilidade e interatividade que, quando aplicados ao software, definem qual o nível de
qualidade do meio de comunicação que este oferece ao usuário. Nesse aspecto, é clara a
diferença que existe entre a interação do usuário com um editor de textos comum (aplicação
desktop) e uma página web contendo um formulário de cadastro. Como visto anteriormente,
aplicações desktop são ricas nas maneiras em que a interação pode ocorrer, enquanto
aplicações web apresentam um paradigma requisição-resposta que compromete a
qualidade de sua interface. Com o uso cada vez maior da Internet, a demanda por
interatividade como a proporcionada pela aplicação desktop cresce e é preciso satisfazê-la.
Ajax se propõe a atender tal necessidade, combinando uma série de recursos de várias
tecnologias já existentes com um novo paradigma de funcionamento da aplicação web.
Após a realização do estudo do modelo de funcionamento do Ajax e dos recursos
disponíveis nas tecnologias que este utiliza, juntamente com os resultados provenientes da
implementação do software protótipo, é possível concluir que esta abordagem é capaz de
atender o objetivo a que se propõe. Como pôde ser constatado, através da experiência de
uso do protótipo, Ajax torna a aplicação web muito mais dinâmica e coloca o nível de
qualidade de sua interface bastante próximo ao nível das aplicações desktop. A utilização de
um motor Ajax que capta as ações do usuário e responde a elas de forma contínua, sem a
necessidade de recarregamento da interface, é o ponto fundamental da técnica. O motor
Ajax é uma verdadeira aplicação responsável por gerenciar todo fluxo de funcionamento do
programa. Isso significa que o navegador deixa de hospedar apenas conteúdo e passa a
hospedar a aplicação em si enquanto o servidor passa a fornecer dados ao invés de
conteúdo. A vantagem imediata é a diminuição do tráfego entre cliente e servidor, como
pôde ser visto através do protótipo: o cliente envia pequenas requisições, e o servidor
retorna apenas os dados necessários ao funcionamento da aplicação, ao invés de enviar
toda a interface novamente a cada nova requisição, como no modelo tradicional. Além disso,
a interação do usuário com a aplicação é mais contínua, já que a resposta consiste em
atualizar apenas alguns aspectos da interface ao invés do processo completo.
Apesar das várias vantagens que a adoção da técnica apresenta, Jacobs (2006)
lembra que Ajax não é um substituto para os outros modelos de aplicações web. Em alguns
casos Ajax pode não ser indicado, como por exemplo em situações em que é preciso
carregar páginas inteiras. O ponto importante a ser ressaltado é que a abordagem deve ser
utilizada para o fim a que se destina, ou seja, aplicações web que demandam maior
94
interatividade com o usuário. Nem todas as páginas web necessitam de um motor Ajax, o
que significa que a técnica não deve ser adotada indistintamente. Existem ainda
implementações que fazem uso de Ajax para funcionalidades especifícas dentro de uma
página web conforme a necessidade, sem obrigatoriamente adotar a abordagem em todo o
site.
O emprego da técnica Ajax também apresenta desvantagens, tais como:
– Botão "Voltar" (Back) do navegador: devido ao fato da aplicação Ajax realizar todas
as ações na mesma página e as requisições feitas com o objeto XMLHttpRequest
não serem gravadas no histórico do navegador, o botão "Voltar" (Back) deixa de
produzir o mesmo resultado que as aplicações web tradicionais. Isso pode ser um
ponto negativo para os usuários que estão familiarizados com a utilização do botão
para navegar dentro da aplicação. Para contornar essa questão, existem
implementações disponíveis que fazem o botão produzir o resultado desejado.
– Bookmarks: como o endereço da página não muda durante a execução da
aplicação, não é possível fazer bookmarks.
– Segurança: sendo o código fonte da aplicação visível para o navegador, ele pode
ser acessado por qualquer pessoa que pode tentar descobrir como a aplicação foi
feita.
Tendo em vista que as aplicações Ajax se encontram muito próximas das aplicações
desktop, é natural que suas características também sejam semelhantes. Ou seja, da mesma
maneira que uma aplicação desktop não apresenta um botão "Voltar" igual ao do navegador
web e não disponibiliza bookmarks, o mesmo ocorre com a aplicação Ajax. Ainda assim,
havendo a necessidade, Ajax possui os recursos necessários para que o desenvolvedor
possa disponibilizar funcionalidades equivalentes. Como citado já existem implementações
que corrigem o comportamento do botão "Voltar" e é possível criar mecanismos de
salvamento de estado em substituição aos bookmarks.
Com relação à segurança, uma vez que a aplicação cliente apenas envia requisições e
quem efetivamente implementa a lógica de negócio é a aplicação do lado servidor, o fato do
usuário poder acessar o código fonte da aplicação Ajax não representa um problema real de
segurança. Uma pessoa que esteja visualizando as requisições enviadas por qualquer
aplicação web a um servidor (interceptando o tráfego de rede, por exemplo) terá
praticamente o mesmo nível de acesso a informações que uma pessoa acessando o código
fonte desta aplicação. Além disso, o próprio modelo atual já apresenta essa característica.
Ainda assim, existe controvérsia em relação ao tema segurança em Ajax. Alguns
especialistas não vêem grandes problemas de segurança. Pascarello, por exemplo,
referenciado em Frye (2006), afirma que a utilização do objeto XMLHttpRequest não é nada
95
mais do que uma submissão normal de um formulário igual ao de páginas web
convencionais, e que as mesmas informações possíveis de serem visualizadas no objeto
XHR também podem ser visualizadas no código fonte de qualquer página web. Em
contrapartida, outros especialistas consideram que o emprego da abordagem torna os
problemas de segurança maiores. Hoffman, referenciado em Hines (2006), afirma que
“Aplicações Ajax possuem uma grande superfície de ataque, muito maior que as aplicações
tradicionais”. Por estar fora do escopo deste trabalho, a questão não será abordada a fundo,
mas apresenta um vasto campo para pesquisa e caracteriza-se como uma oportunidade a
outros pesquisadores interessados em estudar o tema em trabalhos futuros.
7.1 Frameworks
No processo de adoção da técnica Ajax existem ainda as questões relativas à
compatibilidade entre navegadores e o aumento da complexidade do código. Apesar de Ajax
empregar uma série de tecnologias baseadas em padrões W3C, muitas vezes ocorrem
discrepâncias principalmente entre o funcionamento dos navegadores que seguem o padrão
DOM e o navegador Internet Explorer. Esse fato pôde ser observado durante a
implementação do protótipo deste trabalho e obriga o desenvolvedor a ter um esforço
adicional para criar soluções que contemplem as diferenças entre os navegadores. Apesar
de ser um ponto negativo, não é na verdade uma desvantagem em relação ao modelo
tradicional, uma vez que este também utiliza as mesmas tecnologias. O que ocorre na
verdade é que o problema se torna mais evidente na medida em que a complexidade do
código da aplicação aumenta com o emprego da abordagem. Uma vez que a aplicação
dispõe de um maior número de recursos e se aproxima da aplicação desktop, o mesmo
ocorre com o código, que aumenta sua complexidade. Para facilitar o processo de geração
de código Ajax, diminuindo sua complexidade e evitando os problemas relativos à
compatibilidade de navegadores, é possível encontrar um grande número de frameworks
Ajax disponíveis. A maioria é de código aberto (open source), mas também existem alguns
proprietários. Os principais são:
– Dojo: framework de código aberto e um dos mais antigos, seu objetivo é
disponibilizar um kit de ferramentas enquanto foca em questões de usabilidade.
Para utilizar o objeto XMLHttpRequest por exemplo, ao invés do desenvolvedor
realizar toda a configuração do objeto basta realizar uma chamada ao método bind,
definindo a URL a ser feita a requisição e o método que manipulará a resposta. Um
destaque é o suporte aos botões "Voltar" (Back) e "Avançar" (Forward) do
navegador, sendo possível definir uma função a ser chamada quando o usuário
96
pressiona um dos botões. Dojo também procura solucionar a questão dos
bookmarks em aplicações Ajax disponibilizando uma flag chamada changeURL.
– qooxdoo: também um framework de código aberto, disponiliza vários recursos
encontrados em aplicações desktop como menus, tooltips, desenho de grades de
dados e suporte a arrastar-e-soltar (drag and drop), possui boa documentação e
seu ponto forte são os elementos sofisticados como os citados.
– Sarissa: liberado sob a licença General Public License (GPL), este framework
permitir trabalhar de forma independente de navegador oferecendo suporte a APIs
XML e facilitando o trabalho com o objeto XMLHttpRequest, não sendo necessário
realizar checagens no navegador, além de também oferecer suporte para trabalhar
com o DOM.
– Sajax: também sob código aberto, este framework permite a realização de
chamadas a código do lado servidor diretamente a partir do JavaScript. Suporta
várias linguagens como Perl, Python, Ruby e ASP.
Também merece destaque o framework disponibilizado pela Google, empresa que tem
feito uso intensivo da abordagem Ajax em seus produtos, como o GMail e o Google Maps.
Trata-se de um framework que permite o desenvolvimento de aplicações Ajax utilizando a
linguagem
Java.
De
acordo
com
a
descrição
da
própria
Google
(http://code.google.com/webtoolkit/overview.html, nov. 2007), com o Google Web Toolkit
(GWT) "você pode desenvolver e depurar aplicações Ajax na linguagem Java usando as
ferramentas de desenvolvimento Java de sua escolha. [...] o compilador GWT traduz sua
aplicação Java para JavaScript e HTML em conformidade com o navegador."
Os
frameworks
apresentam-se
como
uma
alternativa
bastante
viável
ao
desenvolvimento de código Ajax sem que haja a necessidade de enfrentar as questões
referentes à maior complexidade do código e à compatibilidade entre navegadores.
Utilizando suas bibliotecas, o desenvolvedor não precisa se preocupar em checar as
particularidades de implementação específicas de cada navegador e tem à sua disposição
APIs prontas para a utilização de poderosos recursos da abordagem, sendo possível
preocupar-se apenas com a funcionalidade específica de sua aplicação.
7.2 Considerações finais
Como conclusão, pode-se definir a abordagem Ajax como uma alternativa indicada e
viável de se superar o modelo estático tradicional da web com o objetivo de desenvolver
aplicações com melhores recursos de usabilidade e interatividade. Observado o fato de ser
97
utilizada para o fim a que se destina, a técnica demonstra eficiência na criação de
aplicações que atendam a demanda crescente dos usuários por maior interatividade na web
e por uma experiência de utilização mais próxima da oferecida por aplicações desktop. Suas
desvantagens não comprometem a adoção, na medida em que ela própria disponibiliza os
recursos para que tais desvantagens sejam endereçadas. Implementações específicas
podem solucionar as questões referentes ao botão "Voltar" do navegador e ao uso de
bookmarks, enquanto que a variedade de frameworks disponíveis diminui a complexidade
do código e elimina a necessidade de esforço adicional para solucionar problemas de
incompatibilidade entre navegadores. Apesar de recente, Ajax tem sido cada vez mais
empregado na web e sua adoção tende a crescer nos últimos anos, desenhando um
panorama futuro de cada vez mais funcionalidades, antes exclusivas das aplicações desktop
(como editores de textos e planilhas), migrando para a web. Exemplo disso é a empresa
Google, que atualmente já disponibiliza seu próprio editor de textos e uma planilha de
cálculo através da web, semelhantes aos aplicativos encontrados nas suítes de escritório
existentes. A maneira como a Internet é vista e utilizada hoje deve mudar, e Ajax exerce um
papel central nesse processo que deve tornar cada vez mais a web no meio de escolha por
parte das empresas e desenvolvedores para a disponibilização de seus softwares ao
consumo pelo usuário final.
98
8. REFERÊNCIAS BIBLIOGRÁFICAS
ASLESON, R.; SCHUTTA, N. T. Foundations of Ajax. Berkeley, CA: Apress, 2006.
CRANE, Dave et al. Ajax in Action. Greenwich, CT: Manning Publications Co., 2006.
DARIE, Cristian et al. AJAX and PHP: building responsive web applications.
Birmingham, UK: Packt Publishing, 2006.
ECMA. Standard ECMA-262 – ECMAScript Language Specification, 3rd edition,
December 1999. Disponível via URL em: http://www.ecmainternational.org/publications/standards/Ecma-262.htm. Acesso em: 7 de out. de 2007.
FRYE, Colleen. Eric Pascarello dissects Ajax security vulnerabilities. Data de
publicação: 07 de fev. de 2006. Disponível via URL em:
http://searchsoa.techtarget.com/qna/0,289202,sid26_gci1164745,00.html. Acesso em: 15 de
nov. de 2007.
GARRET, Jesse James. Ajax: A New Approach to Web Applications. Data de publicação:
18 de fev. de 2005. Disponível via URL em:
http://www.adaptivepath.com/publications/essays/archives/000385.php. Acesso em: 28 de
mai. de 2007.
GEHTLAND, J.; GALBRAITH B.; ALMAER D. Pragmatic Ajax: a Web 2.0 primer. [S.I.]:
Pragmatic Bookshelf, 2006.
GOODMAN, Danny. JavaScript Bible. 4th ed. New York, NY: Hungry Minds, 2001.
GOOGLE. Product Overview - Google Web Toolkit. Disponível via URL em:
http://code.google.com/webtoolkit/overview.html. Acesso em 10 de nov. de 2007.
GRIFFITHS, Patrick. HTML dog: the best-practice guide to XHTML & CSS. Berkeley, CA:
New Riders, 2007.
HAINE, Paul. HTML Mastery: semantics, standards, and styling. Berkeley, CA: Friends of
ED, 2006.
HINES, Matt. Ajax Security Vulnerabilities Could Pose Serious Risk. FOXNews.com.
Data de publicação: 04 de ago. de 2006. Disponível via URL em:
http://www.foxnews.com/story/0,2933,207095,00.html. Acesso em: 15 de nov. de 2007.
JACOBS, Sas. Beginning XML with DOM and Ajax - From Novice to Professional. New
York, NY: Apress, 2006.
KENNEDY, B.; MUSCIANO, C. HTML & XHTML: the Definitive Guide. 6th ed. [S.I.]:
O'Reilly, 2006.
99
MCLAUGHLIN, Brett. Mastering Ajax, Part 7: Using XML in requests and responses.
Disponível via URL em: http://www.ibm.com/developerworks/web/library/wa-ajaxintro7.html.
Acesso em: 01 de nov. de 2007.
YORK, Richard. Beginning CSS: cascading Style Sheets for Web Design. Indianapolis,
IN: Wiley Publishing, 2005.
W3C. About the World Wide Web Consortium (W3C). Disponível via URL em:
http://www.w3.org/Consortium. Acesso em: 29 de mai. de 2007A.
W3C. Serving XHTML 1.0. Disponível via URL em:
http://www.w3.org/International/articles/serving-xhtml/Overview.en.php. Acesso em: 2 de jun.
de 2007B.
ZAKAS, N.C.; MCPEAK J.; FAWCETT J. Professional Ajax. Indianapolis, IN: Wiley
Publishing, 2006.
ZAKAS, Nicholas C. Professional JavaScript for Web Developers. Indianapolis, IN: Wiley
Publishing, 2005.

Documentos relacionados

Tratamento de XML com JavaScript e com PHP

Tratamento de XML com JavaScript e com PHP Tratamento de XML com JavaScript e com PHP

Leia mais

13. web 2.0 – a web social

13. web 2.0 – a web social Revista CEPPG – CESUC – Centro de Ensino Superior de Catalão , Ano XI, Nº 20, 1º Semestre/2009

Leia mais