final
This commit is contained in:
commit
cc803fcf76
6 changed files with 420 additions and 0 deletions
3
README.md
Normal file
3
README.md
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
# js-library
|
||||||
|
|
||||||
|
Proof-of-concept library/book manager written in ES6 JS
|
||||||
79
assets/css/style.css
Normal file
79
assets/css/style.css
Normal file
|
|
@ -0,0 +1,79 @@
|
||||||
|
.row {
|
||||||
|
--bs-gutter-x: 0;
|
||||||
|
row-gap: 1.5rem;
|
||||||
|
margin-top: 1.5rem;
|
||||||
|
margin-left: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.col-sm-6 {
|
||||||
|
flex: 1;
|
||||||
|
width: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card, header {
|
||||||
|
box-shadow: 0.5px 0.5px 5px black;
|
||||||
|
}
|
||||||
|
|
||||||
|
header {
|
||||||
|
background-color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-link.active {
|
||||||
|
margin-right: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.delete-button, .read-button {
|
||||||
|
border-radius: .25rem;
|
||||||
|
color: white;
|
||||||
|
border: 0;
|
||||||
|
padding: .5rem 1rem;
|
||||||
|
text-decoration: none;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
column-gap: .25rem;
|
||||||
|
height: 100%;
|
||||||
|
line-height: 16px;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.read-button {
|
||||||
|
background-color: green;
|
||||||
|
line-height: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.delete-button {
|
||||||
|
background-color: darkred;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-link {
|
||||||
|
margin-left: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.read-checkbox {
|
||||||
|
width: 24px;
|
||||||
|
height: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.buttons-flex {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
justify-content: space-around;
|
||||||
|
}
|
||||||
|
|
||||||
|
#newbookform {
|
||||||
|
right: 1.5rem;
|
||||||
|
max-width: 500px;
|
||||||
|
position: absolute;
|
||||||
|
z-index: 2;
|
||||||
|
padding: 1rem 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-control {
|
||||||
|
color: #6c757d !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
#closebutton {
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
}
|
||||||
BIN
assets/images/trash-can-outline.png
Normal file
BIN
assets/images/trash-can-outline.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 361 B |
1
assets/images/trash-can-outline.svg
Normal file
1
assets/images/trash-can-outline.svg
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M9,3V4H4V6H5V19A2,2 0 0,0 7,21H17A2,2 0 0,0 19,19V6H20V4H15V3H9M7,6H17V19H7V6M9,8V17H11V8H9M13,8V17H15V8H13Z" /></svg>
|
||||||
|
After Width: | Height: | Size: 187 B |
307
assets/js/main.js
Normal file
307
assets/js/main.js
Normal file
|
|
@ -0,0 +1,307 @@
|
||||||
|
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);
|
||||||
30
index.html
Normal file
30
index.html
Normal file
|
|
@ -0,0 +1,30 @@
|
||||||
|
<!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">
|
||||||
|
<meta name="Description" content="Enter your description here"/>
|
||||||
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/5.1.0/css/bootstrap.min.css">
|
||||||
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css">
|
||||||
|
<link rel="stylesheet" href="assets/css/style.css">
|
||||||
|
<title>Title</title>
|
||||||
|
</head>
|
||||||
|
<body style="background-color: darkgray;">
|
||||||
|
<header class="d-flex flex-wrap justify-content-center py-3 mb-4 border-bottom">
|
||||||
|
<a href="/" class="d-flex align-items-center mb-3 mb-md-0 me-md-auto text-dark text-decoration-none">
|
||||||
|
<svg class="bi me-2" width="40" height="32"><use xlink:href="#bootstrap"/></svg>
|
||||||
|
<span class="fs-4">Books</span>
|
||||||
|
</a>
|
||||||
|
<ul class="nav nav-pills">
|
||||||
|
<li class="nav-item">
|
||||||
|
<button class="nav-link active" id="newbutton">New</button></li>
|
||||||
|
</ul>
|
||||||
|
</header>
|
||||||
|
<div class="row">
|
||||||
|
</div>
|
||||||
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/2.9.2/umd/popper.min.js"></script>
|
||||||
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/5.1.0/js/bootstrap.min.js"></script>
|
||||||
|
<script src="assets/js/main.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
Loading…
Add table
Reference in a new issue