Treat blank fields in calculation

Asked

Viewed 130 times

0

I’m making a simulator on my site with Javascript, everything is working just one thing.

When I leave the fields blank he does not do the calculation, forcing me to fill in, even with 0 for him to make the calculation.

Here I leave the code I have so far and a picture of the problem:

            function calculate()
            {
                var field1=document.getElementById("num1").value;
                var field2=document.getElementById("num2").value;
                var field3=document.getElementById("num3").value;
                var field4=document.getElementById("num4").value;
                var field5=document.getElementById("num5").value;
                var field6=document.getElementById("num6").value;
                var field7=document.getElementById("num7").value;
                var field8=document.getElementById("num8").value;
                var field9=document.getElementById("num9").value;
                var field10=document.getElementById("num10").value;
                var field11=document.getElementById("num11").value;
                var field12=document.getElementById("num12").value;
                var field13=document.getElementById("num13").value;
                var field14=document.getElementById("num14").value;
                var field15=document.getElementById("num15").value;
                var field16=document.getElementById("num16").value;
                
                var result=(parseFloat(field1)*0+parseFloat(field2)*1.10+parseFloat(field3)*2.20+parseFloat(field4)*1.70+parseFloat(field5)*2+parseFloat(field6)*2.50+parseFloat(field7)*2.10+parseFloat(field8)*2.20+parseFloat(field9)*2.30+parseFloat(field10)*1+parseFloat(field11)*6.70+parseFloat(field12)*1.70+parseFloat(field13)*3.80+parseFloat(field14)*1.70+parseFloat(field15)*1.50)*parseFloat(field16);
                var arredondado = parseFloat(result.toFixed(2));
                if(!isNaN(result))
                {
                    document.getElementById("answer").innerHTML="O valor é €" +arredondado;
                    
                }
                
                
            }
Pessoas<br>
            Até 5 anos.............<input type="text" id="num1">
            <br>
            De 5 a 10 anos......<input type="text" id="num2">
            <br>
            Mais de 10 anos..<input type="text" id="num3">
            <br>
            Tendas<br>
            Até 4 metros........<input type="text" id="num4">
            <br>
            De 5 a 12 metros..<input type="text" id="num5">
            <br>
            De 13 a 20 metros<input type="text" id="num6">
            <br>
            Caravana<br>
            Até 4 metros........<input type="text" id="num7">
            <br>
            De 5 a 6 metros....<input type="text" id="num8">
            <br>
            Mais de 6 metros<input type="text" id="num9">
            <br>
            Viaturas
            <br>
            Reboque................<input type="text" id="num10">
            <br>
            Autocarro.............<input type="text" id="num11">
            <br>
            Automóvel...........<input type="text" id="num12">
            <br>
            Autocaravana.....<input type="text" id="num13">
            <br>
            Motocicletas........<input type="text" id="num14">
            <br>
            Outras<br>
            Electricidade.......<input type="text" id="num15">
            <br>
            <br>
            Dias.........................<input type="text" id="num16">
            <br>
            <br>
            <button onclick="calculate()">Calcular</button>

Texto

  • Makes an if for if the field is empty, put that its value is zero

  • tried, but every time I leave a blank field still not giving output.

4 answers

1

Use the logical operator OR || - is a logical operator that returns its right-side operand when its left-side operator is null or Undefined.

    var field1 = document.getElementById("num1").value || 0;

    function calculate()
        {
         var field1=document.getElementById("num1").value || 0;
         var field2=document.getElementById("num2").value || 0;
         var field3=document.getElementById("num3").value || 0;
         var field4=document.getElementById("num4").value || 0;
         var field5=document.getElementById("num5").value || 0;
         var field6=document.getElementById("num6").value || 0;
         var field7=document.getElementById("num7").value || 0;
         var field8=document.getElementById("num8").value || 0;
         var field9=document.getElementById("num9").value || 0;
         var field10=document.getElementById("num10").value || 0;
         var field11=document.getElementById("num11").value || 0;
         var field12=document.getElementById("num12").value || 0;
         var field13=document.getElementById("num13").value || 0;
         var field14=document.getElementById("num14").value || 0;
         var field15=document.getElementById("num15").value || 0;
         var field16=document.getElementById("num16").value || 0;
                     
          var result=(parseFloat(field1)*0+parseFloat(field2)*1.10+parseFloat(field3)*2.20+parseFloat(field4)*1.70+parseFloat(field5)*2+parseFloat(field6)*2.50+parseFloat(field7)*2.10+parseFloat(field8)*2.20+parseFloat(field9)*2.30+parseFloat(field10)*1+parseFloat(field11)*6.70+parseFloat(field12)*1.70+parseFloat(field13)*3.80+parseFloat(field14)*1.70+parseFloat(field15)*1.50)*parseFloat(field16);

         var arredondado = parseFloat(result.toFixed(2));
         if(!isNaN(result))
           {
              //document.getElementById("answer").innerHTML="O valor é €" +arredondado;
        
             console.log(arredondado)
                        
           }
                               
        }
  Pessoas<br>
      Até 5 anos.............<input type="text" id="num1">
      <br>
      De 5 a 10 anos......<input type="text" id="num2">
      <br>
      Mais de 10 anos..<input type="text" id="num3">
      <br>
      Tendas<br>
      Até 4 metros........<input type="text" id="num4">
      <br>
      De 5 a 12 metros..<input type="text" id="num5">
      <br>
      De 13 a 20 metros<input type="text" id="num6">
      <br>
      Caravana<br>
      Até 4 metros........<input type="text" id="num7">
      <br>
      De 5 a 6 metros....<input type="text" id="num8">
      <br>
      Mais de 6 metros<input type="text" id="num9">
      <br>
      Viaturas
      <br>
      Reboque................<input type="text" id="num10">
      <br>
      Autocarro.............<input type="text" id="num11">
      <br>
      Automóvel...........<input type="text" id="num12">
      <br>
      Autocaravana.....<input type="text" id="num13">
      <br>
      Motocicletas........<input type="text" id="num14">
      <br>
      Outras<br>
      Electricidade.......<input type="text" id="num15">
      <br>
      <br>
      Dias.........................<input type="text" id="num16">
      <br>
      <br>
      <button onclick="calculate()">Calcular</button>

To do the test in Run you must enter at least one input from the second and also mandatory number of days. I’m not doing this validation because it’s not the focus of the question.

  • thanks, I did it differently, I changed the type to number and made a condition, if the value was 0 for the field to be 0 and also gave.

  • corrected by its shape, gets much better, thank you

  • is, thank you again

1


I would like to suggest another solution, because it does not seem to me that you are doing it in the best way (take it as constructive criticism).

If the idea is to have multiple numbers, each coming from one input, and you want to iterate for all of them, one option would be to use selectors, along with querySelectorAll, to make your life easier.

For example, if the idea is to take all the fields input type="text", an alternative would be to use document.querySelectorAll('input[type="text"]'). With this, you will have a list of all the fields, just scroll through them with a loop simple. Or, if you only want fields whose attribute id start with "num," you could do document.querySelectorAll('input[id^="num"]'), for example.

Or else you arrow the fields that matter with a class. Ex:

<input type="text" id="num1" class="quantidade-item">

And then you search for all the elements that possess this class, with document.querySelectorAll('input.quantidade-item').


As each of the fields has a multiplicative factor, you can use a dataset for each field to have the corresponding value. Ex:

<input type="text" id="num2" class="quantidade-item" data-multiplicador="1.1">

Thus, each field has the information of the value by which it will be multiplied (as we will see below, the use of dataset, together with the selectors, will greatly facilitate the algorithm and simplify the code).


Now for the calculation itself. You are multiplying each field by a number and adding up the results, and you want the value to be zero if the field is empty.

Let’s assume we only have 3 fields, then the bill would be:

field1 * valor1 + field2 * valor2 + field3 * valor3

Now let’s think: what happens if field1 is zero? In this case, field1 * valor1 will be zero and will not change the result of the sum. So why turn the field to zero, and this will not change the result? If the field is empty, simply don’t include it in the sum.

I know you thought that "if empty, turns to zero" could be a good solution, but if we analyze well, just ignore the empty fields, since the value zero will not make a difference in the result.

By the way, in your code you’re doing parseFloat(field1)*0, that is, is multiplying the first input by zero, which also does not alter the sum. That means the value of field1 it won’t make the slightest difference in the end result, so I don’t even know what that field is for (unless it’s used elsewhere, of course, but even then including it in that particular calculation is totally unnecessary - and I just kept it in the example below for you to see how it would look).

In the example below I also changed the id of the latter input to "days" (could have changed that of others also, so that they have more significant names, but left as the original), and this input id="dias" is the only one who does not have the class="quantidade-item", because it has no multiplier factor and should not be included in the loop main (although in the example below I could also do document.querySelectorAll('input[data-multiplicador]') to pick up all fields except this one, as it is the only one that has no value in the dataset).

I also use a mathematical method to leave the number to only 2 decimal places (because toFixed can round up the value depending on the case) - but just to say that there is another way because you see which fits best for your case (for example, if the result is 1.427, use toFixed(2) round to 1.43, already using what I did, it does not round and only keeps the decimal places, resulting in 1.42).

The code below also shows a message if no number is entered in the field. And as the final result is a monetary value, I included an option with toLocaleString, to show how to properly format for your case (but be sure to see more options on documentation):

function arredonda(valor, casas) {
    let fator = Math.pow(10, casas);
    return Math.floor(valor * fator) / fator;
}

function calculate() {
    let dias = parseFloat(document.querySelector('input#dias').value);
    if (isNaN(dias)) {
        alert('quantidade de dias deve ser um número');
    } else {
        let soma = 0;
        for (const input of document.querySelectorAll('input.quantidade-item')) {
            if (input.value !== '') { // só prossigo se o campo não for vazio
                let valor = parseFloat(input.value);
                if (isNaN(valor)) {
                    alert(`Campo ${input.id} não é um número`);
                    return; // não é número, interrompe o cálculo (não tem porque prosseguir)
                } else {
                    // multiplica o valor do campo pelo multiplicador que está no dataset e atualiza a soma
                    soma += valor * parseFloat(input.dataset.multiplicador);
                }
            }
        }
        // multiplica a soma pela quantidade de dias e arredonda para 2 casas decimais
        document.querySelector('p#resultado').textContent = 'O valor é ' + arredonda(soma * dias, 2);
        // só incluí um alert para mostrar que o valor foi calculado corretamente
        // e também para mostrar a opção com toLocaleString
        alert('O valor é ' + arredonda(soma * dias, 2).toLocaleString('en', {style: 'currency', currency: 'EUR'}));
    }
}
Pessoas<br>
Até 5 anos.............<input type="text" id="num1" class="quantidade-item" data-multiplicador="0">
<br>
De 5 a 10 anos......<input type="text" id="num2" class="quantidade-item" data-multiplicador="1.1">
<br>
Mais de 10 anos..<input type="text" id="num3" class="quantidade-item" data-multiplicador="2.2">
<br>
Tendas<br>
Até 4 metros........<input type="text" id="num4" class="quantidade-item" data-multiplicador="1.7">
<br>
De 5 a 12 metros..<input type="text" id="num5" class="quantidade-item" data-multiplicador="2">
<br>
De 13 a 20 metros<input type="text" id="num6" class="quantidade-item" data-multiplicador="2.5">
<br>
Caravana<br>
Até 4 metros........<input type="text" id="num7" class="quantidade-item" data-multiplicador="2.1">
<br>
De 5 a 6 metros....<input type="text" id="num8" class="quantidade-item" data-multiplicador="2.2">
<br>
Mais de 6 metros<input type="text" id="num9" class="quantidade-item" data-multiplicador="2.3">
<br>
Viaturas
<br>
Reboque................<input type="text" id="num10" class="quantidade-item" data-multiplicador="1">
<br>
Autocarro.............<input type="text" id="num11" class="quantidade-item" data-multiplicador="6.7">
<br>
Automóvel...........<input type="text" id="num12" class="quantidade-item" data-multiplicador="1.7">
<br>
Autocaravana.....<input type="text" id="num13" class="quantidade-item" data-multiplicador="3.8">
<br>
Motocicletas........<input type="text" id="num14" class="quantidade-item" data-multiplicador="1.7">
<br>
Outras<br>
Electricidade.......<input type="text" id="num15" class="quantidade-item" data-multiplicador="1.5">
<br>
<br>
Dias.........................<input type="text" id="dias">
<br>
<br>
<button onclick="calculate()">Calcular</button>
<p id="resultado"></p>

One detail is that the attribute data-multiplicador will be available in Javascript on the property dataset.multiplicador (I don’t know why they didn’t call each other by the same name, but that’s how it works).

It is also worth remembering that it does not make sense dias be zero if the field is empty, as you multiply the sum by dias, then if dias is zero, the final result will be zero (i.e., if dias is empty or has any other invalid value, it makes no sense to even start the calculation, so the first if to check whether the field dias is a number).


I know your way "works," but I just wanted to show that there are other - in my opinion, better - ways to tackle this problem :-)

For example, if you have to add or remove a field, or change the multiplier factor, just change the HTML, because the Javascript code will remain the same (in your code, in addition to changing the HTML, you would have to add/remove the field in the Javascript function and change the multiplier). Not to mention that the above code has become much simpler and easier to understand (and modify, if applicable).

  • I have just one question, when you print the final result in the alert appears with 2 decimal places, but below appears only with 1, I checked and the code is the same, what could be the problem? and also how to increase the font size of the answer?

  • @Davidpeixoto has a difference. No alert i use toLocaleString, which precisely serves to format the value

  • i tried with fontsize to change but could not, has how to leave a sample of how it would look?

  • @Davidpeixoto In the example above is only do at the end document.querySelector('p#resultado').textContent = 'O valor é ' + arredonda(soma * dias, 2).toLocaleString('en', {style: 'currency', currency: 'EUR'}); - fontsize only changes the font size, who controls the format and decimals is the toLocaleString

  • I of the decimal places got, I didn’t get was the part of increasing the font size

  • @DavidPeixoto https://answall.com/a/240139/112052

  • I was missing a part closing, so it wasn’t working, it already did, thankful once again.

  • Nice answer, congratulations! I learned a little more. Now tell me, this id thing = I think it has a name, you know what it is?

  • @LeoCaracciolo https://developer.mozilla.org/en-US/docs/Web/CSS/Attribute_selectors

Show 4 more comments

-2

  • I tried both and I couldn’t, but thank you

  • would not really work only with the addition of the operator I indicated, to work you would need to pass all inputs to the same number I commented (this would avoid typing letters for example) and assign an initial value for each of the inputs with the tag value="0" For example, I believe that the operator 'would work? ' because it validates null and Undefined and leaves as text without initializing the field the Document.getElementById("num1"). value comes as empty string.

-3

Your variables get undefined when they don’t get post value you’ve already created them by getting a value from inputs where it can be anything after you created it as text. To solve this try to pass them off the function and attaching the zero to them.

var field1 = 0;

And within the function call :

field1=document.getElementById("num1").value;

Do the same for all and pass your input to type number to prevent the user to put letters and generate an error in the account.

  • 1

    tested this? the variable fiedl1 will have its contents overwritten in it, do a test and see if this solution works

  • tested and gave nothing, gave no output

Browser other questions tagged

You are not signed in. Login or sign up in order to post.