Как сохранить динамически созданные элементы в локальном хранилище

У меня есть эта программа, которая может динамически создавать складные элементы с содержимым. Я пытаюсь сохранить складные файлы, созданные в локальном хранилище. Мне удалось успешно сохранить ввод пользователя в локальном хранилище, но я столкнулся с препятствием, когда попытался сохранить элементы с тем же именем класса в локальном хранилище. Я пробовал что-то вроде этого:

   var collapsibles = document.getElementsByClassName('collapsible');

    function populateStorage() {
      localStorage.setItem('collapsibles', document.getElementsByClassName('collapsible'));
      setStyles();
    }

    function setStyles() {
      var collapsibles = localStorage.getItem('collapsibles');
      document.getElementById("myCollapsibles").innerHTML = collapsibles;
    }

    collapsibles.onchange = populateStorage;

Но не получилось, можно ли сохранять динамически созданные элементы в локальном хранилище?

Фрагмент кода программы (исключая фрагмент локального хранилища):

var currentClosable;
var currentContent;
function selectedColl() {
    document.getElementById("inputTaskDiv").style.display = "block";
    currentClosable = event.target;
    currentContent = currentClosable.nextElementSibling;
    var inputTaskDiv = document.getElementById("inputTaskDiv");
    $(currentContent).append(inputTaskDiv);
}

var taskCounter = 0;
function addTask() {
    var text = document.getElementById("taskInput").value;
    // create a new div element and give it a unique id
    var newTask = $("<div class='currentTask'><input class='checkbox' type='checkbox'><label>" + text + "</label></div>");
    newTask.id = 'temp' + taskCounter;
    taskCounter++
    // and give it some content
    var newContent = document.createTextNode(text);

    $(currentContent).append(newTask); 
    console.info("appended");


  $(".currentTask").hover(
    function() {
      var taskCur = event.target;
      $( this ).find( "a" ).last().remove();
    $(taskCur).append( $( "<a class='taskX'> x</a>" ) );
    
    function dump() {
      $(taskCur).remove();
      
    }
    $( "a" ).on( "click", dump );

    }, function() {
    $( this ).find( "a" ).last().remove();
   });
  document.getElementById("taskInput").value = " ";
}

var elementCounter = 0;
var elementCounterContent = 0;
var text;
function addElement() {
    text = document.getElementById("input").value;
    // create a new div element and give it a unique id

    var newDiv = $("<button class='collapsible' onclick='selectedColl()'></button>").text(text);
    $(newDiv).append("<button class='btnDelete'>Delete</button>");
    var newContentOfDiv = $("<div class='content'></div>");

    newDiv.id = 'temp' + elementCounter;
    newContentOfDiv.id = 'content' + elementCounterContent;

    newDiv.classList = "div";
    elementCounter++
    elementCounterContent++
    // and give it some content
    var newContent = document.createTextNode(text);

    // add the newly created element and its content into the DOM

    document.getElementById("input").value = " ";
    $("#divColl").append(newDiv, newContentOfDiv);

    newDiv.click(function () {
        this.classList.toggle("active");
        content = this.nextElementSibling;
        if (content.style.display === 'block') {
            content.style.display = 'none';
        } else {
            content.style.display = 'block';
        }
    });
}


$("#divColl").on('click', '.btnDelete', function () {
      $(this).closest('.collapsible').remove();
      content.style.display = 'none';
    });
.collapsible {
    background-color: #777;
    color: white;
    cursor: pointer;
    padding: 18px;
    width: 100%;
    border: none;
    text-align: left;
    outline: none;
    font-size: 15px;
}

.active,
.collapsible:hover {
    background-color: #555;
}

.collapsible:after {
    content: '\002B';
    color: white;
    font-weight: bold;
    float: right;
    margin-left: 5px;
}

.active:after {
    content: "\2212";
}

.content {
    padding: 0 18px;
    transition: max-height 0.2s ease-out;
    background-color: #f1f1f1;
}

.taskX{
  color:red;
}
<!DOCTYPE html>
<html>
  <head>
    <meta charset = "utf-8">
    <meta name = "viewport" content = "width=device-width">
    <script src = "https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
  </head>
  <body>
    

    <!---Add Step --->
    <div id = "addSteps">
     <p>Make a collapsible:</p>
     <input id = "input" type = "text" placeholder = "title for collapsible"><button onclick = "addElement()">Make</button>
    </div>

    <!-- Add tasks to steps --->
    <div id = "addTasksToSteps" style = "display:none">
    <div id = "inputTaskDiv" style = "display:none">
     <input id = "taskInput" type = "text"><button onclick = "addTask()">Add Task</button>
    </div>
    </div>

    <!-- Final --->
    <div id = "scheduleDiv" style = "display:none">
    </div> 

       <div id = "divColl"></div>   

       <header></header>

      </body>
    </html>

Вы можете хранить строки только в localStorage. document.getElementById('someId').outerHTML возвращает строку, поэтому вы можете сохранить строку непосредственно в localStorage. document.getElementsByClassname возвращает массив узлов DOM, поэтому вам, возможно, придется перебирать и сохранять строки. Маленький пример: JSON.stringify(Array.from(document.getElementsByClassname('s‌​ome-class')).map(i => i.outerHTML));

Rishabh Anand 21.12.2020 09:36

@RishabhAnand jQUery уже умеет составлять карты const arr = $("#divColl").find("button .text") .map(function() { return this.textContent }) .get();

mplungjan 21.12.2020 09:49
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
Раскрытие чувствительных данных
Раскрытие чувствительных данных
Все внешние компоненты, рассмотренные здесь до сих пор, взаимодействуют с клиентской стороной. Однако, если они подвергаются атаке, они не...
Зод: сила проверки и преобразования данных
Зод: сила проверки и преобразования данных
Сегодня я хочу познакомить вас с библиотекой Zod и раскрыть некоторые ее особенности, например, возможности валидации и трансформации данных, а также...
Эпизод 23/17: Twitter Space о будущем Angular, Tiny Conf
Эпизод 23/17: Twitter Space о будущем Angular, Tiny Conf
Мы провели Twitter Space, обсудив несколько проблем, связанных с последними дополнениями в Angular. Также прошла Angular Tiny Conf с 25 докладами.
Руководство ChatGPT по продаже мини JS-файлов
Руководство ChatGPT по продаже мини JS-файлов
JS-файл - это файл, содержащий код JavaScript. JavaScript - это язык программирования, который в основном используется для добавления интерактивности...
1
2
1 707
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Просто для лучшего конечного результата попробуйте отделить логику представления от логики данных. Итак, вместо того, чтобы хранить весь HTML в локальном хранилище, почему бы вам не создать структуру данных, содержащую задачи, внести изменения в эту структуру данных и сохранить ее в локальном хранилище? И когда вы загружаете страницу, вы получаете данные из хранилища и просто отображаете их на своей странице. Такое разделение упростит поддержку и изменение вашего приложения.

Я могу предложить эту структуру данных, которую я бы использовал на вашем месте:

[
    {
        title: "Task group title",
        tasks: [{
           status: "done",
           title: "Task title"
        }]
    }
]

Это даст вам полный контроль над вашими предметами, и вам будет легче расширить его позже. Потому что хранение слоя презентации обойдется вам намного позже, когда вы что-то измените в своем дизайне. конечно, в этом случае вам было бы намного проще использовать какой-нибудь фреймворк, такой как Vuejs или React...


Но для вашей текущей проблемы:

document.getElementsByClassName вернет массив объектов HTML, и он не может быть сохранен внутри локального хранилища в виде строки, вместо этого вам нужно сохранить строку HTML. локальное хранилище может хранить только строки

Для получения дополнительной информации о localStorage посетите: https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage

Поэтому вам нужно перебрать их и получить их HTML. Или вы можете использовать их контейнер и просто получить его содержимое по идентификатору, сохранить его innerHTML и получить его при необходимости.

если вы используете следующий код в цикле с i, это будет:

localStorage.setItem('collapsibles', document.getElementsByClassName('collapsible')[i].outerHTML);

поэтому в основном вы можете использовать:

localStorage.setItem('collapsibles', document.getElementById('divColl').innerHTML);

Затем вы устанавливаете innerHTML divColl, когда это необходимо. нравиться

document.getElementById('divColl').innerHTML = localStorage.getItem('collapsibles')

Таким образом, вы сохраняете весь HTML в локальном хранилище. не просто объект, который будет храниться как: "[object HTMLDivElement]"

Его проблема в том, что он хранит объект в виде строки! используя setItem в localStorage, это приведет к сохранению [object HTMLDivElement], который не является HTML!

HSLM 21.12.2020 09:38
Ответ принят как подходящий

localStorage ожидает строки

Вы можете добавить диапазон

var newDiv = $("<button class='collapsible'><span class='text'>"+text+"</span></button>");

также используя делегирование

$("#divColl").on("click","collapsible", selectedColl)

и

const arr = $("#divColl").find("button .text")
  .map(function() { return this.textContent })
  .get();
localStorage.setItem("arr",JSON.stringify(arr)); // stringify is mandatory for non-strings

Зачем смешивать доступ к DOM, когда у вас есть jQuery? Или зачем использовать jQuery, если вы хотите использовать доступ к DOM

var currentClosable;
var currentContent;

function selectedColl() {
  document.getElementById("inputTaskDiv").style.display = "block";
  currentClosable = event.target;
  currentContent = currentClosable.nextElementSibling;
  var inputTaskDiv = document.getElementById("inputTaskDiv");
  $(currentContent).append(inputTaskDiv);
}

var taskCounter = 0;

function addTask() {
  var text = document.getElementById("taskInput").value;
  // create a new div element and give it a unique id
  var newTask = $("<div class='currentTask'><input class='checkbox' type='checkbox'><label>" + text + "</label></div>");
  newTask.id = 'temp' + taskCounter;
  taskCounter++
  // and give it some content
  var newContent = document.createTextNode(text);

  $(currentContent).append(newTask);
  console.info("appended");


  $(".currentTask").hover(
    function() {
      var taskCur = event.target;
      $(this).find("a").last().remove();
      $(taskCur).append($("<a class='taskX'> x</a>"));

      function dump() {
        $(taskCur).remove();

      }
      $("a").on("click", dump);

    },
    function() {
      $(this).find("a").last().remove();
    });
  document.getElementById("taskInput").value = " ";
}

var elementCounter = 0;
var elementCounterContent = 0;
var text;

function addElement() {
  text = document.getElementById("input").value;
  // create a new div element and give it a unique id

  var newDiv = $("<button class='collapsible'><span class='text'>"+text+"</span></button>");
  $(newDiv).append("<button class='btnDelete'>Delete</button>");
  var newContentOfDiv = $("<div class='content'></div>");

  newDiv.id = 'temp' + elementCounter;
  newContentOfDiv.id = 'content' + elementCounterContent;

  newDiv.classList = "div";
  elementCounter++
  elementCounterContent++
  // and give it some content
  var newContent = document.createTextNode(text);

  // add the newly created element and its content into the DOM

  document.getElementById("input").value = " ";
  $("#divColl").append(newDiv, newContentOfDiv);
  // here store the content in localStorage
  console.info($("#divColl").find("button .text").map(function() { return this.textContent }).get())
  newDiv.click(function() {
    this.classList.toggle("active");
    content = this.nextElementSibling;
    if (content.style.display === 'block') {
      content.style.display = 'none';
    } else {
      content.style.display = 'block';
    }
  });
}


$("#divColl").on('click', '.btnDelete', function() {
  $(this).closest('.collapsible').remove();
  content.style.display = 'none';
});

$("#divColl").on("click","collapsible", selectedColl)
.collapsible {
  background-color: #777;
  color: white;
  cursor: pointer;
  padding: 18px;
  width: 100%;
  border: none;
  text-align: left;
  outline: none;
  font-size: 15px;
}

.active,
.collapsible:hover {
  background-color: #555;
}

.collapsible:after {
  content: '\002B';
  color: white;
  font-weight: bold;
  float: right;
  margin-left: 5px;
}

.active:after {
  content: "\2212";
}

.content {
  padding: 0 18px;
  transition: max-height 0.2s ease-out;
  background-color: #f1f1f1;
}

.taskX {
  color: red;
}
<!DOCTYPE html>
<html>
<head>
  <meta charset = "utf-8">
  <meta name = "viewport" content = "width=device-width">
  <title>Project HOB</title>
  <link href = "style.css" rel = "stylesheet" type = "text/css" />
  <link rel = "stylesheet" href = "//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
  <link rel = "stylesheet" href = "/resources/demos/style.css">
  <script src = "https://code.jquery.com/jquery-1.12.4.js"></script>
  <script src = "https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
  <script src = "https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
</head>
<body>


  <!---Add Step --->
  <div id = "addSteps">
    <p>Make a collapsible:</p>
    <input id = "input" type = "text" placeholder = "title for collapsible"><button onclick = "addElement()">Make</button>
  </div>

  <!-- Add tasks to steps --->
  <div id = "addTasksToSteps" style = "display:none">
    <div id = "inputTaskDiv" style = "display:none">
      <input id = "taskInput" type = "text"><button onclick = "addTask()">Add Task</button>
    </div>
  </div>

  <!-- Final Schedule --->
  <div id = "scheduleDiv" style = "display:none">
  </div>

  <div id = "divColl">
    <h1 id = "assignmentTitle"></h1>
  </div>

  <div class = "container"></div>

  <header></header>

  <script src = "script.js"></script>


</body>

</html>

Большое вам спасибо за вашу помощь! Сейчас я пытаюсь сохранить содержимое закрываемого файла, как только вы убедитесь, что вы готовы взглянуть на мой вопрос по этому поводу здесь: stackoverflow.com/questions/65404845/…

hp2345 22.12.2020 08:42

Конечно. Я далеко от клавиатуры, так что еще нет

mplungjan 22.12.2020 09:02

Другие вопросы по теме