In my code I am making a simple library application and in my javaScript code for some reason, without checking, I had assumed I had defined a query selector by the variable name of read for the checkbox input in the add book button pop-up menu, however I hadn't, I then referenced this in my **submit and cancel eventlisteners **and there was no error. i am confused as to why this is happening as I believed that elements could not be accesses unless you selected them using one of the defined document methods e.g. querySelector()
HTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Javascript Library</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<!-- popup form -->
<div class="popup-form">
<button class="cancel">x</button>
<form class="form">
<ul>
<li>
<label for="title">Title*</label>
<input type="text" id="title" required>
</li>
<li>
<label for="author">Author*</label>
<input type="text" id='author' required>
</li>
<li>
<label for="pages">Pages*</label>
<input type="number" id="pages" min="0" required>
</li>
<li>
<label for="read">Read</label>
<input type="checkbox" id = 'read'>
</li>
<button type='button' class="submit">Submit</button>
</ul>
</form>
</div>
<!-- header -->
<header>
<h1 class="title">Fkhadim's Library</h1>
</header>
<!-- add book button -->
<button class="add-book">Add Book</button>
<!-- main article -->
<div class="book-grid">
</div>
<script src="script.js"></script>
</body>
</html>
CSS
@import url('https://fonts.googleapis.com/css2?family=Poppins:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&display=swap');
/* general */
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
li {
list-style-type: none;
}
body {
background-color: rgb(240, 232, 232);
font-family: 'Poppins', sans-serif;
}
/* header */
header {
background-color: #fff;
height: 15vh;
display: flex;
align-items: center;
justify-content: center;
color: black;
font-family: 'Poppins', sans-serif;
font-size: 25px;
}
h1 {
text-align: center;
}
/* add book button */
.add-book:active {
background-color: black;
color: #fff;
transition-duration: 300ms;
}
.add-book {
display: block;
margin: 0 auto;
padding: 10px 35px;
font-size: 22px;
margin-top: 20px;
background-color: #fff;
border: none;
border: 2px solid black;
border-radius: 5px;
}
/* book grid and card styling */
.book-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(450px, 1fr));
gap: 20px;
margin: 0 auto;
margin-top: 20px;
max-width: 70vw;
align-items: stretch;
}
.card {
background-color: #fff;
padding: 30px;
padding-top: 20px;
display: grid;
grid-template-columns: 6fr 4fr;
gap: 10px;
border: 2px solid black;
}
.card-title {
font-size: 30px;
font-weight: 700;
}
.card-author {
font-size: 16px;
font-weight: 500;
}
.card-pages {
font-size: 20px;
}
.card-read {
font-size: 18px;
}
.card-buttons {
display: flex;
gap: 10px;
align-items: flex-end;
}
.card-buttons button {
flex: 1;
height: 25%;
max-height: 50px;
background-color: #fff;
border: none;
border: 1px solid black;
border-radius: 3px;
padding: 0 10px;
}
.card-buttons button:hover {
background-color: black;
color: #fff;
transition-duration: 200ms;
}
/* popup form */
.popup-form {
position: fixed;
background-color: rgb(240, 232, 232);
display: none; /*switches to display flex in javascript */
flex-direction: column;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
border: 2px solid black;
border-radius: 10px;
}
.cancel {
align-self: flex-end;
font-size: 20px;
padding: 3.5px 10px;
margin-top: 10px;
margin-right: 10px;
background-color: red;
border: none;
border-radius: 15px;
border: 1px solid black;
}
.cancel:active {
background-color: rgb(175, 13, 13);
}
.popup-form form ul li label {
font-size: 25px;
}
.popup-form form ul li {
margin-bottom: 10px;
}
.popup-form form ul li label {
display: block;
margin-bottom: 5px;
}
.popup-form form ul li input {
padding: 5px;
border-radius: 3px;
height: 30px;
border: 1px solid #ccc;
font-size: 20px;
}
.popup-form form ul li:nth-child(4) {
width: 100%;
display: flex;
align-items: center;
gap: 20px;
}
#read {
margin-left: 20px;
}
form {
padding: 0 30px;
padding-bottom: 25px;
}
.submit {
padding: 5px 20px;
font-size: 22px;
background-color: #fff;
border: none;
border: 2px solid black;
border-radius: 5px;
}
.submit:active {
background-color: black;
color: #fff;
transition-duration: 200ms;
}
/* media queries */
@media (max-width: 640px){
.book-grid{
grid-template-columns: 1fr;
}
.card-buttons {
flex-direction: column;
align-items: stretch;
justify-content: center;
height: 100%;
}
.card {
padding: 20px;
}
}
JAVASCRIPT
const addBook = document.querySelector('.add-book');
const popupForm = document.querySelector('.popup-form');
const form = document.querySelector('.form');
const cancel = document.querySelector('.cancel');
const submit = document.querySelector('.submit');
const title = document.querySelector('#title');
const pages = document.querySelector('#pages');
const author = document.querySelector('#author');
const bookgrid = document.querySelector('.book-grid');
function Book(title, author, pages, read){
this.title = title;
this.author = author;
this.pages = pages;
this.read = read;
}
Book.prototype.addCard = function(){
let card = document.createElement('div');
let cardDesc = document.createElement('div');
let cardButtons = document.createElement('div');
let cardTitle = document.createElement('div');
let cardAuthor = document.createElement('div');
let cardPages = document.createElement('div');
let cardRead = document.createElement('div');
let read = document.createElement('button');
let del = document.createElement('button');
card.classList.add('card');
cardDesc.classList.add('card-desc');
cardButtons.classList.add('card-buttons');
cardTitle.classList.add('card-title');
cardAuthor.classList.add('card-author');
cardPages.classList.add('card-pages');
cardRead.classList.add('card-read');
read.classList.add('read');
del.classList.add('delete');
read.addEventListener('click', () => {
if(this.read){
cardRead.textContent = 'not read'
this.read = false;
}
else {
cardRead.textContent = 'read'
this.read = true;
}
})
del.addEventListener('click', () => {
card.remove();
})
cardTitle.textContent = this.title;
cardAuthor.textContent = this.author;
cardPages.textContent = this.pages;
cardRead.textContent = this.read ? 'read': 'Not Read'
read.textContent = 'Read';
del.textContent = 'Delete';
cardDesc.appendChild(cardTitle);
cardDesc.appendChild(cardAuthor);
cardDesc.appendChild(cardPages);
cardDesc.appendChild(cardRead);
cardButtons.appendChild(read);
cardButtons.appendChild(del);
card.appendChild(cardDesc);
card.appendChild(cardButtons);
bookgrid.appendChild(card);
}
addBook.addEventListener('click', () => {
popupForm.style.display = 'flex';
})
cancel.addEventListener('click', () => {
popupForm.style.display = 'none';
title.value = '';
pages.value = '';
author.value = '';
read.checked = false
})
submit.addEventListener('click', () => {
if(form.checkValidity()){
popupForm.style.display = 'none';
const newBook = new Book(title.value, author.value, pages.value, read.checked)
title.value = '';
pages.value = '';
author.value = '';
read.checked = false;
newBook.addCard()
}
})
// example book
const theHobbit = new Book('The Hobbit', 'George R.R Martin', 576, true);
theHobbit.addCard();
I tried to play around with different ways to log the read variable but I had no luck finding out how this happened I asked chatgpt and it couldnt give me a straight answer so I just want to understand what this is. I feel like it may have to do with me being new to this object oriented style of programming.
Not sure where in the spec it is, but adding an "id" attribute assigns it to window.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<div id="read">I am READ</div>
<script>
console.log(read);
</script>
</body>
</html>
It's bad practice to assume these exist, so using DOM selectors is best.