Click here to Skip to main content
15,868,016 members
Please Sign up or sign in to vote.
1.00/5 (3 votes)
See more: , +
JavaScript
<!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;
      }

      /* th {
            background-color: rgb(236, 200, 188);
        } */

      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;
      // Get the user input
      let filterValue = document.getElementById("myInput").value;
      //Check if input is empty
      if (filterValue.length === 0) {
        return crudApp.createTable();
      }
      var table = document.getElementById("booksTable");
      var headerRow = table.rows[0];
      table.innerHTML = "";
      //this lines of code of cose change str-int
      // let filterValueInt = parseInt(filterValue);
      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) {
        //start to create table based on match data
        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;
      }
      //this method add header element in first row of
      table.prepend(headerRow);
    }

    // this function is work on dropdown sort
    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 = [];
      // create an array of all the rows in the table
      for (var i = 1; i < dataRows.length; i++) {
        rowArray.push(dataRows[i]);
      }
      // sort the array based on the selected option
      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);
    // tis function start to create table
    var crudApp = new (function () {
      this.myBooks = [];
      // get the data into table if data is there on localStorage
      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");
        }
      }
      //these array store table header value
      this.col = ["ID", "Book_Image", "Book_Name", "Category", "Price"];
      this.category = [
        "Business",
        "Computers",
        "Programming",
        "Science",
        "History",
      ];
      //start to create table in this function
      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);
          //th.setAttribute('margin', '2px')
          var i = document.createElement("i");
          i.style.marginLeft = "10px";
          i.setAttribute("class", "fa-solid");
          th.appendChild(i);
          tr.appendChild(th);
        }
        // this lines of code add data inside a table
        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");

          // this is for cancel the current opperation
          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);

          // this is for save the data
          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);

          // this is for update the data
          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 is for delete the data
          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);
        }
        // this lines of code sort table when we click header element
        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);
          });
        });
        //this function check the types of input fields
        const transform = function (index, content) {
          const type = headers[index].getAttribute("type");
          switch (type) {
            case "number":
              return parseFloat(content);
            case "string":
            default:
              return content;
          }
        };
        //this is use to to find direction of the array and store in this variable
        let directions = Array(headers.length).fill("");
        function sortColumn(headerIndex) {
          //Check the direction asc or desc
          const direction = directions[headerIndex] || "asc";
          const multiplier = direction == "asc" ? 1 : -1;
          changeIcon(direction, headerIndex);
          //lets make new instance of rows
          let arrayRows = Array.from(table.rows);
          // this shift method removes table header
          arrayRows.shift();
          let newRows = Array.from(arrayRows);
          let emptyRows = [];
          newRows.forEach((row) => {
            //this line find the index of td[0] them push that row in last
            let cell = row.querySelectorAll("td")[0];
            if (!cell || cell.innerHTML === "") {
              emptyRows.push(row);
            }
          });
          // we use the filter to check empty or new 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);
          });
          // find the tbody of the table
          let tbody = document.getElementsByTagName("tbody");
          for (let i = 0; i < newRows.length; i++) {
            tbody[0].appendChild(newRows[i]);
            // update the index of the save, cancel, and update buttons
            

          }
          for (let i = 0; i < emptyRows.length; i++) {
            tbody[0].appendChild(emptyRows[i]);
          }
          directions[headerIndex] = direction === "asc" ? "desc" : "asc";
        }

        //this function is to use change the icons accordind to current sort
        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";
            }
          }
        }
        // insert the row into table
        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(output)
              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);

        //to create create button
        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);

        //lines of code show the data inside this html container
        var div = document.getElementById("container");
        div.innerHTML = "";
        div.appendChild(table);
      };
      //this function cancel the current operation
      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;"
        );
        // this lines of code for image section when we click the image is there not gone
        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 function update the value in the table
      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 td = td;
            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);
          }
        }
        //this lines of code check and show which bt user click
        var lblCancel = document.getElementById("lbl" + (activeRow - 1));
        lblCancel.setAttribute(
          "style",
          "cursor:pointer; display:block; width:20px; float:left; position: absolute;"
        );
        //this is show the save bt when click update bt
        var btSave = document.getElementById("Save" + (activeRow - 1));
        btSave.setAttribute(
          "style",
          "display:block; margin-left:30px; float:left; background-color:#2DBF64;"
        );
        //this lines hide the save button only show when update bt is click
        oButton.setAttribute("style", "display:none;");
      };

      //Delete the table row
      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();
          //also delete the data into localStorage
          window.localStorage.setItem("myBook", JSON.stringify(this.myBooks));
        }
      };
      //Save the data if we update the data
      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 function create a new row in the table
      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;
            }
          }
        }
        //check if table row is empty if empty then run if condition otherwise else condition
        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));
          // incement the current id+1
          this.nextId = maxId + 1;
          obj[this.col[0]] = this.nextId;
        }
        if (Object.keys(obj).length > 0) {
          this.myBooks.push(obj);
          this.createTable();
        }
        //save myBook array to localStorage
        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
Posted
Updated 23-Jan-23 8:17am
v2
Comments
Richard MacCutchan 24-Jan-23 4:00am    
You have just dumped some 750+ lines of code with no explanation of the problem or where it occurs. If you want help then please remove all the lines not related to the problem, and add a complete explanation of exactly what is happening and where.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900