IndexedDB in Action: Complete Sample App
After a bit more sweat and tears, I've now got a "full" (if ugly) example of an IndexedDB application. It allows you to create and delete simple notes. You can view this demo here:
http://www.raymondcamden.com/demos/2012/apr/30/test5.html
Right now this demo is Firefox only. It doesn't work in Chrome because of the bug I mentioned in my earlier blog post. Here's the code - and again - I want to mention (and credit) the excellent MDN tutorial for making this easier to build.
<!DOCTYPE html>
<html>
<head>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<script>
var db;
// https://developer.mozilla.org/en/IndexedDB/Using_IndexedDB
var indexedDB = window.indexedDB || window.webkitIndexedDB || window.mozIndexedDB || window.msIndexedDB;
var IDBTransaction = window.IDBTransaction || window.webkitIDBTransaction;
$(document).ready(function() {
var openRequest = indexedDB.open("notes",5);
//handle setup
openRequest.onupgradeneeded = function(e) {
console.log("running onupgradeneeded");
var thisDb = e.target.result;
//temp delete
//thisDb.deleteObjectStore("note");
//Create Note
if(!thisDb.objectStoreNames.contains("note")) {
console.log("I need to make the note objectstore");
var objectStore = thisDb.createObjectStore("note", { keyPath: "id", autoIncrement:true });
objectStore.createIndex("title", "title", { unique: false });
}
}
openRequest.onsuccess = function(e) {
db = e.target.result;
db.onerror = function(event) {
// Generic error handler for all errors targeted at this database's
// requests!
alert("Database error: " + event.target.errorCode);
console.dir(event.target);
};
displayNotes();
}
function displayNotes() {
var transaction = db.transaction(["note"], IDBTransaction.READ);
var content="<ul>";
transaction.oncomplete = function(event) {
console.log("All done!");
$("#noteList").html(content);
};
transaction.onerror = function(event) {
// Don't forget to handle errors!
console.dir(event);
};
var objectStore = transaction.objectStore("note");
objectStore.openCursor().onsuccess = function(event) {
var cursor = event.target.result;
if (cursor) {
content += "<li data-key=\""+cursor.key+"\"><span class=\"label\">"+cursor.value.title+"</span>";
content += " <a class=\"delete\">[Delete]</a>";
content +="</li>";
cursor.continue();
}
else {
content += "</ul>";
console.log("Done with cursor");
}
};
}
$("#noteList").on("click", "a.delete", function(e) {
e.preventDefault();
var thisId = $(this).parent().data("key");
console.log("delete "+thisId);
var request = db.transaction(["note"], IDBTransaction.READ_WRITE)
.objectStore("note")
.delete(thisId);
request.onsuccess = function(event) {
displayNotes();
};
return false;
});
$("#noteList").on("click", "li", function() {
var thisId = $(this).data("key");
var transaction = db.transaction(["note"]);
var objectStore = transaction.objectStore("note");
var request = objectStore.get(thisId);
request.onerror = function(event) {
console.dir(event);
};
request.onsuccess = function(event) {
var note = request.result;
$("#noteDetail").html("<h2>"+note.title+"</h2><p>"+note.body+"</p>");
};
});
//TEMP TO REMOVE
$("#addNoteButton").click(function() {
var title = $("#title").val();
var body = $("#body").val();
var request = db.transaction(["note"], IDBTransaction.READ_WRITE)
.objectStore("note")
.add({title:title,body:body});
request.onsuccess = function(event) {
$("#title").val("");
$("#body").val("");
displayNotes();
};
return false;
});
});
</script>
<style>
#noteList li span.label {
cursor:pointer;
}
a.delete {
color:red;
font-size:.6em;
cursor: pointer;
}
</style>
</head>
<body>
<h2>Notes</h2>
<div id="noteList"></div>
<div id="noteDetail"></div>
<h2>Add Note</h2>
<form>
<input type="text" id="title" placeholder="Title" required><br/>
<textarea id="body" placeholder="Enter body here..." required></textarea>
<p>
<button id="addNoteButton">Save Note</button>
</p>
</form>
</body>
</html>Nothing too scary, right? Using method chaining makes the code a bit more palatable and simpler to work with.
After getting this working, I began to look at how you can retrieve data. I guess I shouldn't be surprised (and @thefalken pointed it out to me), but you are limited to primary key lookups only.
So let me make sure that is clear. This is not a replacement for WebSQL. You cannot search. I guess - technically - you could search if you load everything up and iterate over it, but that's not really efficient. You can do range based filters, so for example, given a set of names I could go from Bob to Mary, but if I wanted to quickly find all the objects with property X set to Y and property Z set to A, then I'm out of luck. I was really thinking this was a Mongo-ish type solution, but I was wrong.
I don't know about you - but this is kind of disappointing. Maybe my opinion will change, but right now I'm sad that WebSQL is being dumped for this.
(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)





