// TODO(jwall): Use RequireJS http://requirejs.org/docs/jquery.html if (typeof dynamicbible == "undefined") { dynamicbible = {}; } // dynamicbible.db implements a basic wrapper for IndexedDB databases. // See http://www.w3.org/TR/IndexedDB/ for more details about the // IDB* interfaces referenced below. dynamicbible.db = { version: 1, dbName: "localdata", stores: ['settings', 'verselists'], debug: false, // Initialize database. If debug is true then logging will be turned on. Init: function(debug) { var self = this; self.debug = debug; self.Session( function(e) { self.debug && console.log("Database Init complete"); }); return self; }, // Internal method not for external use. handleError: function(e) { this.debug && console.log("Error: ", e); }, // Internal method not for external use. handleUpdate: function(e) { var db = e.target.result; e.target.transaction.onerror = this.handleError; for (i in this.stores) { if (db.objectStoreNames.contains(this.stores[i])) { // TODO(jwall): handle this more gracefully? db.deleteObjectStore(this.stores[i]); } var store = db.createObjectStore(this.stores[i], {keyPath: "key"}); } }, // Do operations on an open database. // ops is expected to be a function taking an IDBDatabase object // as a parameter. Session: function(ops) { var self = this; var req = indexedDB.open(this.dbname, this.version); // HandleUpgrades req.onupgradeneeded = function(e) { self.handleUpdate(e); }; req.onsuccess = function(e) { ops(e.target.result); }; }, // Do operations on an open transaction scoped to the list of stores. // ops is expected to be a function taking an IDBTransation object // as a parameter. // type is an optional transaction type. values should be one of the // following: readonly or readwrite Transaction: function(stores, ops, type) { var self = this; var transType = type || "readonly"; self.debug && console.log( "running", transType, "transaction on stores", stores); self.Session( function(db) { // Figure this api out. var trans = db.transaction(stores, transType); ops(trans); }); }, // Get a key from the the object store. // success is expected to be a function taking an IDBRequest object // as a parameter. // error is optional and expected to be a function taking an IDBRequest // object as a parameter. Get: function(storeName, key, success, error) { var self = this; self.Transaction( [storeName], function(trans) { var store = trans.objectStore(storeName); var req = store.get(key); req.onsuccess = success; req.onerror = error || self.handleError; }); }, // Store or update a key with data in an object store. // success is expected to be a function taking an IDBRequest object // as a parameter. // error is optional and expected to be a function taking an IDBRequest // object as a parameter. Update: function(storeName, key, data, success, error) { var self = this; self.Transaction( [storeName], function(trans) { var store = trans.objectStore(storeName); var req = store.put({"key": key, "data": data}); req.onsuccess = success; req.onerror = error || self.handleError; }, "readwrite"); }, // Delete a key from an object store. // success is expected to be a function taking an IDBRequest object // as a parameter. // error is optional and expected to be a function taking an IDBRequest // object as a parameter. Delete: function(storeName, key, success, error) { var self = this; self.Transaction( [storeName], function(trans) { var store = trans.objectStore(storeName); var req = store.delete(key); req.onsuccess = success; req.onerror = error || self.handleError; }, "readwrite"); }, // Query a range of values from an object store. // range is expected to be an IDBKeyRange. // success is expected to be a function taking an IDBRequest object // as a parameter. // error is optional and expected to be a function taking an IDBRequest // object as a parameter. Query: function(storeName, range, success, error) { var self = this; self.Transaction( [storeName], function(trans) { var store = trans.objectStore(storeName); var req = store.openCursor(range); req.onsuccess = success; req.onerror = error || self.handleError; }); } };