Switch to using IndexedDB from LocalStorage

Automatically imports from old LocalStorage data
This commit is contained in:
Neil Brommer 2017-12-09 19:57:20 -08:00
parent d86fbae8ed
commit c91f76b197

View file

@ -1,3 +1,6 @@
// use this when making changes so that there is no need to parse the page
var bookmarkList;
$(document).ready(function () { $(document).ready(function () {
calcBackground(); calcBackground();
loadBookmarks(); loadBookmarks();
@ -14,7 +17,7 @@ $(document).ready(function () {
var combo = $("#newBookmarkGroup"); var combo = $("#newBookmarkGroup");
var data = getList(); var data = getList();
for (var i = 0; i < data.length; i++) { for (var i = 0; i < data.length; i++) {
combo.append($("<option></option>").attr({ "value": i }).text(data[i].title)); combo.append($("<option>").attr({ "value": i }).text(data[i].title));
} }
@ -36,27 +39,88 @@ function importBookmarks() {
var newData = $.parseJSON($("#importText").val()); var newData = $.parseJSON($("#importText").val());
} catch (err) { } catch (err) {
console.error("Import failed: " + err.message); console.error("Import failed: " + err.message);
window.alert("Failed to import"); window.alert("Invalid Format");
return; return;
} }
if (verifyBookmarks(newData)) {
setList(newData); setList(newData);
$(".bookmarkGroup").remove();
loadBookmarks();
$("#importExportModal").modal("hide"); $("#importExportModal").modal("hide");
} else {
window.alert("Invalid Format");
}
} }
function loadBookmarks() { function loadBookmarks() {
var groups = getList(); $("#cardList").empty();
var openDBRequest = window.indexedDB.open("bookmarks");
if (groups != null) { openDBRequest.onsuccess = function (dbEvt) {
for (var i = 0; i < groups.length; i++) { console.log("Opened database");
var item = groups[i]; db = dbEvt.target.result;
buildCard(item.title, item.bookmarks); bookmarkList = [];
db.transaction(["groupIndexes"], "readonly")
.objectStore("groupIndexes")
.getAll()
.onsuccess = function (indexEvt) {
var indexes = indexEvt.target.result;
// use a placholder because getting the group info is async
// and groups could finish loading in a different order
var cardList = $("#cardList");
for (var i = 0; i < indexes.length; i++) {
var placeholder = $("<div>").attr("id", "group-" + i).appendTo(cardList);
buildGroup(indexes[i], placeholder);
} }
db.close();
}
;
}
openDBRequest.onerror = function (e) { console.log(e); }
openDBRequest.onupgradeneeded = function (e) {
// the database doesn't exist
console.log("Creating database");
db = e.target.result;
var data = window.localStorage.getItem("bookmarks");
if (data != null) {
console.log("Importing data from old version");
data = JSON.parse(data);
db.close();
setList(data);
window.localStorage.removeItem("bookmarks");
} else { } else {
$("#aboutModal").modal("show"); var groupStore = initDB(db);
// add example bookmarks
var exBookmarks = db.createObjectStore("Examples");
exBookmarks.createIndex("name", "name", { unique: false });
exBookmarks.createIndex("address", "address", { unique: false });
groupStore.add({ "title": "Examples", "groupIndex": 0 });
exBookmarks.add({ "name": "Github", "address": "https://github.com/" }, 0);
exBookmarks.add({ "name": "This project on Github", "address": "https://github.com/NeilBrommer/NewTabPage" }, 1);
exBookmarks.add({ "name": "Hacker News", "address": "https://news.ycombinator.com/" }, 2);
exBookmarks.add({ "name": "reddit", "address": "https://www.reddit.com/" }, 3);
}
}
}
function buildGroup(groupInfo, placeholder) {
var groupTransaction = db.transaction([groupInfo.title], "readonly");
var groupStore = groupTransaction.objectStore(groupInfo.title);
var groupRequest = groupStore.getAll();
groupRequest.onsuccess = function (e) {
var bookmarks = e.target.result;
bookmarkList[groupInfo.groupIndex] = { "title": groupInfo.title, "bookmarks": bookmarks };
buildCard(groupInfo.title, bookmarks).appendTo(placeholder);
} }
} }
@ -85,7 +149,7 @@ function buildCard(title, itemList) {
cardList.append(link); cardList.append(link);
} }
$("#cardList").append(card); return card;
} }
function selectGroupChanged(value) { function selectGroupChanged(value) {
@ -129,19 +193,92 @@ function setBackground(num, dark) {
$(".btn-dark").removeClass("btn-dark").addClass("btn-light"); $(".btn-dark").removeClass("btn-dark").addClass("btn-light");
} }
function getList() {
return $.parseJSON(window.localStorage.getItem("bookmarks"));
}
function getListString() { function getListString() {
return window.localStorage.getItem("bookmarks"); return JSON.stringify(bookmarkList, null, 4);
} }
function setList(list) { function setList(data) {
if (typeof list == "string") { // empty the DB and fill it with the new data
window.localStorage.setItem("bookmarks", list); bookmarkList = data;
} else {
var stringified = JSON.stringify(list, null, 4); try {
window.localStorage.setItem("bookmarks", stringified); indexedDB.deleteDatabase("bookmarks");
} catch (err) {
// it's OK if the DB doesn't exist
if (err.name != "NotFoundError") {
console.error(err);
return;
}
}
var openDBRequest = window.indexedDB.open("bookmarks", 1);
openDBRequest.onsuccess = function (e) {
db.close();
loadBookmarks();
}
openDBRequest.onerror = function (err) { console.error(err); }
openDBRequest.onupgradeneeded = function (e) {
console.log("filling db");
db = e.target.result;
var groupStore = initDB(db);
// create the object stores
for (var i = 0; i < data.length; i++) {
addGroup(data[i], groupStore, i);
}
} }
} }
function initDB(db) {
// use a table to keep track of the order of groups
var groupStore = db.createObjectStore("groupIndexes", { keyPath: "title" });
groupStore.createIndex("title", "groupName", { unique: true });
groupStore.createIndex("groupIndex", "groupIndex", { unique: true });
return groupStore;
}
function addGroup(group, groupStore, index) {
var objStore = db.createObjectStore(group.title);
objStore.createIndex("name", "name", { unique: false });
objStore.createIndex("address", "address", { unique: false });
groupStore.add({ "title": group.title, "groupIndex": index });
var bookmarks = group.bookmarks;
for (var i = 0; i < bookmarks.length; i++) {
var bkmk = bookmarks[i];
objStore.add({ "name": bkmk.name, "address": bkmk.address }, i);
}
}
function verifyBookmarks(bookmarks) {
if (!Array.isArray(bookmarks))
return false;
for (var i = 0; i < bookmarks.length; i++) {
var item = bookmarks[i];
if (item == null || typeof item != "object")
return false;
if (item.title == null || typeof item.title != "string")
return false;
for (var j = 0; j < item.bookmarks.length; j++) {
var bkmk = item.bookmarks[j];
if (bkmk == null || typeof bkmk != "object")
return false;
if (bkmk.name == null || typeof bkmk.name != "string")
return false;
if (bkmk.address == null || typeof bkmk.address != "string")
return false;
}
}
return true;
}