Una lista sencilla de tareas pendientes con las bases de datos web de HTML5

Introducción

Las bases de datos web son nuevas en HTML5. Las bases de datos web se alojan y persisten en el navegador de un usuario. Dado que permite a los desarrolladores crear aplicaciones con capacidades de consulta enriquecidas, se prevé que surgirá una nueva generación de aplicaciones web que podrán funcionar en línea y sin conexión.

En el código de ejemplo de este artículo, se muestra cómo crear un administrador de listas de tareas pendientes muy simple. Es una visita de alto nivel a algunas de las funciones disponibles en HTML5.

Requisitos previos

En este ejemplo, se usa un espacio de nombres para encapsular la lógica de la base de datos.

var html5rocks = {};
html5rocks.webdb = {};

Asíncrono y transaccional

En la mayoría de los casos en los que usas la compatibilidad con la base de datos web, usarás la API asíncrona. La API asíncrona es un sistema no bloqueador y, como tal, no obtendrá datos a través de valores devueltos, sino que recibirá datos enviados a una función de devolución de llamada definida.

La compatibilidad con la base de datos web a través de HTML es transaccional. No es posible ejecutar instrucciones de SQL fuera de una transacción. Hay dos tipos de transacciones: transacciones de lectura y escritura (transaction()) y transacciones de solo lectura (readTransaction()). Ten en cuenta que la lectura y escritura bloquearán toda la base de datos.

Paso 1: Abre la base de datos

La base de datos debe estar abierta para poder acceder a ella.
Debes definir el nombre, la versión, la descripción y el tamaño de la base de datos.

html5rocks.webdb.db = null;

html5rocks.webdb.open = function() {
var dbSize = 5 * 1024 * 1024; // 5MB
html5rocks.webdb.db = openDatabase("Todo", "1", "Todo manager", dbSize);
}

html5rocks.webdb.onError = function(tx, e) {
alert("There has been an error: " + e.message);
}

html5rocks.webdb.onSuccess = function(tx, r) {
// re-render the data.
// loadTodoItems is defined in Step 4a
html5rocks.webdb.getAllTodoItems(loadTodoItems);
}

Paso 2: Crea una tabla

Solo puedes crear una tabla si ejecutas una sentencia SQL CREATE TABLE dentro de una transacción.

Definimos una función que creará una tabla en el evento onload del cuerpo. Si la tabla aún no existe, se creará una.

La tabla se llama todo y tiene 3 columnas.

  • ID: Es una columna de ID secuencial incremental.
  • todo: Es una columna de texto que corresponde al cuerpo del elemento.
  • added_on: Es la hora en la que se creó el elemento de lista de tareas pendientes.
html5rocks.webdb.createTable = function() {
var db = html5rocks.webdb.db;
db.transaction(function(tx) {
tx.executeSql("CREATE TABLE IF NOT EXISTS " +
                "todo(ID INTEGER PRIMARY KEY ASC, todo TEXT, added_on DATETIME)", []);
});
}

Paso 3: Cómo agregar datos a una tabla

Estamos compilando un administrador de listas de tareas pendientes, por lo que es muy importante que podamos agregar elementos de tareas pendientes a la base de datos.

Se crea una transacción y, dentro de ella, se realiza una INSERT en la tabla todo.

executeSql toma varios parámetros, el SQL que se ejecutará y los valores de los parámetros para vincular la consulta.

html5rocks.webdb.addTodo = function(todoText) {
var db = html5rocks.webdb.db;
db.transaction(function(tx){
var addedOn = new Date();
tx.executeSql("INSERT INTO todo(todo, added_on) VALUES (?,?)",
    [todoText, addedOn],
    html5rocks.webdb.onSuccess,
    html5rocks.webdb.onError);
});
}

Paso 4: Cómo seleccionar datos de una tabla

Ahora que los datos están en la base de datos, necesitas una función que los recupere. En Chrome, Webdatabase usa consultas SELECT estándar de SQLite.

html5rocks.webdb.getAllTodoItems = function(renderFunc) {
var db = html5rocks.webdb.db;
db.transaction(function(tx) {
tx.executeSql("SELECT * FROM todo", [], renderFunc,
    html5rocks.webdb.onError);
});
}

Ten en cuenta que todos estos comandos que se usan en este ejemplo son asíncronos y, por lo tanto, los datos no se muestran desde la transacción ni la llamada a executeSql. Los resultados se pasan a la devolución de llamada de éxito.

Paso 4a. Renderiza datos de una tabla

Una vez que se recuperen los datos de la tabla, se llamará al método loadTodoItems.

La devolución de llamada onSuccess toma dos parámetros. El primero es la transacción de la consulta y el segundo es el conjunto de resultados. Es bastante simple iterar en los datos:

function loadTodoItems(tx, rs) {
var rowOutput = "";
var todoItems = document.getElementById("todoItems");
for (var i=0; i < rs.rows.length; i++) {
rowOutput += renderTodo(rs.rows.item(i));
}

todoItems.innerHTML = rowOutput;
}
function renderTodo(row) {
return "<li>" + row.todo + 
        " [<a href='javascript:void(0);' onclick=\'html5rocks.webdb.deleteTodo(" + 
        row.ID +");\'>Delete</a>]</li>";
}

El efecto de esta llamada al método es que la lista de tareas pendientes se renderiza en un elemento DOM llamado "todoItems".

Paso 5: Borra datos de una tabla

html5rocks.webdb.deleteTodo = function(id) {
var db = html5rocks.webdb.db;
db.transaction(function(tx){
tx.executeSql("DELETE FROM todo WHERE ID=?", [id],
    html5rocks.webdb.onSuccess,
    html5rocks.webdb.onError);
});
}

Paso 6: Cómo conectar todo

Cuando se cargue la página, abre la base de datos y crea la tabla (si es necesario) y renderiza los elementos de tareas pendientes que ya puedan estar en la base de datos.

....
function init() {
html5rocks.webdb.open();
html5rocks.webdb.createTable();
html5rocks.webdb.getAllTodoItems(loadTodoItems);
}
</script>

<body onload="init();">

Se necesita una función que extraiga los datos del DOM, por lo que debes llamar al método html5rocks.webdb.addTodo.

function addTodo() {
var todo = document.getElementById("todo");
html5rocks.webdb.addTodo(todo.value);
todo.value = "";
}