O uso do desenvolvimento da web em aplicativos remotos é uma tendência crescente. No entanto, a disponibilidade intermitente da rede é um grande obstáculo no uso da tecnologia da web como parte de uma infraestrutura em nuvem. Um aplicativo da web tradicional simplesmente não funciona sem uma rede. Uma solução para esse problema é utilizar dois recursos do Padrão HTML5 (consulte Recursos):
- Aplicativos da web offline;
- Armazenamento do banco de dados do lado do cliente.
O usuário pode utilizar funções em nuvem em um dispositivo móvel, trabalhar offline com um aplicativo implementado localmente em um banco de dados e compartilhar dados com o resto da nuvem quando voltar a ficar online.
Neste artigo, aprenda os detalhes técnicos para um cenário de uso típico. Um protótipo de um aplicativo de gerenciamento de inventário simples demonstra a tecnologia HTML5.
Faça o download do código fonte para o aplicativo de exemplo neste artigo a partir da tabela Download abaixo.
Visão geral
A Figura 1 mostra uma visão geral dos principais componentes da arquitetura do aplicativo de amostra.
- Página HTML – A página HTML, o núcleo do aplicativo, possui a função do modelo. Ela contém os dados exibidos e as informações de renderização (padrão). Os elementos do HTML da página são organizados em uma hierarquia da árvore do Modelo de Objeto de Documento (DOM) do HTML. Eventos iniciados pelo usuário causam um ciclo de resposta à solicitação convencional, com o carregamento de uma página e a execução das funções JavaScript associadas.Notavelmente, esse aplicativo consiste em uma única página HTML sem a necessidade do carregamento de mais páginas HTML por meio de ciclos de resposta à solicitação. Toda a ação encontra-se em uma página.
- JavaScript – O elemento JavaScript contém as funções do controlador do aplicativo. Os elementos HTML são ligados às funções JavaScript por meio de manipuladores de eventos. O JavaScript pode acessar a árvore do DOM do HTML do aplicativo com todos os elementos da interface com o usuário (IU) e utilizá-la como entrada de dados para cálculo. Os resultados do processamento podem ser apresentados ao usuário modificando a página HTML.
- Folha de Estilo em Cascata – A Folha de Estilo em Cascata (CSS) descreve como a página HTML é renderizada. A tarefa de visualização é omitida para simplificar a solução. Nesse estágio da expansão, somente o comportamento de renderização padrão dos elementos HTML é utilizado.Para dispositivos móveis, há várias bibliotecas e estruturas JavaScript/CSS para fornecer uma experiência do usuário praticamente nativa com aplicativos da web (por exemplo, iUi para iPhone). Consulte Recursos para mais informações. Embora seja necessário aumentar a aceitação do usuário, essa abordagem possui a desvantagem da dependência da plataforma.
- Banco de dados – O padrão HTML5 apresentou o armazenamento de banco de dados local. Ele é implementado em versões atuais do navegador Safari da Apple® . O navegador oferece um banco de dados integrado, com SQLite, que pode ser acessado a partir do JavaScript ao processar consultas de SQL. Os dados de negócios do modelo do aplicativo são armazenados aqui.
- Manifesto – O arquivo de manifesto é o componente do descritor de implementação obrigatório para um aplicativo da web offline. Ele simplesmente lista todos os campos que precisam ser carregados.
Aplicativo de amostra
Esta seção oferece uma visão geral do aplicativo de amostra, denominado MyHomeStuff. É um simples aplicativo de gerenciamento de inventário que possibilita manter o controle dos itens de sua propriedade. A Figura 2 mostra o aplicativo no iPhone.
Para fins de simplicidade, a sincronização dos dados com o servidor é omitida. A Figura 3 mostra o aplicativo de gerenciamento de inventário MyHomeStuff no navegador da web do Palm Pre.
A lista da parte superior da tela oferece uma visão geral de todos os itens inseridos (livros, computador, entre outros).
Quando um usuário seleciona um item na lista, seus detalhes (Id, Qty, Name) são exibidos no meio do formulário. Eles podem ser alterados utilizando o botão update. O item selecionado também pode ser excluído do aplicativo utilizando o botão delete. Novos itens podem ser criados inserindo a quantidade e o nome do item no formulário e selecionando o botão create.
O Status do aplicativo é exibido na parte inferior da tela.
Detalhes do HTML
A página HTML contém declarações, meta tags para uma exibição móvel otimizada, referências a arquivos externos (manifesto, JavaScript, css) e elementos HTML fundamentais, que formam a estrutura básica do aplicativo. A Listagem 1 mostra o código.
<!DOCTYPE HTML> <html manifest="MyHomeStuff.manifest"> <head> <meta name="viewport" content="width=device-width; initial-scale=1.0; maximum-scale=1.0; user-scalable=0;"> <title>MyHomeStuff</title> <script type="text/javascript" src="MyHomeStuff.js" ></script> </head> <body onload="onInit()"> <h3>Overview</h3> <ul id="itemData" ></ul> <h3>Details</h3> <form name="itemForm"> <label for="id">Id: </label> <input type="text" name="id" id="id" size=2 disabled="true"/> <label for="amount">Amount: </label> <input type="text" name="amount" id="amount" size = 3/> <label for="name">Name: </label> <input type="text" name="name" id="name" size=16 /> <br> <br> <input type="button" name="create" value="create" onclick="onCreate()" /> <input type="button" name="update" value="update" onclick="onUpdate()" /> <input type="button" name="delete" value="delete" </form> <h4>Status</h4> <div id="status"></div> </body> </html>
Os atributos do manipulador de eventos dos elementos HTML especificam quais funções JavaScript são executadas quando a página é inicialmente carregada (onload
) e os elementos do botão são clicados (onclick
).
A página HTML de um aplicativo da web offline começa com a tag <!DOCTYPE HTML>
. O manifesto é referenciado por meio do atributo do manifesto na tag <html manifest="MyHomeStuff.manifest">
.
Como mencionado, o manifesto especifica os arquivos necessários que precisam ser carregados no cache. Esse aplicativo consiste em um arquivo HTML e um JavaScript. O arquivo HTML com a referência ao manifesto é automaticamente incluído no cache do aplicativo. O manifesto contém somente:
CACHE MANIFEST MyHomeStuff.js
Detalhes do JavaScript
O código JavaScript consiste em três blocos principais:
- Funções de inicialização
- Funções db (crud) e de atualização da visualização
- Algumas pequenas funções de utilitário
O primeiro bloco contém o manipulador de eventos para inicializar o aplicativo (onload
) e a inicialização do banco de dados, como mostra a Listagem 3.
function onInit(){ try { if (!window.openDatabase) { updateStatus("Error: DB not supported"); } else { initDB(); createTables(); queryAndUpdateOverview(); } } catch (e) { if (e == 2) { updateStatus("Error: Invalid database version."); } else { updateStatus("Error: Unknown error " + e + "."); } return; } } function initDB(){ var shortName = 'stuffDB'; var version = '1.0'; var displayName = 'MyStuffDB'; var maxSize = 65536; // in bytes localDB = window.openDatabase(shortName, version, displayName, maxSize); }
No código acima:
- A função
onInit
primeiro verifica a existência da função obrigatóriaopenDatabase
, cuja falta sinaliza que o navegador não suporta um banco de dados local; - A função
initDB
abre o banco de dados do navegador HTML5; - Depois da abertura bem-sucedida do banco de dados, a SQL DDL para criar a tabela de banco de dados é executada. Finalmente, as funções que consultam os registros existentes e preenchem a página HTML com os dados são chamadas.
Cada função do segundo bloco do JavaScript possui uma parte para acesso do DB e lógica de apresentação. Essa consolidação da lógica é característica de uma arquitetura Modelo 1 (consulte Recursos), que é a forma mais fácil de desenvolver aplicativos da web simples. Para um cenário real, uma arquitetura com uma separação clara das partes do Model View Controller (MVC) seria apropriada.
Para criar a lista de visão geral do exemplo, a função queryAndUpdate
é chamada a partir das funções do manipulador de eventos. A Listagem 4 mostra o código.
function queryAndUpdateOverview(){ //remove old table rows var dataRows = document.getElementById("itemData").getElementsByClassName("data"); while (dataRows.length > 0) { row = dataRows[0]; document.getElementById("itemData").removeChild(row); }; //read db data and create new table rows var query = "SELECT * FROM items;"; try { localDB.transaction(function(transaction){ transaction.executeSql(query, [], function(transaction, results){ for (var i = 0; i < results.rows.length; i++) { var row = results.rows.item(i); var li = document.createElement("li"); li.setAttribute("id", row['id']); li.setAttribute("class", "data"); li.setAttribute("onclick", "onSelect(this)"); var liText = document.createTextNode(row['amount'] + " x "+ row['name']); li.appendChild(liText); document.getElementById("itemData").appendChild(li); } }, function(transaction, error){ updateStatus("Error: " + error.code + "<br>Message: " + error.message); }); }); } catch (e) { updateStatus("Error: Unable to select data from the db " + e + "."); } }
No código acima:
- Os dados antigos são removidos da árvore do DOM;
- Uma consulta para selecionar todos os conjuntos de dados é executada;
- Para cada conjunto de dados no resultado, um elemento da lista de HTML é criado e anexado a ela;
- Um manipulador de eventos,
onSelect
, é incluído a cada elemento da lista para responder a um clique.
As funções desse bloco também contêm o manipulador de eventos para a barra de botões e a lista com onUpdate
, onDelete
, onCreate
e onSelect
. A Listagem 5 mostra o código para onUpdate
. (onCreate
e onDelete
possuem uma estrutura semelhante, por isso, não são mostrados aqui; é possível fazer o download de todo o código fonte para o aplicativo de exemplo da tabela abaixo.)
function onUpdate(){ var id = document.itemForm.id.value; var amount = document.itemForm.amount.value; var name = document.itemForm.name.value; if (amount == "" || name == "") { updateStatus("'Amount' and 'Name' are required fields!"); } else { var query = "update items set amount=?, name=? where id=?;"; try { localDB.transaction(function(transaction){ transaction.executeSql(query, [amount, name, id], function(transaction, results){ if (!results.rowsAffected) { updateStatus("Error: No rows affected"); } else { updateForm("", "", ""); updateStatus("Updated rows:" + results.rowsAffected); queryAndUpdateOverview(); } }, errorHandler); }); } catch (e) { updateStatus("Error: Unable to perform an UPDATE " + e + "."); } } }
No código acima:
- Os valores do campo do formulário são lidos e validados;
- Se os valores forem válidos, a consulta de atualização será executada;
- O resultado da consulta é exibido na página HTML atualizada.
A função onSelect
é executada quando o usuário seleciona um elemento da lista. O formulário de detalhes será preenchido com os dados desse elemento utilizando o código da Listagem 6.
function onSelect(htmlLIElement){ var id = htmlLIElement.getAttribute("id"); query = "SELECT * FROM items where id=?;"; try { localDB.transaction(function(transaction){ transaction.executeSql(query, [id], function(transaction, results){ var row = results.rows.item(0); updateForm(row['id'], row['amount'], row['name']); }, function(transaction, error){ updateStatus("Error: " + error.code + "<br>Message: " + error.message); }); }); } catch (e) { updateStatus("Error: Unable to select data from the db " + e + "."); } }
No código acima:
- O ID do elemento selecionado é determinado;
- Uma consulta de seleção é executada;
- Uma função para atualizar o formulário de detalhes com o conjunto de dados de leitura é chamada.
O último bloco JavaScript com funções de utilitário começa com manipuladores de dados, necessários como parâmetros para as consultas.
errorHandler = function(transaction, error){ updateStatus("Error: " + error.message); return true; } nullDataHandler = function(transaction, results){ }
Para evitar redundância, as funções de utilitário preenchem os campos do formulário de detalhes (updateForm
) e da mensagem de status (updateStatus
), como mostra abaixo.
function updateForm(id, amount, name){ document.itemForm.id.value = id; document.itemForm.amount.value = amount; document.itemForm.name.value = name; } function updateStatus(status){ document.getElementById('status').innerHTML = status; }
Implementação
Um iPhone 3GS e um Palm Pre foram utilizados para executar o exemplo em um dispositivo móvel HTML5 real. Um navegador Safari atual em um computador também funciona.
É possível fazer o download e implementar os arquivos para o aplicativo em um servidor HTTP a partir da tabela Downloads abaixo. O arquivo de manifesto deve ser atendido pelo servidor HTTP com o tipo Mime text/cache-manifest
. Depois de abrir o aplicativo no iPhone, salve o Marcador e fique no modo offline Avião. O aplicativo será aberto quando o marcador for selecionado e funciona sem uma rede.
Resumo
O foco deste artigo foi o ponto de vista técnico para aplicativos da web offline. Um protótipo de um aplicativo de gerenciamento de inventário simples demonstrou a tecnologia HTML5 com um aplicativo implementado localmente e um banco de dados local.
Download
Descrição | Nome | Tamanho | Método de download |
---|---|---|---|
Source code for this article | OfflineWebAppSrc.zip | 3KB | HTTP |
Informações sobre métodos de download
Recursos
Aprender
- “Safari Client-Side Storage and Offline Applications Programming Guide” (Apple Inc., 20 de janeiro de 2010) oferece detalhes sobre o suporte do banco de dados do JavaScript do HTML5.
- “ABI Research: Cloud computing will transform mobile apps” (Dusan Belic, 2009) explora tecnologias baseadas na web como o modelo predominante para aplicativos remotos, no qual somente uma versão do aplicativo seria necessária.
- “HTML 5 – A vocabulary and associated APIs for HTML and XHTML” (W3C Working Draft, 4 de março de 2010) é a fonte definitiva sobre o HTML5.
- Leia iUi: Estrutura da Interface com o Usuário do iPhone para saber mais sobre o desenvolvimento de aplicativos da web em dispositivos para iPhone. iUi é uma estrutura que consiste em uma biblioteca JavaScript, CSS e imagens para o desenvolvimento de aplicativos da web avançados para iPhone e dispositivos comparáveis/compatíveis.
- “Mobile app dev trends: Making life easier for developers” (John K. Waters, julho de 2009) discute a tendência relacionada ao desenvolvimento da web no espaço móvel.
- Saiba mais sobre o modelo de design Modelo 1 para aplicativos da web Java. Com o Modelo 1, uma solicitação é feita a um JSP ou servlet e, em seguida, esse JSP ou servlet lida com todas as responsabilidades para a solicitação, incluindo seu processamento, a validação dos dados, a manipulação da lógica de negócios e a geração de uma resposta.
- A zona Web development no developerWorks é especializada em artigos que mostram várias soluções baseadas na web.
- Eventos técnicos e webcasts IBM: Permaneça atualizado com os webcasts e eventos técnicos do developerWorks.
- demos on demand no developerWorks: Acompanhe demos que abrangem desde a instalação de produto e configuração para iniciantes a funcionalidade avançada para desenvolvedores experientes.
Obter produtos e tecnologias
- Avalie os produtos IBM da maneira que seja melhor para você: Faça o download da avaliação de um produto, experimente um produto online, use um produto em um ambiente de nuvem ou passe algumas horas no no Ambiente de Simulação da SOA aprendendo a implementar Arquitetura Orientada a Serviços de modo eficiente.
Discutir
- My developerWorks: Comunique-se com outros usuários do developerWorks e explore os blogs, fóruns, grupos e wikis voltados para desenvolvedores.
***
Sobre o autor: Dietmar Krueger trabalha para o Application Innovation Services, uma Linha de Serviço do IBM Global Business Services. Ele desenvolveu softwares orientados a objetos por 17 anos. Dietmar é apaixonado pelo desenvolvimento de software ágil, arquiteturas leves e linguagens de programação de tipo dinâmico.
***
Artigo original disponível em: http://www.ibm.com/developerworks/br/library/wa-offlineweb/index.html