У меня есть эта программа, которая может динамически создавать складные элементы с содержимым. Я пытаюсь сохранить складные файлы, созданные в локальном хранилище. Мне удалось успешно сохранить ввод пользователя в локальном хранилище, но я столкнулся с препятствием, когда попытался сохранить элементы с тем же именем класса в локальном хранилище. Я пробовал что-то вроде этого:
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>
@RishabhAnand jQUery уже умеет составлять карты const arr = $("#divColl").find("button .text") .map(function() { return this.textContent }) .get();
Просто для лучшего конечного результата попробуйте отделить логику представления от логики данных. Итак, вместо того, чтобы хранить весь 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!
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/…
Конечно. Я далеко от клавиатуры, так что еще нет
Вы можете хранить строки только в
localStorage
.document.getElementById('someId').outerHTML
возвращает строку, поэтому вы можете сохранить строку непосредственно в localStorage.document.getElementsByClassname
возвращает массив узлов DOM, поэтому вам, возможно, придется перебирать и сохранять строки. Маленький пример:JSON.stringify(Array.from(document.getElementsByClassname('some-class')).map(i => i.outerHTML));