I am working on a library project but my function called changeColor inside the readStatus function does not appear to be working.
I've tried separating it but having two event listeners on the same button does not appear to work. My goal is for readStatus function to allow a user to update the status of a book from no to yes when finished with the book.
Likewise, I want to change the background color of the div (class: card) when yes to be green and no to be red.
Can anyone tell me what I'm doing wrong?
let myLibrary = [];
function Book(title, author, pages, read) {
this.title = title;
this.author = author;
this.pages = pages;
this.read = read;
}
function addBookToLibrary(title, author, pages, read) {
let book = new Book(title, author, pages, read);
myLibrary.push(book);
displayOnPage();
}
function displayOnPage() {
const books = document.querySelector(".books");
const removeDivs = document.querySelectorAll(".card");
for (let i = 0; i < removeDivs.length; i++) {
removeDivs[i].remove();
}
let index = 0;
myLibrary.forEach((myLibrarys) => {
let card = document.createElement("div");
card.classList.add("card");
books.appendChild(card);
for (let key in myLibrarys) {
let para = document.createElement("p");
para.textContent = `${key}: ${myLibrarys[key]}`;
card.appendChild(para);
}
let read_button = document.createElement("button");
read_button.classList.add("read_button");
read_button.textContent = "Read ";
read_button.dataset.linkedArray = index;
card.appendChild(read_button);
read_button.addEventListener("click", readStatus);
let delete_button = document.createElement("button");
delete_button.classList.add("delete_button");
delete_button.textContent = "Remove";
delete_button.dataset.linkedArray = index;
card.appendChild(delete_button);
delete_button.addEventListener("click", removeFromLibrary);
function removeFromLibrary() {
let retrieveBookToRemove = delete_button.dataset.linkedArray;
myLibrary.splice(parseInt(retrieveBookToRemove), 1);
card.remove();
displayOnPage();
}
function readStatus() {
let retrieveBookToToggle = read_button.dataset.linkedArray;
Book.prototype = Object.create(Book.prototype);
const toggleBook = new Book();
if (myLibrary[parseInt(retrieveBookToToggle)].read == "yes") {
toggleBook.read = "no";
myLibrary[parseInt(retrieveBookToToggle)].read = toggleBook.read;
} else if (myLibrary[parseInt(retrieveBookToToggle)].read == "no") {
toggleBook.read = "yes";
myLibrary[parseInt(retrieveBookToToggle)].read = toggleBook.read;
}
let colorDiv = document.querySelector(".card");
function changeColor() {
for (let i = 0; i < length.myLibrary; i++) {
if (myLibrary[i].read == "yes") {
colorDiv.style.backgroundColor = "green";
} else if (myLibrary[i].read == "no") {
colorDiv.style.backgroundColor = "red";
}
}
}
displayOnPage();
}
index++;
});
}
let add_book = document.querySelector(".add-book");
add_book.addEventListener("click", popUpForm);
function popUpForm() {
document.getElementById("data-form").style.display = "block";
}
function closeForm() {
document.getElementById("data-form").style.display = "none";
}
let close_form_button = document.querySelector("#close-form");
close_form_button.addEventListener("click", closeForm);
function intakeFormData() {
let title = document.getElementById("title").value;
let author = document.getElementById("author").value;
let pages = document.getElementById("pages").value;
let read = document.getElementById("read").value;
if (title == "" || author == "" || pages == "" || read == "") {
return;
}
addBookToLibrary(title, author, pages, read);
document.getElementById("data-form").reset();
}
let submit_form = document.querySelector("#submit-form");
submit_form.addEventListener("click", function (event) {
event.preventDefault();
intakeFormData();
});
* {
margin: 0;
padding: 0;
background-color: rgb(245, 227, 205);
}
.books {
display: grid;
grid-template-columns: 1fr 1fr 1fr 1fr;
text-align: center;
margin: 20px;
gap: 10px;
}
.card {
border: 1px solid black;
border-radius: 15px;
padding: 10px;
}
.forms {
display: flex;
flex-direction: column;
align-items: center;
}
form {
margin-top: 20px;
}
select,
input[type="text"],
input[type="number"] {
width: 100%;
box-sizing: border-box;
}
.buttons-container {
display: flex;
margin-top: 10px;
}
.buttons-container button {
width: 100%;
margin: 2px;
}
.add-book {
margin-top: 20px;
}
#data-form {
display: none;
}
.read_button {
margin-right: 10px;
}
<!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" />
<link rel="stylesheet" href="style.css" />
<title>Document</title>
</head>
<body>
<div class="container">
<div class="forms">
<button class="add-book">Add Book To Library</button>
<div class="pop-up">
<form id="data-form">
<div class="form-container">
<label for="title">Title</label>
<input type="text" name="title" id="title" />
</div>
<div class="form-container">
<label for="author">Author</label>
<input type="text" name="author" id="author" />
</div>
<div class="form-container">
<label for="pages">Pages</label>
<input type="number" name="pages" id="pages" />
</div>
<div class="form-container">
<label for="read">Read</label>
<select name="read" id="read">
<option value="yes">Yes</option>
<option value="no">No</option>
</select>
</div>
<div class="buttons-container">
<button type="submit" id="submit-form">Submit Form</button>
<button type="button" id="close-form">Close Form</button>
</div>
</form>
</div>
</div>
<div class="books"></div>
</div>
<script src="script.js"></script>
</body>
</html>
A couple things needed.
First, you should put the readStatus and removeFromLibrary functions outside of the foreach loop.
Then I think you are wanting changeColor to run whenever readStatus is run. Either put the changeColor code directly inside the readStatus or put changeColor() inside readStatus.
I think you want the Book to not be a function but a class.
Related
Hello guys i am new to this i am trying to re render my page any time i click on the show details buttons so i can show the name, height and gender of the sky wars characters i have tried initializing a variable to false and on click i tried changing the value to true but it did not work. please here is my code.
const containerEl = document.getElementById("container");
const list = document.createDocumentFragment();
const images = [
"https://oyster.ignimgs.com/mediawiki/apis.ign.com/star-wars-episode-7/2/2d/Luke.jpg?width=1280",
"https://images.immediate.co.uk/production/volatile/sites/3/2019/10/EP9-FF-001686-336e75b.jpg?quality=90&resize=980,654",
"https://hips.hearstapps.com/digitalspyuk.cdnds.net/17/07/1487160686-r2-d2.jpg",
"https://lumiere-a.akamaihd.net/v1/images/darth-vader-main_4560aff7.jpeg?region=0%2C67%2C1280%2C720",
"https://www.costumerealm.com/wp-content/uploads/2019/12/51G4Jox9MlL._SX466_.jpg",
"https://static.wikia.nocookie.net/starwars/images/e/eb/OwenCardTrader.png/revision/latest?cb=20171108050140",
"https://static.wikia.nocookie.net/fanmade-works/images/8/8d/Beru_Lars.png/revision/latest/scale-to-width/360?cb=20200317025929",
"https://static.wikia.nocookie.net/star-wars-canon-extended/images/2/23/R5.jpg/revision/latest?cb=20160123232521",
"https://static.wikia.nocookie.net/starwars/images/0/00/BiggsHS-ANH.png/revision/latest?cb=20130305010406",
"https://media.gq.com/photos/622919842677fb88bf480855/16:9/w_2143,h_1205,c_limit/Screen%20Shot%202022-03-09%20at%204.15.50%20PM.png"
]
const getData = async () => {
const res = await fetch("https://swapi.dev/api/people");
const resData = await res.json();
const result = resData.results;
console.log(result)
main(result)
}
getData();
const main = (data) => {
let isVisible = false;
containerEl.innerHTML = "";
data.map(({ gender, height, name }, i) => {
const starWars = `
<img class="images" src=${images[i]}/>
<button id="btn" class="btn">Show Details</button>
<h1 class="starwars">${isVisible ? name : ""}</h1>
<h3>${isVisible ? gender : ""}</h3>
<h3>${isVisible ? height : ""}</h3>
`;
const item = document.createElement("div");
item.classList.add("items")
item.innerHTML = starWars
const btn = item.querySelector(".btn");
btn.addEventListener("click", () => {
isVisible = true
})
list.appendChild(item)
})
containerEl.append(list)
}
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="stylesheet" href="./style/index.css" >
<title>Star Wars</title>
</head>
<body>
<!-- Write your implementation here -->
<div id="container" class="container">
</div>
<script src="./script/index.js"></script>
</body>
</html>
This approach is not possible. The string literals, such as ${isVisible ? name : ""} are evaluated at the time that your template item is created, so since you've set the isVisible is false, it will only ever produce an empty string.
Instead, generate your string template with the values and then use a class to toggle the visibility of the details.
const containerEl = document.getElementById("container");
const images = [
"https://oyster.ignimgs.com/mediawiki/apis.ign.com/star-wars-episode-7/2/2d/Luke.jpg?width=1280",
"https://images.immediate.co.uk/production/volatile/sites/3/2019/10/EP9-FF-001686-336e75b.jpg?quality=90&resize=980,654",
"https://hips.hearstapps.com/digitalspyuk.cdnds.net/17/07/1487160686-r2-d2.jpg",
"https://lumiere-a.akamaihd.net/v1/images/darth-vader-main_4560aff7.jpeg?region=0%2C67%2C1280%2C720",
"https://www.costumerealm.com/wp-content/uploads/2019/12/51G4Jox9MlL._SX466_.jpg",
"https://static.wikia.nocookie.net/starwars/images/e/eb/OwenCardTrader.png/revision/latest?cb=20171108050140",
"https://static.wikia.nocookie.net/fanmade-works/images/8/8d/Beru_Lars.png/revision/latest/scale-to-width/360?cb=20200317025929",
"https://static.wikia.nocookie.net/star-wars-canon-extended/images/2/23/R5.jpg/revision/latest?cb=20160123232521",
"https://static.wikia.nocookie.net/starwars/images/0/00/BiggsHS-ANH.png/revision/latest?cb=20130305010406",
"https://media.gq.com/photos/622919842677fb88bf480855/16:9/w_2143,h_1205,c_limit/Screen%20Shot%202022-03-09%20at%204.15.50%20PM.png"
]
async function getData () {
const res = await fetch("https://swapi.dev/api/people");
const resData = await res.json();
return resData.results;
}
async function main () {
const data = await getData();
containerEl.innerHTML = "";
const list = document.createElement("ul")
data.map(({ gender, height, name }, i) => {
const starWars = `
<img class="images" src=${images[i]}/>
<button id="btn" class="btn">Show Details</button>
<div class="details">
<h2 class="starwars">${name}</h2>
<h3>${gender}</h3>
<h3>${height}</h3>
</div>
`;
const item = document.createElement("li");
item.classList.add("item", "hidden")
item.innerHTML = starWars
const btn = item.querySelector(".btn");
btn.addEventListener("click", toggleVisibility)
list.appendChild(item)
})
containerEl.append(list)
}
main()
function toggleVisibility(event) {
const el = event.target.closest('.item')
el.classList.toggle("hidden")
}
img {
width: 100%;
}
ul {
padding: 0;
margin: 0;
list-style-type: none;
display: grid;
gap: 1rem;
}
li {
border: 2px solid #ccc;
border-radius: .5rem;
overflow: hidden;
}
button {
font-weight: bold;
border: 0;
background-color: #222;
padding: .5rem .75rem;
color: white;
}
.item {
display: grid;
width: 25rem;
margin: auto;
}
.details {
padding: 1rem;
}
.hidden .details {
display: none;
}
<div id="container" class="container"></div>
I am creating a simple etch-a-sketch game. currently on hover it colors in black. I am trying to use a button to reset the colors back to white. However, i can't get the button to function with an event listener, if i add an alert it displays the alert but nothing else. Please guide me and supply a documentation that I can reference as I want to learn and fixing it without explaining will be counterproductive at this point.
Thank you !
const containerGrid = document.getElementById("mainGrid");
function makeGrid(col) {
for (let i = 0; i < col * col; i++) {
const gridAdd = document.createElement("div");
gridAdd.classList.add("box");
gridAdd.textContent = "";
containerGrid.appendChild(gridAdd);
}
}
makeGrid(16); // make grid 16*16
const btnClear = document.getElementById("clear");
//mouseover event black - need to link to button (well done :)
const boxes = document.querySelectorAll('.box').forEach(item => {
item.addEventListener('mouseover', event => {
item.style.backgroundColor = "black";
})
});
btnClear.addEventListener("click", () => {
boxes.style.backgroundColor = "white";
});
const changeGrid = document.getElementById(".sizechange");
/*clearBtn.forEach.addEventListener("click", function () {
clearBtn.style.color ="white";
});
*/
/*const randomBtn = document.getElementById("randomgen").addEventListener('click',(e) => {
console.log(this.classname)
console.log(e.currentTarget === this)
}) */
//change color
#mainGrid {
display: grid;
justify-content: center;
align-items: center;
grid-template-columns: repeat(16, 1fr);
grid-template-rows: auto;
margin-left: 150px;
width: 200px;
}
.box {
color: black;
border: 3px solid;
height: 10px;
width: 10px;
}
<!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>Etch-a-Sketch</title>
<link type="text/css" rel="stylesheet" href="styles.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
</head>
<body>
<div id="colorContainer">
<input type="radio" id="blackchoice" value="color" name="black" class="defaultbtn">
<label for="defaultcolor">black</label>
<input type="radio" id="randomgen" class="hey">
<label for="randomchoice">random</label>
</div>
<div id="changeGrid">
<button id="clear">clear</button>
</div>
<div id="mainGrid"></div>
<script src="app.js"></script>
</body>
</html>
A couple of related problems:
The variable boxes is undefined. It looks as though it was required to be the set elements with class box. When it is being defined this is indeed done, but then made undefined by the forEach attached to it. Separate out these two things and boxes will become the collection of all elements with class box.
Then when the clear is clicked you need to step through each of these boxes making their background color white, so again use a forEach.
<!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>Etch-a-Sketch</title>
<link type="text/css" rel="stylesheet" href="styles.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<style>
#mainGrid {
display: grid;
justify-content: center;
align-items: center;
grid-template-columns: repeat(16, 1fr);
grid-template-rows: auto;
margin-left: 150px;
width: 200px;
}
.box {
color: black;
border: 3px solid;
height: 10px;
width: 10px;
}
</style>
</head>
<body>
<div id="colorContainer">
<input type="radio" id="blackchoice" value="color" name="black" class="defaultbtn">
<label for="defaultcolor">black</label>
<input type="radio" id="randomgen" class="hey">
<label for="randomchoice">random</label>
</div>
<div id="changeGrid">
<button id="clear">clear</button>
</div>
<div id="mainGrid"></div>
<script src="app.js"></script>
<script>
const containerGrid = document.getElementById("mainGrid");
function makeGrid(col) {
for (let i = 0; i < col * col; i++) {
const gridAdd = document.createElement("div");
gridAdd.classList.add("box");
gridAdd.textContent = "";
containerGrid.appendChild(gridAdd);
}
}
makeGrid(16); // make grid 16*16
const btnClear = document.getElementById("clear");
//mouseover event black - need to link to button (well done :)
const boxes = document.querySelectorAll('.box');
boxes.forEach(box => {
box.addEventListener('mouseover', event => {
box.style.backgroundColor = "black";
})
});
btnClear.addEventListener("click", () => {
boxes.forEach(box => {
box.style.backgroundColor = "white";
});
});
const changeGrid = document.getElementById(".sizechange");
/*clearBtn.forEach.addEventListener("click", function () {
clearBtn.style.color ="white";
});
*/
/*const randomBtn = document.getElementById("randomgen").addEventListener('click',(e) => {
console.log(this.classname)
console.log(e.currentTarget === this)
}) */
//change color
</script>
</body>
</html>
Simplify your CSS
Use a SELECT element for your colors
Define the gridTemplateColumns in JS, not in CSS.
Use simpler functions
Use global variables to store the current grid size and color
Don't forget to clear your grid before changing the size
Assign the mouseenter Event on each cell on creation!
Add a boolean variable isPenDown for a better user experience!
const NewEL = (sel, prop) => Object.assign(document.createElement(sel), prop);
const EL_grid = document.querySelector("#grid");
const EL_clear = document.querySelector("#clear");
const EL_color = document.querySelector("[name=color]");
const EL_size = document.querySelector("[name=size]");
let size = parseInt(EL_size.value, 10);
let color = "black";
let isPenDown = false;
function makeGrid() {
EL_grid.innerHTML = ""; // Clear current grid!
for (let i = 0; i < size ** 2; i++) {
EL_grid.style.gridTemplateColumns = `repeat(${size}, 1fr)`;
EL_grid.append(NewEL("div", {
className: "box",
onmousedown() { isPenDown = true; paint(this); },
onmouseup() { isPenDown = false; },
onmouseenter() { if (isPenDown) paint(this); },
}));
}
};
function paint(EL) {
EL.style.backgroundColor = color;
}
EL_clear.addEventListener("click", () => {
const tmp_color = color; // Remember current color
color = "transparent"; // Temporarily set it to transparent
EL_grid.querySelectorAll(".box").forEach(paint); // Paint all cells as transparent
color = tmp_color; //* Reset as it was before.
});
EL_color.addEventListener("change", () => {
color = EL_color.value;
if (color === "random") color = `hsl(${~~(Math.random() * 360)}, 80%, 50%)`;
});
EL_size.addEventListener("change", () => {
size = parseInt(EL_size.value, 10);
makeGrid();
});
// INIT!
makeGrid();
#grid {
display: inline-grid;
margin: 10px 0;
}
#grid .box {
border: 1px solid;
height: 10px;
width: 10px;
margin: 0;
user-select: none;
}
<div>
<label>
Size:
<input type="number" name="size" value="16">
</label>
<label>
Color:
<select name="color">
<option value="black">black</option>
<option value="white">white</option>
<option value="red">red</option>
<option value="yellow">yellow</option>
<option value="orange">orange</option>
<option value="fuchsia">fuchsia</option>
<option value="transparent">CLEAR (transparent)</option>
<option value="random">RANDOM COLOR</option>
</select>
</label>
<button id="clear">Clear canvas</button>
</div>
<div id="grid"></div>
I am practicing Javascript. I want each link to display something different in the DOM when clicked.
Here is my current Javascript that works.
//used a 'for' loop to hide each 'notes' page
const element = document.querySelectorAll(".notes");
for (let x = 0; x < element.length; x++)
element[x].style.display = 'none';
const html_link= document.getElementById('html-link');
const css_link = document.getElementById('css-link');
const javascript_link = document.getElementById('js-link');
const html_notes = document.getElementById('html-notes');
const css_notes = document.getElementById('css-notes');
const js_notes = document.getElementById('js-notes');
html_link.onclick = function() {
html_notes.style.display = "block";
css_notes.style.display = "none";
js_notes.style.display = "none";
}
css_link.onclick = function() {
css_notes.style.display = "block";
html_notes.style.display = "none";
js_notes.style.display = "none";
}
javascript_link.onclick = () => {
js_notes.style.display = "block";
html_notes.style.display = "none";
css_notes.style.display = "none";
}
How can I refactor it using a for loop? My thinking was for each link clicked, display notes. But I am struggling to figure out how to display the notes div correctly that matches the link clicked. This is what I have started.
const links = document.querySelectorAll('.links')
for (const link of links) {
link.addEventListener('click', function() {
let ref = event.target.parentElement.id.replace('link','notes');
//replaces parent element with id 'notes'
const show = document.getElementById(ref);
//'show' div with new id
})
}
Welcome, fellow newbie! I've taken the liberty of writing the html and very minimal styling as well. This is my first attempt at an answer on stackoverflow.
Please note some features of the code I've added:
'links' class added to all links.
'notes' class added to all notes.
'data-notes' attribute added to all links (with the id of each link's respective notes)
<!DOCTYPE html>
<html dir="ltr" lang="en-US">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1.0"/>
</head>
<body>
<div class="outer">
<div id="html-link" data-notes="html-notes" class="links">
<p>html-link</p>
</div>
<div id="css-link" data-notes="css-notes" class="links">
<p>css-link</p>
</div>
<div id="javascript-link" data-notes="javascript-notes" class="links">
<p>javascript-link</p>
</div>
</div>
<div class="outer">
<div id="html-notes" class="notes">
<p>html-notes</p>
</div>
<div id="css-notes" class="notes">
<p>css-notes</p>
</div>
<div id="javascript-notes" class="notes">
<p>javascript-notes</p>
</div>
</div>
<style>
.links {
cursor: pointer;
background: green;
color: white;
padding: 1rem;
margin: 1rem;
}
.notes {
display: none;
background: blue;
color: white;
padding: 1rem;
margin: 1rem;
}
.outer {
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-around;
margin: 2rem 0;
}
</style>
<script>
const links = document.querySelectorAll('.links');
const notes = document.querySelectorAll('.notes');
for (const link of links) {
link.onclick = function () {
for (const note of notes) {
if (note.id == link.dataset.notes) {
note.style.display = "block";
} else {
note.style.display = "none";
}
}
}
}
</script>
</body>
</html>
This question already has answers here:
JavaScript code to stop form submission
(14 answers)
Closed 2 years ago.
I'm trying to create a form that when submitted, creates a new object with the input values, and then stores that object in an array.
For some reason, the array is "resetting" and not saving the objects.
let myLibrary = []
function Book(title,author,pages,read) {
this.title = title
this.author = author
this.pages = pages
this.read = read
myLibrary.push(this)
}
function checkForm(){
let name = document.querySelector('input[name="title"]').value
let author = document.querySelector('input[name="author"]').value
let pages = document.querySelector('input[name="pages"]').value
let read = document.querySelector('input[name="read"]').checked
new Book(name,author,pages,read)
document.getElementById('library').innerText = JSON.stringify(myLibrary)
}
const submit = document.getElementById('btn1')
submit.addEventListener("click",checkForm);
<input name='title' />
<input name='author' />
<input name='pages' />
<input name='read' />
<button id='btn1'>Click me! </button>
<div >Library:</div>
<div id='library'></div>
You are listening for a click event on the submit button, however the submit button also submits the form. Forms will naturally cause a refresh if the default "submit" event is not prevented.
Instead you could listen to your forms submit event and prevent it:
// Query select the form and
form.addEventListener('submit', function(e){
e.preventDefault();
checkForm();
});
As you have a form in your html, you'll have to prevent its default submission event which results in a reload of the page with preventDefault(). You could, for example, change your checkForm() and add the e.preventDefault() there to prevent the form from being submitted.
let myLibrary = []
function Book(title, author, pages, read) {
this.title = title
this.author = author
this.pages = pages
this.read = read
}
function addtoLibrary(title, author, pages, read) {
let book = new Book(title, author, pages, read)
myLibrary.push(book)
}
let table = document.querySelector(".table");
myLibrary.forEach(function(e) {
table.innerHTML += `<tr><td>${e.title}</td>
<td>${e.author}</td>
<td>${e.pages}</td>
<td>${e.read}</td>
</tr>
`
});
// Selectors
let add = document.querySelector("#add")
let submit = document.querySelector("#submit")
function checkForm(e) {
e.preventDefault(); // prevent the form from being submitted
let name = document.querySelector('input[name="title"]').value
let author = document.querySelector('input[name="author"]').value
let pages = document.querySelector('input[name="pages"]').value
let read = document.querySelector('input[name="read"]').checked
addtoLibrary(name, author, pages, read)
console.log(myLibrary);
}
submit.addEventListener("click", checkForm);
html,
body {
height: 100%;
}
* {
font-family: Graphik Regular;
}
ul {
list-style-type: none;
}
table,
th,
td {
border-collapse: collapse;
text-align: left;
border: 1px solid black;
}
table {
width: 100%;
}
td,
th {
height: 50px;
padding: 10px;
width: 200px;
min-width: 100px;
}
th {
background-color: gray;
margin-bottom: 50px;
}
.headers {
margin-bottom: 5px;
}
button {
background-color: #4CAF50;
/* Green */
border: none;
color: white;
padding: 15px 32px;
text-align: center;
text-decoration: none;
display: inline-block;
font-size: 16px;
margin-top: 30px;
}
.pop-container {
text-align: center;
/* display: none;*/
position: fixed;
left: 0;
top: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.6);
}
form {
background-color: gray;
}
input {
font-size: 20px;
width: 300px;
margin-bottom: 5px;
}
<!DOCTYPE html>
<meta charset="UTF-8">
<html lang="en">
<head>
<link rel="stylesheet" type="text/css" href="style.css">
</stylesheet>
<script type="text/javascript" src="http://livejs.com/live.js"></script>
</head>
<body>
<div class="pop-container">
<form id="bookquery">
<input type="text" name="title" id="title" placeholder="Title"></br>
<input type="text" name="author" placeholder="Author"></br>
<input type="text" name="pages" placeholder="Pages"></br>
<p>Have you read it?<input type="checkbox" placeholder="Title" name="read"></p>
</br>
<button id="submit">Submit</button>
</form>
</div>
<table class="headers">
<th>Title</th>
<th>Author</th>
<th>Pages</th>
<th>Read</th>
</table>
<table class="table tstyle">
</table>
<button id="add">Add new book</button>
<script src="script.js"></script>
</body>
</html>
function checkForm(e) {
e.preventDefault(); // prevent the form from being submitted
let name = document.querySelector('input[name="title"]').value
let author = document.querySelector('input[name="author"]').value
let pages = document.querySelector('input[name="pages"]').value
let read = document.querySelector('input[name="read"]').checked
addtoLibrary(name, author, pages, read)
}
The above answers didn't quite work for me so here is a simplified, fully working example. As a general guide to getting things like this to work I always try to simplify as much as possible.
index.html
<html>
<header></header>
<body>
<div>
<form id="myForm">
<label for="title">title:</label><br>
<input type="text" id="title" name="title" value="title"><br>
<button id="submit">Submit</button>
</form>
</div>
<script type="text/javascript" src="functions.js"></script>
</body>
</html>
functions.html
let myLibrary = [];
function Book(title) {
this.title = title;
myLibrary.push(this);
}
function checkForm(){
let title = document.querySelector('input[name="title"]').value;
new Book(title);
myLibrary.forEach(function(element) {
console.log(element);
});
}
document.getElementById("myForm").addEventListener(
'submit',
function(e) {
e.preventDefault();
checkForm();
}
);
I'll leave it to you to add back in the other fields on the Book object.
I am not sure because I've tried to illustrate that your code actually stores the object. It's either that your form refreshes the page... that might be the cause but as far as the code you've provided is concerned, everything works as expected.
let myLibrary = []
function Book(title,author,pages,read) {
this.title = title
this.author = author
this.pages = pages
this.read = read
myLibrary.push(this)
}
function checkForm(name,author,pages,read)
{
new Book(name,author,pages,read)
}
checkForm("Chris","Jerry","56","65");
checkForm("Sean","John","56","65");
// Both Objects are still stored...
console.log(myLibrary);
I'm trying to make a ninja fruit style game in javascript but problems are happening. I have this if statements that compare the variable "fruit" with the index of the "fruits" array. The problem is when I "eliminate" a fruit the other if statements doenst work.
That's how the game needs to work:
1 You start the game, a random name of a fruit appears for you to click on.
2 You click in the image of the fruit and it disappears, in this click another random fruit is generated.
3 An then you finish the game, that's prety much this.
So it's kind hard to explain, but its the same logic as the ninja fruit game. And I dont know if I need to use the shift function to eliminate the fruits in the array as well.
var fruits = ['Banana', 'Apple', 'Pineapple'];
var fruit = fruits[Math.floor(Math.random() * fruits.length)];
document.getElementById("frut").innerHTML = fruit;
if (fruit == fruits[0]) {
bana.onclick = function() {
var fruit = fruits[Math.floor(Math.random() * fruits.length)];
document.getElementById("frut").innerHTML = fruit;
bana.style.display = "none";
}
}
if (fruit == fruits[1]) {
app.onclick = function() {
var fruit = fruits[Math.floor(Math.random() * fruits.length)];
document.getElementById("frut").innerHTML = fruit;
app.style.display = "none";
}
}
if (fruit == fruits[2]) {
pin.onclick = function() {
var fruit = fruits[Math.floor(Math.random() * fruits.length)];
document.getElementById("frut").innerHTML = fruit;
pin.style.display = "none";
}
}
function movFruit() {
document.getElementById("info").style.display = "table";
document.getElementById("fruitAnimation").style.display = "table";
document.getElementById("insructions").style.display = "none";
var elem = document.getElementById("fruitAnimation");
var pos = 0;
var id = setInterval(frame, 10);
function frame() {
if (pos == 350) {
clearInterval(id);
} else {
pos++;
elem.style.top = pos + 'px';
}
}
}
#fruitAnimation {
position: relative;
display: none;
margin: 0 auto;
}
.fr {
float: left;
padding: 80px;
}
#info {
display: none;
margin: 0 auto;
}
#insructions {
display: table;
margin: 0 auto;
margin-top: 200px;
border: 1px solid black;
padding: 10px;
}
<!doctype html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.0/css/bootstrap.min.css" integrity="sha384-9gVQ4dYFwwWSjIDZnLEWnxCjeSWFphJiwGPXr1jddIhOegiu1FwO5qRGvFXOdJZ4" crossorigin="anonymous">
<title>JSfruit</title>
</head>
<body>
<div id="info">
<h1>Fruit: <span id="frut"></span></h1>
</div>
<button onclick="movFruit() " style="display: table; margin: 0 auto;"><h4>Start the game</h4></button>
<div id="fruitAnimation">
<div class="fr" id="bana">
<img src="https://orig00.deviantart.net/5c87/f/2016/322/8/9/banana_pixel_art_by_fireprouf-daosk9z.png" width="60" height="60">
</div>
<div class="fr" id="app">
<img src="https://art.ngfiles.com/images/404000/404664_thexxxreaper_pixel-apple.png?f1454891997" width="60" height="60">
</div>
<div class="fr" id="pin">
<img src="https://i.pinimg.com/originals/c2/f9/e9/c2f9e9f8d332da97a836513de98f7b29.jpg" width="60" height="60">
</div>
</div>
<span id="insructions">Click in the fruits and erase them!</span>
</body>
</html>
Right now, you're only attaching handlers to the fruit images at the top level, in your if statements - but once those statements run and the main block finishes, it doesn't get run again.
You should attach handlers to all fruit images at once in the beginning, and then in the handlers, check to see the clicked fruit was valid.
If you're assigning text to an element, assign to textContent, not innerHTML; textContent is quicker, safer, and more predictable.
const fruits = ['Banana', 'Apple', 'Pineapple'];
const getRandomFruit = () => {
const randomIndex = Math.floor(Math.random() * fruits.length);
const fruit = fruits[randomIndex];
document.getElementById("frut").textContent = fruit;
fruits.splice(randomIndex, 1);
return fruit;
};
let fruitToClickOn = getRandomFruit();
bana.onclick = function() {
if (fruitToClickOn !== 'Banana') return;
bana.style.display = "none";
fruitToClickOn = getRandomFruit();
}
app.onclick = function() {
if (fruitToClickOn !== 'Apple') return;
app.style.display = "none";
fruitToClickOn = getRandomFruit();
}
pin.onclick = function() {
if (fruitToClickOn !== 'Pineapple') return;
pin.style.display = "none";
fruitToClickOn = getRandomFruit();
}
function movFruit() {
document.getElementById("info").style.display = "table";
document.getElementById("fruitAnimation").style.display = "table";
document.getElementById("insructions").style.display = "none";
var elem = document.getElementById("fruitAnimation");
var pos = 0;
var id = setInterval(frame, 10);
function frame() {
if (pos == 350) {
clearInterval(id);
} else {
pos++;
elem.style.top = pos + 'px';
}
}
}
#fruitAnimation {
position: relative;
display: none;
margin: 0 auto;
}
.fr {
float: left;
padding: 80px;
}
#info {
display: none;
margin: 0 auto;
}
#insructions {
display: table;
margin: 0 auto;
margin-top: 200px;
border: 1px solid black;
padding: 10px;
}
<!doctype html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.0/css/bootstrap.min.css" integrity="sha384-9gVQ4dYFwwWSjIDZnLEWnxCjeSWFphJiwGPXr1jddIhOegiu1FwO5qRGvFXOdJZ4" crossorigin="anonymous">
<title>JSfruit</title>
</head>
<body>
<div id="info">
<h1>Fruit: <span id="frut"></span></h1>
</div>
<button onclick="movFruit() " style="display: table; margin: 0 auto;"><h4>Start the game</h4></button>
<div id="fruitAnimation">
<div class="fr" id="bana">
<img src="https://orig00.deviantart.net/5c87/f/2016/322/8/9/banana_pixel_art_by_fireprouf-daosk9z.png" width="60" height="60">
</div>
<div class="fr" id="app">
<img src="https://art.ngfiles.com/images/404000/404664_thexxxreaper_pixel-apple.png?f1454891997" width="60" height="60">
</div>
<div class="fr" id="pin">
<img src="https://i.pinimg.com/originals/c2/f9/e9/c2f9e9f8d332da97a836513de98f7b29.jpg" width="60" height="60">
</div>
</div>
<span id="insructions">Click in the fruits and erase them!</span>
</body>
</html>