I'm trying to link my jQuery table with IndexedDB (IDB). Currently, I'm able to add items to the browser UI and to IDB successfully, which generates an identifier key. When the item is pulled from IDB I've stored the identifier key in a hidden column at the furthest right of the table (see screenshot) for each item.
What I want to do is delete the item from the UI and IDB. My code from line 26 of the main.js (bottom-right in screenshot) is successfully deleting the item from the UI, however the code at line 32 isn't deleting the item from IDB as required.
I've run both an alert/console.log for the variable (line 34) which is reporting the correct key identifier has been stored in the variable, but seems to be functioning unusually in that it is reporting it multiple times based on which row is selected in the table (i.e. if I delete "exercise" it reports 36 on three separate alerts?). The variable is then not correctly deleted. However, if I run line 35 and pass the literal key identifier into it (i.e. "36") instead of a variable, the item is deleted.
Any suggestions would be really welcome, thank you!
Screenshot[1]
Table and code https://i.stack.imgur.com/Etb2S.png
Full code available here (please note I've included all separate files on the JS page) https://codepen.io/QuiveringCoward/pen/gOMqpRv
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>jQuery Add / Remove Table Rows</title>
<!-- link to CSS-->
<link rel="stylesheet" href="./style.css">
<!-- link to JQuery-->
<script src="https://code.jquery.com/jquery-3.4.1.js" integrity="sha256-WpOohJOqMqqyKL9FccASB9O0KwACQJpFTUBLTYOVvVU=" crossorigin="anonymous"></script>
<!--link to JS-->
<script src="./main.js"></script>
<script src="../lib/indexedDB.js"></script>
</head>
<body>
<!-- user inputs for tasks -->
<h1> Simplicity | Simplify Your Life </h1>
<form id="todo-list">
<label for=task>Task</label>
<input type="text" id="task" placeholder="Task" required="required">
<label for=task>Description</label>
<input type="text" id="description" placeholder="Description">
<label for=task>Due Date</label>
<input type="date" id="date" placeholder="Due Date" required="required">
<label for=task>Time</label>
<input type="time" id="time" placeholder="00:00">
<label for=task>Frequency</label>
<select id="frequency" name="frequency" class="todo-frequency">
<option value="Daily">Daily</option>
<option value="Weekly">Weekly</option>
<option value="Monthly">Monthly</option>
</select>
<label for=task>Location</label>
<input type="text" id="location" name="location" placeholder="Location">
<label for=task>Priority</label>
<select id="priority" name="priority" class="todo-priority">
<option value="1-high">1 - High</option>
<option value="2-medium">2 - Medium</option>
<option value="3-low">3 - Low</option>
</select>
<br>
<br>
<!-- add task button -->
<input type="submit" class="add-task" value="Add Task">
<br>
<br>
<label for=search>Search Table</label>
<input type="text" id="search" placeholder="Search here...">
</form>
<h2>Todo List</h2>
<table id="todo-table">
<!-- headers for todolist-->
<thead>
<tr>
<th>Select</th>
<th>Task</th>
<th>Description</th>
<th>Due Date<span> ↕</span></th>
<th>Time</th>
<th>Frequency</th>
<th>Location</th>
<th>Priority<span> ↕</span></th>
<th class="key" id="key"></th>
</tr>
</thead>
<tbody>
<!-- where the JS will append the tasks -->
</tbody>
</table>
<!-- submit button for todolist -->
<button type="button" class="delete-task">Delete Task(s)</button>
<br>
<br>
<button type="button" id="all-tasks">All Tasks</button>
<button type="button" id="daily-tasks">Daily Tasks</button>
<button type="button" id="weekly-tasks">Weekly Tasks</button>
<button type="button" id="monthly-tasks">Monthly Tasks</button>
<script src="./AddItemPage/AddItem.js"></script>
<script src="./AddItemPage/AddItemDAO.js"></script>
<script src="./ListItemsPage/ListItems.js"></script>
<script src="./ListItemsPage/ListItemsDAO.js"></script>
</body>
</html>
//*************** OTHER PAGES STORED LOCALLY **************//
// AddItem.js
$("#todo-list").submit(function(event){
event.preventDefault();
setDatabaseName("Luke's Todo List", ["UsersObjectStore", "ItemsObjectStore"]);
setCurrObjectStoreName("ItemsObjectStore");
startDB(function () {
saveItemData();
alert("Item has been saved successfully!");
})
})
// AddItemDAO.js
function saveItemData() {
var data = {
};
insertOne(data, function(lastID){
event.preventDefault();
return false;
});
}
// ListItems.js
setDatabaseName("Luke's Todo List", ["UsersObjectStore", "ItemsObjectStore"]);
setCurrObjectStoreName("ItemsObjectStore");
startDB(function() {
showAllItems();
});
//ListItemsDAO.js
function showAllItems() {
selectAll(function(results) {
var len = results.length, i;
for(i = 0; i < len; i++) {
$("#todo-table").append(
'<tr id="' + results[i].id +'" class="' + results[i].frequency + " " + results[i].priority +'">\
<td> <input type="checkbox" name="record"></td>\
<td class="task">' + results[i].task + '</td>\
<td class="description">' + results[i].description + '</td>\
<td class="date">' + results[i].date + '</td>\
<td class="time">' + results[i].time + '</td>\
<td class="frequency">' + results[i].frequency + '</td>\
<td class="location">' + results[i].location + '</td>\
<td class="priority">' + results[i].priority + '</td>\
<td class="key" id="key">' + results[i].id + '</td>\
</tr>'
)
}
});
}
// Indexed DB library wrapper
//This is an indexeddb wrapper javascript library
//Global variables
var db, indexedDB, IDBTransaction, currObjectStoreName, databaseName, objectStores;
//startDB creates connection with the databaseName
//and create database and object stores
function startDB(successCallback, failureCallback) {
try {
indexedDB = window.indexedDB || window.webkitIndexedDB || window.mozIndexedDB || window.msIndexedDB;
IDBTransaction = window.IDBTransaction || window.webkitIDBTransaction || window.msIDBTransaction;
IDBKeyRange = window.IDBKeyRange || window.webkitIDBKeyRange || window.msIDBKeyRange;
}
catch(e) {
console.log('Initial IndexedDB error: ' + e);
failureCallback();
}
if(!window.indexedDB) {
failureCallback();
return;
}
var request = indexedDB.open(databaseName, 1);
//The onupgradeneeded property is triggered when a database
//of a bigger version number than the existing stored database is loaded.
request.onupgradeneeded = function(event) {
console.log('onupgradeneeded method is invoked');
db = event.target.result;
for(i=0; i < objectStores.length; i++) {
db.createObjectStore(objectStores[i], { keyPath: 'id', autoIncrement: true });
}
};
request.onsuccess = function(event) {
db = event.target.result;
successCallback && successCallback();
};
request.onerror = function(event) {
console.log('User don\'t allow IndexedDB to use offline storage.');
failureCallback();
};
}
//Just print any indexeddb related error message in console window
function indexedDBError(event) {
console.log('An error occurred in IndexedDB', event);
}
//setDatabaseName sets the Database name and Object Stores required for a website
function setDatabaseName(dbName, objStores) {
databaseName = dbName;
objectStores = objStores;
console.log('Database : ', dbName);
}
//setCurrObjectStoreName set the current object store to store or retrieve data
function setCurrObjectStoreName(objStoreName) {
currObjectStoreName = objStoreName;
console.log('Current Object Store Name : ', currObjectStoreName);
}
//selectAll retrieves all data from the current object store
function selectAll(successCallback) {
var transaction = db.transaction([currObjectStoreName], IDBTransaction.READ_ONLY || 'readonly'),
objectStore, request, results = [];
transaction.onerror = indexedDBError;
objectStore = transaction.objectStore(currObjectStoreName);
request = objectStore.openCursor();
request.onerror = indexedDBError;
request.onsuccess = function(event) {
// event.target means request
var cursor = event.target.result;
if(!cursor) {
if(successCallback) {
successCallback(results);
}
return;
}
results.push(cursor.value);
cursor.continue();
};
}
//insertOne inserts data into the current object store
//This function also creates unique id for each data
function insertOne(data, successCallback) {
var transaction = db.transaction([currObjectStoreName], IDBTransaction.READ_WRITE || 'readwrite'),
objectStore, request, lastID;
objectStore = transaction.objectStore(currObjectStoreName);
request = objectStore.add(data);
request.onsuccess = function(event) {
lastID = event.target.result;
}
request.onerror = indexedDBError;
transaction.onerror = indexedDBError;
transaction.oncomplete = function(event) {
console.log('Data was inserted succesfully');
if(successCallback) {
successCallback(lastID);
}
};
}
//deleteOne inserts data into the current object store
function deleteOne(id, successCallback) {
var transaction = db.transaction([currObjectStoreName], IDBTransaction.READ_WRITE || 'readwrite'),
objectStore, request;
objectStore = transaction.objectStore(currObjectStoreName);
request = objectStore.delete(id);
request.onerror = indexedDBError;
request.onsuccess = function(event) {
var result = event.target.result;
};
transaction.onerror = indexedDBError;
transaction.oncomplete = function() {
console.log('Data with ' + id + ' was deleted successfully');
if(successCallback) {
successCallback();
}
};
}
//updateOne updates a specific data in the current object store
function updateOne(data, successCallback) {
var transaction = db.transaction([currObjectStoreName], IDBTransaction.READ_WRITE || 'readwrite'),
objectStore, request, lastID;
objectStore = transaction.objectStore(currObjectStoreName);
request = objectStore.put(data);
request.onsuccess = function(event) {
lastID = event.target.result;
}
request.onerror = indexedDBError;
transaction.onerror = indexedDBError;
transaction.oncomplete = function(event) {
console.log('Data with ' + lastID + ' was deleted successfully');
if(successCallback) {
successCallback(lastID);
}
};
}
//selectOne select just one data
function selectOne(id, successCallback) {
var transaction = db.transaction([currObjectStoreName], IDBTransaction.READ_ONLY || 'readonly'),
objectStore, request;
transaction.onerror = indexedDBError;
objectStore = transaction.objectStore(currObjectStoreName);
request = objectStore.get(parseInt(id));
request.onerror = indexedDBError;
request.onsuccess = function(event) {
// event.target means request
var record = request.result;
if(record) {
if(successCallback) {
successCallback(record);
}
return;
}
};
}