/content/tutorials/webdatabase/todo/en/index.html

https://github.com/imclab/www.html5rocks.com · HTML · 307 lines · 282 code · 25 blank · 0 comment · 0 complexity · 6dd085f74edf3a13c4ac6bc52b9babc5 MD5 · raw file

  1. {% extends "tutorial.html" %}
  2. {% block html5badge %}
  3. <img src="/static/images/identity/html5-badge-h-storage.png" width="133" height="64" alt="This article is powered by HTML5 Offline &amp; Storage" title="This article is powered by HTML5 Offline &amp; Storage" />
  4. {% endblock %}
  5. {% block iscompatible %}
  6. return typeof window.openDatabase == "function" ? true : false;
  7. {% endblock %}
  8. {% block head %}
  9. {% if is_mobile %}
  10. <script>
  11. var html5rocks = {};
  12. html5rocks.webdb = {};
  13. html5rocks.webdb.db = null;
  14. html5rocks.webdb.open = function() {
  15. var dbSize = 5 * 1024 * 1024; // 5MB
  16. html5rocks.webdb.db = openDatabase("Todo", "1.0", "Todo manager", dbSize);
  17. }
  18. html5rocks.webdb.createTable = function() {
  19. var db = html5rocks.webdb.db;
  20. db.transaction(function(tx) {
  21. tx.executeSql("CREATE TABLE IF NOT EXISTS todo(ID INTEGER PRIMARY KEY ASC, todo TEXT, added_on DATETIME)", []);
  22. });
  23. }
  24. html5rocks.webdb.addTodo = function(todoText) {
  25. var db = html5rocks.webdb.db;
  26. db.transaction(function(tx){
  27. var addedOn = new Date();
  28. tx.executeSql("INSERT INTO todo(todo, added_on) VALUES (?,?)",
  29. [todoText, addedOn],
  30. html5rocks.webdb.onSuccess,
  31. html5rocks.webdb.onError);
  32. });
  33. }
  34. html5rocks.webdb.onError = function(tx, e) {
  35. alert("There has been an error: " + e.message);
  36. }
  37. html5rocks.webdb.onSuccess = function(tx, r) {
  38. // re-render the data.
  39. html5rocks.webdb.getAllTodoItems(loadTodoItems);
  40. }
  41. html5rocks.webdb.getAllTodoItems = function(renderFunc) {
  42. var db = html5rocks.webdb.db;
  43. db.transaction(function(tx) {
  44. tx.executeSql("SELECT * FROM todo", [], renderFunc,
  45. html5rocks.webdb.onError);
  46. });
  47. }
  48. html5rocks.webdb.deleteTodo = function(id) {
  49. var db = html5rocks.webdb.db;
  50. db.transaction(function(tx){
  51. tx.executeSql("DELETE FROM todo WHERE ID=?", [id],
  52. html5rocks.webdb.onSuccess,
  53. html5rocks.webdb.onError);
  54. });
  55. }
  56. function loadTodoItems(tx, rs) {
  57. var rowOutput = "";
  58. var todoItems = document.getElementById("todoItems");
  59. for (var i=0; i < rs.rows.length; i++) {
  60. rowOutput += renderTodo(rs.rows.item(i));
  61. }
  62. todoItems.innerHTML = rowOutput;
  63. }
  64. function renderTodo(row) {
  65. return "<li>" + row.todo + " [<a href='javascript:void(0);' onclick='html5rocks.webdb.deleteTodo(" + row.ID +");'>Delete</a>]</li>";
  66. }
  67. function init() {
  68. html5rocks.webdb.open();
  69. html5rocks.webdb.createTable();
  70. html5rocks.webdb.getAllTodoItems(loadTodoItems);
  71. }
  72. function addTodo() {
  73. var todo = document.getElementById("todo");
  74. html5rocks.webdb.addTodo(todo.value);
  75. todo.value = "";
  76. }
  77. </script>
  78. {% endif %}
  79. {% endblock %}
  80. {% block onload %}{% if is_mobile %}init();{% endif %}{% endblock %}
  81. {% block content %}
  82. <h2 id="toc-intro">Introduction</h2>
  83. <p>
  84. <a href="http://dev.w3.org/html5/webdatabase">Web Databases</a> are new
  85. in HTML5. Web Databases are hosted and persisted inside a user's browser.
  86. By allowing developers to create applications with rich query abilities
  87. it is envisioned that a new breed of web applications will emerge that
  88. have the ability to work online and off-line.
  89. </p>
  90. <p>
  91. On November 18, 2010, the <a href="http://www.w3.org/TR/webdatabase/">W3C
  92. announced</a> that Web SQL database is a deprecated specification. This is a
  93. recommendation for web developers to no longer use the technology as
  94. effectively the spec will receive no new updates and browser vendors aren't
  95. encouraged to support this technology. Many major browsers including Chrome,
  96. Safari, Opera and nearly all Webkit based mobile devices support WebSQL and
  97. will likely maintain support for the foreseeable future.
  98. </p>
  99. <p class="notice" style="text-align:center;">
  100. This tutorial is also <a href="/tutorials/indexeddb/todo/">
  101. available written using "IndexedDB"</a>, the replacement offline storage
  102. technology.
  103. </p>
  104. <p>
  105. The example code in this article demonstrates how to create a very simple
  106. todo list manager. It is a very high level tour of some of the features
  107. available in HTML5.
  108. </p>
  109. <h2 id="toc-prereqs">Pre-requisites</h2>
  110. <p>
  111. This sample uses a namespace to encapsulate the database logic.
  112. </p>
  113. <pre class="prettyprint">var html5rocks = {};
  114. html5rocks.webdb = {};</pre>
  115. <h2 id="toc-transactions">Asynchronous and Transactional</h2>
  116. <p>
  117. In the majority of cases where you are using Web Database
  118. support you will be using the <a
  119. href="http://dev.w3.org/html5/webdatabase/#asynchronous-database-api">Asynchronous API</a>. The Asynchronous API
  120. is a non-blocking system and as such will not get data
  121. through return values, but rather will get data delivered to a defined
  122. callback function.
  123. </p>
  124. <p>
  125. The Web Database support through HTML is transactional. It is not
  126. possible to execute SQL statements outside of a transaction.
  127. There are two types of transactions: read/write transactions
  128. (<em>transaction()</em>) and read
  129. only transactions (<em>readTransaction()</em>). Please note, read/write will lock the entire database.
  130. </p>
  131. <h2 id="toc-step1">Step 1. Opening the database</h2>
  132. <p>The database needs to be opened before it can be accessed.
  133. You need to define the name, version, description and the size of the database.
  134. </p>
  135. <pre class="prettyprint">html5rocks.webdb.db = null;
  136. html5rocks.webdb.open = function() {
  137. var dbSize = 5 * 1024 * 1024; // 5MB
  138. html5rocks.webdb.db = openDatabase("Todo", "1.0", "Todo manager", dbSize);
  139. }
  140. html5rocks.webdb.onError = function(tx, e) {
  141. alert("There has been an error: " + e.message);
  142. }
  143. html5rocks.webdb.onSuccess = function(tx, r) {
  144. // re-render the data.
  145. // loadTodoItems is defined in Step 4a
  146. html5rocks.webdb.getAllTodoItems(loadTodoItems);
  147. }</pre>
  148. <h2 id="toc-step2">Step 2. Creating a table</h2>
  149. <p>
  150. You can only create a table by executing a CREATE TABLE SQL statement
  151. inside a <a href="#toc-transactions">transaction</a>.
  152. </p>
  153. <p>
  154. We have defined a function that will create a table in the body onload
  155. event. If the table doesn't already exist, a table will be created.
  156. The table is called todo and has 3 columns.
  157. <ul>
  158. <li>ID - a incrementing sequential ID column</li>
  159. <li>todo - a text column that is the body of the item</li>
  160. <li>added_on - the time that the todo item was created</li>
  161. </ul>
  162. </p>
  163. <pre class="prettyprint">html5rocks.webdb.createTable = function() {
  164. var db = html5rocks.webdb.db;
  165. db.transaction(function(tx) {
  166. tx.executeSql("CREATE TABLE IF NOT EXISTS " +
  167. "todo(ID INTEGER PRIMARY KEY ASC, todo TEXT, added_on DATETIME)", []);
  168. });
  169. }</pre>
  170. <h2 id="toc-step3">Step 3. Adding data to a table</h2>
  171. <p>
  172. We are building a todo list manager so it is pretty important that
  173. we are able to add todo items in to the database.
  174. </p>
  175. <p>
  176. A transaction is created, inside the transaction an INSERT into the todo
  177. table is performed.
  178. </p>
  179. <p>
  180. executeSql takes several parameters, the SQL to execute and the parameters
  181. values to bind the query.
  182. </p>
  183. <pre class="prettyprint">html5rocks.webdb.addTodo = function(todoText) {
  184. var db = html5rocks.webdb.db;
  185. db.transaction(function(tx){
  186. var addedOn = new Date();
  187. tx.executeSql("INSERT INTO todo(todo, added_on) VALUES (?,?)",
  188. [todoText, addedOn],
  189. html5rocks.webdb.onSuccess,
  190. html5rocks.webdb.onError);
  191. });
  192. }</pre>
  193. <h2 id="toc-step4">Step 4. Selecting data from a table</h2>
  194. <p>
  195. Now that the data is in the database, you need a function that gets
  196. the data back out. In Chrome, Webdatabase's use standard SQLite SELECT
  197. queries.
  198. </p>
  199. <pre class="prettyprint">html5rocks.webdb.getAllTodoItems = function(renderFunc) {
  200. var db = html5rocks.webdb.db;
  201. db.transaction(function(tx) {
  202. tx.executeSql("SELECT * FROM todo", [], renderFunc,
  203. html5rocks.webdb.onError);
  204. });
  205. }</pre>
  206. <p>
  207. Note that all of these commands used in this sample
  208. are asynchronous and as such the data is not returned from the transaction
  209. or the executeSql call. The results are passed through to the success
  210. callback.
  211. </p>
  212. <h2>Step 4a. Rendering data from a table</h2>
  213. <p>
  214. Once the data has been fetched from the table, the loadTodoItems method
  215. will be called.
  216. </p>
  217. <p>
  218. The onSuccess callback takes two parameters. The first being the
  219. transaction of the query and the second being the result set. It is
  220. fairly simple to iterate across the data:
  221. </p>
  222. <pre class="prettyprint">function loadTodoItems(tx, rs) {
  223. var rowOutput = "";
  224. var todoItems = document.getElementById("todoItems");
  225. for (var i=0; i < rs.rows.length; i++) {
  226. rowOutput += renderTodo(rs.rows.item(i));
  227. }
  228. todoItems.innerHTML = rowOutput;
  229. }
  230. function renderTodo(row) {
  231. return "&lt;li&gt;" + row.todo +
  232. " [&lt;a href='javascript:void(0);' onclick='html5rocks.webdb.deleteTodo(" +
  233. row.ID +");'&gt;Delete&lt;/a&gt;]&lt;/li&gt;";
  234. }</pre>
  235. <p>
  236. The effect of this method call is that the todo list is rendered into
  237. a DOM Element called "todoItems".
  238. </p>
  239. <h2 id="toc-step5">Step 5. Deleting data from a table</h2>
  240. <pre class="prettyprint">html5rocks.webdb.deleteTodo = function(id) {
  241. var db = html5rocks.webdb.db;
  242. db.transaction(function(tx){
  243. tx.executeSql("DELETE FROM todo WHERE ID=?", [id],
  244. html5rocks.webdb.onSuccess,
  245. html5rocks.webdb.onError);
  246. });
  247. }</pre>
  248. <h2 id="toc-step6">Step 6. Hooking it all up</h2>
  249. <p>
  250. When the page loads, open the database and create the table (if
  251. needed) and render any todo items that might already be in the database.
  252. </p>
  253. <pre class="prettyprint">....
  254. function init() {
  255. html5rocks.webdb.open();
  256. html5rocks.webdb.createTable();
  257. html5rocks.webdb.getAllTodoItems(loadTodoItems);
  258. }
  259. &lt;/script&gt;
  260. &lt;body onload="init();"&gt;</pre>
  261. <p>
  262. A function that takes the data out of the DOM is needed so,
  263. call the html5rocks.webdb.addTodo method
  264. </p>
  265. <pre class="prettyprint">function addTodo() {
  266. var todo = document.getElementById("todo");
  267. html5rocks.webdb.addTodo(todo.value);
  268. todo.value = "";
  269. }</pre>
  270. <h2 id="toc-final">The final product</h2>
  271. {% if is_mobile %}
  272. <ul id="todoItems">
  273. </ul>
  274. <form type="post" onsubmit="addTodo(); return false;">
  275. <input type="text" id="todo" name="todo"
  276. placeholder="What do you need to do?" style="width: 200px;" />
  277. <input type="submit" value="Add Todo Item"/>
  278. </form>
  279. {% else %}
  280. <iframe src="http://playground.html5rocks.com/?mode=frame&hu=210&hl=150#a_simple_todo_list_using_web_sql_database" style="border: none; width: 100%; height: 480px;"></iframe>
  281. {% endif %}
  282. {% endblock %}