Локальное хранилище Electron не сохраняет мои события нажатия на динамически создаваемых элементах - PullRequest
0 голосов
/ 21 ноября 2018

Я создаю настольное приложение с использованием Electron и сталкиваюсь с проблемой, касающейся локального хранения событий щелчка.

В моем приложении пользователь вводит 5 групп информации (название публикации, издательимя, статус, дата отправки, дата ответа)

информация затем помещается в таблицу HTML через DOM, где она разделяется на строки по входу и столбцы по категории информации с помощью кнопок «Удалить» и «Редактировать» на дальнем расстоянии.правые столбцы.

например,

| name1 | publisher1 | awaiting | noDate | NoDate2 | [RemoveButton] [EditButton] |

| name2 | publisher2 | denied |noDate3 | NoDate4 | [RemoveButton] | [EditButton] |

| name3 | publisher3 | accept | noDate5 | NoDate6 | [RemoveButton] | [EditButton] |

и т. д.,когда пользователь вводит больше записей, тем больше строк добавляется в таблицу.Однако в каждой добавляемой строке всегда есть 2 кнопки удаления и редактирования справа.Я назначил функции этим двум кнопкам, например:

Кнопка удаления:

editButton.addEventListener("click", function() {
 if (confirm("Are you sure you want to delete this item?")) {
         var td = event.target.parentNode;
         var tr = td.parentNode;
         tr.parentNode.removeChild(tr);

         localStorage.setItem("TableStorage", table.innerHTML);
       } else {}
     };

Кнопка редактирования:

 editButton.addEventListener("click", function() {
       if (confirm("Are you sure you want to edit this item?")) {
         var publicationName = document.getElementById("publicationNameTextField");
         var publisherName = document.getElementById("publisherNameTextField");
         var publicationStatus = document.getElementById(
           "publicationStatusTextField"
         );
         var publicationDateSubmitted = document.getElementById(
           "publicationDateSubmittedTextField"
         );
         var publicationDateResponse = document.getElementById(
           "publicationDateResponseTextField"
         );
         var table = document.getElementById("myTable");
         var td = event.target.parentNode;
         var tr = td.parentNode;

     rowIndex = tr.rowIndex;

     var cell1 = table.rows[rowIndex].cells[0].innerHTML;
     var cell2 = table.rows[rowIndex].cells[1].innerHTML;
     var cell3 = table.rows[rowIndex].cells[2].innerHTML;
     var cell4 = table.rows[rowIndex].cells[3].innerHTML;
     var cell5 = table.rows[rowIndex].cells[4].innerHTML;

     publicationName.value = cell1;
     publisherName.value = cell2;
     publicationStatus.value = cell3;
     publicationDateSubmitted.value = cell4;
     publicationDateResponse.value = cell5;
     publicationName.focus();
     localStorage.setItem("TableStorage", table.innerHTML);
     tr.parentNode.removeChild(tr);
   } else {}
 };

(Более подробно оКнопка редактирования. Удаляет строку, в которой находится кнопка, и повторно вводит все названия публикации столбца, статус и т. д. обратно в текстовые поля, которые необходимо отредактировать и повторно отправить.)

(Форматирование кода может бытьточный, поскольку я не привык здесь форматировать его)

Эти кнопки выполняют свою работу во время активного сеанса (когда представления добавляются во время работы приложения), но когда я закрываю приложение и снова открываю его и/ или принудительно перезагрузите его, кнопки, кажется, теряют свою функциональность.Я полагаю, что это своего рода проблема с тем, как я храню свое локальное хранилище.

Что я нахожу странным, тем не менее, у меня есть кнопка «Очистить все», которая, по сути, очищает все содержимое таблицы,Эта кнопка отформатирована так же, как остальные кнопки, но она не генерируется динамически, как они.Из-за этого это заставляет меня поверить, что существует проблема в том, как мои функции объявляются.

var clearBtn = document.getElementById("clearAllButton");
clearBtn.addEventListener("click", function() {
  if (confirm("Are you sure you want to clear your Publications?")) {
    for (var i = 1; i < table.rows.length; ) {
      table.deleteRow(i);

      localStorage.setItem("TableStorage", table.innerHTML);
    }
  } else {
  }
});

Вот полный фрагмент кода:

   // ALL javascript code that interacts with the page is used here.

// This code is required in the HTML by a require('renderer.js) and thus runs from the page.

// The DOM can be accessed from this file.

// Declare variables from document
//var publicationName = document.getElementById('publicationNameTextField');
//var publisherName = document.getElementById('publisherNameTextField');
//var publicationStatus = document.getElementById('publicationStatusTextField');
//var publicationDateSubmitted = document.getElementById('publicationDateSubmittedTextField');
//var publicationDateResponse = document.getElementById('publicationDateResponseTextField');
"use strict";

// Save Data on close
window.onclose = function() {
  localStorage.setItem("TableStorage", table.innerHTML);
};

// Save data failsafe in event of crash
window.onabort = function() {
  localStorage.setItem("TableStorage", table.innerHTML);
};

// Declare submit button
var submitBtn = document.getElementById("submitButton");

// Declare table data will be displayed and saved to
var table = document.getElementById("myTable");

// Get value of textfields from DOM
var publicationName = document.getElementById("publicationNameTextField").value;
var publisherName = document.getElementById("publisherNameTextField").value;
var publicationStatus = document.getElementById("publicationStatusTextField")
  .value;
var publicationDateSubmitted = document.getElementById(
  "publicationDateSubmittedTextField"
).value;
var publicationDateResponse = document.getElementById(
  "publicationDateResponseTextField"
).value;

// Create a event listener for when the add button is pressed.
submitBtn.addEventListener("click", function(o) {
  // Re declare variables for scope
  var table = document.getElementById("myTable");

  var publicationName = document.getElementById("publicationNameTextField")
    .value;
  var publisherName = document.getElementById("publisherNameTextField").value;
  var publicationStatus = document.getElementById("publicationStatusTextField")
    .value;
  var publicationDateSubmitted = document.getElementById(
    "publicationDateSubmittedTextField"
  ).value;
  var publicationDateResponse = document.getElementById(
    "publicationDateResponseTextField"
  ).value;

  // Save values entered as possible option entries for later submissions.
  var publicationNameDataList = document.getElementById(
    "publicationNameDataList"
  );
  var publicationNameOption = document.createElement("option");
  publicationNameOption.innerHTML = publicationName;
  publicationNameDataList.appendChild(publicationNameOption);

  var publisherNameDataList = document.getElementById("publisherNameDataList");
  var publisherNameOption = document.createElement("option");
  publisherNameOption.innerHTML = publisherName;
  publisherNameDataList.appendChild(publisherNameOption);

  var publicationDateSubmittedDataList = document.getElementById(
    "publicationDateSubmittedDataList"
  );
  var publicationDateSubmittedOption = document.createElement("option");
  publicationDateSubmittedOption.innerHTML = publicationDateSubmitted;
  publicationDateSubmittedDataList.appendChild(publicationDateSubmittedOption);

  var publicationDateResponseDataList = document.getElementById(
    "publicationDateResponseDataList"
  );
  var publicationDateResponseOption = document.createElement("option");
  publicationDateResponseOption.innerHTML = publicationDateResponse;
  publicationDateResponseDataList.appendChild(publicationDateResponseOption);

  // Add a button to remove the particular row on each row
  var deleteButton = document.createElement("img");
  deleteButton.className = "deleteButton";
  deleteButton.innerHTML = "Remove";
  deleteButton.addEventListener("click", function() {
    if (confirm("Are you sure you want to delete this item?")) {
     var td = event.target.parentNode;
     var tr = td.parentNode;
     tr.parentNode.removeChild(tr);

     localStorage.setItem("TableStorage", table.innerHTML);
   } else {}
  });
  deleteButton.src = "assets/img/icons8-cancel-48.png";

  var editButton = document.createElement("img");
  editButton.className = "editButton";
  editButton.innerHTML = "Edit";
  editButton.addEventListener("click", function() {
   if (confirm("Are you sure you want to edit this item?")) {
     var publicationName = document.getElementById("publicationNameTextField");
     var publisherName = document.getElementById("publisherNameTextField");
     var publicationStatus = document.getElementById(
       "publicationStatusTextField"
     );
     var publicationDateSubmitted = document.getElementById(
       "publicationDateSubmittedTextField"
     );
     var publicationDateResponse = document.getElementById(
       "publicationDateResponseTextField"
     );
     var table = document.getElementById("myTable");
     var td = event.target.parentNode;
     var tr = td.parentNode;

     rowIndex = tr.rowIndex;

     var cell1 = table.rows[rowIndex].cells[0].innerHTML;
     var cell2 = table.rows[rowIndex].cells[1].innerHTML;
     var cell3 = table.rows[rowIndex].cells[2].innerHTML;
     var cell4 = table.rows[rowIndex].cells[3].innerHTML;
     var cell5 = table.rows[rowIndex].cells[4].innerHTML;

     publicationName.value = cell1;
     publisherName.value = cell2;
     publicationStatus.value = cell3;
     publicationDateSubmitted.value = cell4;
     publicationDateResponse.value = cell5;
     publicationName.focus();
     localStorage.setItem("TableStorage", table.innerHTML);
     tr.parentNode.removeChild(tr);
   } else {}
  });
  editButton.src = "assets/img/icons8-edit-file-40.png";

  // Create cells for each row
  var row = table.insertRow(1);
  var cell1 = row.insertCell(0);
  var cell2 = row.insertCell(1);
  var cell3 = row.insertCell(2);
  var cell4 = row.insertCell(3);
  var cell5 = row.insertCell(4);
  var cell6 = row.insertCell(5);
  var cell7 = row.insertCell(6);

  // Give each cell of the row content from the textfields
  cell1.innerHTML = publicationName;
  cell2.innerHTML = publisherName;
  cell3.innerHTML = publicationStatus;
  cell4.innerHTML = publicationDateSubmitted;
  cell5.innerHTML = publicationDateResponse;
  cell6.appendChild(deleteButton);
  cell7.appendChild(editButton);

  // Save data to localstorage
  localStorage.setItem("TableStorage", table.innerHTML);

  // Clear text fields for next entry
  document.getElementById("publicationNameTextField").value = "";
  document.getElementById("publisherNameTextField").value = "";
  document.getElementById("publicationStatusTextField").value = "";
  document.getElementById("publicationDateSubmittedTextField").value = "";
  document.getElementById("publicationDateResponseTextField").value = "";
});
// Load previous data upon application loading
window.onload = function() {
  var saved = localStorage.getItem("TableStorage");

  // If there are any saved items, update our list
  if (saved) {
    table.innerHTML = saved;
  }
};
// Clear Button to clear all items of the table.
var clearBtn = document.getElementById("clearAllButton");
clearBtn.addEventListener("click", function() {
  if (confirm("Are you sure you want to clear your Publications?")) {
    for (var i = 1; i < table.rows.length; ) {
      table.deleteRow(i);

      localStorage.setItem("TableStorage", table.innerHTML);
    }
  } else {
  }
});
body {
    font-family: Arial, Helvetica, sans-serif;
}

* {
    box-sizing: border-box;
}


#form {
    text-align: center;
}

.input-container {
    display: -ms-flexbox;
    /* IE10 */
    display: flex;
    width: 100%;
    margin-bottom: 15px;
    text-align: left;
}

.blueB {
    padding: 10px;
    background: dodgerblue;
    color: white;
    min-width: 50px;
    text-align: center;
}

.input-field {
    width: 100%;
    padding: 10px;
    outline: none;
}

.input-field:focus {
    border: 2px solid dodgerblue;
}

/* Set a style for the submit button */
.btn {
    background-color: dodgerblue;
    color: white;
    padding: 15px 20px;
    border: none;
    cursor: pointer;
    width: 50%;
    opacity: 0.9;
}

.btn:hover {
    opacity: 1;
}







img:hover {
    transform: scale(1.1);
    cursor: pointer;
}

/* Style the main content */
.main {
    /* Same as the width of the sidenav */
    padding: 0px 10px;
}

/* Add media queries for small screens (when the height of the screen is less than 450px, add a smaller padding and font-size) */
@media screen and (max-height: 450px) {
    .sidebar {
        padding-top: 15px;
    }

    .sidebar a {
        font-size: 18px;
    }
}


p {
    color: white;
}

h1 {
    color: #3500D3;
}

h2 {
    color: white;

}

#myInput {
    background-image: url('../assets/img/icons8-search-32.png');
    /* Add a search icon to input */
    background-position: 10px 10px;
    /* Position the search icon */
    background-repeat: no-repeat;
    /* Do not repeat the icon image */
    width: 100%;
    /* Full-width */
    font-size: 16px;
    /* Increase font-size */
    padding: 12px 20px 12px 40px;
    /* Add some padding */
    border: 1px solid #3500D3;
    /* Add a grey border */
    margin-bottom: 12px;
    /* Add some space below the input */
}


.PublicationShow {
    height: 50%;
    width: 100%;
    overflow: auto;

}

#myTable {
    border-collapse: collapse;
    /* Collapse borders */
    width: 100%;
    /* Full-width */
    border: 1px solid #3500D3;
    /* Add a grey border */
    font-size: 18px;
    height: 50%;
    overflow-y: auto;
    /* Increase font-size */
    text-align: center;
}

#myTable th,
#myTable td {
    text-align: center;
    /* Left-align text */
    padding: 12px;
    /* Add padding */
}

#myTable tr {
    /* Add a bottom border to all table rows */
    border-bottom: 1px solid #ddd;
}

#myTable tr.header,
#myTable tr:hover {
    /* Add a grey background color to the table header and on hover */
    background-color: #3500D3;
}

td {
    color: white;
}

#clearItemText {
    display: inline;
    text-align: center;
    top: 50%;
}

.deleteButton {
    border-radius: 50%;

}



.editButton {
    border-radius: 50%;

}


.trashHover {
    background-color: none !important;
    color: white;
    font-size: 35px;
}

.trashHover:hover {
    transform: scale(1.1);
    cursor: pointer;
    color: #fb0253;

}
<!DOCTYPE html>
<html style="width: 100%; height: 90%; background-color: #190061">

<head>
  <meta charset="UTF-8" />
  <title>Easy Track | Publication Manager</title>
  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm"
    crossorigin="anonymous" />
  <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.5.0/css/all.css" integrity="sha384-B4dIYHKNBt8Bc12p+WXckhzcICo0wtJAoU8YZTY5qE0Id1GSseTk6S+L3BlXeVIU"
    crossorigin="anonymous" />
  <link rel="stylesheet" href="css/index.css" />
</head>

<body style="width: 100%; height: 90%; background-color: #190061">
  <!-- All of the Node.js APIs are available in this renderer process. -->

  <div class="main">
    <h1>Easy Track | Publication Manager</h1>
    <br />
    <p>Manage your publications and submissions with ease!</p>
    <br />
    <div id="form" style="margin:auto">
      <h2>Add Publication</h2>
      <div class="input-container">
        <i class="blueB"></i>
        <input id="publicationNameTextField" class="input-field" type="text" placeholder="Publication Name" name="publicationName"
          list="publicationNameDataList" />
        <datalist id="publicationNameDataList"> </datalist>
      </div>

      <div class="input-container">
        <i class="blueB"></i>
        <input id="publisherNameTextField" class="input-field" type="text" placeholder="Publisher Name" name="publisherName"
          list="publisherNameDataList" />
        <datalist id="publisherNameDataList"> </datalist>
      </div>

      <div class="input-container">
        <i class="blueB"></i>
        <input id="publicationStatusTextField" class="input-field" type="text" placeholder="Status" name="publicationStatus"
          list="statusList" />
        <datalist id="statusList">
          <option>Awaiting</option>
          <option>Denied</option>
          <option>Accepted</option>
        </datalist>
      </div>

      <div class="input-container">
        <i class="blueB"></i>
        <input id="publicationDateSubmittedTextField" class="input-field" type="text" placeholder="Date Submitted" name="publicationDateSubmitted"
          list="publicationDateSubmittedDataList" />
        <datalist id="publicationDateSubmittedDataList"> </datalist>
      </div>

      <div class="input-container">
        <i class="blueB"></i>
        <input id="publicationDateResponseTextField" class="input-field" type="text" placeholder="Date of Response"
          list="publicationDateResponseDataList" name="publicationDateResponse" />
        <datalist id="publicationDateResponseDataList"> </datalist>
      </div>

      <button id="submitButton" class="btn">Submit</button> <br />
    </div>
    <br />
    <br />

    <div class="PublicationsShow">
      <input type="text" id="myInput" onkeyup="searchBar()" placeholder="Search" />
      <br />
      <i id="clearAllButton" class="fas fa-trash-alt trashHover"></i>
      <p id="clearItemText">Clear All Items</p>

      <table id="myTable">
        <tr class=" header">
          <th style="width:15%; color: white !important;">
            Publication name
          </th>
          <th style="width:15%; color: white !important;">Publisher Name</th>
          <th style="width:15%; color: white !important;">Status</th>
          <th style="width:15%; color: white !important;">Date Submitted</th>
          <th style="width:15%; color: white !important;">
            Date of Response
          </th>
          <th style="width:15%; color: white !important;">Change</th>
        </tr>
      </table>
    </div>
  </div>
  <script>
    // You can also require other files to run in this process
    require("./js/renderer.js");



    function filterTable(event) {
      var filter = event.target.value.toUpperCase();
      var rows = document.querySelector("#myTable tbody").rows;
      for (var i = 1; i < rows.length; i++) {
        var firstCol = rows[i].cells[0].textContent.toUpperCase();
        var secondCol = rows[i].cells[1].textContent.toUpperCase();
        var thirdCol = rows[i].cells[2].textContent.toUpperCase();
        var fourthCol = rows[i].cells[3].textContent.toUpperCase();
        var fifthCol = rows[i].cells[4].textContent.toUpperCase();
        if (
          firstCol.indexOf(filter) > -1 ||
          secondCol.indexOf(filter) > -1 ||
          thirdCol.indexOf(filter) > -1 ||
          fourthCol.indexOf(filter) > -1 ||
          fifthCol.indexOf(filter) > -1
        ) {
          rows[i].style.display = "";
        } else {
          rows[i].style.display = "none";
        }
      }
    }
    document
      .querySelector("#myInput")
      .addEventListener("keyup", filterTable, false);

  </script>
</body>

</html>

Фрагмент не совсем точный, так как мое приложение проходит через Узел и Электрон.

Если я ничего не сделалдостаточно ясно, не стесняйтесь задавать мне вопросы, чтобы устранить путаницу.

Если у вас есть какие-либо решения для этого или советы по поводу моего плохого кода и практики, я ценю любые отзывы.

Спасибо.

1 Ответ

0 голосов
/ 24 ноября 2018

После дальнейшего изучения я обнаружил проблему.События нажатия кнопок на кнопках назначались в сеансе, но локальное хранилище не могло сохранять события, потому что они не были строками.

Чтобы решить эту проблему:

Оставьте свои события при нажатиина вашей кнопке добавления, чтобы они работали во время сеанса, но добавьте цикл for на странице загрузки для кнопок, которые вы хотите использовать.Убедитесь, что вы присвоили класс своему элементу во время нажатия кнопки, чтобы сослаться на него при загрузке страницы.

Например,

window.onload = function() {
  var savedInner = localStorage.getItem("listStorageInner");
  var savedOuter = localStorage.getItem("listStorageOuter");

  // If there are any saved items, update our list
  if (savedInner) {
    let targetList = document.getElementById("projectList");
    targetList.innerHTML = savedInner;
  }
  if (savedOuter) {
    let targetList = document.getElementById("projectList");
    targetList.outerHTML = savedOuter;
  }

  var removeButtons = document.getElementsByClassName("removeMeBtn");

  for (let i = 0; i < removeButtons.length; i++) {
    removeButtons[i].addEventListener(
      "click",
      (function() {
        return function() {
          let parent = this.parentElement;
          parent.parentElement.removeChild(parent);
          let targetList = document.getElementById("projectList");
          localStorage.removeItem("listStorageInner", targetList.innerHTML);
          localStorage.removeItem("listStorageOuter", targetList.outerHTML);
          localStorage.setItem("listStorageInner", targetList.innerHTML);
          localStorage.setItem("listStorageOuter", targetList.outerHTML);
        };
      })(i),
      false
    );
  }

  var editBtns = document.getElementsByClassName("editMeBtn");

  for (let j = 0; j < editBtns.length; j++) {
    editBtns[j].addEventListener(
      "click",
      (function() {
        return function() {
          let parent = this.parentElement;
          document.getElementById("entryInput").value = parent.textContent;
          parent.focus();
          parent.parentElement.removeChild(parent);
          let targetList = document.getElementById("projectList");
          localStorage.removeItem("listStorageInner", targetList.innerHTML);
          localStorage.removeItem("listStorageOuter", targetList.outerHTML);
          localStorage.setItem("listStorageInner", targetList.innerHTML);
          localStorage.setItem("listStorageOuter", targetList.outerHTML);
        };
      })(j),
      false
    );
  }
};

Цикл for проходит через все элементы, которые имеют имена классов:кнопки, а затем назначает событие onclick при загрузке страницы.Таким образом, события нажатия кнопки всегда работают и сохраняются должным образом через локальное хранилище.Кроме того, обязательно следите за областью применения локального хранилища.

Надеюсь, это поможет, если кто-то еще столкнется с этой проблемой.

...