I have a "piggy bank" project that saves and withdraws an amount of money passed through two different forms (Each modal is for one type of transaction), but when trying to withdraw, the values are empty as in the example:
{date: "", amount: "", type: "Retirada"}
When saving the values normally:
{date: "2021-02-27", amount: "1", type: "Depósito"}
I'm not able to find the error of not taking the values
Snipped Code:
const Modals = {
modalType: "",
openModals(type){
if(type == "Depósito") {
this.modalType = type;
document.querySelector('.modal1-overlay').classList.add('active')
} else {
document.querySelector('.modal2-overlay').classList.add('active')
this.modalType = type;
}
},
closeModals(type) {
if(type == "Depósito") {
document.querySelector('.modal1-overlay').classList.remove('active')
this.modalType = "";
} else {
document.querySelector('.modal2-overlay').classList.remove('active')
this.modalType = "";
}
},
openErrorModal(message) {
document.querySelector('.modalError-overlay').classList.add('active')
document.getElementById('errorMessage').innerHTML = message
},
closeErrorModal() {
document.querySelector('.modalError-overlay').classList.remove('active')
}
}
const Transaction = {
all: [],
add(transaction) {
Transaction.all.push(transaction)
App.reload()
},
totalBalance() {
let total = 0;
Transaction.all.forEach(transaction => {
if (transaction.type == "Retirada") {
total -= transaction.amount;
} else {
total += transaction.amount;
}
})
return total;
},
}
const DOM = {
transactionsContainer: document.querySelector('#data-table tbody'),
addTransaction(transaction, index) {
const tr = document.createElement('tr');
tr.innerHTML = this.innerHTMLTransaction(transaction);
this.transactionsContainer.appendChild(tr)
},
innerHTMLTransaction(transaction) {
const CSSclass = transaction.type === 'Retirada' ? "withdraw" : "income"
const amount = Utils.formatCurrency(transaction.amount, transaction.type)
const html = `
<tr>
<td class="${CSSclass}">${transaction.type}</td>
<td class="price-transaction">${amount}</td>
<td class="date">${transaction.date}</td>
<td></td>
</tr>
`;
return html;
},
updateBalance() {
document
.getElementById("totalCurrency")
.innerHTML = Utils.formatCurrency(Transaction.totalBalance())
},
clearTransactions() {
DOM.transactionsContainer.innerHTML = "";
}
}
const Utils = {
formatAmount(value) {
value = Number(value)*100
return value;
},
formatDate(date){
const splittedDate = date.split("-")
return `${splittedDate[2]}/${splittedDate[1]}/${splittedDate[0]}`
},
formatCurrency(value, type) {
if (type == "Retirada") {
value = String(value).replace(/\D/g, "");
value = Number(value) / 100
value = value.toLocaleString("pt-BR", {style: "currency", currency: "BRL"})
return "- " + value;
} else {
const signal = "";
value = String(value).replace(/\D/g, "");
value = Number(value) / 100
value = value.toLocaleString("pt-BR", {style: "currency", currency: "BRL"})
return value
}
}
}
const Form = {
amount: Modals.modalType == "Retirada" ? document.querySelector('input#amount2') : document.querySelector('input#amount'),
date: Modals.modalType == "Retirada" ? document.querySelector('input#date2') : document.querySelector('input#date'),
getValues() {
return {
date: this.date.value,
amount: this.amount.value,
type: Modals.modalType
}
},
validateField() {
const {date, amount, type} = Form.getValues()
if(date.trim() === "" || amount.trim() === "" || type.trim() === "") {
throw new Error("Por favor, preencha todos os campos!")
}
},
formatValues() {
let { date, amount, type} = Form.getValues()
amount = Utils.formatAmount(amount)
date = Utils.formatDate(date)
return {date, amount, type}
},
clearFieldsForm(){
Form.amount.value = "";
Form.date.value = "";
Modals.modalType = "";
},
submit(event) {
event.preventDefault()
try {
console.log(this.getValues())
// Form.validateField()
const transaction = Form.formatValues()
Transaction.add(transaction)
Modals.closeModals(Modals.modalType)
Form.clearFieldsForm();
} catch (error) {
Modals.openErrorModal(error.message)
}
}
}
const App = {
init() {
Transaction.all.forEach(transaction => {
DOM.addTransaction(transaction)
});
DOM.updateBalance()
},
reload() {
DOM.clearTransactions()
App.init()
}
}
App.init()
/* Global CSS */
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: 'Ubuntu', sans-serif;
}
:root {
--darkblue: #363f5f;
--green: rgb(0, 172, 0);
}
body {
background-color: rgb(241, 241, 241);
}
.sr-only {
position: absolute;
margin: 0;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0,0,0,0);
white-space: nowrap;
border-width: 0;
}
.container {
width: min(90vw, 800px);
margin: auto;
}
/* Header */
header {
background-color: green;
padding: 2rem 2rem 5rem 2rem;
text-align: center;
color: white;
}
/* Modal CSS */
.modal1-overlay {
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.7);
position: fixed;
top: 0;
display: flex;
align-items: center;
justify-content: center;
opacity: 0;
visibility: hidden;
}
.modal1-overlay.active {
opacity: 1;
visibility: visible;
}
.modal1 {
background:snow;
padding: 2.4rem;
position: relative;
display: flex;
flex-direction: column;
}
.modal2-overlay {
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.7);
position: fixed;
top: 0;
display: flex;
align-items: center;
justify-content: center;
opacity: 0;
visibility: hidden;
}
.modal2-overlay.active {
opacity: 1;
visibility: visible;
}
.modal2 {
background:snow;
border-radius: 2px;
padding: 2.4rem;
position: relative;
}
#form {
max-width: 500px;
}
#form h2 {
margin-top: 0;
}
.modalError-overlay {
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.7);
position: fixed;
top: 0;
display: flex;
align-items: center;
justify-content: center;
opacity: 0;
visibility: hidden;
}
.modalError-overlay.active {
opacity: 1;
transition: opacity .25s ease-in;
visibility: visible;
}
.modalErrorContainer {
background-color: white;
border-radius: 2px;
width: 70vh;
height: 16vh;
padding: 10px;
}
.modalErrorContainer h3 {
margin-bottom: 1.5rem;
}
input {
border: 1px solid rgba(0, 0, 0, 0.192);
border-radius: 0.2rem;
padding: 0.8rem;
width: 100%;
}
.input-group {
margin-top: 0.8rem;
}
.input-group small {
opacity: 0.4;
margin-left: 5px;
font-size: 10px;
}
.input-group.actions {
display: flex;
justify-content: space-between;
align-items: center;
}
.input-group.actions .button,
.input-group.actions button {
width: 48%;
margin: 0;
}
/* Main CSS */
#logo {
width: 40vh;
margin-left: -2vh;
}
#balance {
margin-top: -3rem;
color: white;
display: flex;
flex-wrap: wrap;
}
h2 {
font-weight: 400;
user-select: none;
padding-top: 10px;
padding-bottom: 6px;
}
h3 {
color: black;
}
.card {
display: flex;
flex-direction: column;
width: 100%;
background-color: white;
border-radius: 3px;
margin-right: 0;
padding: 5px 10px;
margin-bottom: 1.5rem;
box-shadow: 0px 1px 1px 0px rgba(59, 59, 59, 0.527);
}
.card h3 {
margin: 0;
margin-top: 5px;
font-size: 16px;
font-weight: 400;
user-select: none;
}
.card p {
margin-left: 1.5vw;
color: var(--darkblue);
margin-top: 0.5rem;
font-weight: 600;
font-size: 24px;
}
.card.total {
background: rgb(0, 190, 0);
margin-right: 0;
margin-left: 0;
}
.card.total p {
color: white;
}
.card.total h3 {
color: white;
}
.containerButtons {
display: flex;
justify-content: center;
}
.button {
text-decoration: none;
margin: 15px;
border: 1px solid;
padding: 1.5vh;
border-radius: 5px;
}
.button.save {
color: var(--green);
}
.button.withdraw {
color: red;
}
.button.ok {
color: white;
background-color: var(--green);
margin-left: 85%;
}
button {
width: 100%;
height: 50px;
background-color: var(--green);
color: white;
border: 0;
border-radius: 5px;
cursor: pointer;
font-weight: 400;
font-size: 16px;
}
button:hover {
box-shadow: 0px 0px 2px 1px green;
}
.button.cancel {
color: red;
height: 50px;
display: flex;
justify-content: center;
align-items: center;
font-weight: 400;
}
#data-table {
border-spacing: 0 0.5rem;
color: black;
}
#data-table th {
background: white;
color: #646464;
width: 50%;
font-weight: normal;
padding: 1rem 2rem;
user-select: none;
text-align: left;
}
#data-table tbody tr{
opacity: 0.7;
}
#data-table tbody tr:hover{
opacity: 1;
}
#data-table td {
background-color: white;
padding: 1rem 2rem;
}
td.price-transaction {
color: var(--darkblue);
}
td.withdraw {
color: red;
}
td.income {
color: green;
}
td.date {
color: var(--darkblue);
}
td.moneyatbank {
color: var(--darkblue);
}
/* Responsive */
#media screen and (min-width: 800px) {
#balance {
flex-wrap: nowrap;
}
.card {
margin-right: 2.5vh;
}
.card.total {
margin-left: 2.5vh;
}
}
#media screen and (max-width: 800px) {
#data-table {
display: block;
width: 100%;
border-spacing: 0 0.5rem;
color: black;
overflow: scroll;
}
}
<header>
<img src="assets/logo.svg" alt="Logo BiggyBank" id="logo">
</header>
<main class="container">
<section id="balance">
<h2 class="sr-only">Balanço</h2>
<div class="card">
<h3>Meta</h3>
<p>R$ 2000,00</p>
</div>
<div class="card total">
<h3>Total</h3>
<p id="totalCurrency"></p>
</div>
</section>
<section id="transaction">
<h2 class="sr-only">Transações</h2>
<div class="containerButtons">
+ Guardar
- Retirar
</div>
<table id="data-table">
<thead>
<tr>
<th>Tipo</th>
<th>Valor</th>
<th>Data</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
</section>
</main>
<footer>
<img src="assets/darkmode.svg" alt="Icone DarkMode">
<img src="assets/lightmode.svg" alt="Icone DarkMode">
</footer>
<div class="modal1-overlay">
<div class="modal1">
<div id="form">
<h2>Guardar Dinheiro</h2>
<form action="" onsubmit="Form.submit(event)" id="form1">
<div class="input-group">
<label class="sr-only" for="amount">Valor à ser guardado</label>
<input id="amount" name="amount" type="number" step="0.01" placeholder="Valor à ser guardado" />
<small class="helpText">Use a vírgula (,) para casas decimais</small>
</div>
<div class="input-group">
<label class="sr-only" for="date">Valor à ser guardado</label>
<input id="date" name="date" type="date" />
</div>
<div class="input-group actions">
Cancelar
<button>Guardar</button>
</div>
</form>
</div>
</div>
</div>
<div class="modal2-overlay">
<div class="modal2">
<div id="form">
<h2>Retirar Dinheiro</h2>
<form action="" onsubmit="Form.submit(event)" id="form2">
<div class="input-group">
<label class="sr-only" for="amount2">Valor à ser guardado</label>
<input id="amount2" name="amount2" type="number" step="0.01" placeholder="Valor à ser guardado" />
<small class="helpText">Use a vírgula (,) para casas decimais</small>
</div>
<div class="input-group">
<label class="sr-only" for="date2">Valor à ser guardado</label>
<input id="date2" name="date2" type="date" />
</div>
<div class="input-group actions">
Cancelar
<button>Retirar</button>
</div>
</form>
</div>
</div>
</div>
<div class="modalError-overlay">
<div class="modalErrorContainer">
<h3 id="errorMessage"></h3>
OK
</div>
</div>
Related
let myLibrary = [
{
id: 0,
title: "The Once and Future King",
author: "White",
pages: 654,
read: false,
},
{
id: 1,
title: "The Hobbit",
author: "Tolkien",
pages: 304,
read: false,
},
];
const bookContent = document.getElementById("content");
function displayBook(book) {
const addBook = document.createElement("div");
addBook.className = "book";
addBook.id = book.id;
bookContent.appendChild(addBook);
addBook.innerHTML = `
<div class="title">
<p class="bookTitle">
<span>${book.title}</span>
</p>
</div>
<div class="body">
<p>
Author: <span>${book.author}</span>
</p>
<p>
Pages: <span>${book.pages}</span>
</p>
</div>
<div class="read">
<label class="switch" data-book="0">
<input type="checkbox" />
<span class="slider round"></span>
</label>
</div>
<div class="delete">
<button class="delete-btn">DELETE</button>
</div>`;
}
// Display your original object list
myLibrary.forEach((book) => {
displayBook(book);
});
// Handle your object creation
const form = document.getElementById("form");
form.addEventListener("submit", updateLibrary);
function updateLibrary(event) {
// Need this so it doesn't refresh page
event.preventDefault();
const title = document.getElementById("title").value;
const author = document.getElementById("author").value;
const pages = document.getElementById("pages").value;
const book = {
title: title,
author: author,
pages: parseInt(pages),
read: false,
};
// Adds object to array
myLibrary.push(book);
// Displays new book
displayBook(book);
// Reset form
resetForm();
// Close form
document.getElementById("addBookForm").style.display = "none";
console.log(myLibrary);
}
// Resets the form so user can input another book
function resetForm() {
document.getElementById("form").reset();
}
// The form is automatically set to hidden. This loads it up for the user
const openForm = function () {
document.getElementById("addBookForm").style.display = "block";
document.getElementById("title").focus();
};
// Sets the form display back to none
const closeForm = () =>
(document.getElementById("addBookForm").style.display = "none");
/* .main {
} */
.header {
display: flex;
flex-direction: column;
background-color: #c689c6;
height: 150px;
border: 1px solid #3b133b;
}
.btn {
margin: 0 auto;
margin-top: 55px;
display: block;
text-align: center;
background-color: #4649ff;
padding: 0.75rem 1.25rem;
border-radius: 10rem;
color: #fff;
cursor: pointer;
font-size: 1rem;
letter-spacing: 0.15rem;
transition: all 0.3s;
}
.btn:hover {
background-color: #3134fa;
}
.content {
display: flex;
flex-flow: row wrap;
align-content: flex-start;
justify-content: flex-start;
background-color: #fffdfa;
height: auto;
}
.book {
border: 2px solid #ffa94d;
background-color: #ffd8a8;
color: #d9480f;
width: 280px;
height: 365px;
margin: 10px;
}
.title {
border-bottom: 2px solid #ffa94d;
}
.title p {
display: flex;
align-items: center;
text-align: center;
justify-content: center;
font-size: larger;
}
.title span {
color: #3c4048;
}
.body {
border: 1px solid transparent;
height: 200px;
background-color: #fff4e6;
}
.body p {
padding-left: 20px;
}
p span {
color: #3c4048;
}
.read {
display: flex;
align-items: center;
justify-content: center;
height: 50px;
border-top: 2px solid #ffa94d;
text-align: center;
}
/* The switch - the box around the slider */
.switch {
position: relative;
display: inline-block;
width: 60px;
height: 34px;
}
/* Hide default HTML checkbox */
.switch input {
opacity: 0;
width: 0;
height: 0;
}
/* The slider */
.slider {
position: absolute;
cursor: pointer;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: #ccc;
-webkit-transition: 0.4s;
transition: 0.4s;
}
.slider:before {
position: absolute;
content: "";
height: 26px;
width: 26px;
left: 4px;
bottom: 4px;
background-color: white;
-webkit-transition: 0.4s;
transition: 0.4s;
}
input:checked + .slider {
background-color: #3d8361;
}
input:focus + .slider {
box-shadow: 0 0 1px #3d8361;
}
input:checked + .slider:before {
-webkit-transform: translateX(26px);
-ms-transform: translateX(26px);
transform: translateX(26px);
}
/* Rounded sliders */
.slider.round {
border-radius: 34px;
}
.slider.round:before {
border-radius: 50%;
}
.delete {
height: 50px;
border-top: 2px solid #ffa94d;
}
.delete-btn {
margin: 0 auto;
margin-top: 8px;
display: block;
text-align: center;
background-color: #e94560;
padding: 0.5rem 0.75rem;
border-radius: 10rem;
color: #fff;
cursor: pointer;
letter-spacing: 0.15rem;
transition: all 0.3s;
}
.delete-btn:hover {
background-color: #e7082d;
}
.close-btn {
color: #e7082d;
font-size: large;
background-color: #c689c6;
border: none;
float: right;
cursor: pointer;
}
/* THE FORM */
.form-content {
display: flex;
justify-content: center;
}
.form {
display: none;
position: fixed;
margin-top: 5px;
border: 2px solid #3b133b;
animation: openForm 0.5s;
z-index: 1;
}
#keyframes openForm {
from {
transform: scale(0);
}
to {
transform: scale(1);
}
}
.form h1 {
text-align: center;
}
.form-container {
background-color: #c689c6;
border: 2px solid black;
max-width: 300px;
padding: 10px;
}
.form-container h1 {
padding-left: 20px;
}
.form-container input[type="text"],
.form-container input[type="number"] {
width: 80%;
padding: 15px;
margin: 5px 0 22px 0;
border: none;
}
.form-container input[type="text"]:focus,
.form-container input[type="number"]:focus {
outline: none;
}
<!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.css" />
<title>Library</title>
</head>
<body>
<div class="main">
<div class="header">
<button class="btn" id="btn" onclick="openForm()">Add a Book</button>
</div>
<div class="form-content">
<div class="form" id="addBookForm">
<form id="form" action="" class="form-container">
<button type="button" class="close-btn" onclick="closeForm()">
x
</button>
<h1>Add a Book</h1>
<label for="title">Title</label>
<input
type="text"
placeholder="Title"
name="title"
id="title"
required
/>
<label for="author">Author</label>
<input
type="text"
placeholder="Author"
name="author"
id="author"
required
/>
<label for="pages">Pages</label>
<input
type="number"
placeholder="Pages"
name="pages"
required
id="pages"
/>
<button type="submit" id="submit-btn">Submit</button>
</form>
</div>
</div>
<div id="content" class="content"></div>
</div>
</body>
</html>
I have a form where the user inputs information from a book they are reading and upon hitting submit, the information is sent as its own object inside an array. I also have a forEach method running which loops through the array and displays each object as a div on the web page.
let myLibrary = [];
const book = {
title: title,
author: author,
pages: parseInt(pages),
read: false,
};
myLibrary.push(book)
As you can see from the code above, the three properties that the user fills out are the books title, author and page count. There's also a property that is automatically added called the read property and it is automatically set as false.
The Problem
My problem is this. I have the following code displayed at the bottom of each div.
<div class="read">
<label class="switch">
<input type="checkbox" />
<span class="slider round"></span>
</label>
</div>
This code is very simple. It's a toggle switch which I found here.
I want it so when the toggle switch is grayed out, the read status is set to false. But when the toggle switch is turned on, the read property is set to true. I am having a very difficult time figuring out how to get this done.
What I've Tried
I was able to use an onclick to select the toggle switch's parent element, and I tested it using console.log however I am unsure of where to go from there. I attempted to update the book.read to true using the ternary operator but it was out of scope and resulted in an error.
document.querySelector(".main").onclick = (ev) => {
let el = ev.target.classList.contains("switch")
? ev.target.parentElement
: ev.target.classList.contains("slider")
? ev.target
: false;
if (el) {
let toggle = el.parentElement.parentElement.parentElement;
let index = [...toggle.parentElement.children].indexOf(toggle);
myLibrary[index].read = false ? false : true;
console.log(myLibrary[index].read);
}
console.log(myLibrary);
};
Change this
function displayBook(book) {
...
<label class="switch" data-book="0">
to
function displayBook(book,bookIndex) {
...
<label class="switch" data-book="${bookIndex}">
and
myLibrary.forEach((book) => {
displayBook(book);
});
to
myLibrary.forEach((book,i) => {
displayBook(book,i);
});
lastly change
// Displays new book
displayBook(book);
to
// Displays new book
displayBook(book,myLibrary.length-1);
Here is the code inclusive a delete function
It would be slightly simpler if we had an associate array on book_id
Note I removed the numeric ID because it is not needed since the index of the array is the same
let myLibrary = [{
title: "The Once and Future King",
author: "White",
pages: 654,
read: false,
},
{
title: "The Hobbit",
author: "Tolkien",
pages: 304,
read: false,
},
];
const bookContent = document.getElementById("content");
const formDiv = document.getElementById("addBookForm");
function displayBook(book, idx) {
const addBook = document.createElement("div");
addBook.className = "book";
addBook.id = `book_${idx}`;
bookContent.appendChild(addBook);
addBook.innerHTML = `
<div class="title">
<p class="bookTitle">
<span>${book.title}</span>
</p>
</div>
<div class="body">
<p>
Author: <span>${book.author}</span>
</p>
<p>
Pages: <span>${book.pages}</span>
</p>
</div>
<div class="read">
<label class="switch" data-book="${idx}">
<input type="checkbox" />
<span class="slider round"></span>
</label>
</div>
<div class="delete">
<button class="delete-btn">DELETE</button>
</div>`;
}
// Display your original object list
myLibrary.forEach((book, i) => {
displayBook(book, i);
});
const deleteBook = (e) => {
const parent = e.target.closest("div.book");
const idx = parent.querySelector(".switch").dataset.book;
parent.remove();
console.log(idx);
myLibrary.splice(idx, 1);
console.log(myLibrary);
content.querySelectorAll("div.book").forEach((book, i) => { // reset the hard way
book.id = `book_${i}`;
book.querySelector("label.switch").dataset.book = i;
})
};
content.addEventListener("click", function(e) {
const tgt = e.target;
if (!tgt.matches(".delete-btn")) return; // not the delete
deleteBook(e); // pass the event to the delete
})
// Handle your object creation
const form = document.getElementById("form");
form.addEventListener("submit", updateLibrary);
function updateLibrary(event) {
// Need this so it doesn't refresh page
event.preventDefault();
const title = document.getElementById("title").value;
const author = document.getElementById("author").value;
const pages = document.getElementById("pages").value;
const book = {
title: title,
author: author,
pages: parseInt(pages),
read: false,
};
// Adds object to array
myLibrary.push(book);
// Displays new book
displayBook(book);
// Reset form
resetForm();
// Close form
formDiv.style.display = "none";
console.log(myLibrary);
}
// Resets the form so user can input another book
function resetForm() {
document.getElementById("form").reset();
}
// The form is automatically set to hidden. This loads it up for the user
const openForm = function() {
formDiv.style.display = "block";
document.getElementById("title").focus();
};
// Sets the form display back to none
const closeForm = () => formDiv.style.display = "none";
/* .main {
} */
.header {
display: flex;
flex-direction: column;
background-color: #c689c6;
height: 150px;
border: 1px solid #3b133b;
}
.btn {
margin: 0 auto;
margin-top: 55px;
display: block;
text-align: center;
background-color: #4649ff;
padding: 0.75rem 1.25rem;
border-radius: 10rem;
color: #fff;
cursor: pointer;
font-size: 1rem;
letter-spacing: 0.15rem;
transition: all 0.3s;
}
.btn:hover {
background-color: #3134fa;
}
.content {
display: flex;
flex-flow: row wrap;
align-content: flex-start;
justify-content: flex-start;
background-color: #fffdfa;
height: auto;
}
.book {
border: 2px solid #ffa94d;
background-color: #ffd8a8;
color: #d9480f;
width: 280px;
height: 365px;
margin: 10px;
}
.title {
border-bottom: 2px solid #ffa94d;
}
.title p {
display: flex;
align-items: center;
text-align: center;
justify-content: center;
font-size: larger;
}
.title span {
color: #3c4048;
}
.body {
border: 1px solid transparent;
height: 200px;
background-color: #fff4e6;
}
.body p {
padding-left: 20px;
}
p span {
color: #3c4048;
}
.read {
display: flex;
align-items: center;
justify-content: center;
height: 50px;
border-top: 2px solid #ffa94d;
text-align: center;
}
/* The switch - the box around the slider */
.switch {
position: relative;
display: inline-block;
width: 60px;
height: 34px;
}
/* Hide default HTML checkbox */
.switch input {
opacity: 0;
width: 0;
height: 0;
}
/* The slider */
.slider {
position: absolute;
cursor: pointer;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: #ccc;
-webkit-transition: 0.4s;
transition: 0.4s;
}
.slider:before {
position: absolute;
content: "";
height: 26px;
width: 26px;
left: 4px;
bottom: 4px;
background-color: white;
-webkit-transition: 0.4s;
transition: 0.4s;
}
input:checked+.slider {
background-color: #3d8361;
}
input:focus+.slider {
box-shadow: 0 0 1px #3d8361;
}
input:checked+.slider:before {
-webkit-transform: translateX(26px);
-ms-transform: translateX(26px);
transform: translateX(26px);
}
/* Rounded sliders */
.slider.round {
border-radius: 34px;
}
.slider.round:before {
border-radius: 50%;
}
.delete {
height: 50px;
border-top: 2px solid #ffa94d;
}
.delete-btn {
margin: 0 auto;
margin-top: 8px;
display: block;
text-align: center;
background-color: #e94560;
padding: 0.5rem 0.75rem;
border-radius: 10rem;
color: #fff;
cursor: pointer;
letter-spacing: 0.15rem;
transition: all 0.3s;
}
.delete-btn:hover {
background-color: #e7082d;
}
.close-btn {
color: #e7082d;
font-size: large;
background-color: #c689c6;
border: none;
float: right;
cursor: pointer;
}
/* THE FORM */
.form-content {
display: flex;
justify-content: center;
}
.form {
display: none;
position: fixed;
margin-top: 5px;
border: 2px solid #3b133b;
animation: openForm 0.5s;
z-index: 1;
}
#keyframes openForm {
from {
transform: scale(0);
}
to {
transform: scale(1);
}
}
.form h1 {
text-align: center;
}
.form-container {
background-color: #c689c6;
border: 2px solid black;
max-width: 300px;
padding: 10px;
}
.form-container h1 {
padding-left: 20px;
}
.form-container input[type="text"],
.form-container input[type="number"] {
width: 80%;
padding: 15px;
margin: 5px 0 22px 0;
border: none;
}
.form-container input[type="text"]:focus,
.form-container input[type="number"]:focus {
outline: none;
}
<div class="main">
<div class="header">
<button class="btn" id="btn" onclick="openForm()">Add a Book</button>
</div>
<div class="form-content">
<div class="form" id="addBookForm">
<form id="form" action="" class="form-container">
<button type="button" class="close-btn" onclick="closeForm()">
x
</button>
<h1>Add a Book</h1>
<label for="title">Title</label>
<input type="text" placeholder="Title" name="title" id="title" required />
<label for="author">Author</label>
<input type="text" placeholder="Author" name="author" id="author" required />
<label for="pages">Pages</label>
<input type="number" placeholder="Pages" name="pages" required id="pages" />
<button type="submit" id="submit-btn">Submit</button>
</form>
</div>
</div>
<div id="content" class="content"></div>
</div>
I am writing some javascript code called account register. The requirement is showing information inputted on the screen when clicked the register button, and each row can be deleted by clicking the delete button on the left.
My problem is when the first time I click the register button, information not showing up. The second time is fine. From the third time, extra rows start added. For me it seems the 'if else' statement is looping over inside the function.
What is the reason of that?
Execute result
var counterVal = 0;
document.getElementById("tuikaBtn").onclick = function() {
const addButton = document.getElementById('tuikaBtn');
const listContainer = document.getElementById('result');
const name = document.getElementById('namae');
const nick = document.getElementById('nickname');
const rmvButton = document.getElementById('rmv');
console.log('counter = ' + counterVal);
if (name.value == "" | nick.value == "") {
window.alert("Please input both name and nickname.");
} else if (counterVal == 3) {
document.getElementById("tuikaBtn").style.display = 'none';
} else {
//funtion to get parent item
const handleRemove = function(e) {
const item = e.target.closest('.item');
//remove the listener, to avoid memory leaks.
item.querySelector('.remove-btn').removeEventListener('click', handleRemove);
item.parentElement.removeChild(item);
};
//adds text and button to list once clicked the button
addButton.addEventListener('click', e => {
const item = document.createElement('div');
const paragraph = document.createElement('div');
const remove = document.createElement('button');
item.classList.add('item');
paragraph.classList.add('paragraph-style');
remove.classList.add('remove-btn');
paragraph.textContent = name.value + ' ' + nick.value;
remove.textContent = 'Remove';
item.append(paragraph);
item.append(remove);
listContainer.append(item);
name.value = '';
nick.value = '';
remove.addEventListener('click', handleRemove);
})
return counterVal += 1;
}
}
.base {
margin: 2% 7% 0;
height: 500px;
background: blue;
padding: 5% 10%;
box-shadow: 5px 9px 8px 5px rgba(0, 0, 0, 0.5);
}
input {
width: 300px;
height: 40px;
font-size: large;
}
#tuikaBtn {
background: green;
}
h1 {
font-family: serif;
}
.form-control::placeholder {
color: #cacaca;
opacity: 1;
}
table {
border-collapse: collapse;
}
th,
td {
border: 1px solid #312929;
padding: 5px 10px;
}
.card {
width: 100%;
height: 350px;
}
.back {
padding: 30px;
position: absolute;
bottom: 0;
right: 0;
}
.form-group {
margin: 10px 0 15px 0px;
}
#result {
font-size: 120%;
margin: 10;
margin: 10px 20px;
padding: 10px 5px 20px;
margin: 10px 5px 10px 5px;
}
.row .card {
color: black;
}
.card {
color: blue;
display: block;
position: relative;
}
#modal {
display: none;
margin: 1.5em auto 0;
background-color: white;
border: 1px solid black;
width: 50%;
padding: 10px 20px;
position: fixed;
border-radius: 5px;
}
#overLay {
display: none;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 120%;
background-color: rgba(0, 0, 0, 0.75);
}
.items {
display: flex;
}
.item {
display: grid;
grid-auto-flow: column;
grid-template-columns: 1fr 6em;
grid-column-gap: 1em;
margin-bottom: 0.667em;
align-items: center;
}
.paragraph-style {
font-style: italic;
}
<div class="base container">
<div class="row">
<h1>Account Register</h1>
</div>
<div class="row">
<div class="card" id="card">
<div class="card-block">
<form id="form-area" class="form-inline" method="post">
<div class="form-group">
<div class="input-group">
<input id="namae" name="namae" type="text" class="form-control" placeholder="Full Name">
</div>
</div>
<div class="form-group">
<div class="input-group">
<input id="nickname" name="nickname" type="text" class="form-control" placeholder="Nick Name">
</div>
</div>
<div class="form-group">
<input id="tuikaBtn" type="button" name="touroku" value="Add">
</div>
</form>
<div id="tuikaMoto">User Information</div>
<div id="result"></div>
</div>
</div>
</div>
</div>
<div id="overLay"></div>
Only one tuikaBtn.onclick is needed. Also no need of counter
document.getElementById("tuikaBtn").onclick = function() {
const listContainer = document.getElementById('result');
const name = document.getElementById('namae');
const nick = document.getElementById('nickname');
const rmvButton = document.getElementById('rmv');
if (name.value == "" || nick.value == "") {
window.alert("Please input both name and nickname.");
}
else {
//funtion to get parent item
const handleRemove = function(e) {
const item = e.target.closest('.item');
//remove the listener, to avoid memory leaks.
item.querySelector('.remove-btn').removeEventListener('click', handleRemove);
item.parentElement.removeChild(item);
document.getElementById("tuikaBtn").style.display = '';
};
//adds text and button to list once clicked the button
////// addButton.addEventListener('click', e => { /// // /no need of this
const item = document.createElement('div');
const paragraph = document.createElement('div');
const remove = document.createElement('button');
item.classList.add('item');
paragraph.classList.add('paragraph-style');
remove.classList.add('remove-btn');
paragraph.textContent = name.value + ' ' + nick.value;
remove.textContent = 'Remove';
item.append(paragraph);
item.append(remove);
listContainer.append(item);
name.value = '';
nick.value = '';
remove.addEventListener('click', handleRemove);
if(listContainer.querySelectorAll('.item').length>=3)
{
document.getElementById("tuikaBtn").style.display = 'none';
}else{
document.getElementById("tuikaBtn").style.display = '';
}
////// })
}
}
.base {
margin: 2% 7% 0;
height: 500px;
background: blue;
padding: 5% 10%;
box-shadow: 5px 9px 8px 5px rgba(0, 0, 0, 0.5);
}
input {
width: 300px;
height: 40px;
font-size: large;
}
#tuikaBtn {
background: green;
}
h1 {
font-family: serif;
}
.form-control::placeholder {
color: #cacaca;
opacity: 1;
}
table {
border-collapse: collapse;
}
th,
td {
border: 1px solid #312929;
padding: 5px 10px;
}
.card {
width: 100%;
height: 350px;
}
.back {
padding: 30px;
position: absolute;
bottom: 0;
right: 0;
}
.form-group {
margin: 10px 0 15px 0px;
}
#result {
font-size: 120%;
margin: 10;
margin: 10px 20px;
padding: 10px 5px 20px;
margin: 10px 5px 10px 5px;
}
.row .card {
color: black;
}
.card {
color: blue;
display: block;
position: relative;
}
#modal {
display: none;
margin: 1.5em auto 0;
background-color: white;
border: 1px solid black;
width: 50%;
padding: 10px 20px;
position: fixed;
border-radius: 5px;
}
#overLay {
display: none;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 120%;
background-color: rgba(0, 0, 0, 0.75);
}
.items {
display: flex;
}
.item {
display: grid;
grid-auto-flow: column;
grid-template-columns: 1fr 6em;
grid-column-gap: 1em;
margin-bottom: 0.667em;
align-items: center;
}
.paragraph-style {
font-style: italic;
}
<div class="base container">
<div class="row">
<h1>Account Register</h1>
</div>
<div class="row">
<div class="card" id="card">
<div class="card-block">
<form id="form-area" class="form-inline" method="post">
<div class="form-group">
<div class="input-group">
<input id="namae" name="namae" type="text" class="form-control" placeholder="Full Name">
</div>
</div>
<div class="form-group">
<div class="input-group">
<input id="nickname" name="nickname" type="text" class="form-control" placeholder="Nick Name">
</div>
</div>
<div class="form-group">
<input id="tuikaBtn" type="button" name="touroku" value="Add">
</div>
</form>
<div id="tuikaMoto">User Information</div>
<div id="result"></div>
</div>
</div>
</div>
</div>
<div id="overLay"></div>
While building a basic application, when I click a button, the text inside my currently focused input overflows only in Chrome. However, that text can be accessed using (right) arrow key(s). Is there any way to avoid this? I tried clipboard copy-paste but that did not work.
const peopleElem = document.querySelector("#people");
const billElem = document.querySelector("#bill");
const submit = document.querySelector("[type=\"submit\"]");
const form = document.querySelector("form");
const tipPerPersonElem = document.querySelector("[data-tip-person]");
const totalPerPersonElem = document.querySelector("[data-total-person]");
let billError = peopleError = false;
class TipCalc {
constructor() {
this.tipPerPerson = 0;
this.totalPerPerson = 0;
this.tip = 0
this.tipPercent = 0;
this.bill = parseFloat(billElem.value);
this.people = parseFloat(peopleElem.value);
}
getTip() {
const element = document.querySelector(".active");
if (!element) return 0;
if (element.tagName === "BUTTON") return this.tipPercent = element.innerText.replace("%", "");
return this.tipPercent = element.value.replace("%", "");
}
getTipPerPerson() {
this.getTip();
this.tip = ((this.tipPercent / 100) * this.bill);
this.tipPerPerson = this.tip / this.people;
return this.tipPerPerson;
}
getTotalPerPerson() {
this.getTipPerPerson();
this.totalPerPerson = (this.bill + this.tip) / this.people
return this.totalPerPerson;
}
}
const tipOptions = [...document.querySelectorAll("button"), document.querySelector("#custom")];
tipOptions.forEach(option => {
if (option.tagName === "INPUT" && option.value.length) option.addEventListener("keyup", () => {
tipOptions.forEach(option => option.classList.remove("active"));
option.classList.toggle("active");
})
if (!(option.type == "submit")) option.addEventListener("click", () => {
tipOptions.forEach(option => option.classList.remove("active"));
option.classList.toggle("active");
})
})
form.addEventListener("submit", event => {
event.preventDefault();
checkInputForError(peopleElem, peopleError, true);
checkInputForError(billElem, billError, false);
if (billError || peopleError) return;
const tipCalculator = new TipCalc();
const tip = isNaN(tipCalculator.getTipPerPerson()) ? 0 : tipCalculator.getTipPerPerson();
const total = isNaN(tipCalculator.getTotalPerPerson()) ? 0 : tipCalculator.getTotalPerPerson();
const formatter = new Intl.NumberFormat(undefined, {
style: "currency",
currency: "USD",
signDisplay: "never"
});
tipPerPersonElem.innerText = formatter.format(tip);
totalPerPersonElem.innerText = formatter.format(total);
submit.style.display = "none";
const resetBtn = document.querySelector("[type=\"reset\"]");
resetBtn.style.display = "block";
resetBtn.addEventListener("click", () => {
reset()
resetBtn.style.display = "none";
submit.style.display = "block";
})
})
document.addEventListener("DOMContentLoaded", () => {
reset()
})
peopleElem.addEventListener("keyup", () => checkInputForError(peopleElem, peopleError, true));
billElem.addEventListener("keyup", () => checkInputForError(billElem, billError, false));
function checkInputForError(input, error, showError) {
const value = input.value.trim() || 0;
if (!value || isNaN(parseFloat(value)) || parseFloat(value) == 0) {
if (showError) document.querySelector(".warning").style.display = "inline";
input.classList.add("error");
error = true;
} else {
if (showError) document.querySelector(".warning").style.display = "none";
input.classList.remove("error");
input.classList.add("correct");
error = false;
}
}
function reset(submit = false) {
const tipPerPersonElem = document.querySelector("[data-tip-person]");
const totalPerPersonElem = document.querySelector("[data-total-person]");
tipPerPersonElem.innerText = "";
totalPerPersonElem.innerText = "";
console.log(tipPerPersonElem.innerText, totalPerPersonElem.innerText, "reset", submit);
tipOptions.forEach(option => option.classList.remove("active"));
document.querySelectorAll("input").forEach(input => {
input.classList.remove("correct");
input.classList.remove("error");
input.value = "";
})
}
:root {
--primary-color: hsl(172, 67%, 45%);
--very-dark-cyan: hsl(183, 100%, 15%);
--dark-grayish-cyan: hsl(186, 14%, 43%);
--grayish-cyan: hsl(184, 14%, 56%);
--light-grayish-cyan: hsl(185, 41%, 84%);
--very-light-grayish-cyan: hsl(189, 41%, 97%);
--white: hsl(0, 0%, 100%);
--primary-font-size: 24px;
--primary-font-family: 'Space Mono', monospace;
}
/* GLOABAL TAGS */
body {
width: 100%;
margin: 0;
overflow: hidden;
font-family: var(--primary-font-family);
background-color: var(--light-grayish-cyan);
}
header {
text-align: center;
}
h1 {
color: var(--very-dark-cyan);
margin-top: 0;
text-transform: uppercase;
}
h1 span {
display: block;
margin: 0;
}
label {
display: block;
text-transform: capitalize;
}
button {
outline: none;
border: none;
text-align: center;
background-color: var(--very-dark-cyan);
font-size: var(--primary-font-size);
color: var(--white);
text-transform: capitalize;
margin: 8px;
padding-top: 8px;
padding-bottom: 8px;
border-radius: 4px;
cursor: pointer;
}
legend {
margin-bottom: 8px;
}
/* Chrome,
Safari,
Edge, */
/* Opera */
input::-webkit-outer-spin-button,
input::-webkit-inner-spin-button {
-webkit-appearance: none;
margin: 0;
}
/* Firefox */
input[type=number] {
-moz-appearance: textfield;
}
input {
display: block;
border: none;
background-color: var(--very-light-grayish-cyan);
font-size: var(--primary-font-size);
height: 30px;
color: var(--very-dark-cyan);
background-repeat: no-repeat;
background-position: left center;
}
input:not(#custom) {
text-indent: 99.8%;
}
aside {
font-size: 11px;
text-align: center;
}
aside a {
color: hsl(228, 45%, 44%);
}
/* END OF GLOBAL TAGS GENERIC IDs */
#bill {
background-image: url('https://kaustubhmaladkar.github.io/Tip-Calculator/images/icon-dollar.svg');
}
#people {
background-image: url('https://kaustubhmaladkar.github.io/Tip-Calculator/images/icon-person.svg');
}
/* END OF GENERIC IDs GENERIC CLASSES*/
button,
#custom {
width: calc(50% - 20px);
font-weight: bold;
}
/* END OF GENERIC CLASSES */
/* INPUT */
.input {
background-color: var(--white);
color: var(--dark-grayish-cyan);
border-top-right-radius: 20px;
border-top-left-radius: 20px;
margin-top: 20px;
padding-bottom: 30px;
}
.input legend {
margin-top: 20px;
margin-left: 20px;
}
legend:nth-of-type(2) label {
width: 100%;
}
legend:nth-of-type(2) {
display: flex;
flex-wrap: wrap;
}
[for="people"] {
display: inline;
}
.warning {
display: none;
/* margin-left: 92px; */
color: red;
font-size: 12px;
background-color: transparent;
}
input#custom {
background-color: var(--white);
color: var(--dark-grayish-cyan);
margin-top: 12px;
margin-left: 2px;
padding-bottom: 8px;
opacity: 1;
}
input#custom::placeholder {
text-transform: capitalize;
color: var(--dark-grayish-cyan);
opacity: 1;
}
/* END OF INPUT */
/*OUTPUT*/
.output {
background-color: var(--very-dark-cyan);
display: flex;
margin-top: -8px;
justify-content: center;
align-items: center;
flex-direction: column;
border-radius: 10px;
}
.output div,
.output span {
width: 100%;
}
.output>div>div {
display: flex;
gap: 15px;
}
.output>div>div:first-of-type {
margin-top: 30px;
margin-bottom: 15px;
}
.output>div>div:last-of-type {
margin-top: 15px;
margin-bottom: 30px;
}
[type="submit"],
[type="reset"] {
font-family: var(--primary-font-family);
background-color: var(--primary-color);
width: 90%;
text-align: center;
color: var(--very-dark-cyan);
}
.tip-person,
.total-person {
font-size: 35px;
color: var(--primary-color);
}
.output>div>div>div>span:first-of-type {
text-transform: capitalize;
color: var(--white);
display: block;
}
.output>div>div>div>span:last-of-type {
color: var(--grayish-cyan);
}
/*END OF OUTPUT */
.active:not(input) {
background-color: var(--primary-color);
color: var(--very-dark-cyan);
transition: background 0.7s ease-in-out;
}
.correct {
border: lightgreen 2px solid;
}
.error {
border: red 2px solid;
}
.correct:focus,
.error:focus {
outline: none;
}
/* JAVASCRIPT CLASSES */
/* END OF JAVASCRIPT CLASSES */
/* FOR DESKTOP */
#media (min-width: 1200px) {
/* RESET */
html,
body,
main {
margin: 0;
}
/* END OF RESET */
/* GENERIC TAGS */
form {
width: 100%;
max-width: 900px;
border-radius: 15px;
overflow: hidden;
margin: auto;
padding-right: 15px;
display: flex;
width: fit-content;
background-color: var(--white);
}
input {
width: 90%;
}
aside {
display: none;
}
/* END OF GENERIC TAGS */
/* GENERIC CLASSES */
.output,
.input {
height: 400px;
}
.warning {
margin-left: 92px;
}
/* END OF GENERIC CLASSES */
/* INPUT */
.input button,
.input input#custom {
width: calc(100% / 3 - 20px);
}
.input {
width: 50%;
padding-bottom: 0;
}
.input legend {
margin-left: 25px;
}
/* END OF INPUT */
/* OUTPUT */
.output {
width: 50%;
margin: 22px;
padding: 0;
display: flex;
flex-direction: column;
justify-content: space-around;
}
.output div {
margin-left: 20px;
}
.output>div>div:first-of-type {
margin-top: -20px;
margin-bottom: 40px;
}
[type="reset"] {
display: none;
}
/* END OF OUTPUT */
}
<h1>
<span>spli</span>
<span>tter</span>
</h1>
<form action="post">
<div class="input">
<legend>
<label for="bill">bill</label>
<input type="number" name="bill" id="bill" class="correct">
</legend>
<legend>
<label for="custom">select tip %</label>
<button type="button">5%</button>
<button type="button" class="">10%</button>
<button type="button">15%</button>
<button type="button">25%</button>
<button type="button">50%</button>
<input placeholder="custom" name="custom" id="custom" class="">
</legend>
<legend>
<label for="people">Number of People</label>
<p class="warning" style="display: inline;">Can't be zero</p>
<input type="number" name="people" id="people" class="">
</legend>
</div>
<div class="output">
<div>
<div>
<div>
<span>tip amount</span>
<span>/ person</span>
</div>
<span class="tip-person" data-tip-person=""></span>
</div>
<div>
<div>
<span>Total</span>
<span>/ person</span>
</div>
<span class="total-person" data-total-person=""></span>
</div>
</div>
<button type="submit" style="display: block;">Calculate</button>
<button type="reset" class="" style="display: none;">Reset</button>
</div>
</form>
Live site: https://kaustubhmaladkar.github.io/Tip-Calculator/
Code on Github: https://github.com/KaustubhMaladkar/Tip-Calculator/
The problem comes from this line:
input:not(#custom) {
text-indent: 99.8%;
}
If you only want a alignment to the right, change it to:
input:not(#custom) {
text-align: right;
}
Working example:
const peopleElem = document.querySelector("#people");
const billElem = document.querySelector("#bill");
const submit = document.querySelector("[type=\"submit\"]");
const form = document.querySelector("form");
const tipPerPersonElem = document.querySelector("[data-tip-person]");
const totalPerPersonElem = document.querySelector("[data-total-person]");
let billError = peopleError = false;
class TipCalc {
constructor() {
this.tipPerPerson = 0;
this.totalPerPerson = 0;
this.tip = 0
this.tipPercent = 0;
this.bill = parseFloat(billElem.value);
this.people = parseFloat(peopleElem.value);
}
getTip() {
const element = document.querySelector(".active");
if (!element) return 0;
if (element.tagName === "BUTTON") return this.tipPercent = element.innerText.replace("%", "");
return this.tipPercent = element.value.replace("%", "");
}
getTipPerPerson() {
this.getTip();
this.tip = ((this.tipPercent / 100) * this.bill);
this.tipPerPerson = this.tip / this.people;
return this.tipPerPerson;
}
getTotalPerPerson() {
this.getTipPerPerson();
this.totalPerPerson = (this.bill + this.tip) / this.people
return this.totalPerPerson;
}
}
const tipOptions = [...document.querySelectorAll("button"), document.querySelector("#custom")];
tipOptions.forEach(option => {
if (option.tagName === "INPUT" && option.value.length) option.addEventListener("keyup", () => {
tipOptions.forEach(option => option.classList.remove("active"));
option.classList.toggle("active");
})
if (!(option.type == "submit")) option.addEventListener("click", () => {
tipOptions.forEach(option => option.classList.remove("active"));
option.classList.toggle("active");
})
})
form.addEventListener("submit", event => {
event.preventDefault();
checkInputForError(peopleElem, peopleError, true);
checkInputForError(billElem, billError, false);
if (billError || peopleError) return;
const tipCalculator = new TipCalc();
const tip = isNaN(tipCalculator.getTipPerPerson()) ? 0 : tipCalculator.getTipPerPerson();
const total = isNaN(tipCalculator.getTotalPerPerson()) ? 0 : tipCalculator.getTotalPerPerson();
const formatter = new Intl.NumberFormat(undefined, {
style: "currency",
currency: "USD",
signDisplay: "never"
});
tipPerPersonElem.innerText = formatter.format(tip);
totalPerPersonElem.innerText = formatter.format(total);
submit.style.display = "none";
const resetBtn = document.querySelector("[type=\"reset\"]");
resetBtn.style.display = "block";
resetBtn.addEventListener("click", () => {
reset()
resetBtn.style.display = "none";
submit.style.display = "block";
})
})
document.addEventListener("DOMContentLoaded", () => {
reset()
})
peopleElem.addEventListener("keyup", () => checkInputForError(peopleElem, peopleError, true));
billElem.addEventListener("keyup", () => checkInputForError(billElem, billError, false));
function checkInputForError(input, error, showError) {
const value = input.value.trim() || 0;
if (!value || isNaN(parseFloat(value)) || parseFloat(value) == 0) {
if (showError) document.querySelector(".warning").style.display = "inline";
input.classList.add("error");
error = true;
} else {
if (showError) document.querySelector(".warning").style.display = "none";
input.classList.remove("error");
input.classList.add("correct");
error = false;
}
}
function reset(submit = false) {
const tipPerPersonElem = document.querySelector("[data-tip-person]");
const totalPerPersonElem = document.querySelector("[data-total-person]");
tipPerPersonElem.innerText = "";
totalPerPersonElem.innerText = "";
console.log(tipPerPersonElem.innerText, totalPerPersonElem.innerText, "reset", submit);
tipOptions.forEach(option => option.classList.remove("active"));
document.querySelectorAll("input").forEach(input => {
input.classList.remove("correct");
input.classList.remove("error");
input.value = "";
})
}
:root {
--primary-color: hsl(172, 67%, 45%);
--very-dark-cyan: hsl(183, 100%, 15%);
--dark-grayish-cyan: hsl(186, 14%, 43%);
--grayish-cyan: hsl(184, 14%, 56%);
--light-grayish-cyan: hsl(185, 41%, 84%);
--very-light-grayish-cyan: hsl(189, 41%, 97%);
--white: hsl(0, 0%, 100%);
--primary-font-size: 24px;
--primary-font-family: 'Space Mono', monospace;
}
/* GLOABAL TAGS */
body {
width: 100%;
margin: 0;
overflow: hidden;
font-family: var(--primary-font-family);
background-color: var(--light-grayish-cyan);
}
header {
text-align: center;
}
h1 {
color: var(--very-dark-cyan);
margin-top: 0;
text-transform: uppercase;
}
h1 span {
display: block;
margin: 0;
}
label {
display: block;
text-transform: capitalize;
}
button {
outline: none;
border: none;
text-align: center;
background-color: var(--very-dark-cyan);
font-size: var(--primary-font-size);
color: var(--white);
text-transform: capitalize;
margin: 8px;
padding-top: 8px;
padding-bottom: 8px;
border-radius: 4px;
cursor: pointer;
}
legend {
margin-bottom: 8px;
}
/* Chrome,
Safari,
Edge, */
/* Opera */
input::-webkit-outer-spin-button,
input::-webkit-inner-spin-button {
-webkit-appearance: none;
margin: 0;
}
/* Firefox */
input[type=number] {
-moz-appearance: textfield;
}
input {
display: block;
border: none;
background-color: var(--very-light-grayish-cyan);
font-size: var(--primary-font-size);
height: 30px;
color: var(--very-dark-cyan);
background-repeat: no-repeat;
background-position: left center;
}
input:not(#custom) {
text-align: right;
}
aside {
font-size: 11px;
text-align: center;
}
aside a {
color: hsl(228, 45%, 44%);
}
/* END OF GLOBAL TAGS GENERIC IDs */
#bill {
background-image: url('https://kaustubhmaladkar.github.io/Tip-Calculator/images/icon-dollar.svg');
}
#people {
background-image: url('https://kaustubhmaladkar.github.io/Tip-Calculator/images/icon-person.svg');
}
/* END OF GENERIC IDs GENERIC CLASSES*/
button,
#custom {
width: calc(50% - 20px);
font-weight: bold;
}
/* END OF GENERIC CLASSES */
/* INPUT */
.input {
background-color: var(--white);
color: var(--dark-grayish-cyan);
border-top-right-radius: 20px;
border-top-left-radius: 20px;
margin-top: 20px;
padding-bottom: 30px;
}
.input legend {
margin-top: 20px;
margin-left: 20px;
}
legend:nth-of-type(2) label {
width: 100%;
}
legend:nth-of-type(2) {
display: flex;
flex-wrap: wrap;
}
[for="people"] {
display: inline;
}
.warning {
display: none;
/* margin-left: 92px; */
color: red;
font-size: 12px;
background-color: transparent;
}
input#custom {
background-color: var(--white);
color: var(--dark-grayish-cyan);
margin-top: 12px;
margin-left: 2px;
padding-bottom: 8px;
opacity: 1;
}
input#custom::placeholder {
text-transform: capitalize;
color: var(--dark-grayish-cyan);
opacity: 1;
}
/* END OF INPUT */
/*OUTPUT*/
.output {
background-color: var(--very-dark-cyan);
display: flex;
margin-top: -8px;
justify-content: center;
align-items: center;
flex-direction: column;
border-radius: 10px;
}
.output div,
.output span {
width: 100%;
}
.output>div>div {
display: flex;
gap: 15px;
}
.output>div>div:first-of-type {
margin-top: 30px;
margin-bottom: 15px;
}
.output>div>div:last-of-type {
margin-top: 15px;
margin-bottom: 30px;
}
[type="submit"],
[type="reset"] {
font-family: var(--primary-font-family);
background-color: var(--primary-color);
width: 90%;
text-align: center;
color: var(--very-dark-cyan);
}
.tip-person,
.total-person {
font-size: 35px;
color: var(--primary-color);
}
.output>div>div>div>span:first-of-type {
text-transform: capitalize;
color: var(--white);
display: block;
}
.output>div>div>div>span:last-of-type {
color: var(--grayish-cyan);
}
/*END OF OUTPUT */
.active:not(input) {
background-color: var(--primary-color);
color: var(--very-dark-cyan);
transition: background 0.7s ease-in-out;
}
.correct {
border: lightgreen 2px solid;
}
.error {
border: red 2px solid;
}
.correct:focus,
.error:focus {
outline: none;
}
/* JAVASCRIPT CLASSES */
/* END OF JAVASCRIPT CLASSES */
/* FOR DESKTOP */
#media (min-width: 1200px) {
/* RESET */
html,
body,
main {
margin: 0;
}
/* END OF RESET */
/* GENERIC TAGS */
form {
width: 100%;
max-width: 900px;
border-radius: 15px;
overflow: hidden;
margin: auto;
padding-right: 15px;
display: flex;
width: fit-content;
background-color: var(--white);
}
input {
width: 90%;
}
aside {
display: none;
}
/* END OF GENERIC TAGS */
/* GENERIC CLASSES */
.output,
.input {
height: 400px;
}
.warning {
margin-left: 92px;
}
/* END OF GENERIC CLASSES */
/* INPUT */
.input button,
.input input#custom {
width: calc(100% / 3 - 20px);
}
.input {
width: 50%;
padding-bottom: 0;
}
.input legend {
margin-left: 25px;
}
/* END OF INPUT */
/* OUTPUT */
.output {
width: 50%;
margin: 22px;
padding: 0;
display: flex;
flex-direction: column;
justify-content: space-around;
}
.output div {
margin-left: 20px;
}
.output>div>div:first-of-type {
margin-top: -20px;
margin-bottom: 40px;
}
[type="reset"] {
display: none;
}
/* END OF OUTPUT */
}
<h1>
<span>spli</span>
<span>tter</span>
</h1>
<form action="post">
<div class="input">
<legend>
<label for="bill">bill</label>
<input type="number" name="bill" id="bill" class="correct">
</legend>
<legend>
<label for="custom">select tip %</label>
<button type="button">5%</button>
<button type="button" class="">10%</button>
<button type="button">15%</button>
<button type="button">25%</button>
<button type="button">50%</button>
<input placeholder="custom" name="custom" id="custom" class="">
</legend>
<legend>
<label for="people">Number of People</label>
<p class="warning" style="display: inline;">Can't be zero</p>
<input type="number" name="people" id="people" class="">
</legend>
</div>
<div class="output">
<div>
<div>
<div>
<span>tip amount</span>
<span>/ person</span>
</div>
<span class="tip-person" data-tip-person=""></span>
</div>
<div>
<div>
<span>Total</span>
<span>/ person</span>
</div>
<span class="total-person" data-total-person=""></span>
</div>
</div>
<button type="submit" style="display: block;">Calculate</button>
<button type="reset" class="" style="display: none;">Reset</button>
</div>
</form>
I'm trying to create a project card with user info when the user clicks on a button. When the user clicks the new project button, a modal form pops up that takes the user info and has a create button. The program should add a new project card whenever the user clicks the create button. To achieve this I added a click event listener to the Add new project button and another to Create button. I nested the create event listener inside the add new project event listener.
Here's the event listener.
addTileBtn.addEventListener("click", (e) => {
e.preventDefault();
modal.style.display = "block";
const titleField = document.querySelector("#title");
const descriptionField = document.querySelector("#description");
const create = document.querySelector("#create");
const close = document.querySelector("#close");
create.addEventListener("click", (e) => {
e.preventDefault();
title = titleField.value;
description = descriptionField.value;
function createProjectTile() {
const projectTile = document.createElement("div");
projectTile.classList.add("cards-grid__tile");
projectTile.textContent = title;
console.log(title, description);
return projectTile;
}
cardsGrid.appendChild(createProjectTile());
modal.style.display = "none";
});
close.addEventListener("click", (e) => {
e.preventDefault();
modal.style.display = "none";
});
});
The problem is that when I create the first card it works fine. But the second time, it creates two cards and 3 cards on the 3rd time and so on.
Here is the JSFiddle link for the full code.
I've edited your code, this should be what you wanted:
const logoutBtn = document.querySelector("#logout");
const addTileBtn = document.querySelector("#add-tile");
const cardsGrid = document.querySelector(".cards-grid");
const modal = document.querySelector(".modal");
const titleField = document.querySelector("#title");
const descriptionField = document.querySelector("#description");
const create = document.querySelector("#create");
const close = document.querySelector("#close");
addTileBtn.addEventListener("click", (e) => {
e.preventDefault();
modal.style.display = "block";
titleField.value = "";
descriptionField.value = "";
});
create.addEventListener("click", (e) => {
e.preventDefault();
title = titleField.value;
description = descriptionField.value;
function createProjectTile() {
const projectTile = document.createElement("div");
projectTile.classList.add("cards-grid__tile");
projectTile.textContent = title;
console.log(title, description);
return projectTile;
}
cardsGrid.appendChild(createProjectTile());
modal.style.display = "none";
});
close.addEventListener("click", (e) => {
e.preventDefault();
modal.style.display = "none";
});
:root {
--main-red: #be3144;
--main-white: #f0f0f0;
--main-gray: #303841;
--main-blue: #45567d;
--main-blue3: #1c262f;
--main-blue2: #27333d;
--main-blue1: #2e3d49;
--main-light-blue: #02b3e4;
--main-black: #000000;
--main-light-black: #3a3d40;
--main-dark-black: #181719;
}
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
html,
body {
height: 100%;
}
img {
display: block;
max-width: 100%;
height: auto;
}
body {
font-family: "Poppins", sans-serif;
font-size: 1.8rem;
font-weight: 400;
line-height: 1.4;
color: var(--main-white);
}
h1,
h2 {
font-family: "Raleway", sans-serif;
font-weight: 700;
text-align: center;
}
h1 {
font-size: 3.5rem;
}
h2 {
font-size: 2rem;
color: var(--main-blue);
display: block;
}
p {
font-size: 1.8rem;
font-weight: 200;
font-style: italic;
color: var(--main-white);
}
a {
text-decoration: none;
text-align: center;
display: block;
}
.main {
display: flex;
flex-direction: row;
justify-content: space-between;
height: 100vh;
background-color: var(--main-white);
}
.box {
border: none;
box-shadow: 0 2px 4px rgb(0 0 0 / 10%), 0 8px 16px rgb(0 0 0 / 10%);
border-radius: 8px;
background-color: #fff;
}
.box__fields {
padding: 20px;
}
.box-field {
margin-bottom: 20px;
display: flex;
justify-content: center;
}
.icon {
position: absolute;
padding: 10px;
color: gray;
min-width: 50px;
text-align: center;
font-size: 20px;
top: 50%;
transform: translateY(-50%);
}
input,
textarea {
font-size: 17px;
padding: 14px 16px;
width: 300px;
cursor: text;
border: 1px solid var(--main-gray);
border-radius: 6px;
outline: none;
padding-left: 45px;
}
.box-btn {
border: none;
border-radius: 6px;
font-size: 20px;
line-height: 48px;
padding: 0 16px;
}
.app,
.main-content {
height: 100%;
}
.title-area {
background-color: var(--main-blue3);
width: 100%;
font-size: 18px;
min-height: 60px;
display: flex;
flex-direction: row;
flex-wrap: wrap;
justify-content: space-between;
align-items: center;
position: fixed;
top: 0;
left: 0;
}
.title-area__item {
padding: 10px 30px;
}
.logout-btn {
border: none;
border-radius: 6px;
font-size: 20px;
line-height: 30px;
padding: 0 16px;
width: 100px;
cursor: pointer;
color: #fff;
background-color: var(--main-light-blue);
}
.logout-btn:hover {
background-color: #029be4;
}
.content-area {
margin-top: 60px;
width: 100%;
height: 100%;
overflow: auto;
background-color: var(--main-blue);
}
.cards-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
grid-gap: 50px;
margin-bottom: 3rem;
padding: 5rem 3rem;
}
.cards-grid__tile {
background-color: var(--main-blue2);
max-width: 200px;
padding: 30px;
text-align: center;
font-size: 1.2rem;
}
.add-tile-btn {
border: none;
border-radius: 6px;
font-size: 15px;
line-height: 48px;
padding: 0 10px;
cursor: pointer;
color: #fff;
background-color: var(--main-light-blue);
}
.modal {
display: none;
width: 350px;
font-size: 1.2rem;
position: relative;
top: 10%;
left: 50%;
transform: translateX(-50%);
overflow: visible;
}
.box {
background-color: var(--main-blue1);
opacity: 0.95;
}
.box-field {
flex-direction: column;
}
input,
textarea {
padding: 5px 10px;
resize: none;
}
.wrapper {
position: relative;
text-align: center;
}
.create-btn {
width: 100px;
cursor: pointer;
color: #fff;
background-color: var(--main-light-blue);
}
.close {
cursor: pointer;
position: absolute;
top: 20px;
left: 290px;
}
#modal-form {
position: absolute;
}
.icon {
color: var(--main-blue3);
}
<div class="app">
<div class="nav-wrapper">
<nav id="nav" class="nav"></nav>
</div>
<div class="main-content">
<div class="title-area">
<div class="title-area__item">Menu</div>
<div class="title-area__item">Boards</div>
<div class="title-area__item">
<button id="logout" class="logout-btn btn">
Logout
</button>
</div>
</div>
<div class="content-area">
<div class="modal">
<form id="modal-form" class="box">
<a id="close" class="close">
<i class="fa fa-times icon">close</i>
</a>
<div class="box__fields">
<div class="box-field">
<label for="title"> Title </label>
<input
id="title"
type="text"
name="title"
required
autofocus
/>
</div>
<div class="box-field">
<label for="description">
Description
</label>
<textarea
id="description"
name="title"
rows="6"
cols="40"
></textarea>
</div>
<div class="box-field">
<div class="wrapper">
<button
id="create"
class="create-btn box-btn btn"
>
Create
</button>
</div>
</div>
</div>
</form>
</div>
<div class="cards-grid">
<div class="cards-grid__tile">
<button id="add-tile" class="add-tile-btn btn">
+ Add new project
</button>
</div>
</div>
</div>
</div>
</div>
I've created easy game. I added two circular progressBar in setTimeout, but still doesn't work as i expect. I wanna to these bars goes from 0 to 100% and finish. Unfortunately second of them is 2 times quicker than first. If I try add only one bar, there's not problem. I add my program on GH, there I selected the most important lines. I'm sorry for my english, I'm not native :/
HTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<link href="https://fonts.googleapis.com/css?family=Kalam&display=swap" rel="stylesheet">
<link rel="stylesheet" href="font/flaticon.css">
<link rel="stylesheet" href="style.css">
<title>ColorGame</title>
</head>
<body>
<div class="main-layer">
<h1 class="title">Remember this color! </h1>
<div class="square draw-square">
<!-- <div class="my-progress-bar"></div> -->
</div>
<div class="button-box">
<button class="button drawButton">Draw Color</button>
<button class="button listButton">Your scores</button>
</div>
</div>
<div class="check-layer">
<div class="square player-square">
<!-- <div class="my-progress-bar"></div> -->
</div>
<div class="input-box">
<input type="range" class="redInput" value="0" min="0" max="255">
<input type="range" class="greenInput" value="0" min="0" max="255">
<input type="range" class="blueInput" value="0" min="0" max="255">
</div>
</div>
<div class="end-layer">
<div class="result-text"></div>
<div class="compare-box">
<div class="draw-square square-modifier"></div>
<div class="player-square square-modifier"></div>
</div>
<i class="flaticon-close cross"></i>
</div>
<div class="list-layer">
<h1 class="list-title">Scores</h1>
<i class="flaticon-close"></i>
</div>
<script src="http://code.jquery.com/jquery-1.9.1.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-easing/1.4.1/jquery.easing.min.js"></script>
<script src="plugin.js"></script>
<script src="index.js"></script>
</body>
</html>
SCSS
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: 'Kalam', cursive;
}
#mixin flex {
display: flex;
justify-content: center;
align-items: center;
}
:root {
--drawRed: 0;
--drawGreen: 0;
--drawBlue: 0;
--checkRed: 0;
--checkGreen: 0;
--checkBlue: 0;
}
$lightRed: rgb(192, 0, 0);
$mediumRed: rgb(80, 1, 1);
$darkRed: rgb(37, 0, 0);
$lightGreen: rgb(25, 146, 21);
$mediumGreen: rgb(11, 61, 9);
$darkGreen: rgb(3, 17, 2);
$lightBlue: rgb(16, 61, 185);
$mediumBlue: rgb(5, 21, 63);
$darkBlue: rgb(2, 8, 24);
body {
height: 100vh;
}
// main-layer
.main-layer {
#include flex();
position: absolute;
justify-content: space-evenly;
flex-direction: column;
background-color: #171717;
color: white;
width: 100%;
height: 100%;
padding: .5em;
}
.title, .description {
font-size: 1.5rem;
text-shadow: .05em .05em .01em black;
}
.square {
border: .1rem solid white;
width: 30vw;
height: 30vw;
border-radius: 1em;
}
.draw-square {
#include flex();
background-color: rgb(var(--drawRed), var(--drawGreen), var(--drawBlue));
}
.my-progress-bar {
position: relative;
}
.progress-percentage {
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
font-size: 2rem;
font-weight: bold;
color: rgba(0,0,0, .1)
}
.button-box {
#include flex();
width: 100%;
}
.button {
width: 7rem;
height: 2.2rem;
background-color: rgb(223, 70, 0);
color: white;
font-weight: bold;
font-size: 1rem;
border: none;
border-radius: .5em;
margin: 0 .5em;
text-shadow: .07em .07em .05em black;
box-shadow:
inset -.1em -.1em .2em .05em rgb(95, 30, 0),
.03em .03em .01em .01em rgb(12, 4, 0);
transition: 1s;
&:hover {
background-color: rgb(95, 30, 0);
box-shadow:
inset -.1em -.1em .2em .05em rgb(27, 9, 0),
.03em .03em .01em .01em rgb(12, 4, 0);
}
}
// check-layer
.check-layer {
position: absolute;
display: none;
justify-content: space-evenly;
align-items: center;
width: 100%;
height: 100%;
background-color: #171717;
}
.player-square {
#include flex();
background-color: rgb(var(--checkRed), var(--checkGreen), var(--checkBlue));
}
.input-box {
display: flex;
justify-content: space-evenly;
flex-direction: column;
width: 30vw;
height: 50vw;
}
input {
// position: relative;
width: 100%;
height: 1rem;
-webkit-appearance: none;
background: rgba(0,0,0,0.8);
outline: none;
border-radius: 1rem;
}
input::-webkit-slider-thumb {
-webkit-appearance: none;
width: .1rem;
height: .1rem;
border-radius: 50%;
}
.redInput::-webkit-slider-thumb {
box-shadow: 0 0 0 .3rem $lightRed;
border: .5rem solid $darkRed;
}
.greenInput::-webkit-slider-thumb {
box-shadow: 0 0 0 .3rem $lightGreen;
border: .5rem solid $darkGreen;
}
.blueInput::-webkit-slider-thumb {
box-shadow: 0 0 0 .3rem $lightBlue;
border: .5rem solid $darkBlue;
}
.redInput {
background-color: $mediumRed;
box-shadow: .1em 0 .3em .1em $darkRed;
}
.greenInput {
background-color: $mediumGreen;
box-shadow: .1em 0 .3em .1em $darkGreen;
}
.blueInput {
background-color: $mediumBlue;
box-shadow: .1em 0 .3em .1em $darkBlue;
}
// end-layer
.end-layer {
position: relative;
display: none;
justify-content: center;
align-items: center;
width: 100%;
height: 100%;
background-color: #171717;
}
.compare-box {
display: flex;
}
.square-modifier {
height: 100vh;
width: 50vw;
}
.result-text {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
font-size: 5em;
font-weight: bold;
color: white;
text-shadow: .02em .02em .03em black;
}
.flaticon-close::before {
position: absolute;
top: .3em;
right: .3em;
color: white;
text-shadow: .04em .04em .02em black;
font-size: 2em;
margin: 0;
}
// list
.list-layer {
display: flex;
justify-content: flex-start;
align-items: center;
flex-direction: column;
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: black;
padding: 1em 0;
overflow-y: scroll;
}
.list-title {
#include flex();
font-size: 4em;
color: rgb(223, 70, 0);
}
.score {
font-size: 2em;
color: white;
}
#media (min-width: 768px) {
html {
font-size: 1.5rem;
}
.square {
width: 25vw;
height: 25vw;
}
}
#media (min-width: 1024px) {
html {
font-size: 2.5rem;
}
.square {
width: 35vw;
height: 35vw;
}
}
#media (min-width: 1366px) {
html {
font-size: 3rem;
}
.square {
width: 40vw;
height: 40vw;
}
}
#media (min-width: 1500px) {
html {
font-size: 3rem;
}
.square {
width: 30vw;
height: 30vw;
}
}
#media (orientation:portrait) {
// main-layer
.main-layer {
justify-content: space-around;
}
.title {
font-size: 2rem;
text-align: center;
}
.button {
width: 70vw;
height: 2.5rem;
margin: .5em 0;
}
.square {
width: 90vw;
height: 90vw;
}
.button-box {
flex-direction: column;
}
// check-layer
.check-layer {
justify-content: space-evenly;
flex-direction: column;
}
.input-box {
justify-content: space-between;
width: 80%;
height: 50vw;
}
// end-layer
.compare-box {
flex-direction: column;
}
.square-modifier {
height: 50vh;
width: 100vw;
}
}
#media (orientation:portrait) and (min-width: 375px) {
html {
font-size: 1.5rem;
}
}
#media (orientation:portrait) and (min-width: 768px) {
html {
font-size: 1.7rem;
}
.input-box {
height: 25vw;
}
}
JavaScript
const checkDuration = 7000;
const fadeDuration = 1000;
const progressBar = [];
const score = [];
let squareSize;
let currentPercent;
let scoreCounter = 0;
// wylosowane kolory na samym początku
let drawRed = 0;
let drawGreen = 0;
let drawBlue = 0;
// kolory ustawione przez player'a
let checkRed = 0;
let checkGreen = 0;
let checkBlue = 0;
// timeoutsy
let firstTimeOut = 0;
let secondTimeOut = 0;
function addScore() {
score[scoreCounter] = $('<div>').addClass('score').text((scoreCounter+1) + ". " + currentPercent);
$('.list-layer').append(score[scoreCounter]);
}
function randNumber(min, max) {
return Math.round(Math.random()*max + min);
}
function setCssVariable(cssVariable, currentValue) {
document.documentElement.style.setProperty(cssVariable, currentValue);
// console.log(cssVariable+", "+currentValue)
}
function updateValue(cssVariable, sliderClass) {
setCssVariable(cssVariable, parseInt($(sliderClass).val())); // ustawia zmienną css'ową na daną wartość slidera
setGlobalVariable(sliderClass)
}
function setGlobalVariable(sliderClass) {
if(sliderClass == '.redInput') {
checkRed = parseInt($(sliderClass).val());
}
else if(sliderClass == '.greenInput'){
checkGreen = parseInt($(sliderClass).val());
}
else {
checkBlue = parseInt($(sliderClass).val());
}
}
function setColor() { // <<< ----------------------------------- FIRST TIMEOUT
firstTimeOut = setTimeout(()=> {
checkLayer();
console.log("check-layer")
}, checkDuration)
}
function deleteProgressBar() {
$(progressBar[0]).remove();
$(progressBar[1]).remove();
}
function addProgressBar(numberBar, destination) {
progressBar[numberBar] = $('<div>').addClass('my-progress-bar');
$(destination).append(progressBar[numberBar]);
$(progressBar[numberBar]).circularProgress({
width: squareSize,
height: squareSize,
line_width:10,
color: "rgba(0, 0, 0, .25)",
starting_position: 0,
percent: 0
// counter_clockwise: false
}).circularProgress('animate', 100, checkDuration); // <<< --------------------- checkDuration
}
function fadeLayer(show, element, duration) {
if(show) {
$(element).css('display', 'flex').fadeIn(duration); // odkrywa się check-layer
} else {
$(element).css('display', 'none').fadeOut(duration); // odkrywa się check-layer
}
}
function checkLayer() {
// $(progressBar[0]).remove();
fadeLayer(true, '.check-layer', fadeDuration);
addProgressBar(1, '.check-layer .player-square');
secondTimeOut = setTimeout(()=>{ ///////////////////// <<< ------------------------------ SECOND TIMEOUT
compareColors();
addScore();
fadeLayer(true, '.end-layer', fadeDuration);
scoreCounter++;
}, checkDuration);
}
function compareColors() {
// algoryt I
// const redDeviation = drawRed-checkRed
// const greenDeviation = drawGreen-checkGreen;
// const blueDeviation = drawBlue-checkBlue;
// // const distance = Math.sqrt(Math.pow(redDeviation, 2) + Math.pow(greenDeviation, 2) + Math.pow(blueDeviation, 2))
// // const percent = Math.floor(100 - (distance/Math.sqrt(3*Math.pow(255, 2)))*100) +"%";
// const distance = Math.sqrt(redDeviation*redDeviation + greenDeviation*greenDeviation + blueDeviation*blueDeviation);
// console.log(distance)
// const percent = Math.floor(100 - (distance/442)*100) +"%"
// algorytm II
const rmean = (drawRed+checkRed)/2;
const r = drawRed-checkRed
const g = drawGreen-checkGreen;
const b = drawBlue-checkBlue;
const weightR = 2 + rmean/256;
const weightG = 4.0;
const weightB = 2 + (255-rmean)/256;
const d1 = Math.sqrt(weightR*r*r + weightG*g*g + weightB*b*b);
const maxColDist = 764.8339663572415;
const s1 = Math.round(((maxColDist-d1)/maxColDist)*100) + "%";
currentPercent = s1;
$('.result-text').text(s1);
}
function drawButton() {
$('.drawButton').click(()=> {
// dodaje progressBar
addProgressBar(0, '.main-layer .draw-square');
// zablokowanie przycisku
$('.drawButton').prop('disabled', true);
$('.listButton').prop('disabled', true);
// losuje liczby do rgb() w css'ie
drawRed = randNumber(0, 255);
drawGreen = randNumber(0, 255);
drawBlue = randNumber(0, 255);
// ustawia zmiennym wylosowaną wartość
setCssVariable('--drawRed', drawRed)
setCssVariable('--drawGreen', drawGreen)
setCssVariable('--drawBlue', drawBlue)
setColor(); // <<< -------------------------- ODPALA SIĘ TIMEOUT NR1
})
}
function sliders() {
$('.redInput').on('change mousemove touchmove', updateValue.bind(this, "--checkRed", '.redInput'));
$('.greenInput').on('change mousemove touchmove', updateValue.bind(this, "--checkGreen", '.greenInput'));
$('.blueInput').on('change mousemove touchmove', updateValue.bind(this, "--checkBlue", '.blueInput'));
}
function cross() {
$('.cross').click(() => {
restart();
})
}
function setDefaultSliderPosition() {
$('.redInput').val(0);
$('.greenInput').val(0);
$('.blueInput').val(0);
}
function restart() {
$('.drawButton').prop('disabled', false); // odblokowanie przycisku
$('.listButton').prop('disabled', false); // odblokowanie przycisku
fadeLayer(false, '.check-layer', 0);
fadeLayer(false, '.end-layer', 0);
setCssVariable('--drawRed', 0);
setCssVariable('--drawGreen', 0);
setCssVariable('--drawBlue', 0);
setCssVariable('--checkRed', 0);
setCssVariable('--checkGreen', 0);
setCssVariable('--checkBlue', 0);
setDefaultSliderPosition();
deleteProgressBar();
clearTimeout(secondTimeOut); // <<<------------------------- CLEAR TIMEOUTS
clearTimeout(firstTimeOut);
}
function list() {
$('.listButton, .list-layer .flaticon-close').click(() => {
$('.list-layer').slideToggle(1500, 'easeOutBounce');
});
}
function resize() {
$(window).on('resize', () => {
squareSize = $('.square').css("width");
});
}
$('.list-layer').fadeOut(0);
// funckje nasłuchujące
drawButton();
sliders();
cross();
list();
resize();