const addBtn = document.querySelector(".add");
const modal = document.querySelector(".modal__container");
const library = document.querySelector(".library__container");
const submitBook = document.querySelector(".add__book");
const deleteBtn = document.querySelector(".fas fa-trash-alt");
//Modal inputs
const modalTitle = document.querySelector("#title");
const modalAuthor = document.querySelector("#author");
const modalPages = document.querySelector("#pages");
const isRead = document.querySelector("#read-status");
//Toggle Modal
const hideModal = () => {
modal.style.display = "none";
};
const showModal = () => {
modal.style.display = "block";
const cancel = document.querySelector(".cancel");
cancel.addEventListener("click", (e) => {
e.preventDefault();
hideModal();
});
};
addBtn.addEventListener("click", showModal);
let myLibrary = [];
let index = 0;
function Book(title, author, pages, read) {
this.title = title,
this.author = author,
this.pages = pages,
this.read = read
}
submitBook.addEventListener("click", addBookToLibrary);
function addBookToLibrary(e) {
e.preventDefault();
let bookTitle = modalTitle.value;
let bookAuthor = modalAuthor.value;
let bookPages = modalPages.value;
let bookStatus = isRead.checked;
//Display error message if inputs are empty
if (bookTitle === "" || bookAuthor === "" || bookPages === "") {
const errorMessage = document.querySelector(".error__message--container");
hideModal();
errorMessage.style.display = "block";
const errorBtn = document.querySelector(".error-btn");
errorBtn.addEventListener("click", () => {
errorMessage.style.display = "none";
showModal();
})
} else {
let book = new Book(bookTitle, bookAuthor, bookPages, bookStatus);
myLibrary.push(book);
hideModal();
render();
}
}
function render() {
library.innerHTML = "";
for (let i = 0; i < myLibrary.length; i++) {
library.innerHTML +=
'<div class="book__container">' +
'<div class="book">' +
'<div class="title__content">' +
'<span class="main">Title : </span><span class="book__title">' +` ${myLibrary[i].title}`+'</span>' +
'</div>' +
'<div class="author__content">' +
'<span class="main">Author : </span><span class="book__author">'+` ${myLibrary[i].author}`+'</span>' +
'</div>' +
'<div class="pages__content">' +
'<span class="main">Pages : </span><span class="book__pages">'+` ${myLibrary[i].pages}`+'</span>' +
'</div>' +
'<div class="book__read-elements">' +
'<span class="book__read">I read it</span>' +
'<i class="fas fa-check"></i>' +
'<a href="#"><i class="fas fa-times"></i>' +
'<i class="fas fa-trash-alt"></i>' +
'</div>' +
'</div>' +
'</div>'
readStatus(myLibrary[i].checked)
}
modalTitle.value = "";
modalAuthor.value = "";
modalPages.value = "";
isRead.checked = false;
}
function readStatus(bookStatus) {
const bookStatusContainer = document.querySelector(".book__read");
if (bookStatus) {
bookStatusContainer.classList.add("yes");
bookStatusContainer.textContent = "I read it";
bookStatusContainer.style.color = "rgb(110, 176, 120)";
} else {
bookStatusContainer.classList.add("no");
bookStatusContainer.textContent = "I have not read it";
bookStatusContainer.style.color = "rgb(194, 89, 89)";
}
}
#import url('https://fonts.googleapis.com/css2?family=Poppins:wght#300;400;600&display=swap');
:root {
--light-gray: #dededef3;
--title-color: #333756;
--main-color: #c6c6c6f3;
}
* {
padding: 0;
margin: 0;
box-sizing: border-box;
}
body {
font-family: 'Poppins', sans-serif;
background-color: var(--light-gray);
}
header {
text-align: center;
padding-top: 4rem;
color: var(--title-color);
text-transform: uppercase;
letter-spacing: 4px;
}
button {
margin: 1rem;
padding: 0.8rem 2rem;
font-size: 14px;
border-radius: 25px;
background: white;
color: #333756;
font-weight: 600;
border: none;
cursor: pointer;
transition: 0.6s all ease;
}
:focus {
/*outline: 1px solid white;*/
}
button:hover {
background: var(--title-color);
color: white;
}
.add__book:hover,
.cancel:hover {
background: var(--main-color);
color: var(--title-color)
}
.all,
.books__read,
.books__not-read {
border-radius: 0;
text-transform: uppercase;
letter-spacing: 0.1rem;
background: var(--light-gray);
border-bottom: 4px solid var(--title-color)
}
.library__container {
display: flex;
justify-content: center;
flex-wrap: wrap;
}
.book__container {
display: flex;
margin: 2rem 2rem;
}
.modal__container {
display: none;
position: fixed;
z-index: 4;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.4);
padding-top: 0px;
}
.book,
.modal {
padding: 2rem 2rem;
border-radius: 15px;
background: #333756;
line-height: 3rem;
}
.modal {
position: relative;
width: 50%;
margin: 0 auto;
margin-top: 8rem;
}
.modal__content {
display: flex;
flex-direction: column;
}
label {
color: white;
margin-right: 1rem;
}
input {
padding: 0.5rem;
font-size: 14px;
}
.book__read-elements {
display: flex;
justify-content: space-between;
}
.main,
i {
color: white;
pointer-events: none;
margin: 0.5rem;
}
.book__title,
.book__author,
.book__pages,
.book__read {
color: var(--main-color)
}
.error__message--container {
display: none;
position: fixed;
z-index: 4;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.4);
}
.error__message--modal {
position: relative;
margin: 0 auto;
margin-top: 10rem;
width:40%;
}
.error {
display: flex;
flex-direction: column;
align-items: center;
color: rgb(101, 3, 3);
font-size: 20px;
font-weight: bold;
background: rgb(189, 96, 96);
padding: 3rem 5rem;
border-radius: 10px;
}
.error-btn {
color: rgb(101, 3, 3);
font-weight: bold;
}
.error-btn:hover {
color: white;
background: rgb(101, 3, 3);
}
<!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="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.13.1/css/all.min.css" integrity="sha256-2XFplPlrFClt0bIdPgpz8H7ojnk10H69xRqd9+uTShA=" crossorigin="anonymous" />
<link rel="stylesheet" href="styles.css">
<title>Library</title>
</head>
<body>
<header>
<h1>My Library</h1>
<button class="add">Add New Book</button>
<div class="buttons">
<button class="all">View All</button>
<button class="books__read">Read</button>
<button class="books__not-read">Not Read</button>
</div>
</header>
<div class="error__message--container">
<div class="error__message--modal">
<div class="error">
<p>Complete the form!</p>
<button class ="error-btn">Ok</button>
</div>
</div>
</div>
<!--Modal-->
<form class="modal__container">
<div class="modal">
<div class="modal__content">
<label for="">Title:</label>
<input type="text" id="title">
</div>
<div class="modal__content">
<label for="">Author:</label>
<input type="text" id="author">
</div>
<div class="modal__content">
<label for="">Pages:</label>
<input type="number" id="pages">
</div>
<div>
<label for="read-status">Check the box if you've read this book</label>
<input type="checkbox" id="read-status" value ="check">
</div>
<button class="add__book">Add</button>
<button class="cancel">Cancel</button>
</div>
</form>
<!--End of Modal-->
<div class="library__container"></div>
<script src="script.js"></script>
</body>
</html>
I'm new to OOP and I'm struggling.
I'm building a library where you can add a book with the title, author nr of pages and if you've read it or not. When I add the first book if I check the box it displays that to book is not read(which is false). When I add a new book the read functionality is not applied to that book at all. I have no idea how to fix it
In this function you are checking the status if isRead which is incorrect.
Do this
Call the readStatus function inside the for loop
Pass the current parameter readStatus(myLibrary[i].checked)
Modify readStatus as shown below
function readStatus(status) {
const bookReadStatus = document.querySelector(".book__read");
if (status) {
bookReadStatus.classList.add("yes");
bookReadStatus.textContent = "I read it";
bookReadStatus.style.color = "rgb(110, 176, 120)";
} else {
bookReadStatus.classList.add("no");
bookReadStatus.textContent = "I have not read it";
bookReadStatus.style.color = "rgb(194, 89, 89)";
}
}
Related
I have a working code of a 10 text questions' trivia game with a timer (html, javascript, css).
How the questions can be served from a simple .txt file (so I can scale)?
How the javascript can choose the questions in a random order, every time the games starts?
I have studied 1 to get an idea. However, my javascript coding skills are very limited. I would appreciate if you can point me to the right direction.
(function() {
const playButton = document.querySelector("#play");
const letsstartButton = document.querySelector("#lets-start");
const playagainButton = document.querySelector("#play-again");
const howToPlayButton = document.querySelector("#how-to-play-button");
const closeHowToButton = document.querySelector("#close-how-to");
const howToPlayScreen = document.querySelector(".how-to-play-screen");
const mainScreen = document.querySelector(".main-screen");
const triviaScreen = document.querySelector(".trivia-screen");
const resultScreen = document.querySelector(".result-screen");
playButton.addEventListener("click", startTrivia);
letsstartButton.addEventListener("click", startTrivia);
playagainButton.addEventListener("click", startTrivia);
howToPlayButton.addEventListener("click", function() {
howToPlayScreen.classList.remove("hidden");
mainScreen.classList.add("hidden");
});
closeHowToButton.addEventListener("click", function() {
howToPlayScreen.classList.add("hidden");
mainScreen.classList.remove("hidden");
});
const questionLength = 10;
let questionIndex = 0;
let score = 0;
let questions = [];
let timer = null;
function startTrivia() {
//show spinner
questionIndex = 0;
questions = [];
score = 0;
window.setTimeout(function() {
//get questions from server
mainScreen.classList.add("hidden");
howToPlayScreen.classList.add("hidden");
resultScreen.classList.add("hidden");
triviaScreen.classList.remove("hidden");
questions = [{
answers: ["Roma", "Athens", "London", "Japan"],
correct: "Roma",
text: "YOUR TEXT HERE."
},
{
answers: ["Roma1", "Athens1", "London1", "Japan1"],
correct: "Athens1",
text: "YOUR TEXT HERE."
},
{
answers: ["Roma2", "Athens2", "London2", "Japan2"],
correct: "London2",
text: "YOUR TEXT HERE."
},
{
answers: ["Roma3", "Athens3", "London3", "Japan3"],
correct: "London3",
text: "YOUR TEXT HERE."
},
{
answers: ["Roma4", "Athens4", "London4", "Japan4"],
correct: "Athens4",
text: "YOUR TEXT HERE."
},
{
answers: ["Roma5", "Athens5", "London5", "Japan5"],
correct: "Athens5",
text: "YOUR TEXT HERE."
},
{
answers: ["Roma6", "Athens6", "London6", "Japan6"],
correct: "Roma6",
text: "YOUR TEXT HERE."
},
{
answers: ["Roma7", "Athens7", "London7", "Japan7"],
correct: "Japan7",
text: "YOUR TEXT HERE."
},
{
answers: ["Roma8", "Athens8", "London8", "Japan8"],
correct: "London8",
text: "YOUR TEXT HERE."
},
{
answers: ["Roma9", "Athens9", "London9", "Japan9"],
correct: "Japan9",
text: "YOUR TEXT HERE."
}
];
const questionCount = document.getElementById("question-count");
questionCount.innerHTML = questionLength.toString();
displayNextQuestion();
}, 50);
}
const isTriviaCompleted = function() {
return questionLength === questionIndex;
};
function displayNextQuestion() {
const answersContainer = document.getElementById("answers-container");
const answerButtons = answersContainer.querySelectorAll(".default-button");
answerButtons.forEach(function(element) {
element.disabled = false;
element.classList.remove("correct");
element.classList.remove("wrong");
});
if (isTriviaCompleted()) {
showScores();
} else {
startProgressbar();
timer = window.setTimeout(function() {
guess(null);
}, 10000);
setQuizText("This is from");
const textElement = document.getElementById("question-placement");
textElement.innerHTML = questions[questionIndex].text;
const choices = questions[questionIndex].answers;
for (let i = 0; i < choices.length; i++) {
const element = document.getElementById(`answer${i}`);
element.innerHTML = choices[i];
element.addEventListener("click", handleAnswerClick);
}
showProgress();
}
}
function handleAnswerClick(e) {
const el = e.currentTarget;
const answer = el.innerHTML;
el.removeEventListener("click", handleAnswerClick);
guess(answer);
}
function showProgress() {
const questionIndexElement = document.getElementById("question-index");
const index = questionIndex + 1;
questionIndexElement.innerHTML = index.toString();
}
function guess(answer) {
clearTimeout(timer);
const answersContainer = document.getElementById("answers-container");
const answerButtons = answersContainer.querySelectorAll(".default-button");
answerButtons.forEach((element) => {
element.disabled = true;
if (element.innerHTML === questions[questionIndex].correct) {
element.classList.add("correct");
}
});
stopProgressbar();
if (questions[questionIndex].correct === answer) { // correct answer
score++;
setQuizText("Fantastic … Correct!");
} else if (answer) { // incorrect answer
setQuizText("Nice try … You were close.");
answerButtons.forEach((element) => {
if (element.innerHTML === answer) {
element.classList.add("wrong");
}
});
} else {
setQuizText("Your time is out! Oh no!");
}
questionIndex++;
window.setTimeout(function() {
displayNextQuestion();
}, 2500);
}
function setQuizText(text) {
const el = document.getElementById("trivia-text");
el.innerHTML = text;
}
function showScores() {
const scoreElement = document.getElementById("score");
const scoreTotalElement = document.getElementById("score-total");
const scoreNameElement = document.getElementById("score-name");
scoreElement.innerHTML = score.toString();
scoreTotalElement.innerHTML = questionLength.toString();
if (score < 4) {
scoreNameElement.innerHTML = "Newbie";
} else if (score < 7) {
scoreNameElement.innerHTML = "Rookie";
} else if (score < 10) {
scoreNameElement.innerHTML = "Expert";
} else {
scoreNameElement.innerHTML = "Grandmaster";
}
triviaScreen.classList.add("hidden");
resultScreen.classList.remove("hidden");
}
function startProgressbar() {
// select div turn into progressbar
const progressbar = document.getElementById("progress-bar");
progressbar.innerHTML = "";
// create div changes width show progress
const progressbarInner = document.createElement("span");
// Append progressbar to main progressbardiv
progressbar.appendChild(progressbarInner);
// When all set start animation
progressbarInner.style.animationPlayState = "running";
}
function stopProgressbar() {
const progressbar = document.getElementById("progress-bar");
const progressbarInner = progressbar.querySelector("span");
progressbarInner.style.animationPlayState = "paused";
}
}());
*,
*:after,
*:before {
box-sizing: border-box;
}
body {
margin: 0;
font-family: 'Verdana', cursive;
text-transform: uppercase;
color: #ccc;
letter-spacing: 2px;
}
.container {
background: #999999;
}
.wrapper {
max-width: 800px;
margin: auto;
}
.screen-section {
display: flex;
flex-direction: column;
align-items: center;
min-height: 100vh;
padding: 20px 20px 70px;
position: relative;
}
.hidden {
display: none;
}
.trivia-screen-step {
color: #ccc;
}
.trivia-image-wrapper {
max-width: 100%;
margin: 50px auto;
position: relative;
}
.trivia-image {
max-width: 100%;
width: 300px;
position: relative;
z-index: 1;
}
.trivia-timer {
width: 550px;
max-width: 100%;
height: 20px;
border-radius: 3em;
margin-bottom: 50px;
padding: 5px 6px;
}
.trivia-timer span {
display: inline-block;
background: linear-gradient(90deg, #fff, #06c);
height: 10px;
vertical-align: top;
border-radius: 3em;
animation: progressbar-countdown;
animation-duration: 10s;
animation-iteration-count: 1;
animation-fill-mode: forwards;
animation-play-state: paused;
animation-timing-function: linear;
}
#keyframes progressbar-countdown {
0% {
width: 100%;
}
100% {
width: 0%;
}
}
.trivia-question {
margin-bottom: 50px;
}
.how-to-play-screen .default-button {
margin-bottom: 60px;
margin-top: 30px;
}
.button-container {
display: flex;
flex-wrap: wrap;
margin-bottom: 50px;
width: 600px;
max-width: 100%;
}
.button-outer {
flex-basis: 100%;
text-align: center;
margin-bottom: 20px;
max-width: 100%;
}
.default-button {
background: #333333;
border-radius: 3em;
font-family: 'Verdana', cursive;
font-size: 18px;
color: #fff;
letter-spacing: 2.45px;
padding: 10px 8px;
text-transform: uppercase;
transition: background .2s;
outline: none;
width: 250px;
cursor: pointer;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
max-width: 100%;
}
.default-button:hover {
background: #222;
}
.default-button[disabled] {
background: transparent;
color: #222;
cursor: default;
}
.default-button[disabled]:hover {
background: transparent;
}
.default-button.correct {
cursor: default;
background: #2bb24a;
color: #fff;
}
.default-button.correct:hover {
background: #2bb24a;
color: #fff;
}
.default-button.wrong {
cursor: default;
background: #F6484C;
color: #fff;
}
.default-button.wrong:hover {
background: #F6484C;
color: #fff;
}
.title {
font-size: 32px;
margin-top: 100px;
}
.text {
line-height: 24px;
font-size: 16px;
font-family: 'Verdana', sans-serif;
text-align: center;
color: #ffffff;
text-transform: none;
}
.trivia-logo {
position: absolute;
bottom: 20px;
}
.trivia-corner-logo {
position: absolute;
left: 0;
top: 15px;
width: 100px;
}
.close-button {
position: absolute;
top: 50px;
right: 0;
background: transparent;
border: none;
color: #fff;
font-family: 'Verdana', cursive;
font-size: 34px;
outline: none;
text-transform: none;
cursor: pointer;
transition: color .2s;
}
.close-button:hover {
color: #eee;
}
.score-name {
margin: 0 0 28px;
font-size: 46px;
}
.score {
font-size: 18px;
margin-bottom: 10px;
}
.description {
text-align: center;
font-family: Verdana, sans-serif;
font-size: 16px;
color: #fff;
text-transform: none;
line-height: 24px;
display: inline-block;
margin-bottom: 30px;
}
#media screen and (min-width: 700px) {
.screen-section {
padding: 50px;
}
<div class="container">
<div class="wrapper">
<div class="screen-section main-screen">
<div class="trivia-image-wrapper">
<img alt="LOGO" src="./assets/Game-Logo.png" class="trivia-image">
</div>
<h1>Trivia</h1>
<div class="button-container">
<div class="button-outer">
<button class="default-button" id="play" type="button">Play</button>
</div>
<div class="button-outer">
<button class="default-button" id="how-to-play-button" type="button">How to play?</button>
</div>
</div>
<div class="trivia-logo">
<img alt="logo" src="./assets/-Logo.png">
</div>
</div>
<div class="screen-section hidden how-to-play-screen">
<img alt="LOGO" src="./assets/Game-Logo.png" class="trivia-corner-logo">
<button class="close-button" id="close-how-to" type="button">X</button>
<h2 class="title">How to Play</h2>
<p>Answer questions to score points.</p>
<button class="default-button" id="lets-start" type="button">Ok. Let's start</button>
<div class="trivia-logo">
<img alt="logo" src="./assets/-Logo.png">
</div>
</div>
<div class="screen-section hidden trivia-screen">
<div class="trivia-screen-step"><span id="question-index">1</span> out of <span id="question-count">10</span></div>
<div class="trivia-image-wrapper">
<p id="question-placement"></p>
</div>
<div class="trivia-timer" id="progress-bar"></div>
<div class="trivia-question" id="trivia-text"></div>
<div class="button-container" id="answers-container">
<div class="button-outer">
<button class="default-button" id="answer0" type="button"></button>
</div>
<div class="button-outer">
<button class="default-button" id="answer1" type="button"></button>
</div>
<div class="button-outer">
<button class="default-button" id="answer2" type="button"></button>
</div>
<div class="button-outer">
<button class="default-button" id="answer3" type="button"></button>
</div>
</div>
<div class="trivia-logo">
<img alt="logo" src="./assets/-Logo.png">
</div>
</div>
<div class="screen-section hidden result-screen">
<div class="trivia-image-wrapper">
<img alt="Trivia LOGO" src="./assets/Game-Logo.png" class="trivia-image">
</div>
<p class="score"><span id="score">0</span> out of <span id="score-total">10</span></p>
<h1 class="score-name" id="score-name">Trivia</h1>
<span class="description">you will learn more.</span>
<button class="default-button" id="play-again" type="button">Play again</button>
<div class="trivia-logo">
<img alt=" logo" src="./assets/-Logo.png">
</div>
</div>
</div>
</div>
In your case the best way would be to create an API (for example https://fastapi.tiangolo.com/) that would return a random question, but if you want to have it in a separate file you would simply have to move the variable questions to another javascript file and import it into the <head> of your web page.
To randomize the JSON you can use the following function:
function shuffleQuestions(questions) {
for (let i = questions.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[questions[i], questions[j]] = [questions[j], questions[i]];
}
}
(function() {
const playButton = document.querySelector("#play");
const letsstartButton = document.querySelector("#lets-start");
const playagainButton = document.querySelector("#play-again");
const howToPlayButton = document.querySelector("#how-to-play-button");
const closeHowToButton = document.querySelector("#close-how-to");
const howToPlayScreen = document.querySelector(".how-to-play-screen");
const mainScreen = document.querySelector(".main-screen");
const triviaScreen = document.querySelector(".trivia-screen");
const resultScreen = document.querySelector(".result-screen");
playButton.addEventListener("click", startTrivia);
letsstartButton.addEventListener("click", startTrivia);
playagainButton.addEventListener("click", startTrivia);
howToPlayButton.addEventListener("click", function() {
howToPlayScreen.classList.remove("hidden");
mainScreen.classList.add("hidden");
});
closeHowToButton.addEventListener("click", function() {
howToPlayScreen.classList.add("hidden");
mainScreen.classList.remove("hidden");
});
const questionLength = 10;
let questionIndex = 0;
let score = 0;
let questions = [];
let timer = null;
function startTrivia() {
//show spinner
questionIndex = 0;
questions = [];
score = 0;
window.setTimeout(function() {
//get questions from server
mainScreen.classList.add("hidden");
howToPlayScreen.classList.add("hidden");
resultScreen.classList.add("hidden");
triviaScreen.classList.remove("hidden");
questions = [{
answers: ["Roma", "Athens", "London", "Japan"],
correct: "Roma",
text: "YOUR TEXT HERE."
},
{
answers: ["Roma1", "Athens1", "London1", "Japan1"],
correct: "Athens1",
text: "YOUR TEXT HERE."
},
{
answers: ["Roma2", "Athens2", "London2", "Japan2"],
correct: "London2",
text: "YOUR TEXT HERE."
},
{
answers: ["Roma3", "Athens3", "London3", "Japan3"],
correct: "London3",
text: "YOUR TEXT HERE."
},
{
answers: ["Roma4", "Athens4", "London4", "Japan4"],
correct: "Athens4",
text: "YOUR TEXT HERE."
},
{
answers: ["Roma5", "Athens5", "London5", "Japan5"],
correct: "Athens5",
text: "YOUR TEXT HERE."
},
{
answers: ["Roma6", "Athens6", "London6", "Japan6"],
correct: "Roma6",
text: "YOUR TEXT HERE."
},
{
answers: ["Roma7", "Athens7", "London7", "Japan7"],
correct: "Japan7",
text: "YOUR TEXT HERE."
},
{
answers: ["Roma8", "Athens8", "London8", "Japan8"],
correct: "London8",
text: "YOUR TEXT HERE."
},
{
answers: ["Roma9", "Athens9", "London9", "Japan9"],
correct: "Japan9",
text: "YOUR TEXT HERE."
}
];
shuffleQuestions(questions);
const questionCount = document.getElementById("question-count");
questionCount.innerHTML = questionLength.toString();
displayNextQuestion();
}, 50);
}
const isTriviaCompleted = function() {
return questionLength === questionIndex;
};
function displayNextQuestion() {
const answersContainer = document.getElementById("answers-container");
const answerButtons = answersContainer.querySelectorAll(".default-button");
answerButtons.forEach(function(element) {
element.disabled = false;
element.classList.remove("correct");
element.classList.remove("wrong");
});
if (isTriviaCompleted()) {
showScores();
} else {
startProgressbar();
timer = window.setTimeout(function() {
guess(null);
}, 10000);
setQuizText("This is from");
const textElement = document.getElementById("question-placement");
textElement.innerHTML = questions[questionIndex].text;
const choices = questions[questionIndex].answers;
for (let i = 0; i < choices.length; i++) {
const element = document.getElementById(`answer${i}`);
element.innerHTML = choices[i];
element.addEventListener("click", handleAnswerClick);
}
showProgress();
}
}
function handleAnswerClick(e) {
const el = e.currentTarget;
const answer = el.innerHTML;
el.removeEventListener("click", handleAnswerClick);
guess(answer);
}
function showProgress() {
const questionIndexElement = document.getElementById("question-index");
const index = questionIndex + 1;
questionIndexElement.innerHTML = index.toString();
}
function guess(answer) {
clearTimeout(timer);
const answersContainer = document.getElementById("answers-container");
const answerButtons = answersContainer.querySelectorAll(".default-button");
answerButtons.forEach((element) => {
element.disabled = true;
if (element.innerHTML === questions[questionIndex].correct) {
element.classList.add("correct");
}
});
stopProgressbar();
if (questions[questionIndex].correct === answer) { // correct answer
score++;
setQuizText("Fantastic … Correct!");
} else if (answer) { // incorrect answer
setQuizText("Nice try … You were close.");
answerButtons.forEach((element) => {
if (element.innerHTML === answer) {
element.classList.add("wrong");
}
});
} else {
setQuizText("Your time is out! Oh no!");
}
questionIndex++;
window.setTimeout(function() {
displayNextQuestion();
}, 2500);
}
function setQuizText(text) {
const el = document.getElementById("trivia-text");
el.innerHTML = text;
}
function showScores() {
const scoreElement = document.getElementById("score");
const scoreTotalElement = document.getElementById("score-total");
const scoreNameElement = document.getElementById("score-name");
scoreElement.innerHTML = score.toString();
scoreTotalElement.innerHTML = questionLength.toString();
if (score < 4) {
scoreNameElement.innerHTML = "Newbie";
} else if (score < 7) {
scoreNameElement.innerHTML = "Rookie";
} else if (score < 10) {
scoreNameElement.innerHTML = "Expert";
} else {
scoreNameElement.innerHTML = "Grandmaster";
}
triviaScreen.classList.add("hidden");
resultScreen.classList.remove("hidden");
}
function startProgressbar() {
// select div turn into progressbar
const progressbar = document.getElementById("progress-bar");
progressbar.innerHTML = "";
// create div changes width show progress
const progressbarInner = document.createElement("span");
// Append progressbar to main progressbardiv
progressbar.appendChild(progressbarInner);
// When all set start animation
progressbarInner.style.animationPlayState = "running";
}
function stopProgressbar() {
const progressbar = document.getElementById("progress-bar");
const progressbarInner = progressbar.querySelector("span");
progressbarInner.style.animationPlayState = "paused";
}
function shuffleQuestions(questions) {
for (let i = questions.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[questions[i], questions[j]] = [questions[j], questions[i]];
}
}
}());
*,
*:after,
*:before {
box-sizing: border-box;
}
body {
margin: 0;
font-family: 'Verdana', cursive;
text-transform: uppercase;
color: #ccc;
letter-spacing: 2px;
}
.container {
background: #999999;
}
.wrapper {
max-width: 800px;
margin: auto;
}
.screen-section {
display: flex;
flex-direction: column;
align-items: center;
min-height: 100vh;
padding: 20px 20px 70px;
position: relative;
}
.hidden {
display: none;
}
.trivia-screen-step {
color: #ccc;
}
.trivia-image-wrapper {
max-width: 100%;
margin: 50px auto;
position: relative;
}
.trivia-image {
max-width: 100%;
width: 300px;
position: relative;
z-index: 1;
}
.trivia-timer {
width: 550px;
max-width: 100%;
height: 20px;
border-radius: 3em;
margin-bottom: 50px;
padding: 5px 6px;
}
.trivia-timer span {
display: inline-block;
background: linear-gradient(90deg, #fff, #06c);
height: 10px;
vertical-align: top;
border-radius: 3em;
animation: progressbar-countdown;
animation-duration: 10s;
animation-iteration-count: 1;
animation-fill-mode: forwards;
animation-play-state: paused;
animation-timing-function: linear;
}
#keyframes progressbar-countdown {
0% {
width: 100%;
}
100% {
width: 0%;
}
}
.trivia-question {
margin-bottom: 50px;
}
.how-to-play-screen .default-button {
margin-bottom: 60px;
margin-top: 30px;
}
.button-container {
display: flex;
flex-wrap: wrap;
margin-bottom: 50px;
width: 600px;
max-width: 100%;
}
.button-outer {
flex-basis: 100%;
text-align: center;
margin-bottom: 20px;
max-width: 100%;
}
.default-button {
background: #333333;
border-radius: 3em;
font-family: 'Verdana', cursive;
font-size: 18px;
color: #fff;
letter-spacing: 2.45px;
padding: 10px 8px;
text-transform: uppercase;
transition: background .2s;
outline: none;
width: 250px;
cursor: pointer;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
max-width: 100%;
}
.default-button:hover {
background: #222;
}
.default-button[disabled] {
background: transparent;
color: #222;
cursor: default;
}
.default-button[disabled]:hover {
background: transparent;
}
.default-button.correct {
cursor: default;
background: #2bb24a;
color: #fff;
}
.default-button.correct:hover {
background: #2bb24a;
color: #fff;
}
.default-button.wrong {
cursor: default;
background: #F6484C;
color: #fff;
}
.default-button.wrong:hover {
background: #F6484C;
color: #fff;
}
.title {
font-size: 32px;
margin-top: 100px;
}
.text {
line-height: 24px;
font-size: 16px;
font-family: 'Verdana', sans-serif;
text-align: center;
color: #ffffff;
text-transform: none;
}
.trivia-logo {
position: absolute;
bottom: 20px;
}
.trivia-corner-logo {
position: absolute;
left: 0;
top: 15px;
width: 100px;
}
.close-button {
position: absolute;
top: 50px;
right: 0;
background: transparent;
border: none;
color: #fff;
font-family: 'Verdana', cursive;
font-size: 34px;
outline: none;
text-transform: none;
cursor: pointer;
transition: color .2s;
}
.close-button:hover {
color: #eee;
}
.score-name {
margin: 0 0 28px;
font-size: 46px;
}
.score {
font-size: 18px;
margin-bottom: 10px;
}
.description {
text-align: center;
font-family: Verdana, sans-serif;
font-size: 16px;
color: #fff;
text-transform: none;
line-height: 24px;
display: inline-block;
margin-bottom: 30px;
}
#media screen and (min-width: 700px) {
.screen-section {
padding: 50px;
}
<div class="container">
<div class="wrapper">
<div class="screen-section main-screen">
<div class="trivia-image-wrapper">
<img alt="LOGO" src="./assets/Game-Logo.png" class="trivia-image">
</div>
<h1>Trivia</h1>
<div class="button-container">
<div class="button-outer">
<button class="default-button" id="play" type="button">Play</button>
</div>
<div class="button-outer">
<button class="default-button" id="how-to-play-button" type="button">How to play?</button>
</div>
</div>
<div class="trivia-logo">
<img alt="logo" src="./assets/-Logo.png">
</div>
</div>
<div class="screen-section hidden how-to-play-screen">
<img alt="LOGO" src="./assets/Game-Logo.png" class="trivia-corner-logo">
<button class="close-button" id="close-how-to" type="button">X</button>
<h2 class="title">How to Play</h2>
<p>Answer questions to score points.</p>
<button class="default-button" id="lets-start" type="button">Ok. Let's start</button>
<div class="trivia-logo">
<img alt="logo" src="./assets/-Logo.png">
</div>
</div>
<div class="screen-section hidden trivia-screen">
<div class="trivia-screen-step"><span id="question-index">1</span> out of <span id="question-count">10</span></div>
<div class="trivia-image-wrapper">
<p id="question-placement"></p>
</div>
<div class="trivia-timer" id="progress-bar"></div>
<div class="trivia-question" id="trivia-text"></div>
<div class="button-container" id="answers-container">
<div class="button-outer">
<button class="default-button" id="answer0" type="button"></button>
</div>
<div class="button-outer">
<button class="default-button" id="answer1" type="button"></button>
</div>
<div class="button-outer">
<button class="default-button" id="answer2" type="button"></button>
</div>
<div class="button-outer">
<button class="default-button" id="answer3" type="button"></button>
</div>
</div>
<div class="trivia-logo">
<img alt="logo" src="./assets/-Logo.png">
</div>
</div>
<div class="screen-section hidden result-screen">
<div class="trivia-image-wrapper">
<img alt="Trivia LOGO" src="./assets/Game-Logo.png" class="trivia-image">
</div>
<p class="score"><span id="score">0</span> out of <span id="score-total">10</span></p>
<h1 class="score-name" id="score-name">Trivia</h1>
<span class="description">you will learn more.</span>
<button class="default-button" id="play-again" type="button">Play again</button>
<div class="trivia-logo">
<img alt=" logo" src="./assets/-Logo.png">
</div>
</div>
</div>
</div>
I created a constructor function name Book and an empty array named myLibrary as a container for these new book object instances. A separate function to create a book createBook calls a function addBookToLibrary which pushes the book into the myLibrary array, clears the form to add books, then renders the book list via the viewBookList function.
Each time I call createBook and create a new instance of Book, I'm running into a problem where the rendered list of books that show up on the page repeat all instances of Book objects created prior to the new book being added plus the one new book. For instance, I have book1, book2 and book3 that I previously created. I then add book4 so now the array has [ {book1...}, {book2...}, {book3...}, {book4...} ] objects correctly in place, but what's being rendered on the page is a scattered mess of book1, book1, book2, book1, book2, book3, book1, book2, book3, book4 as you see in the attached image. You'll see the array in the console is fine.
I initially cleared out the myLibrary array in createBook which correctly rendered the books to the page, but obviously wipes out my array which won't work because I need to be able to delete these at some point from the array. So my question is, how do I display what's in my array onto the page each time without rendering duplicates of books that were already added?
const submitButton = document.querySelector('#submit');
const btnOpenModal = document.querySelector('.open-modal');
const btnCloseModal = document.querySelector('.close-modal');
const modalElement = document.querySelector('.modal');
// let myLibrary = [
// new Book('Down and Out in Paris and London', 'George Orwell', 232, true),
// new Book('Homage to Catalonia', 'George Orwell', 202, true),
// new Book('Shooting an Elephant', 'George Orwell', 368, false),
// ];
// let count = myLibrary.length - 3;
let myLibrary = [];
let count = myLibrary.length;
// Constructor...
function Book(title, author, pages, read) {
this.title = title;
this.author = author;
this.pages = Number(pages);
this.read = Boolean(read);
// Methods
this.bookInfo = function () {
const wasRead = this.read === true ? 'read' : 'not read';
return `${this.title} written by ${this.author}, ${this.pages} pages in length was ${wasRead}.`;
};
return this.bookInfo();
}
function createBook(e) {
e.preventDefault();
// myLibrary = [];
let title = document.querySelector('#title').value;
let author = document.querySelector('#author').value;
let pages = document.querySelector('#pages').value;
let read = document.querySelector('#read').value;
// Instantiate new Book object
const newBook = new Book(title, author, pages, read); // Add ID when instantiating
addBookToLibrary(newBook);
clearForm();
viewBookList(myLibrary);
}
function addBookToLibrary(book) {
// Hide modal
removeClass();
// Add book to array
return myLibrary.push(book);
}
function clearForm() {
document.querySelector('#form').reset();
}
function setCardStyle(element, details) {
element.setAttribute(
'style',
'display: flex; flex-direction: column; justify-content: space-between; text-align: center; background-color: #fff; padding: 1em; margin: 1em 1em 1em 0; border-radius: 5px; height: 250px; width: 250px; line-height: 1.5; box-shadow: 0 5px 10px 2px rgba(0, 0, 0, 0.2);',
);
element.innerHTML = `
<h3 class="title">${details.title}</h3>
<br>
<hr>
<br>
<p>${details.author}</p>
<p>${details.pages} pages</p>
<p>${details.read === true ? 'Read' : 'Unread'}</p>`;
}
function createCard() {
let bookCard = document.createElement('div');
bookCard.classList.add('card');
bookCard.setAttribute('data-target', `${count++}`); // Set target ID
return bookCard;
}
function removeBookBtn() {
let btn = document.createElement('button');
// Style button
btn.setAttribute(
'style',
'color: red; height: 2.5em; width: 50%; border-radius: 5px; margin: 0 auto; font-weight: bold; text-transform: uppercase; cursor: pointer;',
);
btn.innerHTML = 'Delete';
return btn;
}
function handleDelete(e) {
// Get book's data-target
let bookIndex = parseInt(e.path[1].attributes[1].value);
// console.log(bookIndex);
myLibrary.splice(bookIndex, 1);
// console.log(newArray);
// myLibrary = myLibrary.filter((book, index) => index !== bookIndex);
return viewBookList(myLibrary);
}
function clearDOM(element) {
while (element.firstElementChild) {
element.firstElementChild.remove();
}
}
function viewBookList(list) {
const bookDiv = document.querySelector('.book-list');
clearDOM(bookDiv);
for (book in list) {
let bookDetails = list[book];
let renderCard = createCard();
const deleteButton = removeBookBtn();
deleteButton.addEventListener('click', handleDelete);
setCardStyle(renderCard, bookDetails);
renderCard.appendChild(deleteButton);
bookDiv.appendChild(renderCard);
}
return bookDiv;
}
function addClass() {
return modalElement.classList.add('open');
}
function removeClass() {
return modalElement.classList.remove('open');
}
// Event listeners
btnOpenModal.addEventListener('click', addClass);
btnCloseModal.addEventListener('click', removeClass);
submitButton.addEventListener('click', createBook);
#import url('https://fonts.googleapis.com/css2?family=Roboto&display=swap');
:root {
--roboto: 'Roboto', sans-serif;
--pt: "PT Sans", sans-serif;
}
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
html {
font-family: var(--roboto);
}
body {
min-height: 100vh;
display: flex;
justify-content: center;
background-image: linear-gradient(to top, #a6c1ee 0%, #fbc2eb 100%);
}
.header {
text-align: center;
}
.header h1 {
color: #fff;
font-size: 4rem;
text-shadow: 1px 2px 5px #000;
}
.modal {
padding: 1em;
background-color: #fff;
}
.label {
text-transform: capitalize;
}
.btn {
font-family: "PT Sans", sans-serif;
font-size: 1.2rem;
padding: 1rem 2.5rem;
cursor: pointer;
border: none;
}
.modal {
display: none;
position: fixed;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
align-items: center;
justify-content: center;
background: rgba(0, 0, 0, 0.7);
}
.open-modal {
background: #fff;
border-radius: 5px;
box-shadow: 0 5px 10px 2px rgba(0, 0, 0, 0.2);
transition: all 0.2s linear;
}
.open-modal:hover {
box-shadow: none;
background: rgba(255, 255, 255, 0.8);
}
.modal.open {
display: flex;
}
.form {
padding: 5em;
}
.modal-container {
background-color: #fff;
width: 90%;
max-width: 450px;
position: relative;
}
.modal.open .modal-container {
animation: move 0.6s ease-out;
}
#keyframes move {
from {
transform: translateY(-50px);
}
to {
transform: translateY(0px);
}
}
.close-modal {
font-size: 3rem;
position: absolute;
top: 0;
right: 0;
background-color: #fff;
height: 40px;
width: 40px;
text-align: center;
line-height: 40px;
cursor: pointer;
transition: color 0.15s linear;
}
.close-modal:hover {
color: #f00;
}
.book-list {
display: flex;
flex-wrap: wrap;
margin-top: 1.5em;
gap: 2em;
}
/* Created in app.js */
/* .card {
} */
<!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="styles/style.css">
<script src="scripts/app.js" defer></script>
<title>Odin Library</title>
</head>
<body>
<div class="container">
<header class="header">
<h1>Library</h1>
</header>
<section class="modal open">
<div class="modal-container">
<span id="close-modal" class="close-modal">×</span>
<form action="" method="POST" name="bookForm" id="form" class="form">
<div class="form-row">
<label for="title" class="label">title: </label>
<input type="text" name="title" id="title" placeholder="Animal Farm" required>
</div>
<div class="form-row">
<label for="author" class="label">author: </label>
<input type="text" name="author" id="author" placeholder="George Orwell" required>
</div>
<div class="form-row">
<label for="pages" class="label">pages: </label>
<input type="number" name="pages" id="pages" placeholder="232" required>
</div>
<div class="form-row">
<label for="read" class="label">read: </label>
<input type="checkbox" name="read" id="read" required>
</div>
<div class="button-container">
<input type="submit" value="Create" id="submit" class="submit">
</div>
</form>
</div>
</section class="card-section">
<section>
<!-- Add plus icon -->
<button class="btn open-modal" id="open-modal">Add Book</button>
<div class="book-list">
<!-- Container for cards -->
</div>
</section>
</div>
</body>
</html>
Like the others already said on the comment, the problem is that each time you add a new book, when you try to display ti on the page you are "appending" all the books after the already existing books.
So you get something like this:
Add book 1: (1)
Add book 2: (1) (1 2)
Add book 3: (1) (1 2) (1 2 3)
The solution is to clear the container div before you update it.
Something like this (JS line 107):
const submitButton = document.querySelector('#submit');
const btnOpenModal = document.querySelector('.open-modal');
const btnCloseModal = document.querySelector('.close-modal');
const modalElement = document.querySelector('.modal');
// let myLibrary = [
// new Book('Down and Out in Paris and London', 'George Orwell', 232, true),
// new Book('Homage to Catalonia', 'George Orwell', 202, true),
// new Book('Shooting an Elephant', 'George Orwell', 368, false),
// ];
// let count = myLibrary.length - 3;
let myLibrary = [];
let count = myLibrary.length;
// Constructor...
function Book(title, author, pages, read) {
this.title = title;
this.author = author;
this.pages = Number(pages);
this.read = Boolean(read);
// Methods
this.bookInfo = function() {
const wasRead = this.read === true ? 'read' : 'not read';
return `${this.title} written by ${this.author}, ${this.pages} pages in length was ${wasRead}.`;
};
return this.bookInfo();
}
function createBook(e) {
e.preventDefault();
// myLibrary = [];
let title = document.querySelector('#title').value;
let author = document.querySelector('#author').value;
let pages = document.querySelector('#pages').value;
let read = document.querySelector('#read').value;
// Instantiate new Book object
const newBook = new Book(title, author, pages, read); // Add ID when instantiating
addBookToLibrary(newBook);
clearForm();
viewBookList(myLibrary);
}
function addBookToLibrary(book) {
// Hide modal
removeClass();
// Add book to array
return myLibrary.push(book);
}
function clearForm() {
document.querySelector('#form').reset();
}
function setCardStyle(element, details) {
element.setAttribute(
'style',
'display: flex; flex-direction: column; justify-content: space-between; text-align: center; background-color: #fff; padding: 1em; margin: 1em 1em 1em 0; border-radius: 5px; height: 250px; width: 250px; line-height: 1.5; box-shadow: 0 5px 10px 2px rgba(0, 0, 0, 0.2);',
);
element.innerHTML = `
<h3 class="title">${details.title}</h3>
<br>
<hr>
<br>
<p>${details.author}</p>
<p>${details.pages} pages</p>
<p>${details.read === true ? 'Read' : 'Unread'}</p>`;
}
function createCard() {
let bookCard = document.createElement('div');
bookCard.classList.add('card');
bookCard.setAttribute('data-target', `${count++}`); // Set target ID
return bookCard;
}
function removeBookBtn() {
let btn = document.createElement('button');
// Style button
btn.setAttribute(
'style',
'color: red; height: 2.5em; width: 50%; border-radius: 5px; margin: 0 auto; font-weight: bold; text-transform: uppercase; cursor: pointer;',
);
btn.innerHTML = 'Delete';
return btn;
}
function handleDelete(e) {
// Get book's data-target
let bookIndex = parseInt(e.path[1].attributes[1].value);
// console.log(bookIndex);
myLibrary.splice(bookIndex, 1);
// console.log(newArray);
// myLibrary = myLibrary.filter((book, index) => index !== bookIndex);
return viewBookList(myLibrary);
}
function viewBookList(list) {
const bookDiv = document.querySelector('.book-list');
bookDiv.innerHTML = "";
console.log(myLibrary);
for (book in list) {
let bookDetails = list[book];
let renderCard = createCard();
const deleteButton = removeBookBtn();
deleteButton.addEventListener('click', handleDelete);
setCardStyle(renderCard, bookDetails);
renderCard.appendChild(deleteButton);
bookDiv.appendChild(renderCard);
}
return bookDiv;
}
function addClass() {
return modalElement.classList.add('open');
}
function removeClass() {
return modalElement.classList.remove('open');
}
// Event listeners
btnOpenModal.addEventListener('click', addClass);
btnCloseModal.addEventListener('click', removeClass);
submitButton.addEventListener('click', createBook);
#import url('https://fonts.googleapis.com/css2?family=Roboto&display=swap');
:root {
--roboto: 'Roboto', sans-serif;
--pt: "PT Sans", sans-serif;
}
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
html {
font-family: var(--roboto);
}
body {
min-height: 100vh;
display: flex;
justify-content: center;
background-image: linear-gradient(to top, #a6c1ee 0%, #fbc2eb 100%);
}
.header {
text-align: center;
}
.header h1 {
color: #fff;
font-size: 4rem;
text-shadow: 1px 2px 5px #000;
}
.modal {
padding: 1em;
background-color: #fff;
}
.label {
text-transform: capitalize;
}
.btn {
font-family: "PT Sans", sans-serif;
font-size: 1.2rem;
padding: 1rem 2.5rem;
cursor: pointer;
border: none;
}
.modal {
display: none;
position: fixed;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
align-items: center;
justify-content: center;
background: rgba(0, 0, 0, 0.7);
}
.open-modal {
background: #fff;
border-radius: 5px;
box-shadow: 0 5px 10px 2px rgba(0, 0, 0, 0.2);
transition: all 0.2s linear;
}
.open-modal:hover {
box-shadow: none;
background: rgba(255, 255, 255, 0.8);
}
.modal.open {
display: flex;
}
.form {
padding: 5em;
}
.modal-container {
background-color: #fff;
width: 90%;
max-width: 450px;
position: relative;
}
.modal.open .modal-container {
animation: move 0.6s ease-out;
}
#keyframes move {
from {
transform: translateY(-50px);
}
to {
transform: translateY(0px);
}
}
.close-modal {
font-size: 3rem;
position: absolute;
top: 0;
right: 0;
background-color: #fff;
height: 40px;
width: 40px;
text-align: center;
line-height: 40px;
cursor: pointer;
transition: color 0.15s linear;
}
.close-modal:hover {
color: #f00;
}
.book-list {
display: flex;
flex-wrap: wrap;
margin-top: 1.5em;
gap: 2em;
}
/* Created in app.js */
/* .card {
} */
<!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="styles/style.css">
<script src="scripts/app.js" defer></script>
<title>Odin Library</title>
</head>
<body>
<div class="container">
<header class="header">
<h1>Library</h1>
</header>
<section class="modal open">
<div class="modal-container">
<span id="close-modal" class="close-modal">×</span>
<form action="" method="POST" name="bookForm" id="form" class="form">
<div class="form-row">
<label for="title" class="label">title: </label>
<input type="text" name="title" id="title" placeholder="Animal Farm" required>
</div>
<div class="form-row">
<label for="author" class="label">author: </label>
<input type="text" name="author" id="author" placeholder="George Orwell" required>
</div>
<div class="form-row">
<label for="pages" class="label">pages: </label>
<input type="number" name="pages" id="pages" placeholder="232" required>
</div>
<div class="form-row">
<label for="read" class="label">read: </label>
<input type="checkbox" name="read" id="read" required>
</div>
<div class="button-container">
<input type="submit" value="Create" id="submit" class="submit">
</div>
</form>
</div>
</section class="card-section">
<section>
<!-- Add plus icon -->
<button class="btn open-modal" id="open-modal">Add Book</button>
<div class="book-list">
<!-- Container for cards -->
</div>
</section>
</div>
</body>
</html>
I have an API app that lists of names that clicked on a modal pops up and shows the data.
There is another button that is connected to a second modal with more data.
The problem is that this second modal runs through all the data instead of only displaying the proper data for the name selected. I was told the reason is because I have two event listeners but I should only have 1.
Here is my codepen and here is where I was told the problem was.
https://codepen.io/drxl/pen/WNjJQXa
function addListItem(pokemon) {
let pokeUl = document.querySelector('.list-group');
let listItem = document.createElement('li');
let button = document.createElement('button');
let baseStatsButton = document.querySelector('#base-stats-button');
button.innerText = pokemon.name;
button.classList.add('btn');
button.classList.add('btn-primary');
listItem.classList.add('group-list-item');
button.setAttribute("data-target", "#my-modal");
button.setAttribute("data-toggle", "modal");
listItem.appendChild(button);
pokeUl.appendChild(listItem);
button.addEventListener('click', function() {
showDetails(pokemon);
});
baseStatsButton.addEventListener('click', function() {
showStatModal(pokemon);
});
}
Right now when you add the pokemon, you add the same click event listener to the stats button every time. That ends up executing the event handler number-of-pokemon times when clicked. There is only one button so only one event listener is needed
What we can do is to set up a global currentPokemon outside the functions. Then when you click a pokemon button, you save the pokemon and when you click base stats, show the base stats for currentPokemon
So let's move some constants out of the add function and save the pokemon clicked
const pokeUl = document.querySelector('.list-group');
const baseStatsButton = document.querySelector('#base-stats-button');
let currentPokemon; // define a reusable variable
function addListItem(pokemon) {
let listItem = document.createElement('li');
let button = document.createElement('button');
button.innerText = pokemon.name;
button.classList.add('btn');
button.classList.add('btn-primary');
listItem.classList.add('group-list-item');
button.setAttribute("data-target", "#my-modal");
button.setAttribute("data-toggle", "modal");
listItem.appendChild(button);
pokeUl.appendChild(listItem);
button.addEventListener('click', function () {
showDetails(pokemon);
currentPokemon = pokemon; // save
});
};
then use it in the stats
function showStatModal() {
if (!currentPokemon) return; // for some reason we have invoked the modal before clicking
const item = currentPokemon;
let pokemonRepository = (function () {
let pokemonList = [];
let apiUrl = 'https://pokeapi.co/api/v2/pokemon/?limit=150';
let searchInput = document.querySelector("#searchIn");
function add(pokemon) {
pokemonList.push(pokemon);
}
function getAll() {
return pokemonList;
}
const pokeUl = document.querySelector('.list-group');
const baseStatsButton = document.querySelector('#base-stats-button');
let currentPokemon;
function addListItem(pokemon) {
let listItem = document.createElement('li');
let button = document.createElement('button');
button.innerText = pokemon.name;
button.classList.add('btn');
button.classList.add('btn-primary');
listItem.classList.add('group-list-item');
button.setAttribute("data-target", "#my-modal");
button.setAttribute("data-toggle", "modal");
listItem.appendChild(button);
pokeUl.appendChild(listItem);
button.addEventListener('click', function () {
showDetails(pokemon);
currentPokemon = pokemon;
});
}
baseStatsButton.addEventListener('click', showStatModal);
function loadList() {
return fetch(apiUrl).then(function (response) {
return response.json();
}).then(function (json) {
json.results.forEach(function (item) {
let pokemon = {
name: item.name,
detailsUrl: item.url
};
add(pokemon);
});
}).catch(function (e) {
console.error(e);
})
}
function loadDetails(item) {
let url = item.detailsUrl;
return fetch(url).then(function (response) {
return response.json();
}).then(function (details) {
//Add details to item
item.imageUrl = details.sprites.front_default;
item.imageUrlBack = details.sprites.back_default;
item.height = details.height / 10;
item.weight = details.weight / 10;
// pokemon types
item.types = [];
for (var i = 0; i < details.types.length; i++) {
item.types.push(details.types[i].type.name);
}
item.types = item.types.join(', ');
//pokemon abilities
item.abilities = [];
// eslint-disable-next-line no-redeclare
for (var i = 0; i < details.abilities.length; i++) {
item.abilities.push(details.abilities[i].ability.name);
}
item.abilities = item.abilities.join(', ');
}).catch(function (e) {
console.error(e);
});
}
//loads the stats for 2nd modal
function loadStats(item) {
let url = item.detailsUrl;
return fetch(url).then(function (response) {
return response.json();
}).then(function (details) {
//add details to stats
item.stats = details.stats.map(({ base_stat, stat: { name } }) =>
`${name}: ${base_stat}`).join("<br/>")
}).catch(function (e) {
console.error(e);
});
}
function showDetails(item) {
pokemonRepository.loadDetails(item).then(function () {
// console.log("item:", item);
showModal(item);
});
}
function showModal(item) {
pokemonRepository.loadDetails(item).then(function () {
// eslint-disable-next-line no-undef
let modalBody = $(".modal-body");
// eslint-disable-next-line no-undef
let modalTitle = $(".modal-title");
//clears previous content in modal
modalTitle.empty();
modalBody.empty();
//create elenebtb for pokemon name
// eslint-disable-next-line no-undef
let nameElement = $("<h1>" + item.name + "</h1>");
//create img element
// eslint-disable-next-line no-undef
let imageElementFront = $('<img class="modal-img" style="width:50%">');
imageElementFront.attr("src", item.imageUrl);
// eslint-disable-next-line no-undef
let imageElementBack = $('<img class="modal-img" style="width:50%">');
imageElementBack.attr("src", item.imageUrlBack);
//create element for pokemon height
// eslint-disable-next-line no-undef
let heightElement = $("<p>" + "Height: " + item.height + "m</p>");
//for pokemon weight
let weightElement = $("<p>" + "Weight: " + item.weight + "kgs</p>");
//pokemon types
// eslint-disable-next-line no-undef
let typesElement = $("<p>" + "Types: " + item.types + "</p>");
//pokemon abilities
// eslint-disable-next-line no-undef
let typesAbilities = $("<p>" + "Abilities: " + item.abilities + "</p>");
//eventlistener to for search bar
searchInput.addEventListener('input', function () {
let listPokemon = document.querySelectorAll('.group-list-item');
let value = searchInput.value.toUpperCase();
listPokemon.forEach(function (pokemon) {
if (pokemon.innerText.toUpperCase().indexOf(value) > -1) {
pokemon.style.display = '';
} else {
pokemon.style.display = 'none'
}
})
});
modalTitle.append(nameElement);
modalBody.append(imageElementFront);
modalBody.append(imageElementBack);
modalBody.append(heightElement);
modalBody.append(weightElement);
modalBody.append(typesElement);
modalBody.append(typesAbilities);
// eslint-disable-next-line no-undef
$('#my-modal').modal('toggle');
});
}
function loadStatDetails(item) {
pokemonRepository.loadStats(item).then(function () {
showStatModal(item);
});
}
function showStatModal() {
if (!currentPokemon) return; // for some reason we have invoked the modal before clicking
const item = currentPokemon;
pokemonRepository.loadStats(item).then(function () {
// eslint-disable-next-line no-undef
let StatmodalBody = $(".Statmodal-body");
// eslint-disable-next-line no-undef
let StatmodalTitle = $(".Statmodal-title");
//clears previous content in modal
StatmodalTitle.empty();
StatmodalBody.empty();
//create elenebtb for pokemon name
// eslint-disable-next-line no-undef
let nameElement = $("<h1>" + item.name + "</h1>");
//add stats
let statsElement = $("<p>" + item.stats + "<p>");
StatmodalTitle.append(nameElement);
StatmodalBody.append(statsElement);
$('#my-Statmodal').modal('show');
});
}
return {
add: add,
getAll: getAll,
addListItem: addListItem,
loadList: loadList,
loadDetails: loadDetails,
showDetails: showDetails,
loadStats: loadStats,
loadStatDetails: loadStatDetails,
};
})();
pokemonRepository.loadList().then(function () {
pokemonRepository.getAll().forEach(function (pokemon) {
pokemonRepository.addListItem(pokemon);
});
});
let link = document.getElementById("back-to-top");
var amountScrolled = 250;
//makes button show
window.addEventListener('scroll', function (e) {
if (this.window.pageYOffset > amountScrolled) {
link.classList.add('show');
} else {
link.className = 'back-to-top';
}
});
//scrolls to top
link.addEventListener('click', function (e) {
e.preventDefault();
var distance = 0 - window.pageYOffset;
var increments = distance / (500 / 16);
function animateScroll() {
window.scrollBy(0, increments);
if (window.pageYOffset <= document.body.offsetTop) {
clearInterval(runAnimation);
}
};
// Loop the animation function
var runAnimation = setInterval(animateScroll, 16);
});
/*
* Prefixed by https://autoprefixer.github.io
* PostCSS: v7.0.29,
* Autoprefixer: v9.7.6
* Browsers: last 4 version
*/
* {
-webkit-box-sizing: border-box;
box-sizing: border-box;
}
body {
background-color: rgb(3, 136, 180);
}
.navbar {
background-color: #ffcb05!important;
}
.navbar-brand {
color: #3d7dca!important;
}
.navbar-logo {
width: 42px;
height: 42px;
margin-left: 1rem;
}
.modal-header {
border-bottom: 1px solid black;
-webkit-box-pack: justify;
-ms-flex-pack: justify;
justify-content: space-between;
}
.modal-content {
background-color: #ffcb05!important;
border: #3d7dca solid 6px!important;
text-align: center;
}
.modal-close {
background-color: #ee1515;
border: white solid 2px;
color: white;
padding: 8.5px 16.5px;
border-radius: 50%;
font-size: 1.25rem;
}
.modal-close:active {
border-color: #ee1515;
background-color: white;
color: #ee1515;
}
.modal-title h1 {
margin-bottom: 0;
}
.modal h1 {
margin-top: 0;
text-align: left;
font-family: 'Gill Sans', 'Gill Sans MT', Calibri, 'Trebuchet MS', sans-serif;
text-transform: uppercase;
font-size: 3rem;
color: #3d7dca;
margin-left: 2rem;
}
.modal p {
margin-bottom: 0;
text-align: left;
font-weight: 700;
font-family: 'Gill Sans', 'Gill Sans MT', Calibri, 'Trebuchet MS', sans-serif;
font-size: 1.5rem;
color: #3d7dca;
text-transform: capitalize;
}
.list-group {
list-style-type: none;
text-align: center;
-webkit-padding-start: 0;
padding-inline-start: 0;
margin: 2rem;
text-transform: capitalize;
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-orient: horizontal;
-webkit-box-direction: normal;
-ms-flex-direction: row;
flex-direction: row;
-ms-flex-wrap: wrap;
flex-wrap: wrap;
-webkit-box-pack: center;
-ms-flex-pack: center;
justify-content: center;
}
.list-group li {
width: auto;
margin: 1rem;
}
.Statmodal-body p {
margin-left: 3%;
}
.btn {
/*👉 background-color: #cc1313;👈*/
background-color: #db0606;
border: black solid 2px;
color: white;
text-transform: capitalize;
padding: 24px 72px;
width: 300px;
}
.btn:hover {
background-color: white;
border: black solid 2px;
color: #ee1515;
}
.btn-outline-success:hover {
background-color: white;
color: #ee1515;
border: black 2px solid;
}
.btn-primary {
font-size: 1.5rem;
}
.btn-primary:hover {
color: #ee1515;
background-color: white;
}
#search-button {
background-color: #db0606;
border: black solid 2px;
color: white;
padding: 4px 25px;
}
.modal-footer {
justify-content: center;
border-top: none;
}
.modal-button {
text-align: center;
width: auto;
}
.back-to-top {
background-color: #ee1515;
color: #FFFFFF;
opacity: 0;
transition: opacity .6s ease-in-out;
z-index: 999;
position: fixed;
right: 20px;
bottom: 20px;
width: 50px;
height: 50px;
box-sizing: border-box;
border-radius: 0%;
}
a.back-to-top {
font-weight: 1000;
letter-spacing: 2px;
font-size: 14px;
text-transform: uppercase;
text-align: center;
line-height: 1.6;
padding-left: 2px;
padding-top: 14px;
text-decoration: none;
}
.back-to-top:hover,
.back-to-top:focus,
.back-to-top:visited {
color: #FFFFFF;
}
.back-to-top.show {
opacity: 1;
}
#media screen and (max-width: 727px) {
.btn {
width: 250px;
}
}
#media screen and (max-width:627px) {
.btn {
padding: 10px 10px;
width: 200px;
font-size: 1.15rem;
}
}
#media screen and (max-width:575px) {
.justify-content-between {
-webkit-box-pack: center!important;
-ms-flex-pack: center!important;
justify-content: center!important;
}
.form-inline {
-webkit-box-pack: center;
-ms-flex-pack: center;
justify-content: center;
}
#search-button {
margin-top: .5rem;
padding: 4px 42px;
}
.modal p {
font-size: 1.5rem!important;
}
}
#media screen and (max-width:500px) {
.modal p {
font-size: 1.5rem!important;
}
}
#media screen and (max-width: 493px) {
.justify-content-between {
-webkit-box-pack: center!important;
-ms-flex-pack: center!important;
justify-content: center!important;
}
}
#media screen and (max-width:450px) {
.modal-header {
-webkit-box-align: center!important;
-ms-flex-align: center!important;
align-items: center!important;
}
.modal-title h1 {
font-size: 1.75rem;
}
button {
font-size: .85rem;
}
.modal p {
font-size: 1rem!important;
}
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>PokemonAPI</title>
<link href="img/Poke_Ball.png" rel="shortcut icon" type="image/x-icon" />
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.15.3/css/all.css" integrity="sha384-SZXxX4whJ79/gErwcOYf+zWLeJdY/qpuqC4cAa9rOGUstPomtqpuNWT9wdPEn2fk" crossorigin="anonymous">
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
<link href="css/styles.css" rel="stylesheet">
</head>
<body>
<!--Nav-->
<nav class="navbar navbar-light bg-light justify-content-between">
<a class="navbar-brand">PokemonAPI<img class="navbar-logo" src="img/Poke_Ball.png"></a>
<form class="form-inline">
<input id="searchIn" class="form-control mr-sm-2" type="search" placeholder="Search for a Pokemon" aria-label="Search for Pokemon">
<button id="search-button" type="submit">Search</button>
</form>
</nav>
<!--list of pokemon-->
<ul class="list-group"></ul>
<div class="modal fade" id="my-modal" aria-hidden="true" tabindex="-1" role="dialog" aria-labelledby="pokemonModalLabel">
<div class="modal-dialog modal-dialog-centered" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" aria-labelledby="pokemonModalLabel">Modal 1 title</h5>
<button type="button" class="modal-close" data-bs-dismiss="modal" aria-label="Close">X</button>
</div>
<div class="modal-body">
</div>
<div class="modal-footer">
<button id="base-stats-button" class="btn modal-button" data-bs-target="#my-Statmodal" data-bs-toggle="modal" data-bs-dismiss="modal">Base Stats</button>
</div>
</div>
</div>
</div>
<div class="modal fade" id="my-Statmodal" aria-hidden="true" aria-labelledby="pokemonStatModalLabel" tabindex="-1" role="dialog">
<div class="modal-dialog modal-dialog-centered" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="Statmodal-title" id="exampleModalToggleLabel2" aria-labelledby="pokemonStatModalLabel">Modal 2 title</h5>
<button type="button" class="modal-close" data-bs-dismiss="modal" aria-label="Close">X</button>
</div>
<div class="Statmodal-body">
</div>
<div class="modal-footer">
<button class="btn modal-button" data-bs-target="#my-modal" data-bs-toggle="modal" data-bs-dismiss="modal">Back to Pokemon</button>
</div>
</div>
</div>
</div>
<!--Top of Page Button-->
<i class="fas fa-arrow-up fa-2x"></i>
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
<script src="https://code.jquery.com/jquery-3.5.1.js" integrity="sha256-QWo7LDvxbWT2tbbQ97B53yJnYU3WhH/C8ycbRAkjPDc=" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap#5.0.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM" crossorigin="anonymous"></script>
<!--PolyFills-->
<script src="js/promise-polyfill.js"></script>
<script src="js/fetch-polyfill.js"></script>
<!--JS-->
<script src="js/scripts.js"></script>
</body>
</html>
So, I made a calculator, and I want to add a square root function, but I know there is no already made function that finds the square root of numbers. So what elements can I combine to find the square root of a number?
const screen = document.querySelector("#screen");
const clearButton = document.querySelector("#clear");
const equalsButton = document.querySelector("#equals");
const decimalButton = document.querySelector("#decimal");
let isFloat = false;
let signOn = false;
let firstNumber = "";
let operator = "";
let secondNumber = "";
let result = "";
const allClear = () => {
isFloat = false;
signOn = false;
firstNumber = "";
operator = "";
secondNumber = "";
result = "";
screen.value = "0";
};
const calculate = () => {
if (operator && result === "" && ![" ", "+", "-", "."].includes(screen.value[screen.value.length - 1])) {
secondNumber = screen.value.substring(firstNumber.length + 3);
switch (operator) {
case "+":
result = Number((Number(firstNumber) + Number(secondNumber)).toFixed(3));
break;
case "-":
result = Number((Number(firstNumber) - Number(secondNumber)).toFixed(3));
break;
case "*":
result = Number((Number(firstNumber) * Number(secondNumber)).toFixed(3));
break;
case "/":
result = Number((Number(firstNumber) / Number(secondNumber)).toFixed(3));
break;
default:
}
screen.value = result;
}
};
clear.addEventListener("click", allClear);
document.querySelectorAll(".number").forEach((numberButton) => {
numberButton.addEventListener("click", () => {
if (screen.value === "0") {
screen.value = numberButton.textContent;
} else if ([" 0", "+0", "-0"].includes(screen.value.substring(screen.value.length - 2))
&& numberButton.textContent === "0") {
} else if ([" 0", "+0", "-0"].includes(screen.value.substring(screen.value.length - 2))
&& numberButton.textContent !== "0") {
screen.value = screen.value.substring(0, screen.value.length - 1) + numberButton.textContent;
} else if (result || result === 0) {
allClear();
screen.value = numberButton.textContent;
} else {
screen.value += numberButton.textContent;
}
});
});
decimalButton.addEventListener("click", () => {
if (result || result === 0) {
allClear();
isFloat = true;
screen.value += ".";
} else if (!isFloat) {
isFloat = true;
if ([" ", "+", "-"].includes(screen.value[screen.value.length - 1])) {
screen.value += "0.";
} else {
screen.value += ".";
}
}
});
document.querySelectorAll(".operator").forEach((operatorButton) => {
operatorButton.addEventListener("click", () => {
if (result || result === 0) {
isFloat = false;
signOn = false;
firstNumber = String(result);
operator = operatorButton.dataset.operator;
result = "";
screen.value = `${firstNumber} ${operatorButton.textContent} `;
} else if (operator && ![" ", "+", "-", "."].includes(screen.value[screen.value.length - 1])) {
calculate();
isFloat = false;
signOn = false;
firstNumber = String(result);
operator = operatorButton.dataset.operator;
result = "";
screen.value = `${firstNumber} ${operatorButton.textContent} `;
} else if (!operator) {
isFloat = false;
firstNumber = screen.value;
operator = operatorButton.dataset.operator;
screen.value += ` ${operatorButton.textContent} `;
} else if (!signOn
&& !["*", "/"].includes(operatorButton.dataset.operator)
&& screen.value[screen.value.length - 1] === " ") {
signOn = true;
screen.value += operatorButton.textContent;
}
});
});
equalsButton.addEventListener("click", calculate);
* {
box-sizing: border-box;
font-family: 'Roboto', sans-serif;
font-weight: 300;
margin: 0;
padding: 0;
}
body {
background-color: #222;
height: 100vh;
}
header {
background-color: #333;
padding: 40px 0;
}
header h1 {
-webkit-background-clip: text;
background-clip: text;
background-image: linear-gradient(to right bottom, #fff, #777);
color: transparent;
font-size: 40px;
letter-spacing: 2px;
text-align: center;
text-transform: uppercase;
}
main {
background-color: #222;
display: flex;
justify-content: center;
padding: 60px 0;
}
main #container {
background-color: #333;
box-shadow: 0 5px 5px #111;
padding: 20px;
}
.clearfix:after {
clear: both;
content: " ";
display: block;
font-size: 0;
height: 0;
visibility: hidden;
}
#container .row:not(:last-child) {
margin-bottom: 9px;
}
#container input,
#container button {
float: left;
}
#container input:focus,
#container button:focus {
outline: none;
}
#container input {
background-color: #222;
border: 1px solid #999;
border-right-width: 0;
color: #999;
font-size: 22px;
font-weight: 300;
height: 80px;
padding-right: 14px;
text-align: right;
width: 261px;
}
#container button {
background-color: #222;
border: none;
box-shadow: 0 3px 0 #111;
color: #999;
font-size: 20px;
height: 80px;
margin-right: 7px;
width: 80px;
}
#container button:active {
box-shadow: 0 2px 0 #111;
transform: translateY(1px);
}
#container #clear,
#container .operator,
#container #equals {
color: #111;
}
#container #clear,
#container .operator {
margin-right: 0;
}
#container #clear {
background-color: #e95a4b;
border: 1px solid #999;
border-left-width: 0;
box-shadow: none;
cursor: pointer;
}
#container #clear:active {
box-shadow: none;
transform: none;
}
#container .operator {
background-color: #999;
box-shadow: 0 3px 0 #555;
}
#container .operator:active {
box-shadow: 0 2px 0 #555;
}
#container #equals {
background-color: #2ecc71;
box-shadow: 0 3px 0 #155d34;
}
#container #equals:active {
box-shadow: 0 2px 0 #155d34;
}
#media only screen and (max-width: 400px) {
header {
padding: 28px 0;
}
header h1 {
font-size: 36px;
}
main {
padding: 40px 0;
}
main #container {
padding: 16px;
}
#container .row:not(:last-child) {
margin-bottom: 7px;
}
#container input {
font-size: 18px;
height: 60px;
padding-right: 10px;
width: 195px;
}
#container button {
font-size: 16px;
height: 60px;
margin-right: 5px;
width: 60px;
}
}
<!DOCTYPE html>
<html lang="en">
<head>
<title>Calculator</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="https://fonts.googleapis.com/css?family=Roboto:300" rel="stylesheet">
<link href="Project 1.css" rel="stylesheet">
</head>
<body>
<header>
<h1>Calculator</h1>
</header>
<main>
<div id="container">
<div class="row clearfix">
<input id="screen" value="0" disabled type="text">
<button id="clear">AC</button>
</div>
<div class="row clearfix">
<button class="number">1</button>
<button class="number">2</button>
<button class="number">3</button>
<button data-operator="+" class="operator">+</button>
</div>
<div class="row clearfix">
<button class="number">4</button>
<button class="number">5</button>
<button class="number">6</button>
<button data-operator="-" class="operator">-</button>
</div>
<div class="row clearfix">
<button class="number">7</button>
<button class="number">8</button>
<button class="number">9</button>
<button data-operator="*" class="operator">×</button>
</div>
<div class="row clearfix">
<button id="decimal">.</button>
<button class="number">0</button>
<button id="equals">=</button>
<button data-operator="/" class="operator">÷</button>
</div>
</div>
</main>
<script src="Project 1.js"></script>
</body>
</html>
This is the code for the calc.. Feel free to edit it and explain to me what you did.
There is already one.
The Math.sqrt() function returns the square root of a number, that is, ∀x≥0,Math.sqrt(x)=x
=the uniquey≥0such thaty2=x
MDN Docs
You can use javascript built in
Math.sqrt(number)
Hello I'm stuck on how to add category for my to do list. When you click on Button of category need change class name. I don't understand how to correctly write if/else statement when button is clicked.
plan how it need to work
Write task name
Choose Category
Add new task
May be somebody can help me out ore give some advice how to solve this problem!
Sorry for my english and if my question is to badly explained!
var toDoList = function() {
var addNewTask = function() {
var input = document.getElementById("taks-input").value,
itemTexts = input,
colA = document.getElementById('task-col-a').children.length,
colB = document.getElementById('task-col-b').children.length,
taskBoks = document.createElement("div"),
work = document.getElementById("work"),
Category = "color-2",
taskCount = 1;
if (work.onclick === true) {
var Category = "color";
}
taskBoks.className = "min-box";
taskBoks.innerHTML = '<div class="col-3 chack" id="task_' + (taskCount++) + '"><i class="fa fa-star"></i></div><div class="col-8 task-text" id="taskContent"><p>' + itemTexts + '</p><span id="time-now"></span></div><div class="col-1 ' + (Category) + '"></div>'
if (colB < colA) {
var todolist = document.getElementById("task-col-b");
} else {
var todolist = document.getElementById("task-col-a");
}
//todolist.appendChild(taskBoks);
todolist.insertBefore(taskBoks, todolist.childNodes[0]);
},
addButton = function() {
var btn2 = document.getElementById("add-task-box");
btn2.onclick = addNewTask;
};
addButton()
}
toDoList();
p {
padding: 20px 20px 20px 45px;
}
.chack {
background-color: #4c4b62;
height: 100%;
width: 40px;
}
.task-text {
background-color: #55566e;
height: 100%;
width: 255px;
}
.color {
width: 5px;
height: 100%;
background-color: #fdcd63;
float: right;
}
.color-2 {
width: 5px;
height: 100%;
background-color: red;
float: right;
}
.color-3 {
width: 5px;
height: 100%;
background-color: purple;
float: right;
}
.task {
height: 100px;
width: 300px;
border: 1px solid #fff;
float: left;
}
.chack,
.task-text {
float: left;
}
.add-new-task {
margin-bottom: 50px;
height: 80px;
width: 588px;
background-color: rgb(85, 86, 110);
padding-top: 30px;
padding-left: 15px;
}
.min-box {
height: 100px;
border-bottom: 1px solid #fff;
}
.center {
padding-top: 20px;
padding-left: 50px;
}
.fa-star {
padding-left: 14px;
padding-top: 100%;
}
#add-task-box {
float: right;
margin-right: 10px;
margin-top: -7px;
border: none;
background-color: rgb(255, 198, 94);
padding: 10px;
}
#taks-input {
height: 30px;
width: 350px;
margin-top: -7px;
}
.category {
margin-top: 10px;
}
<div class="container">
<div class="add-new-task">
<input type="text" id="taks-input">
<button id="add-task-box">Add New Task box</button>
<div class="category">
<button class="catBtn" id="work">Work</button>
<button class="catBtn" id="home">Home</button>
<button class="catBtn" id="other">Other</button>
</div>
</div>
<div class="lg-task" id="bigTask"></div>
<div class="task" id="task-col-a"></div>
<div class="task" id="task-col-b"></div>
</div>
you need to bind click event to your buttons and store that value in Category, so in you js add this
var toDoList = function() {
// set to default
var Category = "color-3";
// attach event to buttons
var catButtons = document.getElementsByClassName("catBtn");
// assign value based on event
var myCatEventFunc = function() {
var attribute = this.getAttribute("id");
if (attribute === 'work') {
Category = 'color';
} else if (attribute === 'home') {
Category = 'color-2';
}
};
for (var i = 0; i < catButtons.length; i++) {
catButtons[i].addEventListener('click', myCatEventFunc, false);
}
Demo: Fiddle
and remove this code from addNewTask function
if (work.onclick === true) {
var Category = "color";
}
It is a bit hard to understand what you are doing, what you are going for (a module of some kind?). You were not that far away from a working state.
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<title>Task</title>
<style>
p {
padding: 20px 20px 20px 45px;
}
.chack {
background-color: #4c4b62;
height: 100%;
width: 40px;
}
.task-text {
background-color: #55566e;
height: 100%;
width: 255px;
}
.color {
width: 5px;
height: 100%;
background-color: #fdcd63;
float: right;
}
.color-2 {
width: 5px;
height: 100%;
background-color: red;
float: right;
}
.color-3 {
width: 5px;
height: 100%;
background-color: purple;
float: right;
}
.task {
height: 100px;
width: 300px;
border: 1px solid #fff;
float: left;
}
.chack,
.task-text {
float: left;
}
.add-new-task {
margin-bottom: 50px;
height: 80px;
width: 588px;
background-color: rgb(85, 86, 110);
padding-top: 30px;
padding-left: 15px;
}
.min-box {
height: 100px;
border-bottom: 1px solid #fff;
}
.center {
padding-top: 20px;
padding-left: 50px;
}
.fa-star {
padding-left: 14px;
padding-top: 100%;
}
#add-task-box {
float: right;
margin-right: 10px;
margin-top: -7px;
border: none;
background-color: rgb(255, 198, 94);
padding: 10px;
}
#taks-input {
height: 30px;
width: 350px;
margin-top: -7px;
}
.category {
margin-top: 10px;
}
</style>
<script>
var toDoList = function() {
var addNewTask = function() {
var input = document.getElementById("taks-input").value,
itemTexts = input,
colA = document.getElementById('task-col-a').children.length,
colB = document.getElementById('task-col-b').children.length,
taskBoks = document.createElement("div"),
work = document.getElementById("work"),
Category = "color-2",
taskCount = 1;
if (work.onclick === true) {
Category = "color";
}
taskBoks.className = "min-box";
taskBoks.innerHTML = '<div class="col-3 chack" id="task_'
+ (taskCount++) +
'"><i class="fa fa-star"></i></div><div class="col-8 task-text" id="taskContent"><p>'
+ itemTexts +
'</p><span id="time-now"></span></div><div class="col-1 '
+ (Category) + '"></div>'
if (colB < colA) {
var todolist = document.getElementById("task-col-b");
} else {
var todolist = document.getElementById("task-col-a");
}
//todolist.appendChild(taskBoks);
todolist.insertBefore(taskBoks, todolist.childNodes[0]);
},
// I don't know what to do with that?
addButton = function() {
var btn2 = document.getElementById("add-task-box");
btn2.onclick = addNewTask();
};
// return the stuff you want to have public
return {
addNewTask:addNewTask
};
}
var f;
// wait until all HTML is loaded and put the stuff from above into the variable `f`
// you can call it with f.someFunction() in your case f.addNewTask()
window.onload = function(){
f = toDoList();
}
</script>
</head>
<body>
<div class="container">
<div class="add-new-task">
<input type="text" id="taks-input">
<button id="add-task-box" onclick="f.addNewTask()">Add New Task box</button>
<div class="category">
<button class="catBtn" id="work" >Work</button>
<button class="catBtn" id="home">Home</button>
<button class="catBtn" id="other">Other</button>
</div>
</div>
<div class="lg-task" id="bigTask"></div>
<div class="task" id="task-col-a"></div>
<div class="task" id="task-col-b"></div>
</div>
</body>
</html
I hope you understood what I did?