<!DOCTYPE html>
<html lang="en">
<head>
<title>Books Table CRUD Application using JavaScript</title>
<script
src="https://kit.fontawesome.com/7e1008fd11.js"
crossorigin="anonymous"
></script>
<style>
table {
width: 100%;
text-align: center;
margin-left: 220px;
}
table,
th,
td {
border: solid 1px #ddd;
border-collapse: collapse;
padding: 2px 3px;
text-align: center;
}
input[type="button"] {
border: none;
color: white;
padding: 5px 13px;
text-align: center;
text-decoration: none;
display: inline-block;
font-size: 12px;
border-radius: 8px 0 8px 0;
cursor: pointer;
}
input[type="text"] {
text-align: center;
border: solid 1px #ccc;
width: auto;
height: 18px;
padding: 2px 3px;
}
select {
text-align: center;
border: solid 1px #ccc;
width: auto;
padding: 2px 3px;
}
input[type="number"] {
text-align: center;
border: solid 1px #ccc;
width: 100px;
height: 18px;
padding: 2px 3px;
}
input[type="file"] {
text-align: center;
border: solid 1px #ccc;
width: auto;
margin-top: 12px;
padding: 2px 3px;
}
#myInput {
text-align: start;
width: 52%;
height: 20px;
padding-left: 5px;
margin-bottom: 5px;
margin-left: 220px;
border-radius: 5px;
}
button {
border: none;
background-color: rgb(95, 212, 202);
color: white;
padding: 5px 13px;
text-align: center;
text-decoration: none;
display: inline-block;
font-size: 12px;
border-radius: 8px 0 8px 0;
cursor: pointer;
}
#sortOption {
height: 25px;
border-radius: 5px;
}
</style>
</head>
<body>
<!--load all the table records inside the id= container-->
<input
type="text"
id="myInput"
placeholder="Enter your Book Details..."
onkeyup="SearchTable()"
/>
<select id="sortOption">
<option>Please Select</option>
<option>ID</option>
<option>BookName</option>
<option>Category</option>
<option>Price</option>
</select>
<div id="container" style="width: 700px"></div>
</body>
<script>
const data = window.localStorage.getItem("myBook");
if (data !== null) {
try {
this.myBooks = JSON.parse(data);
if (Array.isArray(obj) && obj.length > 0) {
this.myBooks = obj;
}
} catch (e) {
console.log("could not parse table in localStorage");
}
}
function SearchTable() {
debugger;
let filterValue = document.getElementById("myInput").value;
if (filterValue.length === 0) {
return crudApp.createTable();
}
var table = document.getElementById("booksTable");
var headerRow = table.rows[0];
table.innerHTML = "";
let filteredData = JSON.parse(data).filter(
(x) =>
x.ID === parseInt(filterValue) ||
x.Book_Name.toLowerCase().includes(filterValue.toLowerCase()) ||
x.Category.toLowerCase().includes(filterValue.toLowerCase()) ||
x.Price.includes(filterValue)
);
for (let data of filteredData) {
let row = table.insertRow(-1);
let ID = row.insertCell(0);
ID.innerHTML = data.ID;
let Book_Image = row.insertCell(1);
Book_Image.innerHTML =
"<img src='" + data.Book_Image + "' width = 80 >";
let Book_Name = row.insertCell(2);
Book_Name.innerHTML = data.Book_Name;
let Category = row.insertCell(3);
Category.innerHTML = data.Category;
let Price = row.insertCell(4);
Price.innerHTML = data.Price;
}
table.prepend(headerRow);
}
function sortTable() {
var sortOption = document.getElementById("sortOption").value;
var table = document.getElementById("booksTable");
var headerRow = table.rows[0];
var lastRow = table.rows[table.rows.length - 1];
var dataRows = table.rows;
var rowArray = [];
for (var i = 1; i < dataRows.length; i++) {
rowArray.push(dataRows[i]);
}
if (sortOption === "ID") {
rowArray.sort(function (a, b) {
var x = a.cells[0].innerHTML;
var y = b.cells[0].innerHTML;
return x - y;
});
} else if (sortOption === "BookName") {
rowArray.sort(function (a, b) {
var x = a.cells[2].innerHTML.toLowerCase();
var y = b.cells[2].innerHTML.toLowerCase();
if (x < y) {
return -1;
}
if (x > y) {
return 1;
}
return 0;
});
} else if (sortOption === "Category") {
rowArray.sort(function (a, b) {
var x = a.cells[3].innerHTML.toLowerCase();
var y = b.cells[3].innerHTML.toLowerCase();
if (x < y) {
return -1;
}
if (x > y) {
return 1;
}
return 0;
});
} else if (sortOption === "Price") {
rowArray.sort(function (a, b) {
var x = a.cells[4].innerHTML;
var y = b.cells[4].innerHTML;
return x - y;
});
}
while (table.rows.length > 1) {
table.deleteRow(1);
}
for (var i = 0; i < rowArray.length; i++) {
table.appendChild(rowArray[i]);
}
table.prepend(headerRow);
table.append(lastRow);
}
document.getElementById("sortOption").addEventListener("change", sortTable);
var crudApp = new (function () {
this.myBooks = [];
const data = window.localStorage.getItem("myBook");
if (data !== null) {
try {
this.myBooks = JSON.parse(data);
if (Array.isArray(obj) && obj.length > 0) {
this.myBooks = obj;
}
} catch (e) {
console.log("could not parse table in localStorage");
}
}
this.col = ["ID", "Book_Image", "Book_Name", "Category", "Price"];
this.category = [
"Business",
"Computers",
"Programming",
"Science",
"History",
];
this.createTable = function () {
var table = document.createElement("table");
table.setAttribute("id", "booksTable");
var tr = table.insertRow(-1);
for (var h = 0; h < this.col.length; h++) {
var th = document.createElement("th");
th.setAttribute("id", "header");
var headerText = document.createTextNode(
this.col[h].replace("_", " ")
);
th.appendChild(headerText);
var i = document.createElement("i");
i.style.marginLeft = "10px";
i.setAttribute("class", "fa-solid");
th.appendChild(i);
tr.appendChild(th);
}
for (var i = 0; i < this.myBooks.length; i++) {
tr = table.insertRow(-1);
tr.setAttribute("data-id", this.myBooks[i].id);
for (var j = 0; j < this.col.length; j++) {
var tabCell = tr.insertCell(-1);
if (this.col[j].toLowerCase() == "book_image") {
tabCell.innerHTML =
"<img src='" + this.myBooks[i][this.col[j]] + "' width = 80 >";
} else {
tabCell.innerHTML = this.myBooks[i][this.col[j]];
}
}
this.td = document.createElement("td");
tr.appendChild(this.td);
var lblCancel = document.createElement("label");
lblCancel.innerHTML = "✖";
lblCancel.setAttribute("onclick", "crudApp.Cancel(this)");
lblCancel.setAttribute("style", "display:none;");
lblCancel.setAttribute("title", "Cancel");
lblCancel.setAttribute("id", "lbl" + i);
this.td.appendChild(lblCancel);
tr.appendChild(this.td);
var btSave = document.createElement("input");
btSave.setAttribute("type", "button");
btSave.setAttribute("value", "Save");
btSave.setAttribute("id", "Save" + i);
btSave.setAttribute("style", "display:none;");
btSave.setAttribute("onclick", "crudApp.Save(this)");
this.td.appendChild(btSave);
tr.appendChild(this.td);
var btUpdate = document.createElement("input");
btUpdate.setAttribute("type", "button");
btUpdate.setAttribute("value", "Update");
btUpdate.setAttribute("id", "Edit" + i);
btUpdate.setAttribute("style", "background-color:#44CCEB;");
btUpdate.setAttribute("onclick", "crudApp.Update(this)");
this.td.appendChild(btUpdate);
this.td = document.createElement("td");
tr.appendChild(this.td);
var btDelete = document.createElement("input");
btDelete.setAttribute("type", "button");
btDelete.setAttribute("value", "Delete");
btDelete.setAttribute("style", "background-color:#ED5650;");
btDelete.setAttribute("onclick", "crudApp.Delete(this)");
this.td.appendChild(btDelete);
}
const headers = table.querySelectorAll("th");
const icon = table.querySelectorAll("i");
const rows = table.querySelectorAll("tr");
var headerRow = table.rows[0];
var lastRow = table.rows[table.rows.length - 1];
headers.forEach((header, headerIndex) => {
header.addEventListener("click", () => {
sortColumn(headerIndex);
});
});
const transform = function (index, content) {
const type = headers[index].getAttribute("type");
switch (type) {
case "number":
return parseFloat(content);
case "string":
default:
return content;
}
};
let directions = Array(headers.length).fill("");
function sortColumn(headerIndex) {
const direction = directions[headerIndex] || "asc";
const multiplier = direction == "asc" ? 1 : -1;
changeIcon(direction, headerIndex);
let arrayRows = Array.from(table.rows);
arrayRows.shift();
let newRows = Array.from(arrayRows);
let emptyRows = [];
newRows.forEach((row) => {
let cell = row.querySelectorAll("td")[0];
if (!cell || cell.innerHTML === "") {
emptyRows.push(row);
}
});
newRows = newRows.filter((row) => !emptyRows.includes(row));
newRows.sort(function (rowA, rowB) {
const cellA = rowA.querySelectorAll("td")[headerIndex].innerHTML;
const cellB = rowB.querySelectorAll("td")[headerIndex].innerHTML;
let a = transform(headerIndex, cellA);
let b = transform(headerIndex, cellB);
if (a > b) return 1 * multiplier;
else if (a < b) return -1 * multiplier;
else return 0;
});
newRows.map((row, index) => {
row
.querySelectorAll("td label")[0]
.setAttribute("id", "lbl" + index);
row
.querySelectorAll("td input")[0]
.setAttribute("id", "Save" + index);
row
.querySelectorAll("td input")[1]
.setAttribute("id", "Edit" + index);
});
let tbody = document.getElementsByTagName("tbody");
for (let i = 0; i < newRows.length; i++) {
tbody[0].appendChild(newRows[i]);
}
for (let i = 0; i < emptyRows.length; i++) {
tbody[0].appendChild(emptyRows[i]);
}
directions[headerIndex] = direction === "asc" ? "desc" : "asc";
}
function changeIcon(direction, index) {
for (let i = 0; i < headers.length; i++) {
let className;
if (direction == "desc") {
headers[index].childNodes[1].className =
"fa-solid fa-caret-down active";
} else {
headers[index].childNodes[1].className =
"fa-solid fa-caret-up active";
}
}
}
tr = table.insertRow(-1);
for (var j = 0; j < this.col.length; j++) {
var newCell = tr.insertCell(-1);
if (j >= 1) {
if (this.col[j].toLowerCase() == "book_image") {
const tBox = document.createElement("input");
tBox.setAttribute("type", "file");
tBox.setAttribute(
"accept",
"image/png, image/gif, image/jpeg, image/jpg"
);
tBox.setAttribute("id", "thumbnail");
let output = document.createElement("img");
output.setAttribute("type", "image");
output.setAttribute("id", "output");
output.setAttribute("width", 200);
tBox.addEventListener("change", (event) => {
const image = event.target.files[0];
const reader = new FileReader();
reader.readAsDataURL(image);
reader.addEventListener("load", () => {
this.base64 = reader.result;
});
reader.onload = function () {
if (document.getElementById("thumbnail")) {
var output = document.getElementById("output");
output.src = reader.result;
} else {
var output = document.getElementById("output");
output.src = "";
}
};
});
newCell.appendChild(tBox);
newCell.appendChild(output);
} else if (this.col[j].toLowerCase() == "category") {
var select = document.createElement("select");
select.innerHTML = '<option value="">Please Select</option>';
for (k = 0; k < this.category.length; k++) {
select.innerHTML =
select.innerHTML +
'<option value="' +
this.category[k] +
'">' +
this.category[k] +
"</option>";
}
select.setAttribute("id", "category-select");
newCell.appendChild(select);
} else if (this.col[j].toLowerCase() == "book_image") {
var tBox = document.createElement("input");
tBox.setAttribute("type", "file");
tBox.setAttribute("name", "image");
newCell.appendChild(tBox);
} else {
var tBox = document.createElement("input");
this.col[j] === "Book_Name"
? tBox.setAttribute("type", "text")
: tBox.setAttribute("type", "number");
tBox.setAttribute("value", "");
newCell.appendChild(tBox);
}
}
}
this.td = document.createElement("td");
tr.appendChild(this.td);
var btNew = document.createElement("input");
btNew.setAttribute("type", "button");
btNew.setAttribute("value", "Create");
btNew.setAttribute("id", "New" + i);
btNew.setAttribute("class", "New");
btNew.setAttribute("style", "background-color:#207DD1;");
btNew.setAttribute("onclick", "crudApp.CreateNew(this)");
this.td.appendChild(btNew);
var div = document.getElementById("container");
div.innerHTML = "";
div.appendChild(table);
};
this.Cancel = function (oButton) {
oButton.setAttribute("style", "display:none; float:none;");
var activeRow = oButton.parentNode.parentNode.rowIndex;
var btSave = document.getElementById("Save" + (activeRow - 1));
btSave.setAttribute("style", "display:none;");
var btUpdate = document.getElementById("Edit" + (activeRow - 1));
btUpdate.setAttribute(
"style",
"display:block; margin:0 auto; background-color:#44CCEB;"
);
var tab = document.getElementById("booksTable").rows[activeRow];
for (i = 0; i < this.col.length; i++) {
var x = this.myBooks[activeRow - 1][this.col[i]];
var td = tab.getElementsByTagName("td")[i];
td.innerHTML = "<img src='" + x + "' width = 80/>";
if (this.col[i].toLowerCase() != "book_image") {
td.innerHTML = x;
}
}
};
this.Update = function (oButton) {
debugger;
var activeRow = oButton.parentNode.parentNode.rowIndex;
var tab = document.getElementById("booksTable").rows[activeRow];
var base64 = "";
for (i = 1; i < this.col.length; i++) {
var td = tab.getElementsByTagName("td")[i];
if (this.col[i].toLowerCase() == "book_image") {
let tBox = document.createElement("input");
tBox.setAttribute("type", "file");
tBox.setAttribute("accept", "image/png, image/gif, image/jpeg");
let preview = document.createElement("img");
preview.setAttribute("type", "image");
preview.setAttribute("id", "preview" + activeRow);
preview.setAttribute("width", 200);
tBox.addEventListener("change", (event) => {
const image = event.target.files[0];
const reader = new FileReader();
reader.readAsDataURL(image);
reader.addEventListener("load", () => {
this.base64 = reader.result;
});
reader.onload = function () {
preview = document.getElementById("preview" + activeRow);
preview.src = reader.result;
};
});
td.setAttribute("value", td.innerText);
td.innerText = "";
td.appendChild(tBox);
td.appendChild(preview);
} else if (this.col[i].toLowerCase() == "category") {
var ele = document.createElement("select");
for (k = 0; k < this.category.length; k++) {
ele.innerHTML =
ele.innerHTML +
'<option value="' +
this.category[k] +
'">' +
this.category[k] +
"</option>";
}
ele.setAttribute("type", "select");
td.innerText = "";
td.appendChild(ele);
} else {
var ele = document.createElement("input");
ele.setAttribute("required", "");
this.col[i] === "Book_Name"
? ele.setAttribute("type", "text")
: ele.setAttribute("type", "number");
ele.setAttribute("value", td.innerText);
td.innerText = "";
td.appendChild(ele);
}
}
var lblCancel = document.getElementById("lbl" + (activeRow - 1));
lblCancel.setAttribute(
"style",
"cursor:pointer; display:block; width:20px; float:left; position: absolute;"
);
var btSave = document.getElementById("Save" + (activeRow - 1));
btSave.setAttribute(
"style",
"display:block; margin-left:30px; float:left; background-color:#2DBF64;"
);
oButton.setAttribute("style", "display:none;");
};
this.Delete = function (oButton) {
if (confirm("Do you want to delte you records?")) {
var activeRow = oButton.parentNode.parentNode.rowIndex;
this.myBooks.splice(activeRow - 1, 1);
this.createTable();
window.localStorage.setItem("myBook", JSON.stringify(this.myBooks));
}
};
this.Save = function (oButton) {
debugger;
var activeRow = oButton.parentNode.parentNode.rowIndex;
var tab = document.getElementById("booksTable").rows[activeRow];
var update = false;
for (i = 1; i < this.col.length; i++) {
var td = tab.getElementsByTagName("td")[i];
if (
this.col[i].toLowerCase() == "book_name" ||
this.col[i].toLowerCase() == "category" ||
this.col[i].toLowerCase() == "price"
) {
if (
td.childNodes[0].value != this.myBooks[activeRow - 1][this.col[i]]
) {
this.myBooks[activeRow - 1][this.col[i]] = td.childNodes[0].value;
update = true;
}
} else if (this.col[i].toLowerCase() == "book_image") {
if (td.childNodes[0].value != "") {
if (td.childNodes[0].value != "") {
this.myBooks[activeRow - 1][this.col[i]] = this.base64;
}
}
}
window.localStorage.setItem("myBook", JSON.stringify(this.myBooks));
this.createTable();
}
};
this.CreateNew = function (oButton) {
debugger;
var activeRow = oButton.parentNode.parentNode.rowIndex;
var tab = document.getElementById("booksTable").rows[activeRow];
var obj = {};
for (i = 1; i < this.col.length; i++) {
var td = tab.getElementsByTagName("td")[i];
if (
td.childNodes[0].getAttribute("type") == "text" ||
td.childNodes[0].tagName == "SELECT" ||
td.childNodes[0].getAttribute("type") == "number" ||
td.childNodes[0].getAttribute("type") == "file"
) {
var txtVal = "";
if ((td.childNodes[0].getAttribute("type") == "file") == true) {
txtVal = this.base64;
var img = document.createElement("img");
img.setAttribute("id", "thumbnail");
img.src = txtVal;
img.accept = "image/png, image/gif, image/jpeg";
} else {
txtVal = td.childNodes[0].value;
}
debugger;
if (txtVal != "") {
obj[this.col[i]] = txtVal;
} else {
obj = "";
alert("all fields are compulsory");
break;
}
}
}
if (this.myBooks.length == "") {
obj[this.col[0]] = this.myBooks.length + 1;
} else {
var book = this.myBooks[activeRow - 1];
var maxId = Math.max(...this.myBooks.map((book) => book.ID));
this.nextId = maxId + 1;
obj[this.col[0]] = this.nextId;
}
if (Object.keys(obj).length > 0) {
this.myBooks.push(obj);
this.createTable();
}
window.localStorage.setItem("myBook", JSON.stringify(this.myBooks));
};
})();
crudApp.createTable();
</script>
</html>
What I have tried:
when we sort then update, click save and cancel its override the row value