Skip to content

Instantly share code, notes, and snippets.

@melanyss
Created May 27, 2020 11:01
Show Gist options
  • Save melanyss/c2226bdb1a0db0d76a4fb51523d710e9 to your computer and use it in GitHub Desktop.
Save melanyss/c2226bdb1a0db0d76a4fb51523d710e9 to your computer and use it in GitHub Desktop.
Todo App with IndexedDB
<div id="page-wrapper">
<!-- Form for new Todo Items -->
<form id="new-todo-form" method="POST" action="#">
<input type="text" name="new-todo" id="new-todo" placeholder="Enter a todo item..." required>
</form>
<!-- Todo Item List -->
<ul id="todo-items"></ul>
</div>
/**
* @file A module for interacting with the DB.
* @author Matt West <matt.west@kojilabs.com>
* @license MIT {@link https://opensource.org/licenses/MIT}.
*/
var todoDB = (function() {
var tDB = {};
var datastore = null;
/**
* Open a connection to the datastore.
*/
tDB.open = function(callback) {
// Database version.
var version = 1;
// Open a connection to the datastore.
var request = indexedDB.open('todos', version);
// Handle datastore upgrades.
request.onupgradeneeded = function(e) {
var db = e.target.result;
e.target.transaction.onerror = tDB.onerror;
// Delete the old datastore.
if (db.objectStoreNames.contains('todo')) {
db.deleteObjectStore('todo');
}
// Create a new datastore.
var store = db.createObjectStore('todo', {
keyPath: 'timestamp'
});
};
// Handle successful datastore access.
request.onsuccess = function(e) {
// Get a reference to the DB.
datastore = e.target.result;
// Execute the callback.
callback();
};
// Handle errors when opening the datastore.
request.onerror = tDB.onerror;
};
/**
* Fetch all of the todo items in the datastore.
* @param {function} callback A function that will be executed once the items
* have been retrieved. Will be passed a param with
* an array of the todo items.
*/
tDB.fetchTodos = function(callback) {
var db = datastore;
var transaction = db.transaction(['todo'], 'readwrite');
var objStore = transaction.objectStore('todo');
var keyRange = IDBKeyRange.lowerBound(0);
var cursorRequest = objStore.openCursor(keyRange);
var todos = [];
transaction.oncomplete = function(e) {
// Execute the callback function.
callback(todos);
};
cursorRequest.onsuccess = function(e) {
var result = e.target.result;
if (!!result == false) {
return;
}
todos.push(result.value);
result.continue();
};
cursorRequest.onerror = tDB.onerror;
};
/**
* Create a new todo item.
* @param {string} text The todo item.
*/
tDB.createTodo = function(text, callback) {
// Get a reference to the db.
var db = datastore;
// Initiate a new transaction.
var transaction = db.transaction(['todo'], 'readwrite');
// Get the datastore.
var objStore = transaction.objectStore('todo');
// Create a timestamp for the todo item.
var timestamp = new Date().getTime();
// Create an object for the todo item.
var todo = {
'text': text,
'timestamp': timestamp
};
// Create the datastore request.
var request = objStore.put(todo);
// Handle a successful datastore put.
request.onsuccess = function(e) {
// Execute the callback function.
callback(todo);
};
// Handle errors.
request.onerror = tDB.onerror;
};
/**
* Delete a todo item.
* @param {int} id The timestamp (id) of the todo item to be deleted.
* @param {function} callback A callback function that will be executed if the
* delete is successful.
*/
tDB.deleteTodo = function(id, callback) {
var db = datastore;
var transaction = db.transaction(['todo'], 'readwrite');
var objStore = transaction.objectStore('todo');
var request = objStore.delete(id);
request.onsuccess = function(e) {
callback();
}
request.onerror = function(e) {
console.log(e);
}
};
// Export the tDB object.
return tDB;
}());
/**
* @file The main logic for the Todo List App.
* @author Matt West <matt.west@kojilabs.com>
* @license MIT {@link https://opensource.org/licenses/MIT}.
*/
window.onload = function() {
// Display the todo items.
todoDB.open(refreshTodos);
// Get references to the form elements.
var newTodoForm = document.getElementById('new-todo-form');
var newTodoInput = document.getElementById('new-todo');
// Handle new todo item form submissions.
newTodoForm.onsubmit = function() {
// Get the todo text.
var text = newTodoInput.value;
// Check to make sure the text is not blank (or just spaces).
if (text.replace(/ /g,'') != '') {
// Create the todo item.
todoDB.createTodo(text, function(todo) {
refreshTodos();
});
}
// Reset the input field.
newTodoInput.value = '';
// Don't send the form.
return false;
};
}
// Update the list of todo items.
function refreshTodos() {
todoDB.fetchTodos(function(todos) {
var todoList = document.getElementById('todo-items');
todoList.innerHTML = '';
for(var i = 0; i < todos.length; i++) {
// Read the todo items backwards (most recent first).
var todo = todos[(todos.length - 1 - i)];
var li = document.createElement('li');
var checkbox = document.createElement('input');
checkbox.type = "checkbox";
checkbox.className = "todo-checkbox";
checkbox.setAttribute("data-id", todo.timestamp);
li.appendChild(checkbox);
var span = document.createElement('span');
span.innerHTML = todo.text;
li.appendChild(span);
todoList.appendChild(li);
// Setup an event listener for the checkbox.
checkbox.addEventListener('click', function(e) {
var id = parseInt(e.target.getAttribute('data-id'));
todoDB.deleteTodo(id, refreshTodos);
});
}
});
}
* { -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; }
body, html {
padding: 0;
margin: 0;
}
body {
font-family: Helvetica, Arial, sans-serif;
color: #545454;
background: #F7F7F7;
}
#page-wrapper {
width: 550px;
margin: 2.5em auto;
background: #FFF;
box-shadow: 0 1px 3px rgba(0,0,0,0.2);
border-radius: 3px;
}
#new-todo-form {
padding: 0.5em;
background: #0088CC;
border-top-left-radius: 3px;
border-top-right-radius: 3px;
}
#new-todo {
width: 100%;
padding: 0.5em;
font-size: 1em;
border-radius: 3px;
border: 0;
}
#todo-items {
list-style: none;
padding: 0.5em 1em;
margin: 0;
}
#todo-items li {
font-size: 0.9em;
padding: 0.5em;
background: #FFF;
border-bottom: 1px solid #EEE;
margin: 0.5em 0;
}
input[type="checkbox"] {
margin-right: 10px;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment