3

So im only just really starting out on my javascript journey. I'm only just getting into DOM manipulation and still very new to a lot of javascript...as you can probably tell by my code!

I'm messing around with a tip calculator (pretty standard newbie project I guess) and having real difficulties with the DOM and how to select certain elements from inputs (text and radio) and have them submit.

Any advice on my below code would be awesome. I am all ears and ready to take a spanking for all of the mistakes...but super keen to learn what I'm doing wrong!

<form 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.1">
            </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.2">
            </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>
    </form>

Javascript below...

var bill, percent, tip, finalBill;


document.getElementById('submit-button').addEventListener('click', function() {

// get bill amount
bill = document.getElementById('bill-amount').value

//get percent amount from checkboxes
percent = document.getElementsByName('tip-percent').checked;
tip = calcTip();
finalBill = finalAmount();

// edit results in html
document.getElementById('tip-to-pay').textContent = tip;
document.getElementById('bill-to-pay').textContent = finalBill;

// display result
document.querySelector('.totals-container').style.display = 'flex';

}

function calcTip() {
    tip = percent * bill
}

function finalAmount() {
    finalBill = tip + bill
}

probably be a lot easier to see this with my below pen! https://codepen.io/rickwall/pen/WNbpmoW

rickwall
  • 59
  • 2
  • 7
    You are a newbie, but you added a properly formatted question even with a fiddle for us to mess with. Kudos to you. You have a future in StackOverflow :-) – Jorge Fuentes González Dec 20 '19 at 21:47
  • 3
    THe problem is that his is not CodeReview (there's a site for that) we need exact questions with exact problems. I don't know what exact problem do you have. The only problem I see is that you are submitting the form and losing the webpage. You want it to be blocked and just update the HTML when the button is pressed? – Jorge Fuentes González Dec 20 '19 at 21:49
  • 2
    You can also use Code Snippets in your question to have similar functionality as you would get from codepen, and allow use to view your code live in the body of your question - it also logs mistakes so you can spot mistakes in your question – Shiny Dec 20 '19 at 21:50
  • For example, the missing `)` at the end of your addEventListener function – Shiny Dec 20 '19 at 21:51
  • 2
    I now see a lot more problems. You need to go to https://codereview.stackexchange.com/ and ask there :-) – Jorge Fuentes González Dec 20 '19 at 21:56
  • I wasnt even aware of codereview...thanks for letting us know Jorge. And thanks Light for the insight with code snippets with functionality. Basically, I was trying to get the tip calculator to work out the tip and bill + tip for the selected amount (text input) and selected tip percentage (radio button)...Ill try posting this question to codereview for feedback :) – rickwall Dec 20 '19 at 23:10
  • I've fixed a few of the issues with your calculator and added a couple of notes about some things I noticed while going along - Sorry if my feedback is a bit all over the place, but hopefully some of it is helpful for you – Shiny Dec 20 '19 at 23:18
  • Note that Code Review is only for *working* code that you want to improve. If your code isn't working, or isn't doing what you want, then you should ask about it here, but you should cut down the scope of your question as much as possible to just the part that you're having trouble with to make it easier for answerers. – John Montgomery Dec 20 '19 at 23:20

1 Answers1

1

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>
Shiny
  • 4,945
  • 3
  • 17
  • 33
  • 1
    Thank you so much Light for all of that insight- REALLY appreciate the time taken for the detailed response! All seems to be working fine when I run the code here and in codepen which is amazing, and I can definitely work it from hereafter your input so thank you again :D One strange thing is it doesnt seem to be calculating the tip and displaying tip amount and final bill after clicking the submit button in google chrome...any idea why this might be the case?? – rickwall Dec 21 '19 at 09:05
  • I'm not sure, it works fine for me both here and on your Codepen in google chrome – Shiny Dec 21 '19 at 12:17