307 lines
No EOL
14 KiB
JavaScript
307 lines
No EOL
14 KiB
JavaScript
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); |