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. Cuando se permite a los desarrolladores crear aplicaciones con capacidades de consulta enriquecidas, se prevé que surgirá un nuevo tipo de aplicaciones web con la capacidad de trabajar 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 un recorrido de muy alto nivel de 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íncronos y transaccionales

En la mayoría de los casos en los que uses la compatibilidad con bases de datos web, utilizarás la API asíncrona. La API asíncrona es un sistema sin bloqueo y, por lo tanto, no obtendrá datos a través de valores de retorno, sino que entregará los datos a una función de devolución de llamada definida.

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

Paso 1: Abre la base de datos

La base de datos debe estar abierta antes de que se pueda 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 ejecutando un estado de SQL CREATE TABLE dentro de una transacción.

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

La tabla se denomina tarea pendiente y tiene 3 columnas.

  • ID: una columna de ID secuencial creciente
  • todo: una columna de texto que es el cuerpo del elemento
  • add_on: la hora a la que se creó el elemento 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: Agrega datos a una tabla

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

Se crea una transacción, dentro de ella, se realiza una instrucción INSERT en la tabla de tareas pendientes.

runSql requiere varios parámetros: el SQL para 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: Selecciona 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 los comandos que se usan en esta muestra son asíncronos y, por lo tanto, los datos no se muestran desde la transacción ni la llamada performSql. 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. La primera es la transacción de la consulta y la segunda es el conjunto de resultados. Es bastante sencillo iterar entre 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, crea la tabla (si es necesario) y procesa 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 quite los datos del DOM. Por lo tanto, llama al método html5rocks.webdb.addTodo.

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