diff --git a/README.md b/README.md index 198c296..f8c7ce0 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,20 @@ +Jquery Plugin for the IndexedDB API +=================================== + Summary +------- IndexedDB Jquery plugin demo - http://nparashuram.com/trialtool/index.html#example=/IndexedDB/jquery/trialtool.html Background +----------- The IndexedDB API is in its draft state but is already available in Firefox 4 and Chrome 12 Canary Builds. Internet Explorer also has a version of it on their HTML5 prototypes site. In my previous posts, I have also written about IndexedDB API examples using TrialTool. Problem +-------- I wrote a couple of "non-production" applications and noticed that I was frequently copying non-application-logic, IndexedDB-related code across applications. Should that code be a part of a library? In my opinion, the amount of boiler plate code written to perform simple tasks like persisting or fetching data is not little. Code +---- A typical operation using the IndexedDB API would involve using the request model, creating transactions, checking for existence of object store using error responses and exceptions and then finally getting to the part where the data is actually iterated over. var request = window.indexedDB.open("BookShop-1"); @@ -28,22 +35,24 @@ A typical operation using the IndexedDB API would involve using the request mode The above code would increase if objects have to be created with version transaction, and error conditions are to be added. Solution +-------- The IndexedDB Jquery plugin is an attempt to reduce this boiler plate code in addition to bring back concepts like method chaining and Deferred calls. -The philosophy followed in the library is the same as the $.ajax() call that is more than just a wrapper over the XMLHTTPRequest object. +The philosophy followed in the library is the same as the `$.ajax()` call that is more than just a wrapper over the XMLHTTPRequest object. Some Jquery goodness that I wanted while I designed the API include - Method chaining, access to most probable next operation in a chain. For example, once an objectStore is referenced, the next operations usually are CRUD, cursors or indexes. These operations should be available in the chain. - APIs for most common functions. For example, most people would not want to care about transactions. They would simply like transactions to be implicit and hence, the API opens a READ_WRITE transaction. Alternatively, the user can also explicitly open transactions and use them. - Since the IndexedDB API is an asynchronous API, use of Deferreds() for completion. This model is much more familiar than the request and request.result model exposed in IndexedDB API. - Default error handling, taking advantage of error event propagation in IndexedDB. Error cases are not common and should not be required at every step. The promises in Deferreds() are easier to handle errors. - Falling back on smart defaults. For example, when a user accesses an object store and it does no exist, they would probably want to create on a version change transaction. This is done in the object store call by default. However, the user can explicitly specify that the call should fail if the objectStore does not exist. +1. Method chaining, access to most probable next operation in a chain. For example, once an objectStore is referenced, the next operations usually are CRUD, cursors or indexes. These operations should be available in the chain. +2. APIs for most common functions. For example, most people would not want to care about transactions. They would simply like transactions to be implicit and hence, the API opens a READ_WRITE transaction. Alternatively, the user can also explicitly open transactions and use them. +3. Since the IndexedDB API is an asynchronous API, use of `Deferreds()` for completion. This model is much more familiar than the request and request.result model exposed in IndexedDB API. +4. Default error handling, taking advantage of error event propagation in IndexedDB. Error cases are not common and should not be required at every step. The promises in `Deferreds()` are easier to handle errors. +5. Falling back on smart defaults. For example, when a user accesses an object store and it does no exist, they would probably want to create on a version change transaction. This is done in the object store call by default. However, the user can explicitly specify that the call should fail if the objectStore does not exist. The equivalent code for the snippet above looks something like this -$.indexeddb("BookShop-1").objectStore("BookList").openCursor().each(write); + $.indexeddb("BookShop-1").objectStore("BookList").openCursor().each(write); Code and Demo +-------------- The library is currently hosted here on GitHub and the examples illustrating the API are available at http://nparashuram.com/trialtool/index.html#example=/IndexedDB/jquery/trialtool.html. Watch out this space for more updates on my experiments with IndexedDB. \ No newline at end of file diff --git a/docs/README.md b/docs/README.md index 765cb48..3e6e024 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1 +1,7 @@ -Documentation for the IndexedDB APIs will go here \ No newline at end of file +Jquery-IndexedDB API Reference +=============================== + +$.indexedDB +----------- + + diff --git a/example/index.html b/example/index.html index e69de29..5142562 100644 --- a/example/index.html +++ b/example/index.html @@ -0,0 +1,52 @@ + + + + A self contained example for the Jquery-IndexedDB plugin + + +

Jquery IndexedDB API example

+
+ Load Data from Database + +
+ + + + + +
+ +
+
+
+ + + + + + + diff --git a/jquery.indexeddb.new.js b/jquery.indexeddb.new.js index c31e02f..858a6ac 100644 --- a/jquery.indexeddb.new.js +++ b/jquery.indexeddb.new.js @@ -114,7 +114,14 @@ }); }; - result.createIndex = function(prop, indexName, options){ + result.createIndex = function(prop, options, indexName){ + if (arguments.length === 2 && typeof options === "string") { + indexName = arguments[1] + options = null; + } + if (!indexName) { + indexName = prop; + } return wrap.index(function(){ return idbObjectStore.createIndex(indexName, prop, options); }); diff --git a/package.json b/package.json index 9d56329..46fac42 100644 --- a/package.json +++ b/package.json @@ -5,8 +5,8 @@ "description" : "An easy to use Jquery API over the HTML5 IndexedDB API with smart defaults and support for promises, ", "keywords" : "IndexedDB, storage, database, data", "homepage" : "http://nparashuram.com/jquery-indexeddb/", - "docs" : "", - "demo" : "", + "docs" : "https://github.com/axemclion/jquery-indexeddb/blob/gh-pages/docs/README.md", + "demo" : "http://nparashuram.com/jquery-indexeddb/example/index.html", "files" : "jquery.indexeddb.js" "author" : { "name" : "Parashuram Narasimhan", @@ -14,9 +14,12 @@ "url" : "http://nparashuram.com" }, "licenses": [{ - "type": "GPLv2", - "url": "http://www.example.com/licenses/gpl.html" - }], + "type": "GPLv2", + "url": "http://www.gnu.org/copyleft/gpl.html" + }, { + "type" : "Apache License, Version 2.0", + "url" : "http://www.apache.org/licenses/LICENSE-2.0" + }], "dependencies" : { "jquery" : ">=1.5.x" } diff --git a/test/index.html b/test/index.html index 80493ba..4ff2edd 100644 --- a/test/index.html +++ b/test/index.html @@ -89,7 +89,7 @@ versionTransaction.objectStore(DB.OBJECT_STORE_1).each(function(elem){ objectStore2.add(elem.value); }); - versionTransaction.objectStore(DB.OBJECT_STORE_1).createIndex("Int", DB.INDEX1_ON_OBJECT_STORE_1); + versionTransaction.objectStore(DB.OBJECT_STORE_1).createIndex("Int"); }, "3": function(versionTransaction){ versionTransaction.deleteObjectStore(DB.OBJECT_STORE_3); @@ -390,7 +390,7 @@ var key = sample.integer(); var value = sample.obj(); var objectStore = $.indexedDB(DB.NAME).objectStore(DB.OBJECT_STORE_1); - objectStore.index(DB.INDEX1_ON_OBJECT_STORE_1).each(function(elem){ + objectStore.index("Int").each(function(elem){ ok(true, "Iterating on " + elem.key + ":" + elem.value); start(); stop(); @@ -398,7 +398,7 @@ ok(true, "Index Iteration completed"); start(); }, function(err, e){ - ok(true, "Index Iteration NOT completed"); + ok(false, "Index Iteration NOT completed"); _("Index Iteration NOT completed"); start(); }); @@ -407,8 +407,8 @@ asyncTest("Index iteration with keyCursor", function(){ var key = sample.integer(); var value = sample.obj(); - var objectStore = $.indexedDB(DB.NAME).objectStore(DB.OBJECT_STORE_1); - objectStore.index(DB.INDEX1_ON_OBJECT_STORE_1).eachKey(function(elem){ + var objectStore = $.indexedDB(DB.NAME).objectStore(DB.OBJECT_STORE_2); + objectStore.index(DB.INDEX1_ON_OBJECT_STORE_2).eachKey(function(elem){ ok(true, "Iterating on " + elem.key + ":" + elem.value); start(); stop(); @@ -416,7 +416,7 @@ ok(true, "Index Iteration completed"); start(); }, function(err, e){ - ok(true, "Index Iteration NOT completed"); + ok(false, "Index Iteration NOT completed"); _("Index Iteration NOT completed"); start(); });