Enter the prototype of an Object.prototype.function(), where all the EventListeners are safed (Javascript)

Viewed 25

I am working on an assignment, that constructs a small library. The project requires, that the user can input the title of a book, its author, number of pages and if the user has already read it. Then the content gets displayed on the page.

Here's the code (work in progress):

let myLibrary = [];
let submitBtn = document.querySelector("#submitBtn");
let textInput = document.querySelectorAll("input");
let addNew = document.getElementById("addNew");
let fieldSet = document.getElementById("fieldset");
let cancelBtn = document.querySelector("#cancelBtn");
let bookDisplay = document.getElementById("bookDisplay");
let flexItems = document.getElementsByClassName("flexItems"); 


// object Constructor for new books
class Book {
    constructor(title, author, pages, read) {
        this.title = title;
        this.author = author;
        this.pages = pages;
        this.read = read;
    }
}



Book.prototype.addToDisplay = function() {
    let newDiv = document.createElement("div");
    bookDisplay.appendChild(newDiv).className = "flexItems";
    
    let newSpan = document.createElement("span");

    flexItems[myLibrary.length-1].appendChild(newSpan).className = "spanItem";
    newSpan.innerText = this.title;

    this.read === true ? flexItems[myLibrary.length-1].style.backgroundColor = "green" : 
                         flexItems[myLibrary.length-1].style.backgroundColor = "red";

    newDiv.addEventListener("mouseenter", moreInfo => {
        newSpan.childNodes[0].nodeValue = this.author + "\n" + this.title + "\n" + this.pages + " pages";
    })

    newDiv.addEventListener("mouseleave", defaultInfo => {
        newSpan.childNodes[0].nodeValue = this.title;
    })


}



// creates a new instance of Book and pushes the object into the array
let addToLibrary = function addToLibrary() {
    newBook = new Book(textInput[0].value, textInput[1].value, textInput[2].value, textInput[3].checked)
    myLibrary.push(newBook);

    newBook.addToDisplay();
};


// eventlistener, to submit a new Book to the library
submitBtn.addEventListener("click", addToLibrary);


// sets the form's display from block to non-visible
let cancel = function cancel() {
    fieldSet.style.display = "none";
}

// cancels the form and returns back
cancelBtn.addEventListener("click", cancel);


// sets the form's display from non-visible to visible
let openForm = function openForm() {
    fieldSet.style.display = "block";
}

// opens form to add new book
addNew.addEventListener("click", openForm);
body {
    margin-left: 20px;
}

h1 {
    text-align: center;
}

#fieldset {
    position: fixed;
    z-index: 2;
    border: none;
    display: none;
    background: #3CBC8D;
    border-radius: 10px;
    right: 1%;
    top: 2%;
    width: 400px;
    height: auto;
    overflow: auto;
}

button {
    cursor: pointer;
}


.display {
    display: flex;
    flex-direction: row;
    flex-wrap: wrap;
    position: relative;
}

.flexItems {
    position: relative;
    display: flex;
    margin: 5px;
    color: black;
    font: Georgia;
    font-size: 20px;
    height: 200px;
    width: 200px;
    align-items: center;
    border: 2px solid gray;
    transition: 500ms;
    border-radius: 5px;
}

.spanItem {
    width: 100%;
    text-align: center;
    white-space: wrap;
    overflow: hidden;
    text-overflow: ellipsis;
}



.display .flexItems:focus,
.display .flexItems:hover {
    transform: scale(1.2);
    z-index: 1;
}


#addNew {
    position: fixed;
    z-index: 2;
    border: none;
    background: #3CBC8D;
    color: white;
    border-radius: 10px;
    right: 2%;
    top: 2%;
    width: 100px;
    height: 50px;
    overflow: auto;
    cursor: pointer;

}

















/*. Could be additionally used for the hover-effect, but doesnt look that nice for more than one row

flexItems:hover ~.flexItems {
    transform: translateX(25%);
}

.display:focus-within .flexItems,
.display:hover .flexItems {
    transform: translateX(-25%);
}

.flexItems:focus ~.flexItems,
.flexItems:hover ~.flexItems {
    transform: translateX(25%);
} */
<!DOCTYPE html>
<head>
    <meta charset="UTF-8">
    <link href="style.css" rel="stylesheet" type="text/css" />
    <script src="script.js" defer></script>
    <title>Library</title>
</head>
<body>
    <div><h1>My book library</h1></div>
    <div id="bookDisplay" class="display">
    </div>
    <div>
        <button id="addNew">Test</button>
    </div>
        <fieldset id="fieldset">
            <form id="form">
                <div>
                    <label for="title">Title: </label>
                    <input type="text" name="title" id="title" class="usrInput">
                </div>
                <div>
                    <label for="author">Author: </label>
                    <input type="text" name="author" id="author" class="usrInput">
                </div>
                <div>
                    <label for="number">Number of pages: </label>
                    <input type="number" name="number" id="number" class="usrInput">
                </div>
                <div>
                    <label for="read">Already read?: </label><br>
                    Y <input type="radio" name="read" id="read" value="Y" class="read">
                    N <input type="radio" name="read" id="read" value="N" class="read">
                </div>
                <button id="submitBtn" type="button">Submit</button>
                <button id="cancelBtn" type="button">Cancel</button>
        </fieldset>
    </div>
</body>
</html>

**My question: ** The code is working until here. But I have my concerns with the mouseenter-Eventlistener. On mouseenter, I want to add a <button>, to edit the book's value. And maybe there is moreto be added in the future. That would mean the àddToDisplay() function eventually will get clunky. So I was wondering, if I could enter the Object.prototype of the addToDisplay() function and store all eventListeners in its prototype. Is this possible in Javascript?

The only way I could solve it right now is, to write an extra function for the eventlisteners. But it seems, that this way, I'm just going back to normal function expressions with dozens of values to pass by:

Book.prototype.addToDisplay = function() {
// (...)

mousehover(this, newDiv, newSpan)

}

let mousehover = function mousehover(test, newDiv, newSpan) {
newDiv.addEventListener("mouseenter", moreInfo => {
    newSpan.childNodes[0].nodeValue = test.author + "\n" + test.title + "\n" + test.pages + " pages";
})

newDiv.addEventListener("mouseleave", defaultInfo => {
    newSpan.childNodes[0].nodeValue = test.title;
})

}

Hope I got the problem across. It's the first assignment to Objects I'm working on.

Thanks for any answers and links to informative sources.

0 Answers
Related