3.6 IndexedDB examples

In notebook:
edX Advanced HTML5
Created at:
2016-01-18
Updated:
2016-01-18
Tags:
Fill an indexedDB with some data and createIndexes for values
From this jsbin example: JS Bin - Collaborative JavaScript Debugging
  // This is what our customer data looks like.
var customerData = [
  { ssn: "444-44-4444", name: "Bill", age: 35, email: "bill@company.com" },
  { ssn: "555-55-5555", name: "Donna", age: 32, email: "donna@home.org" }
];
var dbName = "CustomerDB";
 
// Open database with version=2. Use integer valueonly ! Not 1.1, 1.2 etc.
var request = indexedDB.open(dbName, 2);
Use ​unopgradeneeded​ event to fill the database (since version 2 does not yet exist)
  request.onerror = function(event) {
  // Handle errors.
  console.log("request.onerror errcode=" + event.target.error.name);
};
request.onupgradeneeded = function(event) {
  console.log("request.onupgradeneeded, we are creating a new version of the dataBase");
  var db = event.target.result;
 
  // Create an objectStore to hold information about our customers. We're
  // going to use "ssn" as our key path because it's guaranteed to be
  // unique.
  var objectStore = db.createObjectStore("customers", { keyPath: "ssn" });
 
  // Create an index to search customers by name. We may have duplicates
  // so we can't use a unique index.
  objectStore.createIndex("name", "name", { unique: false });
 
  // Create an index to search customers by email. We want to ensure that
  // no two customers have the same email, so use a unique index.
  objectStore.createIndex("email", "email", { unique: true });
 
  // Store values in the newly created objectStore.
  for (var i in customerData) {
    objectStore.add(customerData[i]);
  }
};
The ​onsuccess​ event contains the db object:
  // Handle errors.
  console.log("request.onsuccess, database opened, now we can add / remove / look for data in it!");
    // The result is the database itself
  var db = event.target.result;  
};
Then all operations in the DB will happen through transactions:
var transaction = db.transaction(["customers"], "readwrite"); // or "read"...
​Each transaction has to have a mode set: ​readonly​, ​readwrite​, ​versionchange​ 
multiple readonly transactions can happen concurrently

Example to add a record to indexedDB

  1. Create the transaction object (var transaction = db.transaction(["customers"], "readwrite");​)
  2. create an objectStore object (​var objectStore = transaction.objectStore("customers");​)
  3. use ​objectStore.add({//js object})​ to add new data (returns an object)
  4. observe the ​onsuccess​ and ​onerror​ on the returned object from step 3.
  5. observe the ​oncomplete​ and ​onerror​ events on the transaction object
  function addACustomer() {
   // 1 - get a transaction on the "customers" object store
   // in readwrite, as we are going to insert a new object
   var transaction = db.transaction(["customers"], "readwrite");
   // Do something when all the data is added to the database.
   // This callback is called after transaction has been completely
   // executed (committed)
   transaction.oncomplete = function(event) {
       alert("All done!");
   };
   // This callback is called in case of error (rollback)
   transaction.onerror = function(event) {
      console.log("transaction.onerror errcode=" + event.target.error.name);
   };
   // 2 - Init the transaction on the objectStore
   var objectStore = transaction.objectStore("customers");
   // 3 - Get a request from the transaction for adding a new object
   var request = objectStore.add({ ssn: "123-45-6789",
                                   name: "Michel Buffa",
                                   age: 47,
                                   email: "buffa@i3s.unice.fr" });
   // The insertion was ok
   request.onsuccess = function(event) {
       console.log("Customer with ssn= " + event.target.result + "
                    added.");
   };
   // the insertion led to an error (object already in the store,
   // for example)
   request.onerror = function(event) {
       console.log("request.onerror, could not insert customer,
                    errcode = " + event.target.error.name);
   };
}

Remove data from an object store

same steps as above but call ​objectStore.delete(​key)​ (step 3)

Modifying data from an object store

var request = objectStore.put(customerToUpdate);

Getting data from an object store

var request = objectStore.get(customerToSearch.ssn); the request.onsuccess event will hold the results:

var request = objectStore.get(customerToSearch.ssn);
   request.onsuccess = function(event) {
     console.log("Customer found" + event.target.result);
   };

Using the cursor

Using get() requires that you know which key you want to retrieve. If you want to step through all the values in your object store, or just between a certain range, then you can use a cursor.
  function listAllCustomers() {
   var objectStore =   
     db.transaction("customers").objectStore("customers");
   objectStore.openCursor().onsuccess = function(event) {
     // we enter this callback for each object in the store
     // The result is the cursor itself
     var cursor = event.target.result;
     if (cursor) {
       alert("Name for SSN " + cursor.key + " is " +
              cursor.value.name);
       // Calling continue on the cursor will result in this callback
       // being called again if there are other objects in the store
       cursor.continue();
     } else {
       alert("No more entries!");
     }
  }; // end of onsuccess...
} // end of listAllCustomers()
The openCursor() function takes several arguments.

First, you can limit the range of items that are retrieved by using a key range object that we'll get to in a minute.
Second, you can specify the direction that you want to iterate.

In the above example, we're iterating over all objects in ascending order. The onsuccess callback for cursors is a little special. The cursor object itself is the result property of the request (above we're using the shorthand, so it's event.target.result). Then the actual key and value can be found on the key and value properties of the cursor object. If you want to keep going, then you have to call cursor.continue() on the cursor.
  function listAllCustomersArray() {
  var objectStore =   
      db.transaction("customers").objectStore("customers");
  var customers = []; // the array of customers that will hold
                      // results
  objectStore.openCursor().onsuccess = function(event) {
    var cursor = event.target.result;
    if (cursor) {
      customers.push(cursor.value); // add a customer in the
                                    // array
      cursor.continue();
    } else {
      alert("Got all customers: " + customers);
    }
 }; // end of onsucess
} // end of listAllCustomersArray()

Getting data using an index

  var index = objectStore.index("name");
   index.get("Bill").onsuccess = function(event) {
      alert("Bill's SSN is " + event.target.result.ssn +
            " his email is " + event.target.result.email);
   };

Getting more than one result

When we work with indexes, we can open two different types of cursors on indexes:

A normal cursor that maps the index property to the object in the object store, or,
A key cursor that maps the index property to the key used to store the object in the object store.
The differences are illustrated below.
  // normal cursor
index.openCursor().onsuccess = function(event) {
  var cursor = event.target.result;
  if (cursor) {
    // cursor.key is a name, like "Bill", and cursor.value is the
    // whole object.
    alert("Name: " + cursor.key + ", SSN: " + cursor.value.ssn + ",
           email: " + cursor.value.email);
    cursor.continue();
 }
};
  // key cursor
index.openKeyCursor().onsuccess = function(event) {
   var cursor = event.target.result;
   if (cursor) {
     // cursor.key is a name, like "Bill", and cursor.value is the
     // SSN (the key).
     // No way to directly get the rest of the stored object.
     alert("Name: " + cursor.key + ", "SSN: " + cursor.value);
     cursor.continue();
   }
};