Using local storage in HTML5 with IndexedDB

What is HTML5 IndexedDB?

IndexedDB is not same as other relational databases which has tables with a collection of columns & rows.

It is an ObjectStore, which creates an objectStore for a set of data & persist JavaScript objects to that store.

IndexedDb uses a cursor which is used to iterate across the result set. IndexedDB was introduced in HTML5 to enhance the offline browser features.

Here we are going to implement a task list preparation application by using HTML5 & indexDB – a simple html5 indexeddb example.

Before we start, we have to point out what we need to design a task-list app.

1> Two javaScript files for all the db & application related operations,

2> HTML5 page for UI.

First, we will create database module.

Create a new JavaScript file in your project folder called db.js

Paste the following code in that,

var taskDB = (function() {
  var taskDB = {};
  var taskdatastore = null;

  taskDB.open = function(callback) {
    // Database version is mentioned here.
    var version = 1; // This will be used to keep track of database upgrades

    // Open a connection to the datastore.
    var connection = indexedDB.open('tasksdb', version); // The first parameter is the object store that will be accessed & second is the database version.

    // This method will be called if the datastore does not exists or the version has changed 
    connection.onupgradeneeded = function(e) {
      var database = e.target.result;

      e.target.transaction.onerror = taskDB.onerror;

      // Delete the old datastore if exists.
      if (database.objectStoreNames.contains('tasklist')) {
        database.deleteObjectStore('tasklist');
      }

      // Create a new datastore.
      var store = database.createObjectStore('tasklist', {
        keyPath: 'timestamp'
      });
    };

    // Handle successful datastore access.
    connection.onsuccess = function(e) {
      // Get a reference to the DB.
      taskdatastore = e.target.result;

      // Execute the callback.
      callback();
    };

    // Handle errors when opening the datastore.
    connection.onerror = taskDB.onerror;
  };

This method takes an argument called callback. Database transactions are asynchronous meaning that the browser will not wait for the database request to finish before moving on to the next bit of code it needs to execute. This means that we need to specify a callback function that will be executed once the request has finished in order to make use of the data.

Next we have to create a method for fetching tasklist items from database.


taskDB.fetchTasks = function(callback) {
    var database = taskdatastore; // Here we are assigning the datastore variable that we have initialized earlier,                                  //  to another variable 
    var transaction = database.transaction(['tasklist'], 'readwrite'); // Database interaction is done here by 
                                                           // creating a new IDBTransaction using database variable
    var objStore = transaction.objectStore('tasklist'); // Here we are getting the reference to the tasklist object                                                        // store, & then saving this to a new variable

    var keyRange = IDBKeyRange.lowerBound(0);          // The keyrange is set to 0, in case to get all the items.
    var cursorRequest = objStore.openCursor(keyRange); // The cursorRequest will start from 0 & will cycle through                                                        // each tasklist items in the database.

    var tasks = []; // An empty array is created to store the tasklist items fetched from 

    transaction.oncomplete = function(e) {     // This will be called after fetching all the tasklist items, 
                                               // The tasks array is passed as parameter here.
      // Execute the callback function.
      callback(tasks);
    };
    cursorRequest.onsuccess = function(e) {    // This function is called for each items that is fetched 
                                               // from database.
      var result = e.target.result;

      if (!!result == false) {
        return;
      }

      console.log(result.value);

      tasks.push(result.value);

      result.continue();    // Here the cursor will move to the next item in the database.
    };

    cursorRequest.onerror = taskDB.onerror;  // an error handler that should be used 
                                             // if the cursor encounters a problem.
  };

So, we have fetched the items from database & also gets a first glimpse of the data from database.

Next, we need a methods for creating a new todo item


taskDB.createTasks = function(text, callback) {
    // Get a reference to the db.
    var database = taskdatastore;

    // Initiate a new transaction.
    var transaction = database.transaction(['tasklist'], 'readwrite');

    // Get the datastore.
    var objStore = transaction.objectStore('tasklist');

    // Create a timestamp for the task item.
    var timestamp = new Date().getTime();

    // Create an object for the task item.
    var task = {
      'text': text,
      'timestamp': timestamp
    };

    // Create the datastore request.
    var request = objStore.put(task);

    // Handle a successful datastore put.
    request.onsuccess = function(e) {
      // Execute the callback function.
      callback(task);
    };

    // Handle errors.
    request.onerror = taskDB.onerror;
  };

This method is quite similar like before. We have initiated a new transaction. Create an object for the task item with its properties. If the item is successfully saved, callback function is called with the new item as parameter.

Lastly, we need a method for deleting items from tasklist.


taskDB.deleteTasks = function(id, callback) {
    var database = taskdatastore;
    var transaction = database.transaction(['tasklist'], 'readwrite');
    var objStore = transaction.objectStore('tasklist');

    var request = objStore.delete(id);

    request.onsuccess = function(e) {
      callback();
    }

    request.onerror = function(e) {
      console.log(e);
    }
  };

  taskDB.deleteAllTasks = function(callback) {
    var database = taskdatastore;
    var transaction = database.transaction(['tasklist'], 'readwrite');
    var objStore = transaction.objectStore('tasklist');

    var keyRange = IDBKeyRange.lowerBound(0);

	console.log(keyRange);

    var request = objStore.delete(keyRange);

    request.onsuccess = function(e) {
      callback();
    }

    request.onerror = function(e) {
      console.log(e);
    }
  };

This methods takes id as argument for the item that is to be deleted. On successful deletion of the item callback function is called.

All these for database module.

Now, create a JavaScript file named app.js for application module. Insert the following code,


window.onload = function() {

  // Display the todo items.
  taskDB.open(refreshTasks);

  // Get references to the form elements.
  var newTodoForm = document.getElementById('new-todo-form');
  var newTodoInput = document.getElementById('new-todo');

  // Handle new todo item form submissions.
  newTodoForm.onsubmit = function() {
    // Get the todo text.
    var text = newTodoInput.value;

    // Check to make sure the text is not blank (or just spaces).
    if (text.replace(/ /g,'') != '') {
      // Create the todo item.

      taskDB.createTasks(text, function(task) {

        refreshTasks();

      });
    }

    // Reset the input field.
    newTodoInput.value = '';

    // Don't send the form.
    return false;
  };

}

// Update the list of todo items.
function refreshTasks() {  
  taskDB.fetchTasks(function(tasks) {
    var todoList = document.getElementById('todo-items');
    todoList.innerHTML = '';

    for(var i = 0; i < tasks.length; i++) {
      // Read the todo items backwards (most recent first).
      var task = tasks[(tasks.length - 1 - i)];

      var li = document.createElement('li');
      var checkbox = document.createElement('input');
      checkbox.type = "checkbox";
      checkbox.className = "todo-checkbox";
      checkbox.setAttribute("data-id", task.timestamp);

      li.appendChild(checkbox);

      var span = document.createElement('span');
      span.innerHTML = task.text;

      li.appendChild(span);

      todoList.appendChild(li);

      // Setup an event listener for the checkbox.
      checkbox.addEventListener('click', function(e) {
        var id = parseInt(e.target.getAttribute('data-id'));

        taskDB.deleteTasks(id, refreshTasks);// the deleteTasks is called with id of the todo item
      });
    }

  });
}

In the above code, you will first get text for the new todo item, & then check if the text contains something more than just whitespace. Then with taskDB.createTasks, we are passing in the text for the new todo item as well as a callback function that will execute refreshTasks to update the UI when the new item has been saved.

In the refreshTasks function, taskDB.fetchTasks will be called.

Here, we have added an event listener for the checkbox, which will be called on checkbox click. The deleteTasks function is also called with this, for deletion of the clicked item.

Thats all for application module.

Finally, we have design the html file. Create a html file inside your project folder. The codes are like,


<body>

<div id="page-wrapper">

<!-- Form for new Task Items -->

<form id="new-todo-form" method="POST" action="#">

<input type="text" name="new-todo" id="new-todo" placeholder="Enter a task item..." required>

</form>

<!-- Todo Item List -->

<ul id="todo-items"></ul>

</div>

<script src="db.js"></script> // Here we have included the

<script src="app.js"></script> // js files.

</body>

The CSS code is used for designing the webpage. We have not included any css here. You can construct a css file for custom decoration.

That all. The output looks like,
indexDBdoc1
After clicking on the checkbox beside third, that item removes from the list.
indexDBdoc2
Lets enter an item in the list. Enter the text in the text-box
indexDBdoc3
& click enter.
indexDBdoc4

If you find this article helpful, you can connect us in Google+ and Twitter.

Enter your email address:

Delivered by FeedBurner

Leave a Reply

Your email address will not be published. Required fields are marked *