I created a little app which allows you to add and delete todo's to a list. Because I wanted to share these data with other devices I wrote a little export function to export the data as JSON and import them as well.
However, the import mostly imports only the last item in the list, sometimes more, but never all the data.
Based on advice here on the website I created a function which loops through the todo list everytime the put has been successful, but it still doesn't give the desired result.
edu.indexedDB.importTodos = function(todos) {
var db = edu.indexedDB.db;
var transaction = db.transaction(['todo'], 'readwrite');
var objStore = transaction.objectStore('todo');
var i = 0;
putNext();
function putNext() {
if (i<todos.length) {
var tmpResult = eval('('+todos[i]+')');
var text = tmpResult.text;
var timestamp = new Date().getTime();
var todo = {'text': text,'timestamp': timestamp};
console.log("adding " + text);
objStore.put(todo).onsuccess = putNext;
++i;
} else {
edu.indexedDB.getAllTodoItems();
}
}
};
The complete app basic code:
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0">
<style>
a{cursor:pointer;}
</style>
<script>
var todoContainer = document.getElementById("todo-container");
var edu = {};
var exportObj = {};
exportObj['todo'] = {};
var todoArray = new Array();
window.indexedDB = window.indexedDB || window.webkitIndexedDB || window.mozIndexedDB;
if ('webkitIndexedDB' in window) {
window.IDBTransaction = window.webkitIDBTransaction;
window.IDBKeyRange = window.webkitIDBKeyRange;
}
edu.indexedDB = {};
edu.indexedDB.db = null;
edu.indexedDB.onerror = function(e) {
console.log(e);
};
edu.indexedDB.open = function(callback) {
var version = 2;
var request = indexedDB.open("edudb-dev1",version);
request.onupgradeneeded = function(e) {
var db = e.target.result;
e.target.transaction.onerror = edu.indexedDB.onerror;
//todo datastore
if (db.objectStoreNames.contains('todo')) {
db.deleteObjectStore('todo');
}
var store = db.createObjectStore('todo', {
keyPath: 'timestamp'
});
};
request.onsuccess = function(e) {
edu.indexedDB.db = e.target.result;
var db = edu.indexedDB.db;
callback();
};
request.onerror = edu.indexedDB.onerror;
};
edu.indexedDB.addTodo = function(todoText) {
var db = edu.indexedDB.db;
var transaction = db.transaction(['todo'], 'readwrite');
var objStore = transaction.objectStore('todo');
var timestamp = new Date().getTime();
var todo = {'text': todoText,'timestamp': timestamp};
var request = objStore.put(todo);
request.onsuccess = function(e) {
edu.indexedDB.getAllTodoItems();
};
request.onerror = function(e) {
console.log("Error Adding: ", e);
};
};
edu.indexedDB.deleteTodo = function(id) {
var db = edu.indexedDB.db;
var transaction = db.transaction(['todo'], 'readwrite');
var objStore = transaction.objectStore('todo');
var request = objStore.delete(id);
request.onsuccess = function(e) {
edu.indexedDB.getAllTodoItems();
}
request.onerror = function(e) {
console.log(e);
}
};
edu.indexedDB.getAllTodoItems = function() {
var todos = document.getElementById("todoItems");
todos.innerHTML = "";
var db = edu.indexedDB.db;
var trans = db.transaction(["todo"], "readwrite");
var store = trans.objectStore("todo");
// Get everything in the store;
var cursorRequest = store.openCursor();
cursorRequest.onsuccess = function(e) {
var result = e.target.result;
if(!result)
return;
renderTodo(result.value);
result.continue();
};
cursorRequest.onerror = edu.indexedDB.onerror;
};
function renderTodo(row) {
var todos = document.getElementById("todoItems");
var li = document.createElement("li");
var a = document.createElement("a");
var t = document.createTextNode(row.text);
var timestamp = row.timestamp;
a.addEventListener("click", function() {
edu.indexedDB.deleteTodo(timestamp);
}, false);
a.textContent = " [Delete]";
li.appendChild(t);
li.appendChild(a);
todos.appendChild(li);
//exportobject
addToExport("todo",JSON.stringify(row));
}
function addTodo() {
var todo = document.getElementById("todo");
if(todo.value){
edu.indexedDB.addTodo(todo.value);
todo.value = "";
}else{
showNotification("Please enter a todo description.");
}
}
function init() {
edu.indexedDB.open(refresh);
}
function refresh(){
edu.indexedDB.getAllTodoItems();
}
function showNotification(message){
notification.style.display = 'block';
notification.innerHTML = message;
}
function addToExport(type,row){
switch(type){
case 'todo':
todoArray.push(row);
exportObj['todo'] = todoArray;
break;
}
}
function showExport(){
document.getElementById("data").value = JSON.stringify(exportObj);
}
//imports
function importData(){
var importData = document.getElementById("data").value;
var parsedJSON = eval('('+importData+')');
var dataTodo = parsedJSON.todo;
edu.indexedDB.importTodos(dataTodo);
}
edu.indexedDB.importTodos = function(todos) {
var db = edu.indexedDB.db;
var transaction = db.transaction(['todo'], 'readwrite');
var objStore = transaction.objectStore('todo');
var i = 0;
putNext();
function putNext() {
if (i<todos.length) {
var tmpResult = eval('('+todos[i]+')');
var text = tmpResult.text;
var timestamp = new Date().getTime();
var todo = {'text': text,'timestamp': timestamp};
console.log("adding " + text);
objStore.put(todo).onsuccess = putNext;
++i;
} else {
edu.indexedDB.getAllTodoItems();
}
}
};
window.addEventListener("DOMContentLoaded", init, false);
</script>
</head>
<body>
<nav>
<div id="menu">
<a id="menu-todo" class="menu-item" onclick="showContainer('todo'); return false;">TODO</a>
<a id="menu-export" class="export-item" onclick="showExport(); return false;">export</a>
<a id="menu-import" class="import-item" onclick="importData(); return false;">import</a>
</div>
</nav>
<div id="container">
<!-- todo -->
<div id="todo-container">
<h4>Todo's</h4>
<ul id="todoItems"></ul>
<form id="todo-form">
<input type="text" id="todo" name="todo" placeholder="Enter todo..." />
<input type="submit" value="+" class="btn" onclick="addTodo(); return false;"/>
</form>
</div>
</div>
<nav>
</nav>
<textarea id="data" style="width:98%;height:250px;"></textarea>
<div id="notification"></div>
<div id="footer">©</div>
</body>
</html>