Building a To-do List with Local Storage

While I keep on trying to push web developers to start experimenting and exploring HTML 5 and CSS3 technologies, I will keep introducing you to them. Today we will experiment with HTML5 local JavaScript databases, a new feature lots of web developers are excited to start using. You will be walked through on how to create a simple to-do list with jQuery and local storage.

The Basic Template


Click Image to Download

For the sake of your time and the length of the tutorial I have provided a starting template for you. It contains just a basic page with a 3 tab system (not working yet), and some simple CSS to make the page look nice. Later on we will be adding more to the markup and CSS though.

Switching the Tabs

The first thing to accomplish is how to switch the tabs. The script is quite easy to write. First, on document load we want to show the first area with the to-do items to show and the navigation tab to be highlighted. Then, when we click another tab we want to hide all div elements with the “.content” class to become hidden, and remove the’ highlight from the current active tab. Finally, we want to highlight the new tab and show the new content.

$('#tabs li').click(function() {
	//Clear All Content Areas
	$('.content:not(#new) ul').empty();

	//Load Items
	if($(this).text() == 'todo') {
		loadItems(0);	//Will learn later
		loadItems(1);	//Will learn later

	//Remove Highlighting, Hide Elements

	//Add Highlighting, Show Element with Id of Text
	$('#' + $(this).text()).show();

Opening the Database

Now that we have all of our basics done it is time to start working with are database, and the first things to do is to open it. We will assign the database to a variable so we can call it over and over. Be aware that only browsers that support “window.openDatabase” can use local databases, we will check that in our code.

//Database Instance
var database;

try {
	//Check Browser Support
	if(window.openDatabase) {
		database = openDatabase(
			'To-Do List', 					//Database Name
			'1.0', 							//Database Version (1.0)
			'To-Do List by TutToaster', 	//Database Description
			200000							//Database Size (max: 200000)

		//Check for Opened
		if(!database) {
			alert('Database failed to open. Please reload.');
		else {
	else {
		alert('Your browser does not support local databases.');
catch(error) {
	if(error == 2) {
		//Version Mismatch
		alert('Database Version Mismatch');
		//Other Error

Initialize the To-Do List

Now that we have our database working we need to make a function to start our to-do list. We need to check if it is their first time using the to-do list or if they are returning. If it is the first time we need to create a new table to hold the to-do items. If it is not their first time visiting the to-do list then we can just load the items that are not done for the ‘#todo’ div.

function initialize() {
	//New Database Transaction
	database.transaction(function(data) {
		//Look if table is there
		data.executeSql('SELECT COUNT(*) FROM todos', [],
			function(data, result) {
			function(data, error) {
				//No Table, Create One
				data.executeSql('CREATE TABLE todos(id INTEGER PRIMARY KEY, item VARCHAR(24), date VARCHAR(24), done INTEGER DEFAULT 0)', [],
					function(data, result) {
					function(data, error) {
						alert('Database table failed to open/create. Try reloading?');

Loading the Items

So, now we have the database open, our table is created and our to-do list initialize function is just about done, but we need to load the items. For this we will create a function that has a parameter passed through with a value of 0 if it is not done and 1 if it is done. The function will find the to-do items with the said parameter and append them to the correct div (“#todo” or “#done”).

function loadItems(type) {
	//New Database Transaction
	database.transaction(function(data) {
		//Get Items with type (todo[0] or done[1])
		data.executeSql('SELECT * FROM todos WHERE done = ? LIMIT 10', [type],
			function(data, result) {
				//Determine the Container
				var container = (type == '0') ? 'todo' : 'done';

				//Filter through each result
				for(i = 0; i < result.rows.length; ++i) {
					//Each Items Array
					var row = result.rows.item(i);

					//Create a Element for Result, Append it
					$('<li />', {
						id: row['id'],
						html: row['item'] + '<p>' + row['date'] + '</p>',
						click: function() {
							if(container == 'todo') {
					}).appendTo('#' + container + ' ul');
					//AppendTo Container(#todo or #done) ul
			function(data, error) {
				//There was a problem. :[
				alert('There was a problem with our query. Please reload.');

Finishing a To-Do Item

Once you finish an item from your to-do list you are going to want to make it change from the list of to-do items to the list of done items. This will be done by getting the “id” of the list item and searching for a row with that “id” and setting the “done” column from “0” to “1”.

function itemFinished(id) {
	//New Database Transaction
	database.transaction(function(data) {
		//Find and Set Item (column: done) to 1
		data.executeSql('UPDATE todos SET done = 1 WHERE id = ?', [id],
			function(data, results) {
				//Slide Up Clicked Div
				$('#' + id).slideUp();

Create a New Items

Now onto one of the most important parts, creating new to-do items for your list. In the template you downloaded you will find the items I refer to on the “#new” page or div. What we are going to do is when the “#create” button is clicked we create strings of the inputted variables then create new entries into the database with the information from those strings. Once it successfully is entered a pretty message box will appear.

$('#create').click(function() {
	//Inputed Variables
	var item = $('#item').val();
	var date = $('#month').val() + ' ' + $('#day').val();

	//Sql Statement
	var sql = 'INSERT IGNORE INTO todos (item, date) VALUES (?, ?)';

	//New Database Transaction
	database.transaction(function(data) {
		data.executeSql(sql, [item, date],
			function(data, results) {
				//Show Success Message
				$('#message').text('Todo successfully added!').addClass('success').show();
			function(data, error) {
				//Show Error Message
				$('#message').text('There was a error! Please retry!').addClass('error').show();

The Small Thing

Here are just a couple other small things to add to the JavaScript. The first part to show “#todo” on default and highlight its tab. The second to hide the success and error message on click.

//Show #todo on default

//Fade Out #Message onClick
$('#message').click(function() {

Wrapping Up

Finally, we are done. You might have been able to tell interacting with the database is very similar to interacting with a PHP MySQL database, just not as much configuration. Currently local databases only works in WebKit browsers, hopefully in the near future more browsers will catch on.

I hoped you enjoyed this tutorial, and that you will explore further into HTML5 Databases and someday show us what you are capable of with this new technology!

The testking offers an exceptional training program for designer/developers. Learn the best web designing practices through the use of self paced testking HP0-Y26 tutorials and testking 000-076 study guide.

This entry was posted on Saturday, March 27th, 2010 at 11:00 and is filed under Tutorials. You can follow any responses to this entry through the RSS 2.0 feed. You can leave a response, or trackback from your own site.

Cody Robertson is a 19 year old freelancer. He is currently attending university, but loves to write and create beautiful websites whenever he can. He ranges with a large spectrum of coding languages, all the way from Objective-C to HTML. Follow Cody on Twitter

About the author Published by Cody Robertson

20 Responses »

  1. nice one!! you can use gdata api to integrate it with google calendar that way it will be saved in the cloud and also have reminder service :)

  2. Wow, it very nice! I like it… It can be even integrated in different e-services…

  3. Hey extremely good weblog!! Man .. Beautiful .. Amazing .. I will bookmark your weblog and have the rss feeds also…

  4. This is really cool and innovative, however it did not seem to work with my version of Firefox. I wonder if there is a setting to allow local databases.

  5. Very good, thanks! I’m trying to learn something from HTML5 and it has been very good.

  6. @Jordan Walker,
    I am almost positive it does not support Local Databases yet, however it does support LocalStorage and SessionStorage. So there are alliterative methods to get the same result.

    @Rest of you
    Thanks you!

  7. my Opera 10 says that there’s a problem wit query and doesn’t want to save a to-do. excellent work otherwise :))

  8. Very nice and simple. I was just looking for something like this

    Thank you for sharing

  9. Nice work but why create something that doesn’t work in Firefox???

  10. @Mac
    It will eventually work in FireFox, it is part of the HTML5 Draft.

  11. Thank you.
    Nice reading, bookmarked it to experiment.

  12. Cody, your twitter account appears to no longer exist …

  13. Nice example, but it doesn’t work in IE or Firefox. And well, it isn’t really LocalStorage you are using, but HTML5 databases. I have built a todo list using LocalStorage, which works in IE, Firefox and other browsers. The reason I did this is because it will take a long time before Firefox and others are ready to use HTML5 databases. Check out my blog post about it:

  14. Hi Cody!

    This seems helpful but is this still not working for Firefox or it already works with Firefox now?

  15. Hi Cody!

    My pick up is kinda really hard, Do you have a video tutorial on this?

    -Sandra Bills

  16. Hello , do you think there is any post it application or software that doesn’t also saves memo but also alarms on a certain time you wish before the due?


  1. Building a To-do List with Local Storage | Design Newz
  2. Web Dev Tutorials 1# | Booto'Blog
  3. Move aside Flash, here comes HTML5 | TutToaster
  4. local storage tutorials | tutorials blogs

Leave a Response

We do love friendly, well-constructed and respective comments. We do not love bitchy, stupid and disrespectful comments. Find something wrong in this post?, feel free to send us a note and we will fix the issue asap.