let myLibrary = []; const row = document.querySelector(".row"); const newButton = document.querySelector("#newbutton"); // for setting multiple CSS attributes on an element Element.prototype.setAttributes = function (attributes) { Object.keys(attributes).forEach(key => this.setAttribute(key, attributes[key])); } // Book object constructor class Book { constructor (author, title, pages, read, comment) { this.author = author; this.title = title; this.pages = pages; this.read = read; this.comment = comment; } } // pushes completed book (from makeForm() input) into array and adds it to the DOM function addBookToLibrary(book, readBool) { // do stuff here myLibrary.push(book); // create our divs // column container const columnContainer = document.createElement('div'); columnContainer.setAttribute('class', "col-sm-6"); // card const card = document.createElement('div'); card.setAttributes({class: 'card', style: "width: 18rem"}); // card body const cardBody = document.createElement('div'); cardBody.setAttribute('class', "card-body"); // book title const bookTitle = document.createElement('h5'); bookTitle.setAttribute('class', "card-title"); bookTitle.textContent = book.title; // book author const bookAuthor = document.createElement('h6'); bookAuthor.setAttribute('class', "card-subtitle mb-2 text-muted"); bookAuthor.textContent = book.author; // number of pages in book const bookPages = document.createElement('h6'); bookPages.setAttribute('class', "card-subtitle mb-2 text-muted book-pages"); bookPages.textContent = book.pages + " pages"; // comment, if any const bookComment = document.createElement('p'); bookComment.setAttribute('class', "card-text"); bookComment.textContent = book.comment; // create button container const buttonsFlex = document.createElement('div'); buttonsFlex.setAttribute('class', "buttons-flex"); // delete button const deleteButton = document.createElement('button'); deleteButton.setAttributes({class: "delete-button", onclick: "removeBookFromLibrary(this)"}); const deleteButtonText = document.createElement('div'); deleteButtonText.textContent = "Delete"; // svg stuff const trashcanSVGContainer = document.createElementNS("http://www.w3.org/2000/svg","svg"); trashcanSVGContainer.setAttributes({style: "width:24px;height:24px", "viewBox": "0 0 24 24"}); const trashcanSVGPath = document.createElementNS("http://www.w3.org/2000/svg","path"); trashcanSVGPath.setAttributes({fill: "currentColor", d: "M9,3V4H4V6H5V19A2,2 0 0,0 7,21H17A2,2 0 0,0 19,19V6H20V4H15V3H9M7,6H17V19H7V6M9,8V17H11V8H9M13,8V17H15V8H13Z"}); // read button const readButton = document.createElement('button'); readButton.setAttributes({class: "read-button", onclick: "changeBookReadStatus(this)"}); const readButtonText = document.createElement('div'); readButtonText.textContent = "Read?"; // svg stuff const checkboxSVGContainer = document.createElementNS("http://www.w3.org/2000/svg","svg"); checkboxSVGContainer.setAttributes({style: "width:24px;height:24px", "viewBox": "0 0 24 24"}); const checkboxSVGPath = document.createElementNS("http://www.w3.org/2000/svg","path"); if (readBool === true) { checkboxSVGPath.setAttributes({fill: "currentColor", d: "M19,3H5C3.89,3 3,3.89 3,5V19A2,2 0 0,0 5,21H19A2,2 0 0,0 21,19V5C21,3.89 20.1,3 19,3Z"}); } else { checkboxSVGPath.setAttributes({fill: "currentColor", d: "M19,3H5C3.89,3 3,3.89 3,5V19A2,2 0 0,0 5,21H19A2,2 0 0,0 21,19V5C21,3.89 20.1,3 19,3M19,5V19H5V5H19Z", class: "unchecked"}); } // append to DOM row.appendChild(columnContainer); columnContainer.appendChild(card); card.appendChild(cardBody); cardBody.appendChild(bookTitle); cardBody.appendChild(bookAuthor); cardBody.appendChild(bookPages); cardBody.appendChild(bookComment); cardBody.appendChild(buttonsFlex); buttonsFlex.appendChild(deleteButton); deleteButton.appendChild(deleteButtonText); deleteButton.appendChild(trashcanSVGContainer); trashcanSVGContainer.appendChild(trashcanSVGPath); buttonsFlex.appendChild(readButton); readButton.appendChild(readButtonText); readButton.appendChild(checkboxSVGContainer); checkboxSVGContainer.appendChild(checkboxSVGPath); } // removes book from array and updates DOM function removeBookFromLibrary(element) { // go up a level const buttonsFlex = element.parentElement; const cardBody = buttonsFlex.parentElement; // get the book name const bookTitle = cardBody.firstChild.innerHTML; // remove from array const index = myLibrary.findIndex(item => item.title == bookTitle); myLibrary.splice(index, 1); // go up a few more levels const card = cardBody.parentElement; const columnContainer = card.parentElement; // remove card row.removeChild(columnContainer); } function SVGSwitcheroo (oldpath, container) { const newSVGPath = document.createElementNS("http://www.w3.org/2000/svg","path"); if (oldpath.getAttribute('class') == "unchecked") { newSVGPath.setAttributes({fill: "currentColor", d: "M19,3H5C3.89,3 3,3.89 3,5V19A2,2 0 0,0 5,21H19A2,2 0 0,0 21,19V5C21,3.89 20.1,3 19,3Z"}); } else { newSVGPath.setAttributes({fill: "currentColor", d: "M19,3H5C3.89,3 3,3.89 3,5V19A2,2 0 0,0 5,21H19A2,2 0 0,0 21,19V5C21,3.89 20.1,3 19,3M19,5V19H5V5H19Z", class: "unchecked"}); } container.removeChild(oldpath); container.appendChild(newSVGPath); } // flip the checkmark in DOM and update object in array function changeBookReadStatus(element) { // DOM manipulation // find the checkbox const checkboxSVGContainer = element.lastChild; const oldSVGPath = checkboxSVGContainer.firstChild; // svg switcheroo SVGSwitcheroo(oldSVGPath, checkboxSVGContainer); // update read status in internal array // go up a couple elements const buttonsFlex = element.parentElement; const cardBody = buttonsFlex.parentElement; // get the book name const bookTitle = cardBody.firstChild.innerHTML; // find it in array const index = myLibrary.findIndex(item => item.title == bookTitle); // toggle read boolean myLibrary[index].read = myLibrary[index].read ? myLibrary[index].read = false : myLibrary[index].read = true; } function makeForm() { // create our divs // form body const newBookForm = document.createElement('form'); newBookForm.setAttributes({class: "card", id: "newbookform"}); // close button (SVG) const closeButton = document.createElement('div'); closeButton.setAttributes({class: "mb-3", id: "closebutton"}); const closeButtonContainer = document.createElementNS("http://www.w3.org/2000/svg","svg"); closeButtonContainer.setAttributes({style: "width:24px;height:24px", "viewBox": "0 0 24 24"}); const closeButtonSVGPath = document.createElementNS("http://www.w3.org/2000/svg","path"); closeButtonSVGPath.setAttributes({fill: "#6c757d", d: "M19,6.41L17.59,5L12,10.59L6.41,5L5,6.41L10.59,12L5,17.59L6.41,19L12,13.41L17.59,19L19,17.59L13.41,12L19,6.41Z"}); // close the form if button is clicked function closeForm() { newBookForm.parentElement.removeChild(newBookForm); } closeButtonContainer.addEventListener('click', closeForm); // set properties for close button // make divs and input fields // name field const bookNameDiv = document.createElement('div'); bookNameDiv.setAttribute('class', "mb-3"); const bookNameInput = document.createElement('input'); bookNameInput.setAttributes({type: "text", class: "form-control", value: "Book Name"}); // author field const bookAuthorDiv = document.createElement('div'); bookAuthorDiv.setAttribute('class', "mb-3"); const bookAuthorInput = document.createElement('input'); bookAuthorInput.setAttributes({type: "text", class: "form-control", value: "Book Author"}); // page count field const pageCountDiv = document.createElement('div'); pageCountDiv.setAttribute('class', "mb-3"); const pageCountInput = document.createElement('input'); pageCountInput.setAttributes({type: "text", class: "form-control", value: "Number of Pages"}); // quick number validation because not all browsers support number input fields function numberValidation (e) { const numericValue = this.value.replace(new RegExp(/[^\d]/,'ig'), ""); this.value = numericValue; } pageCountInput.addEventListener('input', numberValidation); // comments field const commentsDiv = document.createElement('div'); commentsDiv.setAttribute('class', "mb-3"); const commentsInput = document.createElement('textarea'); commentsInput.setAttributes({rows: "3", class: "form-control"}); commentsInput.textContent = "Additional Comments"; // create button container const buttonsFlex = document.createElement('div'); buttonsFlex.setAttribute('class', "buttons-flex"); // read button const readButton = document.createElement('button'); const readButtonText = document.createElement('div'); readButtonText.textContent = "Read?"; // svg stuff const checkboxSVGContainer = document.createElementNS("http://www.w3.org/2000/svg","svg"); checkboxSVGContainer.setAttributes({style: "width:24px;height:24px", "viewBox": "0 0 24 24"}); const checkboxSVGPath = document.createElementNS("http://www.w3.org/2000/svg","path"); checkboxSVGPath.setAttributes({fill: "currentColor", d: "M19,3H5C3.89,3 3,3.89 3,5V19A2,2 0 0,0 5,21H19A2,2 0 0,0 21,19V5C21,3.89 20.1,3 19,3M19,5V19H5V5H19Z", class: "unchecked"}); // assign read button to switch SVGs based on click readButton.setAttribute('class', "read-button"); readButton.addEventListener('click', function(event) { event.preventDefault(); SVGSwitcheroo(readButton.lastChild.firstChild, readButton.lastChild); }); // eye candy // book name bookNameInput.onfocus = function () { bookNameInput.setAttributes({value: "", style: "color: black !important"}); } bookNameInput.onblur = function () { bookNameInput.setAttributes({value: "Book Name", style: "color: #6c757d !important;"}); } // book author bookAuthorInput.onfocus = function () { bookAuthorInput.setAttributes({value: "", style: "color: black !important"}); } bookAuthorInput.onblur = function () { bookAuthorInput.setAttributes({value: "Book Author", style: "color: #6c757d !important;"}); } // pages pageCountInput.onfocus = function () { pageCountInput.setAttributes({value: "", style: "color: black !important"}); } pageCountInput.onblur = function () { pageCountInput.setAttributes({value: "Number of Pages", style: "color: #6c757d !important;"}); } // comments box commentsInput.onfocus = function () { commentsInput.textContent = ""; commentsInput.setAttribute('style', "color: black !important"); } commentsInput.onblur = function () { commentsInput.textContent = "Additional Comments"; commentsInput.setAttribute('style', "color: #6c757d !important;"); } // submit button const submitButton = document.createElement('button'); submitButton.setAttributes({type: "submit", class: "btn btn-primary"}); submitButton.textContent = "Submit"; // prevent default and make new Book with submitted values, then close form submitButton.addEventListener('click', function(event) { event.preventDefault(); // some form validation if (bookNameInput.value === "" || bookNameInput.value === "Book Name") { alert("Please enter a book name"); } if (bookAuthorInput.value === "" || bookAuthorInput.value === "Book Author") { alert("Please enter an author"); } if (pageCountInput.value === "" || pageCountInput.value === "Number of Pages") { alert("Please enter a page count"); } else { if (commentsInput.value === "" || commentsInput.value === "Additional Comments") { if (readButton.lastChild.firstChild.getAttribute("class") === "unchecked") { const book = new Book(bookAuthorInput.value, bookNameInput.value, pageCountInput.value, false, ""); addBookToLibrary(book, false); } else { const book = new Book(bookAuthorInput.value, bookNameInput.value, pageCountInput.value, true, ""); addBookToLibrary(book, true); } } else { if (readButton.lastChild.firstChild.getAttribute("class") === "unchecked") { const book = new Book(bookAuthorInput.value, bookNameInput.value, pageCountInput.value, false, commentsInput.value); addBookToLibrary(book, false); } else { const book = new Book(bookAuthorInput.value, bookNameInput.value, pageCountInput.value, true, commentsInput.value); addBookToLibrary(book, true); } } closeForm(); } }); //append to DOM const pageBody = row.parentElement; pageBody.insertBefore(newBookForm, row); newBookForm.appendChild(closeButton); closeButton.appendChild(closeButtonContainer); closeButtonContainer.appendChild(closeButtonSVGPath); newBookForm.appendChild(bookNameDiv); bookNameDiv.appendChild(bookNameInput); newBookForm.appendChild(bookAuthorDiv); bookAuthorDiv.appendChild(bookAuthorInput); newBookForm.appendChild(pageCountDiv); pageCountDiv.appendChild(pageCountInput); newBookForm.appendChild(commentsDiv); commentsDiv.appendChild(commentsInput); newBookForm.appendChild(buttonsFlex); buttonsFlex.appendChild(readButton); readButton.appendChild(readButtonText); readButton.appendChild(checkboxSVGContainer); checkboxSVGContainer.appendChild(checkboxSVGPath); buttonsFlex.appendChild(submitButton); } // calls makeForm() to bring up form for user input of new book newButton.addEventListener('click', makeForm);