Reputation: 155
I have an object literal which contains functions. I'm getting an error "cannot set property title of undefined". In the editBook function below, I want to store the pElement's inner text as the object's title property (look for comment: "//store p's edited value as the title key in object").
//store p's edited value as the title key in object
var object = library.books[index];
object.title = pElement.innerText;
I tried using a 0 in place of the index function and when I added a book and edited it, everything went well. When I put in my function, it doesn't say there was an issue with the function, but that it couldn't set the property of undefined. I don't know if there is a problem with my indexing function, or if there is something else going on.
var addButton = document.querySelector("#add");
var searchButton = document.querySelector("#search");
var titleInput = document.querySelector("#title");
var display = document.querySelector("#display");
function Book(title) {
this.title = title;
}
function Library() {
this.books = [];
}
Library.prototype.add = function(book) {
this.books.push(book);
}
//btw library.books is an array of objects
var library = new Library();
//Library UI
var libraryUI = {
//Add a new book
addBook: function() {
display.innerHTML = "";
var newBook = libraryUI.createNewBook(titleInput.value);
library.add(newBook);
//log the books for console reasons
console.log(library.books);
titleInput.value = "";
},
//Create a new book
createNewBook: function(title) {
var book = new Book(title);
return book;
},
//Search for a book
searchBook: function() {
display.innerHTML = "";
var search = titleInput.value;
for (var i = 0; i < library.books.length; i++) {
var book = library.books[i];
if (book.title === search) {
var bookResult = book.title;
//create editButton, deleteButton and p element
var editButton = document.createElement("button");
var deleteButton = document.createElement("button");
var pElement = document.createElement("p");
//modify elements
editButton.innerText = "Edit";
deleteButton.innerText = "Delete";
editButton.className = "edit";
deleteButton.className = "delete";
pElement.className = "displayResult";
pElement.innerHTML = bookResult;
//display result and append buttons
display.appendChild(pElement);
display.appendChild(editButton);
display.appendChild(deleteButton);
//bind events to new buttons
libraryUI.bindEvents();
}
}
},
//delete a book
deleteBook: function() {
//Access the book's index value in the array
//Remove the book from the array
},
//edit a book
editBook: function() {
var pElement = document.querySelector(".displayResult"); //p element
var displayDiv = document.querySelector("#display"); //div element
var editButton = document.querySelector(".edit");
var containsClass = pElement.classList.contains("editMode");
var index = libraryUI.findIndex(library.books, pElement);
//If class of p is editMode
if (containsClass) {
var input = document.querySelector(".inputEl");
//switch from editMode (remove class)
pElement.classList.toggle("editMode");
//p's value becomes the label's text
pElement.innerText = input.value;
//remove input element
display.removeChild(input);
//switch "Save" to "Edit"
editButton.innerText = "Edit";
//store p's edited value as the title key in object
var object = library.books[index];
object.title = pElement.innerText;
} else {
//switch to editMode
pElement.classList.toggle("editMode");
//create input element
var inputEl = document.createElement("input");
//modify elements
inputEl.type = "text";
inputEl.className = "inputEl";
//append input element
display.insertBefore(inputEl, display.childNodes[0]);
//input value becomes p's text
inputEl.value = pElement.innerText;
//switch "Edit" to "Save"
editButton.innerText = "Save";
}
},
//bind events
bindEvents: function() {
var editButton = document.querySelector(".edit");
var deleteButton = document.querySelector(".delete");
editButton.onclick = libraryUI.editBook;
deleteButton.onclick = libraryUI.deleteBook;
},
//find the index of a book in library
findIndex: function(array, title) {
for (var i = 0; i < array.length; i++) {
if (array[i].title == title)
return i;
}
return -1;
}
};
addButton.addEventListener("click", libraryUI.addBook);
searchButton.addEventListener("click", libraryUI.searchBook);
The HTML:
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title>Library App</title>
<link rel="stylesheet" type="text/css" href="css/style.css">
</head>
<body>
<h1>Personal Library</h1>
<label for="title">Title: </label>
<input type="text" id="title">
<button id="add">Add</button>
<button id="search">Search</button>
<div id="display">
</div>
<script src="js/app.js"></script>
</body>
</html>
Upvotes: 1
Views: 1518
Reputation: 2463
In editBook you are searching on the ".displayResult" paragraph element rather than the text inside the paragraph so libraryUI.findIndex doesn't find the matching element and returns -1 (which is why you're attempting to set the title of 'undefined').
This line:
var index = libraryUI.findIndex(library.books, pElement);
should be:
var index = libraryUI.findIndex(library.books, pElement.innerText);
Upvotes: 1