Search code examples
javascriptprototype

Javascript array being set to null in prototype


I am learning javascript and practicing by making a simple book list app. I wanted to add the books to local storage. But the array I want to push the values into is starting as undefined and then it is set to null. And the if else statement is not working it runs through both the if statement despite the fact that the condition should return true. It starts on line 32 First a variable booklist is declared then it checks to see if bookLists exists in local storage if it does not it sets the value bookLists to a empty array ELSE it grabs booklist from local storage and parses the array adds the book to the book list. Then sets the item to local storage. At least that is what I was trying to do. Any ideas what I am not doing correctly? 0.0

The HTML

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <meta http-equiv="X-UA-Compatible" content="ie=edge">
        <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/skeleton/2.0.4/skeleton.min.css">
        <link rel="stylesheet" href="css/main.css">

        <style>
            .correct {
                color: antiquewhite;
                padding: 7px;
                margin: 5px 0px 16px 0px;
                border: 3px forestgreen solid;
                border-radius: 6px;
                background-color: forestgreen;
            }
            .error {
                color: antiquewhite;
                padding: 7px;
                margin: 5px 0px 16px 0px;
                border: 3px firebrick solid;
                border-radius: 6px;
                background-color: firebrick;
            }
        </style>
        <title>Book List Generator</title>

    </head>
    <body>

    <div id="container" class="container booklistContainer">
        <h1 class="booklistH1">Add a Book to the Booklist &:<)</h1>
        <form id="form">
            <div>
                <label for="title">Title</label>
                <input type="text" id="title" class="u-full-width">
            </div>
            <div>
                <label for="author">Author</label>
                <input type="text" id="author" class="u-full-width">
            </div>
            <div>
                <label for="isbn">ISBN#</label>
                <input type="text" id="isbn" class="u-full-width">
            </div>
            <div>
                <button class="u-full-width" id="submit">Add a bookmark</button> 
            </div>
        <hr>
        <table class="u-full-width">
            <thead>
                <tr>
                    <th>Title</th>
                    <th>Author</th>
                    <th>ISBN</th>
                    <th></th>
                </tr>
            </thead>
            <tbody id="BookListBody"></tbody>
        </table>
    </div>
        <script src="Js/booklistGenerator.js"></script>
    </body>
    </html>

The Css

    .booklistH1 {
        letter-spacing: 1px;
        margin: 3rem 0rem;
        font-size: 1.5rem;
    } 

    .booklistContainer {
        margin-bottom: 7rem;
    }

    @media screen and (max-width: 519px) {
        .booklistH1 {
            letter-spacing: 1px;
            margin: 3rem 0rem;
            font-size: 1rem;
        } 
    }

    @media screen and (max-width: 352px) {
        .booklistH1 {
            font-size: 0.9rem;
        } 
    }

    @media screen and (max-width: 352px) {
        .booklistH1 {
            letter-spacing: 1px;
            margin: 3rem 0rem;
            font-size: 0.8rem;
        } 
    }

The Javascript

    // adding a event listener
    const sub = document.getElementById("submit").addEventListener("click", valuerRetrivel);
    const removeBook = document.getElementById("BookListBody").addEventListener("click", bookRemover);
    // the book constructer
    function BookConstructer (title, author, isbn){

        this.title = title;
        this.author = author;
        this.isbn = isbn;
    };

    // The Ui constructer
    function UiConstructor() {}

    // adding a method to the Ui constructer prtotype
    UiConstructor.prototype.addBookToList = function(book){
        // grab the table  body
        const list = document.getElementById("BookListBody");
        //create the table row to append the table cells
        const row = document.createElement("tr");
        // add the cells to the table row using templet strings 
        row.innerHTML = `
        <td>${book.title}</td>
        <td>${book.author}</td>
        <td>${book.isbn}</td>
        <td><a href="#" class="delete">X</a></td>
        `;
        // append to the table body
        list.appendChild(row);

        let bookList;

        if (localStorage.getItem("bookList" === null)) {
            bookList = [];
        }else {
            bookList = JSON.parse(localStorage.getItem("bookList"));
        }

        bookList.push(book);
        localStorage.setItem("bookList", JSON.stringify(bookList));
        alert("task saved");



    }

    UiConstructor.prototype.alertMessage = function(message, className) {

        // create and append the alert message
        const alertDiv = document.createElement("div");
        alertDiv.className = `alert ${className}`;
        alertDiv.setAttribute("id", "alert");
        const alertDivTextNode = document.createTextNode(message);
        alertDiv.appendChild(alertDivTextNode);
        const parent = document.getElementById("container");
        const form = document.getElementById("form");
        parent.insertBefore(alertDiv, form);

        // remove the alert after 3 seconds
        setTimeout(function(){
            document.getElementById("alert").remove();
        },3000);
    }

    UiConstructor.prototype.successMessage = function(message, className) {

        // create and append the success message
        const successDiv = document.createElement("div");
        successDiv.className = `success ${className}`;
        successDiv.setAttribute("id", "success");
        const successtDivTextNode = document.createTextNode(message);
        successDiv.appendChild(successtDivTextNode);
        const parent = document.getElementById("container");
        const form = document.getElementById("form");
        parent.insertBefore(successDiv, form);
        console.log(UiConstructor);
        // remove the alert after 3 seconds
        setTimeout(function(){
            document.getElementById("success").remove();
        },3000);
    }

    // retriving the form values
    function valuerRetrivel(e) {

        // initating a Ui constructor to accses its methods
        const ui = new UiConstructor();
        // reguler expression that checks for whitespace 
        const regexp = /^\s+$/;

        // retriving the form input values
        const title = document.getElementById("title").value,
            author = document.getElementById("author").value,
            isbn = document.getElementById("isbn").value;

            const resultTitle = regexp.test(title);
            const resultAuthor = regexp.test(author)
            const resultIsbn = regexp.test(isbn);
            // cheacking for white space
            if (resultTitle === true
                || resultAuthor === true
                || resultIsbn === true
                || title === ""
                || author === ""
                || isbn === "") {
                // calling the alert message and passing the arguments
                ui.alertMessage("All form fields must have content", "error");
                e.preventDefault();
                return false;
            }else {
                // calling the book constructer function to create a book object
                const book = new BookConstructer(title, author, isbn);
                // initating the ui constructer and creating a new book object
                ui.addBookToList(book);
                console.log(ui);
                // calling the success message method and passing the arguments
                ui.successMessage("Success!", "correct");
                // clearing the current input values 
                const titleClear = document.getElementById("title").value = "",
                    authorClear = document.getElementById("author").value = "",
                    isbnClear = document.getElementById("isbn").value = "";
                    e.preventDefault();   
                    return true;
            }
    };

    function bookRemover(e) {
        if (e.target.className === "delete") {
            if(confirm("Are you sure you want to delete this link?")) {
            e.target.parentElement.parentElement.remove();
            e.preventDefault();
        }
    }
    }

Solution

  • You have a typo

    if (localStorage.getItem("bookList" === null)) {
    

    which is always false.

    This causes the bookList to never be instantiated from the true clause, and also as a result the storage item is attempted to be used, which is where the null parse comes in from

    JSON.parse(localStorage.getItem("bookList"))