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).
Makes an if for if the field is empty, put that its value is zero
– Leonardo Negrão
tried, but every time I leave a blank field still not giving output.
– David Peixoto