0

I've built a temperature converter using HTML, Bootstrap, and vanilla JavaScript. The user checks a radio button for one of the following options:

  • Fahrenheit to Celsius.
  • Fahrenheit to Kelvin.
  • Celsius to Fahrenheit.
  • Celsius to Kelvin.
  • Kelvin to Celsius.
  • Kelvin to Fahrenheit.

Then the user enters a figure in an input box below this menu and presses a 'Calculate' button. This is all placed inside a form which has an event listener on the calculate button. When the button is pressed the event listener fires off a function which converts the figure the user entered into the selected units. If the user fails to tick a radio button and/or fails to enter a figure, another function fires off which creates a div with an error message in it and inserts it into the page. Finally, a reset button at the bottom of the form is linked to a function which reloads the page when it's clicked.

For any given figure, the form can display one of six outputs, depending on which radio button the user ticked. Assuming that the user input 32, these are the expected results:

  • Fahrenheit to Celsius = expect 0.
  • Fahrenheit to Kelvin = expect 273.1.
  • Celsius to Fahrenheit = expect 89.6
  • Celsius to Kelvin = expect 305.1
  • Kelvin to Celsius = expect -241.1
  • Kelvin to Fahrenheit = expect -402.1

The app works for each of the above possible outcomes except the two I've bolded. When I try to convert Celsius to Kelvin or Kelvin to Celsius, I always get the following error message:

Uncaught TypeError: x.toFixed is not a function at HTMLFormElement.calculate

Here's the HTML code:

<!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 href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
    <title>Document</title>
</head>
<body class="bg-primary">
    <div class="container">
        <div class="row">
            <div class="col-md-6 mx-auto">
                <div class="card card-body text-center mt-5">
                    <h1 class="heading display-5 pb-3">Temperature Converter</h1>

                    <form id="temperatureForm">
                        <div class="form-group">
                            <input class="form-check-input" type="radio" name="flexRadioDefault" id="fahrenheitToCelsiusRadioButton">
                            <label class="form-check-label" for="flexRadioDefault1">Fahrenheit to Celsius?</label>
                        </div>
                        <div class="form-group">
                            <input class="form-check-input" type="radio" name="flexRadioDefault" id="fahrenheitToKelvinRadioButton">
                            <label class="form-check-label" for="flexRadioDefault1">Fahrenheit to Kelvin? &nbsp;</label>
                        </div>
                        <div class="form-group">
                            <input class="form-check-input" type="radio" name="flexRadioDefault" id="celsiusToFahrenheitRadioButton">
                            <label class="form-check-label" for="flexRadioDefault1">Celsius to Fahrenheit?</label>
                        </div>
                        <div class="form-group">
                            <input class="form-check-input" type="radio" name="flexRadioDefault" id="celsiusToKelvinRadioButton">
                            <label class="form-check-label" for="flexRadioDefault1">Celsius to Kelvin?</label>
                        </div>
                        <div class="form-group">
                            <input class="form-check-input" type="radio" name="flexRadioDefault" id="kelvinToCelsiusRadioButton">
                            <label class="form-check-label" for="flexRadioDefault1">Kelvin to Celsius?</label>
                        </div>
                        <div class="form-group">
                            <input class="form-check-input" type="radio" name="flexRadioDefault" id="kelvinToFahrenheitRadioButton">
                            <label class="form-check-label" for="flexRadioDefault1">Kelvin to Fahrenheit?</label>
                        </div>

                        <div class="form-group">
                            <div class="input-group mb-3 mt-3">
                                <span class="input-group-text" id="basic-addon1">Enter figure</span>
                                <input type="number" class="form-control" id="degreesToBeConverted"
                                 aria-label="Username" aria-describedby="basic-addon1">
                            </div>
                        </div>

                        <div class="form-group">
                            <input type="submit" value="Calculate" class="btn btn-success col-6 mt-3">
                        </div>
                    </form>

                   

                    <div id="results">
                        <h5 class="pt-4">Results</h5>
                        <div class="form-group">
                            <div class="input-group mb-3 mt-3">
                                <span class="input-group-text" id="nothingImportant">Result</span>
                                <input type="number" class="form-control" id="resultField"
                            aria-label="Username" aria-describedby="basic-addon1" disabled>
                            </div>
                        </div>
                    </div>

                    <div class="form-group">
                        <input type="submit" value="Reset" id="resetButton" onclick="reloadPage()" class="btn btn-warning col-3 mt-3">
                    </div>

                </div>
            </div>
        </div>
    </div>
            
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM" crossorigin="anonymous"></script>
    <script src="app.js"></script>
</body>
</html>

And here is the JavaScript:

const form = document.getElementById('temperatureForm').addEventListener('submit', calculate)

// User input field
const degreesToBeConverted = document.getElementById('degreesToBeConverted'); 

// The six radio buttons
const fahrenheitToCelsiusRadioButton = document.getElementById('fahrenheitToCelsiusRadioButton')
const fahrenheitToKelvinRadioButton = document.getElementById('fahrenheitToKelvinRadioButton')

const celsiusToFahrenheitRadioButton = document.getElementById('celsiusToFahrenheitRadioButton')
const celsiusToKelvinRadioButton = document.getElementById('celsiusToKelvinRadioButton')

const kelvinToCelsiusRadioButton = document.getElementById('kelvinToCelsiusRadioButton')
const kelvinToFahrenheitRadioButton = document.getElementById('kelvinToFahrenheitRadioButton')


// Reset button    
const resetButton = document.getElementById('resetButton');




function calculate(e) {
    e.preventDefault();
    let resultField = document.getElementById('resultField'); // results output here
    let valueOfDegreesToBeConvertedField = degreesToBeConverted.value.length

    if(fahrenheitToCelsiusRadioButton.checked == true) {
        let x = (degreesToBeConverted.value - 32) * .5556;
        resultField.value = x.toFixed(1);

    } else if(fahrenheitToKelvinRadioButton.checked == true){
        let x = (degreesToBeConverted.value - 32) * .5556 + 273.15;
        resultField.value = x.toFixed(1);
    } 
    
    else if(celsiusToFahrenheitRadioButton.checked == true){
        let x = (degreesToBeConverted.value * 1.8) + 32;
        resultField.value = x.toFixed(1);
    } else if(celsiusToKelvinRadioButton.checked == true){ // Uncaught TypeError: x.toFixed is not a function at HTMLFormElement.calculate
        let x = degreesToBeConverted.value + 273.15;
        resultField.value = x.toFixed(1);
    } 
    
    else if(kelvinToCelsiusRadioButton.checked == true){ // Uncaught TypeError: x.toFixed is not a function at HTMLFormElement.calculate
        let x = degreesToBeConverted.value - 273.15;
        resultField.value = x.toFixed(1);
    }  else if(kelvinToFahrenheitRadioButton.checked == true){
        let x = ((degreesToBeConverted.value - 273.15) * 9 / 5) + 32;
        resultField.value = x.toFixed(1);
    }  

else if (fahrenheitToCelsiusRadioButton.checked == false && celsiusToFahrenheitRadioButton.checked == false) {
            showError('Please tick a button')
        }

    if(valueOfDegreesToBeConvertedField === 0) { 
        resultField.value = '';
        showError('Please type a number in the box')
    } // Checks if input field is empty & displays error message if so.
}

function showError(error) {
    // Create a Div

    const errorDiv = document.createElement('div');

    // Get Elements

    const card = document.querySelector('.card');
    const heading = document.querySelector('.heading');

    // Add class

    errorDiv.className = 'alert alert-danger';

    // Create Text Node & Append to Div

    errorDiv.appendChild(document.createTextNode(error));

    // Insert error above heading

    card.insertBefore(errorDiv, heading); // This means 'insert errorDiv before heading'

    // Clear error after 3 seconds

    setTimeout(clearError, 3000);
}

// Clear error

function clearError() {
    document.querySelector('.alert').remove();
}


function reloadPage(){
    location.reload();
}

What's so peculiar about this, from my point of view, is that I use the .toFixed() method to return every one of the six calculations to one decimal point. It works perfectly for four of them and doesn't work for two, but as far as I can see there's no meaningful difference in the code between the snippets where it does throw an error and the snippets where it doesn't.

Here's what I've already tried:

  • I've tried removing the .toFixed() method from the two snippets in which it's throwing an error. This gets rid of the error, but creates new problems. For the Celsius to Kelvin calculation, removing .toFixed() causes the user's figure to be concatenated to one of the figures used in the calculation. To clarify, the process of converting Celsius to Fahrenheit is very simple; you just add 273.15 to the Celsius figure. This means that if the user input 32, the program should output 305.1. Instead, it concatenates the two figures and outputs 32273.15.

Also, if I remove .toFixed() from the second problematic calculation (Kelvin to Celsius) the calculation works, but it gives the figure to a dozen decimal places (but only when there are a dozen decimal places to give, which is quite often) and that's not what I want.

  • I've also tried googling the error message and I've not found anything helpful.

I'd really appreciate it if someone could explain why this error is happening. Any suggested fixes would, of course, be very welcome.

Many thanks

Nellington
  • 211
  • 3
  • 12
  • 4
    `x = degreesToBeConverted.value + 273.15` sets `x` to a string, not a number because `value` is a string and this concatenates. – Barmar Jul 07 '21 at 21:44
  • agree with Barmar, try parseFloat first then tofixed – Nonik Jul 07 '21 at 21:45
  • Hi. Thanks very much. That seems to have fixed the problem. I don't suppose you have any idea why the other calculations worked, but those two didn't? I've not used parseFloat on any of the other calculations and they all work fine. – Nellington Jul 07 '21 at 21:53

0 Answers0