Hosted Project
https://js-beginners.github.io/Tip-Form-JavaScript-Project/Github Source Files
https://github.com/JS-Beginners/Tip-Form-JavaScript-ProjectJavaScript Used
- DOM Manipulation
- Control Structures
- Array.forEach()
- JavaScript CSS Manipulation
- eventListeners
- setTimeout()
- Immediately Invoked Function Expressions
Project Description/Summary
This project involves using JavaScript to wire up a tip calculator.New Things Learned or Refreshed
I spent a lot of time on this project. I watched about 20 of John's 40 minute solution before tackling the project myself. I wanted to watch the first couple of minutes to make sure I was on the right steps towards completing the project, but then he said he wasn't going to touch any of the HTML. I was curious to see how he would wire up the Service selection option on the from. This brought me to the first thing I learned: How to dynamically include options into an HTML from using a JavaScript object. I didn't end up watching the rest of John's solution. Still, I managed to get the project working as described in the project introduction video. I don't know how John finished the project but here some things I did that I know I he did not do:- I broke up the feedback statement. Before breaking up the feedback statement, if there was an error in one spot, the user would get all three validation errors.
- I created two functions. One function handles error validation and the other handles the calculations for the tips.
- I add a validation statement to make calculations only if there were no errors. I did this by creating and returning a Boolean flag called ‘isFeedback' to indicated whether error feedback existed.
- I add the ‘toFixed(2)' method to my output to ensure two decimals in my output.
- I made the users output and the users input disappear from the form after five seconds to give visual feedback that the calculations were complete.
Time to Code
This took about 3 hours, start to finish, including watching part of John's solution and then going back to finish my own solution.Lines of Code
This took 40 lines of code, including comments and white space.Biggest Take Away(s)
I had yet another BUG in my code. I typed in setInterval() instead of setTimeout(). It didn't hit me until after watching my CSS mysterically appear and disappear in a fixed interval of about every 2 seconds. Then I was like, why are my CSS classes appearing and reappearing in set intervals?…Duh! One more takeaway but not necessarily a bug was when I used the HTML input form field. I tried to input a decimal number (18.67) but got an error. Luckily, I remember from an earlier project that the reason for the error was the HTML input was set to number. When the HTML input has type=”number”, you have to add step=”0.1″ to set the interval to accept decimals.Your Turn!
What to Accomplish
- Download the source code from the github repository above.
- Delete the contents of the
app.js
file. - Implement the JavaScript code in your own
app.js file.
- If you think you need to see a video solution first, be sure to pick up John's JavaScript Tutorial and Projects Course.
- Add a link to your finished project below!
What You Should See
- In the case of tip form calculator above, you should be able to use the calculator to enter an amount of a bill, the number of people who will split the bill, and a selection as to how the service went.
- If a user forgets to add input or if the input is blank (or less than zero), feedback should be alerted to the user and then go away after 5 seconds.
- During the calculation, a GIF animation should show for a couple seconds before the user's answer show up on the screen.
- After about 5 seconds, the calculator should reset all forms.
Need to see the video solution for this project?
Get John's JavaScript Tutorial and Projects Course
let billTotal = document.querySelector(“#input-bill”);
let totalPeople = document.querySelector(“#input-users”);
var feedback = document.querySelector(“.feedback”);
//User Tip options
const services = [
{
title: “Great – 20%”,
value: 0.2,
},
{
title: “Good – 10%”,
value: 0.1,
},
{
title: “Bad – 2%”,
value: 0.02,
},
];
//Allow user to select tip Ammount
const serviceValue = document.querySelector(“#input-service”);
services.forEach((service) => {
let option = document.createElement(“option”);
option.textContent = service.title;
option.value = service.value;
serviceValue.appendChild(option);
});
//Submit Button functionality
const calculateButton = document.querySelector(“.submitBtn”);
calculateButton.addEventListener(“click”, (e) => {
e.preventDefault();
//Start the feedback from a clean slate in case an error was previously made
feedback.innerHTML = “”;
// If something is wrong add it to the Alert box
if (billTotal.value <= 0) {
addToAlert("Bill Cannot Be Blank");
}
if (totalPeople.value <= 0) {
addToAlert("Number Of Users Must Be Greater Than Zero");
}
if (serviceValue.value {
feedback.classList.remove(“showItem”, “alert-danger”);
}, 5000);
} else {
//If Everything is right split the bill + tip among everyone
calculateBill(
Number(billTotal.value),
Number(totalPeople.value),
Number(serviceValue.value)
);
}
});
//Functions for calculate button
const addToAlert = (text) => {
let div = document.createElement(“div”);
div.textContent = text;
feedback.appendChild(div);
};
const calculateBill = (bill, numPeople, serviceQuality) => {
let resultsContainer = document.querySelector(“.results”);
const loaderGif = document.querySelector(“.loader”);
let tip = bill * serviceQuality;
let billTotal = tip + bill;
let individualAmount = billTotal / numPeople;
//Add the tip, bill, and individual person cost to their spots in the html
document.querySelector(“#tip-amount”).textContent = tip.toFixed(2);
document.querySelector(“#total-amount”).textContent = billTotal.toFixed(2);
document.querySelector(“#person-amount”).textContent = individualAmount.toFixed(2);
//Once calculate “Load” the results after 3000ms
loaderGif.classList.add(“showItem”);
setTimeout(() => {
loader.classList.remove(“showItem”);
resultsContainer.classList.add(“showItem”);
}, 3000);
setTimeout(() => {
resultsContainer.classList.remove(“showItem”);
}, 10000);
};