DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Related

  • SelfService HR Dashboards with Workday Extend and APIs
  • How We Reduced LCP by 75% in a Production React App
  • Shipping GenAI Into an Existing App: How to Integrate AI Features Without Rewriting Your Stack
  • Modernizing Applications with the 7 Rs Strategy – A CTO's Guide

Trending

  • From Indicators to Insights: Automating IOC Enrichment Using Python and Threat Feeds
  • Dear Micromanager: Your Distrust Has a Job; It’s Just Not the One You’re Doing
  • One Query, Four GPUs: Tracing a Distributed Training Stall Across Nodes
  • From AI Chaos to Control: Building Enterprise-Grade LLM Gateways With MuleSoft Anypoint

IndexedDB in Action: Complete Sample App

By 
Raymond Camden user avatar
Raymond Camden
·
May. 03, 12 · Interview
Likes (0)
Comment
Save
Tweet
Share
8.6K Views

Join the DZone community and get the full member experience.

Join For Free

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.

 

app

Published at DZone with permission of Raymond Camden. See the original article here.

Opinions expressed by DZone contributors are their own.

Related

  • SelfService HR Dashboards with Workday Extend and APIs
  • How We Reduced LCP by 75% in a Production React App
  • Shipping GenAI Into an Existing App: How to Integrate AI Features Without Rewriting Your Stack
  • Modernizing Applications with the 7 Rs Strategy – A CTO's Guide

Partner Resources

×

Comments

The likes didn't load as expected. Please refresh the page and try again.

  • RSS
  • X
  • Facebook

ABOUT US

  • About DZone
  • Support and feedback
  • Community research

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 215
  • Nashville, TN 37211
  • [email protected]

Let's be friends:

  • RSS
  • X
  • Facebook