HTML
On your HTML, you're wrapping your calculator with <form class="container">
- Forms are typically used for sending data to a web-server, for submission or validation among other things. In this case, you're just using it as a container and so are fine to stick to a standard <div>
This was causing the issue with your calculator disappearing when you submit
JavaScript
Scoping - Originally you were defining all of your variables in the global scope, rather than the function scope. This is typically avoided because it can cause issues with variables overwriting, losing track of changes, generally unexpected behaviour - You can ready more about this here
Functions - Your functions were perhaps a product of your scoping, but in general you would want your functions to take an input, and return you a value rather than modifying the values outside of the function scope - Returning your output helps avoid unexpected changes, while using parameters to input values allows more control and readability
In this code, I would be tempted to just not use the functions and perform the maths directly, being as it's simple & called only once - But you're free to do as you want
// This will change the value of tip globally, while also using set variables for percent and bill
function calcTip () {
tip = percent * bill
}
// This allows us to return the output of our function to our chosen variable
// while also taking the inputs we want
function calcTip (percent, bill) {
return percent * bill;
}
let tip = calcTip(0.10, 120); // returns 12;
Read more about functions from the MDN Docs
Types - In your main function, you're retrieving the .value
of elements, and assigning them to bill
and percent
. However, .value
will return a String, regardless of if the input is a "a" character, or a "2" character - This is causing issues when you're trying to add values, because the add operator +
does different things when used with Strings and Numbers.
For example, when used with a String and a Number, it will simply concatinate the two variables together - not add them as you might expect
let a = "5"; // Type: String
let b = 120; // Type: Number
a + b // "5120"
The correct behavior is seen when used with two Numbers
let a = 5; // Type: Number
let b = 120; // Type: Number
a + b // 125
In your case, we can make our String values bill
& percent
into Numbers by using parseInt(x)
and parseFloat(x)
- parseInt converts to an integer Number, while parseFloat converts to a floating point Number
There are a few more minor changes to your code in the snippet, but this is just some quick things for you before you post this over to code review - by no means is this the absolute correct way to do this, there's a fair few, but it's hopefully gonna help you moving forward
document.getElementById('submit-button').addEventListener('click', function() {
// Get bill amount
let bill = parseInt(document.getElementById('bill-amount').value);
// Get percent from selected checkbox
/* let percent = document.getElementsByName('tip-percent'); */
let percent = parseFloat(document.querySelector('input[name="tip-percent"]:checked').value);
// No reason to have these as functions if they're simple & only called once
let tip = percent * bill;
let finalBill = bill + tip;
// Add results in html
document.getElementById('tip-to-pay').textContent = '$' + tip;
document.getElementById('bill-to-pay').textContent = '$' + finalBill;
// Dislay result
document.querySelector('.totals-container').style.display = 'flex';
})
* {
margin: 0;
padding: 0;
}
html {
font-family: zilla slab;
font-size: 18px;
font-weight: 300;
background-image: url(imgs/restaurant.jpg);
background-position: center;
}
.page {
display: flex;
justify-content: center;
align-items: center;
}
.container {
display: flex;
justify-content: center;
flex-direction: column;
background-color: rgba(204, 238, 255, 0.9);
padding: 50px 100px 50px 100px;
margin-top: 2%;
text-align: center;
box-shadow: 0px 8px 40px rgba(0, 0, 0, 0.5), 0px 10px 20px rgba(0, 0, 0, 0.7);
border-radius: 40px;
}
.container>h2 {
padding-bottom: 1.6rem;
font-size: 2.5rem;
}
.container>p {
padding-bottom: 1rem;
font-size: 1.5rem;
}
.container>input {
text-align: center;
padding: 4px;
font-size: 1.2rem;
width: 160px;
margin-left: 19%;
margin-bottom: 1rem;
}
.radio-container {
display: flex;
justify-content: space-between;
}
.radio-box {
display: flex;
text-align: center;
align-items: center;
flex-direction: column;
}
.radio-styles {
margin: 10px 0 1.2rem 0;
cursor: pointer;
outline: none;
}
button {
padding: 8px 40px 8px 40px;
text-transform: uppercase;
background-color: #fff;
border: none;
border-radius: 45px;
box-shadow: 0px 8px 15px rgba(0, 0, 0, 0.3);
transition: all 0.3s ease 0s;
cursor: pointer;
outline: none;
font-family: zilla slab;
font-weight: 300;
font-size: 1rem;
}
.totals-container {
display: none;
}
.totals {
display: flex;
flex-direction: column;
}
#bill-final {
font-size: 2rem;
}
.totals h2 {
padding-bottom: 1.6rem;
}
<div class="page">
<div class="container">
<h2>Tip Calculator</h2>
<p>Enter Bill Amount</p>
<input type="text" class="input-styles" placeholder="£££" id="bill-amount">
<p>Select Percentage Of Bill</p>
<div class="radio-container">
<div class="radio-styles">
<p>10%</p>
<input type="radio" class="radio-styles" name="tip-percent" value="0.10">
</div>
<div class="radio-styles">
<p>15%</p>
<input type="radio" class="radio-styles" name="tip-percent" value="0.15">
</div>
<div class="radio-styles">
<p>20%</p>
<input type="radio" class="radio-styles" name="tip-percent" value="0.20">
</div>
<div class="radio-styles">
<p>25%</p>
<input type="radio" class="radio-styles" name="tip-percent" value="0.25">
</div>
</div>
<div class="submit-container">
<button type="submit" name="tip-submit" id="submit-button">submit</button>
</div>
<div class="totals-container">
<div class="totals">
<h2>Tip To Pay</h2>
<h2 id="tip-to-pay"></h2>
<h2 id="bill-final">Total Bill To Pay</h2>
<h2 id="bill-to-pay"></h2>
</div>
</div>
</div>
</div>