Warm tip: This article is reproduced from stackoverflow.com, please click
html javascript local-storage

localStorage does not save/show items

发布于 2020-03-27 10:23:42

I do my ToDo list. (I learn vanilla JS). And I have some problem with saving some items to localStorage. When I use Google chrome(F12), I see undefiend. Maybe, I do not save correctly to localStorage. I tried to change var task to array, but it does not help. Pleas, show me my mistakes. I know, my code must be rewritten, it is my first code on JS. P.s. in console (in stackOverflow) I have that error

{
  "message": "Uncaught SyntaxError: Unexpected identifier",
  "filename": "https://stacksnippets.net/js",
  "lineno": 348,
  "colno": 6
}

but in my browser not.

var task = document.querySelector("ul");
var forTask;
function toLocal(){
    forTask = task.innerHTML;
    localStorage.setItem("forLocal",forTask);
}
function newElement(newChild) {
    let btnDel= document.createElement("button");
    btnDel.className = "fa fa-trash-o";
    let myEd = document.getElementById("myEdit");
    let spanClose1 = document.getElementsByClassName("close1")[0];
    let spanRedact = document.getElementsByClassName("redact")[0];
    let myDel = document.getElementById("myDelete");
    let spanClose = document.getElementsByClassName("close")[0];
    let spanYes = document.getElementsByClassName("yes")[0];
    //create button
    let divWithBut = document.createElement("div");
    divWithBut.className = "forButt";
    let btnRedact = document.createElement("button");
    btnRedact.className = "fa fa-pencil";
    //redact but
    btnRedact.onclick = function(){
        myEd.style.display = "block";
        let editText = document.getElementById("editText");
        let divWithText = divWithBut.parentElement.getElementsByClassName("todoPost")[0];
        editText.value = divWithText.innerHTML;
        editText.currentTarget;
        spanRedact.onclick = function(){
            divWithText.textContent = editText.value;
            divWithText.className = "todoPost";
            myEd.style.display = "none";
        };
        spanClose1.onclick = function() {
            myEd.style.display = "none";
        };
    }
    /*************************** */
    /*done but*/
    let doneBut = document.createElement("button");
    doneBut.className = "fa fa-check-circle-o";
    doneBut.onclick = function(){
        let divWithText = divWithBut.parentElement.getElementsByClassName("todoPost")[0];
        divWithText.classList.toggle("checked");
    }
    /******************* */
    divWithBut.appendChild(btnRedact);
    divWithBut.appendChild(doneBut);
    divWithBut.appendChild(btnDel);
    /******************/
//for index
    let indexDiv = document.createElement("div");
    indexDiv.className = "indexDiv";
    let numbInd = 1;
    indexDiv.innerHTML = numbInd;
    /*********************************** */
        //create arrow
    let divWithArrow = document.createElement("div");
    divWithArrow.className = "myArrow";
    let arrowUP = document.createElement("i");
    arrowUP.className = "fa fa-chevron-up";
    let arrowDown = document.createElement("i");
    arrowDown.className = "fa fa-chevron-down";
    divWithArrow.appendChild(arrowUP);
    divWithArrow.appendChild(arrowDown);
    //for date
    let date = new Date();
    let curr_date = date.getDate();
    let curr_month = date.getMonth()+1;
    let curr_year = date.getFullYear();
    let curr_hour = date.getHours();
    let curr_minutes = date.getMinutes();
    let d = (curr_date + "." + curr_month + "." + curr_year+"<br>"+curr_hour+":"+curr_minutes);
    let divTime = document.createElement("div");
    divTime.style.textAlign = "center";;
    divTime.innerHTML = d;
    //***************************/
    let div1 = document.createElement("div");
    div1.className = "timeComent";
    let myli = document.createElement("li");
    myli.className = "todoPost";
    let addField = document.getElementById("addField").value;
    task = document.createTextNode(addField);
    myli.appendChild(task);
    div1.appendChild(divTime);
    div1.appendChild(indexDiv);
    div1.appendChild(divWithArrow);
    div1.appendChild(myli);
    divWithBut.style.display = "flex";
    div1.appendChild(divWithBut);
    if (addField === '') {
        alert("You must write something!");
    } else {
        document.getElementById("forToDo").appendChild(div1);
        toLocal();
    }
    document.getElementById("addField").value = "";
    //delete but
    btnDel.onclick = function(){
        myDel.style.display = "block";
        spanClose.onclick = function() {
            myDel.style.display = "none";
        };
        spanYes.onclick = function() {
            myDel.style.display = "none";
            div1.remove();
        };
    }
toLocal();
}
if(localStorage.getItem("forLocal")){
    task.innerHTML = localStorage.getItem("forLocal");
}
*{
    margin: 0;
    padding: 0;
}
header{

    width: 100%;
    display: flex;
    align-items: center;
    align-content: center;
    justify-content: center;
    overflow: auto;
}
.firstBar{
    width: 100%;
    display: flex;
    align-items: center;
    align-content: center;
    justify-content: center;
    overflow: auto;
}
.indexDiv{
    font-style: normal;
    text-align: center;
    color: #fff;
    width: 15px;
    height: 20px;
    margin: 10px;
    background-color: #888;
}
.fafaArrow{
    font-size: 24px;
    color: #000;
}
.timeComent{
    margin-top: 15px;
    margin-bottom: 15px;
    display: flex;
    justify-content:center;
    align-items: center;
}
.numberpost{
    padding: 5px;
    color: rgb(255, 255, 255);
    background: rgb(141, 112, 112);
}
.todoPost{
    background-color: #eee;
    width: 50%;
    margin: 5px;
    overflow: auto;
    text-align: justify;
}
.shadow {
    background: rgba(102, 102, 102, 0.5);
    width: 100%;
    height: 100%;
    position: absolute;
    top: 0;
    left: 0;
    display: none;
}
.window {
    width: 300px;
    height: 50px;
    text-align: center;
    padding: 15px;
    border: 3px solid #0000cc;
    border-radius: 10px;
    color: #0000cc;
    position: absolute;
    top: 0;
    right: 0;
    bottom: 0;
    left: 0;
    margin: auto;
    background: #fff;
}
.shadow:target {display: block;}


.redact {
    display: inline-block;
    border: 1px solid #0000cc;
    color: #0000cc;
    margin: 10px;
    text-decoration: none;
    background: #f2f2f2;
    font-size: 14pt;
    cursor:pointer;
    right: 0;
    top: 0;
    padding: 12px 16px 12px 16px;
}
.redact:hover {
    background-color: #68f462;
    color: white;}
.close{
    display: inline-block;
    border: 1px solid #0000cc;
    color: #0000cc;
    margin: 10px;
    text-decoration: none;
    background: #f2f2f2;
    font-size: 14pt;
    cursor:pointer;
    right: 0;
    top: 0;
    padding: 12px 16px 12px 16px;
}
.close:hover{
    background-color: #f44336;
    color: white;
}
/* Style the close button */
.close3 {
    position: absolute;
    right: 0;
    top: 0;
    padding: 12px 16px 12px 16px;
}

.yes {
    display: inline-block;
    border: 1px solid #0000cc;
    color: #0000cc;
    margin: 10px;
    text-decoration: none;
    background: #f2f2f2;
    font-size: 14pt;
    cursor:pointer;
    right: 0;
    top: 0;
    padding: 12px 16px 12px 16px;
}
.yes:hover{
    background-color: #68f462;
    color: white;
}

.close1{
    display: inline-block;
    border: 1px solid #0000cc;
    color: #0000cc;
    margin: 10px;
    text-decoration: none;
    background: #f2f2f2;
    font-size: 14pt;
    cursor:pointer;
    right: 0;
    top: 0;
    padding: 12px 16px 12px 16px;
}
.close1:hover{
    background-color: #f44336;
    color: white;
}

/* When clicked on, add a background color and strike out text */
div li.checked {
    background: #888;
    color: #fff;
    text-decoration: line-through;
}

/* Add a "checked" mark when clicked on */
div li.checked::before {
    content: '';
    position: absolute;
    border-color: #fff;
    border-style: solid;
    border-width: 0 2px 2px 0;
    top: 10px;
    left: 16px;
    transform: rotate(45deg);
    height: 15px;
    width: 7px;
}
<!DOCTYPE html>
<html>
<head>
    <title>TO DO List</title>
    <link rel="stylesheet" type="text/css" href="styles/style.css" >
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
</head>
<body>
<header>
    <input id="addField" type="text" size="70%" placeholder="Task" name="Task">
    <button type="button" onclick="newElement()">Add</button>
</header>
<div>
    <div class="firstBar">
        <div class="fafaArrow">
            <i class="fa fa-caret-up" ></i>
            <i class="fa fa-caret-down"></i>
            <input class="inptxt" type="text" size="50%" name="Task">
            <i class="fa fa-filter"></i>
        </div>
    </div>
</div>
    <ul id="forToDo" >
    </ul>
<div id="myDelete" class="shadow">
    <div class="window">Delete item?<br>
        <span class="yes">Yes</span>
        <span class="close">No</span>
    </div>
</div>
<div id="myEdit" class="shadow">
    <div class="window">
        Edit text?<br>
        <label>
            <textarea id="editText"></textarea>
        </label>
        <span class="redact">Save</span>
        <span class="close1">Cancel</span>
    </div>
</div>
<script src="js/script2.js"></script>
</body>
</html>
Questioner
SYVY_UA
Viewed
60
Federico klez Culloca 2019-07-04 15:05

When you add an element to the page, at a certain point you do this

task = document.createTextNode(addField);

Since task is a global variable (you declared it at the top), you're overshadowing it with the TextNode you're creating, so that when you then call toLocal and you do

forTask = task.innerHTML;

task has no innerHTML attribute, so it returns undefined.

Also, for some reason, you call toLocal again at the end of newElement. It's not the problem but it's something you may want to think about. I'm not sure it's what you want.

@TakayashiHarano gave a couple of hints to solve this, but I'm not sure what you want is just to have the latest element in the local storage. So I would re-write toLocal so that it takes a string (the text of the item) as input, writes it at the end of a JSON array (already populated with what was in the local storage previously), and puts the array back in local storage.

function toLocal(toAdd) {
    let storage = localStorage.getItem('forLocal');
    if (storage === null) {
        storage = [];
    } else {
        storage = JSON.parse(storage);
    }
    storage.push(toAdd);
    localStorage.setItem('forLocal', JSON.stringify(storage));
}

Then you should modify the part of the code that reads the local storage (the one at the end) to basically simulate adding a new item as you would do when creating a new task, but for each item in the parsed JSON coming from local storage.

To be fair, your code needs a good dose of rewriting to achieve this, so I'll just leave you with this as an exercise.