O HTML5 de fato contém adicionais altamente interessantes para o desenvolvimento, e a criação e interação com banco de dados offline certamente é uma delas.
E tudo isto sem nenhuma linguagem back-end, apenas sendo realizado via Javascript, responsável por criar a tabela e realizar as querys de CRUD – (Create – Retrieve – Update – Delete), bem como ter suas funções de tratamento de erros e atualizações de status.
Sendo assim uma boa solução para quando suas WebApps necessitam, por algum motivo, de ter um banco de dados local e de acesso offline.
Esta funcionalidade é permitida em navegadores que suportam HTML5 e SQLite, cujo script JS detecta e exibe esta possibilidade logo ao iniciar sua execução.
Este mesmo exemplo foi testado nos navegadores:
Google Chrome;
Safari Mobile (iPad/iPhone/iPod Touch) – Lembrando que para estes por default o limite é de 5MB de cache.
Abaixo a visualização do banco criado utilizando o Google Chrome:
Tudo que precisamos são apenas 3 estruturas:
- HTML – (index.html);
- Javascript – (offlinedatabase.manifest);
- Manifest – (offlinedatabaseJS.js).
Respectivamente e objetivamente: HTML a inteface para o usuário, Javascript com toda criação do banco bem como suas funções de CRUD, tratamento e atualizações de status e o arquivo manifest responsável por “salvar” o arquivo com as funções para uso offline.
Como uma imagem vale mais do que mil palavras, abaixo a representação desta estrutura:
Vamos ao código, parte HTML:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | <!DOCTYPE HTML> <html manifest="offlinedatabase.manifest"> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <meta name="viewport" content="width=480; initial-scale=1.0; maximum-scale=1.0; user-scalable=0;"> <title>Offline HTML5 SQLite - blog.vilourenco.com.br</title> <script type="text/javascript" src="offlinedatabaseJS.js" ></script> <style> body { font-family:Verdana, Geneva, sans-serif; font-size:11px; } </style> </head> <body onload="onInit()"> <h3>Dados:</h3> <ul id="itemData" style="cursor:pointer;"> </ul> <h3>Detalhes:</h3> <form name="itemForm"> <label for="id">Id:</label><input type="text" name="id" id="id" size=2 disabled="true"/> <label for="nome">Nome:</label><input type="text" name="nome" id="nome" size=10/> <label for="idade">Idade</label><input type="text" name="idade" id="idade" size=3 /> <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" onclick="onDelete()" /> </form> <h4>Status:</h4> <div id="status"></div> </body> </html> |
Abaixo a parte Javascript, onde temos as funções CRUD para criação da tabela (função ao iniciar a aplicação), manipulação dos dados, tratamento de erros e atualizações de status.:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 | //1. Inicialização var localDB = null; function onInit(){ try { if (!window.openDatabase) { updateStatus("Erro: Seu navegador não permite banco de dados."); } else { initDB(); createTables(); queryAndUpdateOverview(); } } catch (e) { if (e == 2) { updateStatus("Erro: Versão de banco de dados inválida."); } else { updateStatus("Erro: Erro desconhecido: " + e + "."); } return; } } function initDB(){ var shortName = 'stuffDB'; var version = '1.0'; var displayName = 'MyStuffDB'; var maxSize = 65536; // Em bytes localDB = window.openDatabase(shortName, version, displayName, maxSize); } function createTables(){ var query = 'CREATE TABLE IF NOT EXISTS vilourenco(id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, nome VARCHAR NOT NULL, idade VARCHAR NOT NULL);'; try { localDB.transaction(function(transaction){ transaction.executeSql(query, [], nullDataHandler, errorHandler); updateStatus("Tabela 'vilourenco' status: OK."); }); } catch (e) { updateStatus("Erro: Data base 'vilourenco' não criada " + e + "."); return; } } //2. Query e visualização de Update function onUpdate(){ var id = document.itemForm.id.value; var nome = document.itemForm.nome.value; var idade = document.itemForm.idade.value; if (nome == "" || idade == "") { updateStatus("'Nome' e 'Idade' são campos obrigatórios!"); } else { var query = "update vilourenco set nome=?, idade=? where id=?;"; try { localDB.transaction(function(transaction){ transaction.executeSql(query, [nome, idade, id], function(transaction, results){ if (!results.rowsAffected) { updateStatus("Erro: Update não realizado."); } else { updateForm("", "", ""); updateStatus("Update realizado:" + results.rowsAffected); queryAndUpdateOverview(); } }, errorHandler); }); } catch (e) { updateStatus("Erro: UPDATE não realizado " + e + "."); } } } function onDelete(){ var id = document.itemForm.id.value; var query = "delete from vilourenco where id=?;"; try { localDB.transaction(function(transaction){ transaction.executeSql(query, [id], function(transaction, results){ if (!results.rowsAffected) { updateStatus("Erro: Delete não realizado."); } else { updateForm("", "", ""); updateStatus("Linhas deletadas:" + results.rowsAffected); queryAndUpdateOverview(); } }, errorHandler); }); } catch (e) { updateStatus("Erro: DELETE não realizado " + e + "."); } } function onCreate(){ var nome = document.itemForm.nome.value; var idade = document.itemForm.idade.value; if (nome == "" || idade == "") { updateStatus("Erro: 'Nome' e 'Idade' são campos obrigatórios!"); } else { var query = "insert into vilourenco (nome, idade) VALUES (?, ?);"; try { localDB.transaction(function(transaction){ transaction.executeSql(query, [nome, idade], function(transaction, results){ if (!results.rowsAffected) { updateStatus("Erro: Inserção não realizada"); } else { updateForm("", "", ""); updateStatus("Inserção realizada, linha id: " + results.insertId); queryAndUpdateOverview(); } }, errorHandler); }); } catch (e) { updateStatus("Erro: INSERT não realizado " + e + "."); } } } function onSelect(htmlLIElement){ var id = htmlLIElement.getAttribute("id"); query = "SELECT * FROM vilourenco where id=?;"; try { localDB.transaction(function(transaction){ transaction.executeSql(query, [id], function(transaction, results){ var row = results.rows.item(0); updateForm(row['id'], row['nome'], row['idade']); }, function(transaction, error){ updateStatus("Erro: " + error.code + "<br>Mensagem: " + error.message); }); }); } catch (e) { updateStatus("Error: SELECT não realizado " + e + "."); } } function queryAndUpdateOverview(){ //Remove as linhas existentes para inserção das novas var dataRows = document.getElementById("itemData").getElementsByClassName("data"); while (dataRows.length > 0) { row = dataRows[0]; document.getElementById("itemData").removeChild(row); }; //Realiza a leitura no banco e cria novas linhas na tabela. var query = "SELECT * FROM vilourenco;"; 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['nome'] + " x "+ row['idade']); li.appendChild(liText); document.getElementById("itemData").appendChild(li); } }, function(transaction, error){ updateStatus("Erro: " + error.code + "<br>Mensagem: " + error.message); }); }); } catch (e) { updateStatus("Error: SELECT não realizado " + e + "."); } } // 3. Funções de tratamento e status. // Tratando erros errorHandler = function(transaction, error){ updateStatus("Erro: " + error.message); return true; } nullDataHandler = function(transaction, results){ } // Funções de update function updateForm(id, nome, idade){ document.itemForm.id.value = id; document.itemForm.nome.value = nome; document.itemForm.idade.value = idade; } function updateStatus(status){ document.getElementById('status').innerHTML = status; } |
O arquivo .manifest possui apenas o nome do arquivo de Javascript para que seja armazenado no cache com fins de ser acessado offline.
Espero que tenham gostado do post, em casos de dúvidas bastam comentar ou entrar em contato via email.
Forte abraço e excelente resto de semana.