链接 IndexedDB 和 JQuery:如何通过定位选定行中的 table 数据来删除 table 行?
Linking IndexedDB and JQuery: How to delete a table row by targeting the table data in a selected row?
我正在尝试使用 IndexedDB (IDB) link 我的 jQuery table。目前,我能够将项目添加到浏览器 UI 并成功添加到 IDB,这会生成一个标识符键。当项目从 IDB 中提取时,我将标识符键存储在每个项目 table(参见屏幕截图)最右侧的隐藏列中。
我想要做的是从 UI 和 IDB 中删除项目。我在 main.js 第 26 行的代码(屏幕截图的右下角)成功地从 UI 中删除了该项目,但是第 32 行的代码并未按要求从 IDB 中删除该项目。
我 运行 两个 alert/console.log 变量(第 34 行)报告正确的密钥标识符已存储在变量中,但似乎运行异常它根据在 table 中选择的行多次报告它(即,如果我删除“运动”,它会在三个单独的警报中报告 36?)。然后变量没有被正确删除。但是,如果我 运行 第 35 行并将文字键标识符(即“36”)而不是变量传递给它,则该项目将被删除。
非常欢迎任何建议,谢谢!
截图[1]
Table 和代码
https://i.stack.imgur.com/Etb2S.png
此处提供完整代码(请注意,我在 JS 页面上包含了所有单独的文件)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;
}
};
}
我发现还有一个函数可以调用来从IndexedDB中删除数据,它叫做deleteOne()
,你所要做的就是找到需要删除的数据的键。我用这段代码解决了
$("table tbody").find('input[name="record"]:checked').each(function() {
deleteOne(parseInt($(this).closest('tr')[0].id))
});
我正在尝试使用 IndexedDB (IDB) link 我的 jQuery table。目前,我能够将项目添加到浏览器 UI 并成功添加到 IDB,这会生成一个标识符键。当项目从 IDB 中提取时,我将标识符键存储在每个项目 table(参见屏幕截图)最右侧的隐藏列中。
我想要做的是从 UI 和 IDB 中删除项目。我在 main.js 第 26 行的代码(屏幕截图的右下角)成功地从 UI 中删除了该项目,但是第 32 行的代码并未按要求从 IDB 中删除该项目。
我 运行 两个 alert/console.log 变量(第 34 行)报告正确的密钥标识符已存储在变量中,但似乎运行异常它根据在 table 中选择的行多次报告它(即,如果我删除“运动”,它会在三个单独的警报中报告 36?)。然后变量没有被正确删除。但是,如果我 运行 第 35 行并将文字键标识符(即“36”)而不是变量传递给它,则该项目将被删除。
非常欢迎任何建议,谢谢!
截图[1]
Table 和代码 https://i.stack.imgur.com/Etb2S.png
此处提供完整代码(请注意,我在 JS 页面上包含了所有单独的文件)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;
}
};
}
我发现还有一个函数可以调用来从IndexedDB中删除数据,它叫做deleteOne()
,你所要做的就是找到需要删除的数据的键。我用这段代码解决了
$("table tbody").find('input[name="record"]:checked').each(function() {
deleteOne(parseInt($(this).closest('tr')[0].id))
});